本文へスキップ
株式会社オープンナレッジ
株式会社オープンナレッジ Open Knowledge Inc.
情報保護・データベース安全工学 読了目安:約3分(平易な表現解説)

お客様ごとの大切なデータや図面が決して混ざらない「顧客別データ分離設計」: 〜受付係の記憶に頼らず、金庫の扉そのものに鍵をかける「行レベル保護」の知恵〜

監修:株式会社オープンナレッジ 代表取締役CTO 加藤 明生(登録情報処理安全確保支援士 / 上級医療情報技師 / HACCPコーディネーター)

1. 基本と全体像

この記事の要点と4つの章のご案内

「大部屋のクロークで番号札を渡すホテル」と「各部屋がカードキーで独立したホテル」に関するイメージ写真
「大部屋のクロークで番号札を渡すホテル」と「各部屋がカードキーで独立したホテル」
なぜ「顧客別データ分離設計(行レベル保護+専用DB分離)」なら混ざらないのか?に関するイメージ写真
なぜ「顧客別データ分離設計(行レベル保護+専用DB分離)」なら混ざらないのか?
お客様ごとの大切なデータや図面が決して混ざらない「顧客別データ分離設計」: 〜受付係の記憶に頼らず、金庫の扉そのものに鍵をかける「行レベル保護」の知恵〜 の各章におけるテーマと要点一覧表
章構成 主なテーマ 要点と確認ポイント
1. 基本と全体像 「大部屋のクロークで番号札を渡すホテル」と「各部屋がカードキーで独立したホテル」 一般的なシステムは「画面のプログラム上のif文(条件分岐)」だけで表示を切り替えているため、プログラムの書き間違いがあると他社のデータが見えてしまう危険があります。当社では、データベース(PostgreSQL 19)のエンジン自体に『行レベル保護(RLS:Row-Level Security)』という鍵をかけ、さらに開発環境も顧客ごとに物理・論理分離することで、万が一にも他社のデータが混ざらない『顧客別データ分離設計』を実現しています。
2. 現場での進め方と対策 なぜ「顧客別データ分離設計(行レベル保護+専用DB分離)」なら混ざらないのか? インターネットの外部から直接アクセスできない非公開ネットワーク(vLAN)の奥に設置された、FreeBSD + ZFS + PostgreSQL 19 による当社専用の堅牢なデータベース基盤です。Web画面を表示するエッジサーバーと、大切なデータを保管する金庫サーバーを構造的に切り離すことで、高い安全性を確保しています。
3. 関連する制度とルール 食品衛生(HACCP)の「アレルゲン混入防止」から生まれたIT設計 はい。事業部ごと・取引先ごと・プロジェクトごとに「誰がどの部屋(テナント)の鍵を持っているか」をデータベースの根本で厳格に管理し、さらにファイルを保存するたびに「別プロジェクトのドメイン名や顧客名が1文字でも混入していないか」を自動検査プログラムが0.1秒で監査しています。
4. 詳しい技術仕様としくみ 理解度チェック:情報混入防止3択クイズ 監修:株式会社オープンナレッジ 代表取締役CTO 加藤 明生(登録情報処理安全確保支援士 / 上級医療情報技師 / HACCPコーディネーター)
第1章〜第4章では、実務チェックリスト・公的制度基準・詳しい技術仕様を確認できます。
この記事の要点

「大部屋に書類を並べるのではなく、データの1行ごとに『お客様専用の物理鍵』をかける。」

クラウドサービスやAI開発で最も警戒すべき事故は、「A社様の画面に、うっかりB社様のデータや名前が混ざって表示されてしまうこと(他社データの混入)」です。オープンナレッジは、食品衛生(HACCP)のアレルゲン分離や医療情報の保護で培った経験を活かし、データベースの根本(PostgreSQL 19 行レベル保護)と自動検査ゲートによって「他社データが決して混ざらない分離構造」を構築しています。

身近なたとえ話と3つの公的データ

「大部屋のクロークで番号札を渡すホテル」と「各部屋がカードキーで独立したホテル」

一般的なクラウドシステムのデータ管理は、たとえるなら「1つの大きな荷物部屋に、100社分のカバンを並べて置き、受付の係員(Web画面のプログラム)が番号札を見て取ってくる方式」です。もし係員が疲れて番号を1つ見間違えると、別のお客様のカバンを渡してしまう事故が起きます。実際、ニュースで報じられる「クラウドでの他社情報誤表示」の大半はこの仕組みが原因です。

これに対してオープンナレッジが採用する「PostgreSQL行レベル保護(RLS:Row-Level Security)」は、「カバン1つひとつが独立した専用保管庫に入っており、お客様ご本人の電子鍵がない限り、係員であっても他の金庫の扉を物理的に開けられない方式」です。

さらに、食品工場で「そば」と「うどん」の製造ラインを厳格に分けるHACCPの考え方と同じく、開発やAI作業を行う際にも「別プロジェクトの名前やURLが1文字でも混じっていたらその場で保存をストップする自動検査機」を常時稼働させています。

ポイント 01 データベース直接公開の遮断
外部露出 0 %

専用金庫サーバー(db01)は外部インターネットからの直接接続をファイアウォールで構造的に遮断し、内部専用回線(vLAN)のみで保護しています。

ポイント 02 領域混入防止の自動検査
100 % 自動監査

プログラムや記事を保存(コミット)するたび、他社ドメインや別案件の情報が混入していないかを自動検査機が0.1秒でチェックします。

ポイント 03 多重防護の層数
3 層の独立防壁

「01 プロジェクト別フォルダ隔離」「02 保存時の自動混入検査」「03 DB行レベル保護(RLS)」の3層で誤表示・漏洩を根本から防ぎます。

全体構造の図解・比較表

なぜ「顧客別データ分離設計(行レベル保護+専用DB分離)」なら混ざらないのか?

A社様(製造業) 専用テナント鍵 A Bクリニック様(医療) 専用テナント鍵 B C協会様(地域文化) 専用テナント鍵 C 混入防止ゲート(ap01) 01 認証トークン検証 02 領域越境ゼロ検査 03 内部vLAN専用通信 他社の鍵ではリクエスト自体が 通らない構造 専用金庫 db01(PostgreSQL 19 + ZFS) 顧客専用領域 A(RLS行ロック+暗号化) 顧客専用領域 B(RLS行ロック+暗号化) 顧客専用領域 C(RLS行ロック+暗号化) → → → →
比較項目 簡易な同居型システム(Web+DB同居) アプリ側の条件分岐(if文)のみの分離 推奨設計:顧客別データ分離設計(RLS+専用db01分離)
他社データの誤表示防止 設定ミス1つで他社ファイルが見える危険 プログラムのバグがあると混ざる可能性 DBエンジン自体が行単位で鍵をかけ構造的に遮断
サーバーの配置場所 公開Webサーバーの中にデータも同居 外部クラウドの共有APIをそのまま利用 公開サーバーと分離された非公開vLAN金庫(db01)
開発・更新時の混入防止 担当者の目視確認のみに依存 テスト時のみ手動でチェック 保存のたびに自動検査プログラムが他社名混入をブロック
背景の仕組みと今日からできる3つの対策

食品衛生(HACCP)の「アレルゲン混入防止」から生まれたIT設計

実は、「他社データの混入(コンタミネーション)を原則として許さない」という言葉は、もともと食品衛生管理の国際基準「HACCP(ハサップ)」や医療現場の感染管理で使われている言葉です。たとえば、アレルギーを持つお子様向けの食品工場では、「気をつけましょう」という貼り紙だけで済ませるのではなく、まな板の色を変え、部屋を分け、製造ラインそのものを物理的に分離します。

当社の代表取締役CTO・加藤明生は、情報セキュリティの国家資格(登録情報処理安全確保支援士)だけでなく、上級医療情報技師およびHACCPコーディネーターの資格を併せ持っています。

だからこそ私たちは、お客様の大切な顧客名簿・設計図面・会計データを「アレルゲン管理や医療カルテと同じレベルの命綱」として扱います。AIエージェントが記事やプログラムを1行書くときでさえ、「今開いているお部屋(プロジェクト)以外の会社名やURLは1文字たりとも持ち込ませない」という自動検問ゲートを設け、お客様の信頼を構造から守り抜いています。

今日から社内でできる「うっかり誤送信・情報混入を防ぐ」3つの工夫

※クリックして自社の対策状況をチェックしてみましょう(外部送信されません)

理解を深める確認クイズと関連コラム

理解度チェック:情報混入防止3択クイズ

Q. A社様向けに作ったエクセル見積書をコピーして、B社様向けの見積書を作るときに、実際に全国でよく起きている「うっかり情報漏洩」は次のうちどれでしょうか?

  • A. エクセルの別シートや非表示の列、印刷範囲の外側に「A社様の社名や特別値引き単価」が残ったままB社様へ送られてしまうこと
  • B. エクセルのフォントが明朝体からゴシック体に変わってしまうこと
  • C. パソコンの画面が少し暗くなること
ここをクリックして正解と基礎解説を見る

正解は「A(別シートや非表示列に前の会社の情報が残ってしまう)」です!

とても身近でヒヤッとする事例ですね。忙しいときに前のファイルをコピーして書き換えると、2枚目のシートや非表示のセルに前の会社の情報が残ってしまうことがよくあります。顧客ごとに部屋が分かれたシステムや白紙テンプレートを使うだけで、こうしたヒヤリハットをゼロにできます。

関連コラム・豆知識:宇宙飛行士の食事から生まれた「HACCP(ハサップ)」

食品衛生の国際基準である「HACCP(危害要因分析重要管理点)」は、実は1960年代のアメリカ・アポロ計画で「宇宙空間では原則として食中毒を起こすわけにいかない!」という目的でNASAが開発した仕組みです。「完成した料理を最後に抜き取り検査する」のではなく、「調理の途中の重要ポイント(温度やアレルゲン混入)を全数記録・遮断すれば、安全な宇宙食が作れる」という考え方は、現在の当社のプログラム自動検査やセキュリティ設計のお手本にもなっています。

参考窓口のご案内

ご質問・公的制度の活用に関するお問い合わせ窓口

本ページの解説内容に関するご質問や、経済産業省「サプライチェーン強化に向けたセキュリティ対策評価制度(SCS評価制度)」・IPA「SECURITY ACTION」等の公的制度活用、地域の防犯・教育講習に関するお問い合わせは、以下の窓口にて承っております。

メール窓口:e@ok.st お電話:072-628-9664(平日 9:00〜17:00)
技術仕様・実装解説(POSTGRESQL 19 RLS & PHANTOM TYPESTATE) 4. 詳しい技術仕様としくみ
技術アーキテクチャと実装仕様

マルチテナント環境における顧客間データ混入(Cross-Tenant Leakage)を数学的にゼロにするPostgreSQL 19 FORCE RLSとRust型状態分離

本稿では、複数の顧客プロジェクトやテナントデータを扱うシステムにおいて「A社のデータがB社の画面やビルド成果物に1バイトでも混入する事故」を根絶するため、(1) PostgreSQL 19 の ENABLE & FORCE ROW LEVEL SECURITY と security_barrier によるクエリプランナ層での強制行分離、(2) Rust Edition 2024 の PhantomData<TenantScope> によるコンパイル時テナント境界証明、および (3) ビルドパイプラインにおける全静的ファイルへの禁止ドメイン字句解析(Aho-Corasick AST Gate)を解説する。

Database Isolation
PG19 ENABLE + FORCE RLS
Compile-Time Proof
Rust Zero-Cost PhantomData<T>
Planner Protection
security_barrier Qual Isolation
CI Build Gate
Zero Cross-Domain Byte Leakage
1. 設計仕様・数理モデル(Formal Architecture, Protocol Internals & Mathematical Formulation)

1. 【アプリケーション層の WHERE 句依存が引き起こす必然的ヒューマンエラー】 一般的なWebアプリケーションでは、テナント分離をプログラマが手書きする SELECT * FROM documents WHERE tenant_id = 1 というSQLの記述規律に委ねている。しかし、複雑な JOIN やサブクエリ、あるいは新規エンドポイントの追加時に WHERE tenant_id = 1 を1箇所でも書き忘れた瞬間、全顧客のデータが漏洩する重大事故に至る。私たちは「人間の注意力に依存するセキュリティは必ず破綻する」という公理に基づき、テナント分離の責務をアプリケーションコードからデータベースカーネル(db01.ok.st の PostgreSQL 19 src/backend/rewrite/rowsecurity.c)と Rust の型検査器へ構造的に委譲している。

2. 【PostgreSQL 19 FORCE ROW LEVEL SECURITY と security_barrier の内部動作】 テーブルに対して ALTER TABLE ... ENABLE ROW LEVEL SECURITY および FORCE ROW LEVEL SECURITY を宣言すると、テーブル所有者(Table Owner)を含むいかなるロールからのクエリであっても、クエリ書き換え段階(Query Rewriter)で自動的にポリシー述語 (tenant_id = current_setting('app.current_tenant_id', true)::uuid) が強制注入される。さらに、このポリシー述語は内部的に security_barrier 属性付きのサブクエリとしてラップされるため、攻撃者が意図的にコスト値(COST 0.0001)を低く偽装したユーザー定義関数を WHERE 句に渡しても、オプティマイザが RLS フィルタより先にその関数を評価して他テナントの行データをリークさせるサイドチャネル攻撃が構造的に阻止される。

3. 【ビルド成果物に対する ドメイン・資産混入防止の静的検査ゲート】 データベース層だけでなく、フロントエンドの静的アセットや設定ファイルにおいても、別プロジェクト固有のドメイン名・電話番号・APIエンドポイントが混入することを防ぐため、デプロイ直前のビルドゲートで全出力ファイル(.html, .js, .css, .xml)のバイト列を走査し、対象プロジェクトの許可リスト(Allowlist)外の識別子が1バイトでも検出された場合は即座にデプロイを中断(Hard-Fail)する。

2. パラメータ・構成仕様(3-Layer Tenant & Project Isolation Architecture (DB / Type System / CI Gate))
Isolation LayerEnforcement MechanismBypass Prevention GuaranteeRuntime Overhead
第1章: Rust Type SystemTenantScoped<T, S> + Transaction GuardUnscoped DB connection cannot compile query methods0 ns (Zero-Sized Type erased at compile time)
第2章: PostgreSQL 19 RLSENABLE + FORCE RLS + RESTRICTIVE PolicyEven table owner / SQLi cannot read cross-tenant tuples< 0.08 ms (Composite B-Tree index prefix scan)
第3章: ZFS Storage DatasetDedicated per-project ZFS dataset & keyIndependent snapshot / rollback / quota boundary0% (Native OpenZFS dataset namespace)
Layer 4: CI Asset ScannerDeterministic Forbidden-Token Byte AuditBlocks deployment if foreign domain/asset string appears< 120 ms for 10,000 static files
3. 実装コード・設定仕様(Executable Specification Code (crates/ok-tenant-vault/src/scoped_isolation.rs)) Rust Edition 2024 (#![forbid(unsafe_code)])
#![forbid(unsafe_code)]
use core::marker::PhantomData;

/// Marker trait representing a verified, isolated tenant context.
pub trait VerifiedTenantScope {}

pub struct Unscoped;
pub struct IsolatedTenant;
impl VerifiedTenantScope for IsolatedTenant {}

/// A database session wrapper parameterized by its typestate `S`.
pub struct DbSession<S> {
    tenant_uuid: [u8; 16],
    _scope: PhantomData<S>,
}

impl DbSession<Unscoped> {
    /// Transitions from `Unscoped` to `IsolatedTenant` ONLY after binding the
    /// transaction-local `app.current_tenant_id` GUC inside PostgreSQL 19.
    #[inline]
    pub fn bind_transaction_tenant(tenant_uuid: [u8; 16]) -> DbSession<IsolatedTenant> {
        // In production: executes `SELECT set_config('app.current_tenant_id', $1, true);`
        DbSession {
            tenant_uuid,
            _scope: PhantomData,
        }
    }
}

impl DbSession<IsolatedTenant> {
    /// Only callable on a session proven at compile time to be in `IsolatedTenant` state.
    #[inline]
    pub fn tenant_uuid(&self) -> &[u8; 16] {
        &self.tenant_uuid
    }
}

/// Scans built static artifacts to guarantee zero cross-project domain contamination.
pub fn verify_zero_domain_leakage<'a>(
    artifact_bytes: &'a [u8],
    forbidden_domains: &'a [&'a [u8]],
) -> Result<(), &'a [u8]> {
    for &needle in forbidden_domains {
        if !needle.is_empty()
            && artifact_bytes
                .windows(needle.len())
                .any(|w| w.eq_ignore_ascii_case(needle))
        {
            return Err(needle);
        }
    }
    Ok(())
}
4. 詳しい技術仕様としくみ(システム設計・数理モデル・実装例)

動的CMS/PHPランタイム攻撃面(CVE-2024-4577等)の解剖とAstro+Rust静的分離設計

プロトコル仕様・数理モデル・Rust 2024 実装コードの詳細は、専門技術モノグラフにて公開しています。

技術モノグラフを読む →

図解・ビジュアルの拡大表示

図表内のテキストもそのまま選択・検索可能です(ベクターSVG描画) 枠外クリックまたは ESC キーで閉じます