本文へスキップ
株式会社オープンナレッジ
株式会社オープンナレッジ Open Knowledge Inc.
データベース隔離工学・正規リファレンス db01.ok.st / PostgreSQL 19 / OpenZFS 8K

PostgreSQL 19 FORCE ROW LEVEL SECURITY と ON CONFLICT DO SELECT によるマルチテナント分離設計

監修:加藤 明生(株式会社オープンナレッジ 創業者・代表取締役CTO / データベーススペシャリスト 第DB-2013-04-00083号 / 登録情報処理安全確保支援士 第007617号)

1. 基本と全体像

「画面プログラムの注意深さ」に頼らず、データベース自体で個室の鍵をかける

専用データベース基盤db01.ok.stにおける行単位のテナント分離イメージ写真
db01.ok.st(FreeBSD 15.1 + OpenZFS + PostgreSQL 19) パブリックIPからの直接接続を遮断した閉域vLAN上で、全顧客・全学習者の行に専用の鍵をかけます。
Rust 2024型システムとPostgreSQL 19カーネル検証による二重安全装置イメージ写真
Rust Typestate × PostgreSQL 19 FORCE RLS 二重保護 テナント鍵を束縛しない限りコンパイルすら通らず、DB側も他社データを1行も返却しません。
PostgreSQL 19 FORCE RLS マルチテナント分離設計の各章におけるテーマと要点一覧表
章構成 主なテーマ 要点と確認ポイント
1. 基本と全体像 WHERE句書き忘れ事故の構造的解消 テーブル所有者ロールを含め行単位ポリシーを強制する FORCE ROW LEVEL SECURITY と Rust 型安全ゲートの全体像を解説します。
2. 現場での進め方と対策 3大アンチパターン回避と InitPlan 高速化 コネクションプール混線を防ぐ SET LOCAL と、(SELECT sovereign_auth.current_tenant_id()) による定数化高速スキャンを示します。
3. 関連する制度とルール SCS評価制度 ★3/★4・医療第7.0版との整合 OWASP Top 10 A01(アクセス制御の不備)対策、および3秒・1タップ安全登録における個人学習データの分離保護を整理します。
4. 詳しい技術仕様としくみ PostgreSQL 19 最新機能 × OpenZFS 8K 実装 ON CONFLICT DO SELECT(0B WAL)、uuidv7()、ネイティブ REPACK (CONCURRENTLY)、COPY FORMAT JSON、Rust Typestate コードを公開します。
図解 01:Rust 2024 Typestate トランザクションと PostgreSQL 19 FORCE RLS 二重隔離パイプライン(クリックで拡大)
db01.ok.st(PostgreSQL 19)におけるマルチテナント行レベル分離の3段階ゲート 01. Rust 2024 型安全ゲート ・UnboundTx には SQL 実行メソッドなし ・TenantUuid(RFC 9562 uuidv7)検証 ・SET LOCAL でトランザクション局所束縛 ・COMMIT/ROLLBACK 時に自動破棄 鍵の指定漏れをコンパイル時に拒否 02. PG19 Query Rewriter 検問層 ・ENABLE + FORCE ROW LEVEL SECURITY ・AS RESTRICTIVE ポリシーで論理積強制 ・(SELECT current_tenant_id()) 定数化 ・security_barrier でサイドチャネル防止 WHERE句脱落時も他社データ 0 行を保証 03. OpenZFS 8KB 物理整合 ・BLCKSZ=8192B == recordsize=8K ・WAL専用 zroot/pg19/wal (128K) ・ON CONFLICT DO SELECT (0B WAL) ・REPACK (CONCURRENTLY) 無停止整列 CoW断片化を抑えミリ秒応答を維持
2. 現場での進め方と対策

RLS実装の3大アンチパターン回避と PostgreSQL 19 最適化ポイント

GUARD 01 / 所有者バイパス防止

FORCE RLS + NOBYPASSRLS

ENABLE RLS だけではテーブル所有者が全行を参照できてしまいます。必ず FORCE ROW LEVEL SECURITY と NOBYPASSRLS ロールを併用します。

GUARD 02 / InitPlan 定数化

(SELECT current_tenant_id())

ポリシー内でスカラ副問い合わせとして包むことで、PostgreSQL 19 プランナが InitPlan として1度だけ評価し、複合主キー (tenant_id, id) の高速 Index Scan に直結させます。

GUARD 03 / 0バイトWAL冪等認証

ON CONFLICT DO SELECT

3秒・1タップ安全登録の再ログイン時やWebhook再送時に不要な DO UPDATE を排し、書き込み0バイト・1往復で既存行を安全に取得します。

図解 02:PostgreSQL 19『ON CONFLICT DO SELECT(0バイトWAL)』と『InitPlan 定数化』の実行比較(クリックで拡大)
OpenZFS CoW ストレージの寿命と速度を最大化する PostgreSQL 19 クエリ設計 従来の実装(ダミー DO UPDATE + 行ごとGUC評価) ・ON CONFLICT DO UPDATE SET updated_at = updated_at ・値が変わらなくても新タプル生成+WAL書き込み+ZFS CoW発生 ・100万行スキャン時に current_setting() を100万回呼び出し 課題:テーブル肥大化(Bloat)とCPUオーバーヘッド db01.ok.st 正規実装(PostgreSQL 19 ネイティブ機能) ・INSERT ... ON CONFLICT DO SELECT RETURNING * ・既存行ヒット時は WAL生成 0 Bytes・ディスク書込ゼロで即返却 ・tenant_id = (SELECT sovereign_auth.current_tenant_id()) 効果:B-Tree Skip Scan / Index Scan で 0.1〜1ms 台の安定応答
3. 関連する制度とルール

公的セキュリティ基準(SCS評価制度 ★3/★4・医療ガイドライン第7.0版)との対応

PostgreSQL 19 の機能と公的セキュリティガイドライン要件の対照表
PostgreSQL 19 × OpenZFS 機構 対応する公的基準・リスク分類 実務上の保護効果
FORCE ROW LEVEL SECURITY + AS RESTRICTIVE OWASP Top 10 A01 / 経産省SCS評価制度 ★3・★4 アクセス制御 アプリケーション改修時のSQL条件漏れによる他社情報・他学習者履歴の混入を構造的に防止
sovereign_auth.micro_users + uuidv7() 個人情報保護法 安全管理措置 / 3秒・1タップ無料安全登録基盤 匿名ブラウザ保存の消失・共用PC閲覧リスクを排し、個人ごとの暗号化領域で学習・試算履歴を保全
COPY ... TO ... (FORMAT JSON) + REPACK (CONCURRENTLY) 厚労省 医療情報ガイドライン第6.0版・第7.0版(見読性・可用性) 無停止でのテーブル再編成と、CPUシリアライズ負荷を抑えた監査証跡JSONエクスポートを実現
4. 詳しい技術仕様としくみ

db01.ok.st PostgreSQL 19 正規DDL & Rust 2024 Affine Typestate 実装仕様

jit = off / io_method = worker
図解 03:db01.ok.st で稼働する PostgreSQL 19 の6大コア機能スタック(クリックで拡大)
1. ON CONFLICT DO SELECT 書き込み0バイト・1往復で冪等行返却 ZFS CoW断片化と不要WALを排除 2. REPACK (CONCURRENTLY) 外部C拡張なしで無停止の物理再編成 テナントID順のクラスタ局所性を維持 3. uuidv7() + AIO Worker RFC 9562 時系列UUID主キー&並列AIO B-Tree ページ分割とランダムI/Oを抑制 4. COPY ... (FORMAT JSON) ネイティブJSONストリーミング高速出力 監査証跡・テナントデータ即時エクスポート 5. WAIT FOR LSN & 全順序同期 Read-Your-Writes 整合性と論理レプリカ FOR ALL SEQUENCES で無停止移行対応 6. FORCE RLS + InitPlan security_barrier + 実行計画安定ロック 短命OLTP向けに既定 jit = off で安定化
PostgreSQL 19 DDL(db01.ok.st: sovereign_auth.micro_users & FORCE RLS + ON CONFLICT DO SELECT)
CREATE SCHEMA IF NOT EXISTS sovereign_auth;

CREATE OR REPLACE FUNCTION sovereign_auth.current_tenant_id()
RETURNS uuid LANGUAGE sql STABLE PARALLEL SAFE AS $$
  SELECT NULLIF(current_setting('app.current_tenant_id', true), '')::uuid;
$$;

CREATE TABLE IF NOT EXISTS sovereign_auth.micro_users (
    user_id       UUID NOT NULL DEFAULT uuidv7(),
    tenant_id     UUID NOT NULL,
    provider      VARCHAR(32) NOT NULL,
    subject_hash  BYTEA NOT NULL CHECK (octet_length(subject_hash) = 32),
    created_at    TIMESTAMPTZ NOT NULL DEFAULT clock_timestamp(),
    PRIMARY KEY (tenant_id, user_id),
    UNIQUE (tenant_id, provider, subject_hash)
);

ALTER TABLE sovereign_auth.micro_users ENABLE ROW LEVEL SECURITY;
ALTER TABLE sovereign_auth.micro_users FORCE ROW LEVEL SECURITY;

CREATE POLICY micro_users_tenant_isolation ON sovereign_auth.micro_users
    AS RESTRICTIVE FOR ALL TO PUBLIC
    USING (tenant_id = (SELECT sovereign_auth.current_tenant_id()))
    WITH CHECK (tenant_id = (SELECT sovereign_auth.current_tenant_id()));

-- 0-Byte WAL Idempotent Sign-In / Registration in PostgreSQL 19
INSERT INTO sovereign_auth.micro_users (tenant_id, provider, subject_hash)
VALUES ($1, $2, $3)
ON CONFLICT (tenant_id, provider, subject_hash) DO SELECT
RETURNING user_id, tenant_id, created_at;
ご質問・公的制度の活用に関するお問い合わせ窓口

掲載資料に関するご質問・公的制度活用のご案内

本ページの図解や解説内容に関するご質問、経済産業省「SCS評価制度」やIPA「SECURITY ACTION・サイバーセキュリティお助け隊サービス」等の公的制度の確認方法について、落ち着いた参考窓口としてご案内しております。売り込みや営業連絡は一切行いませんので、社内勉強会やご家庭での確認資料としてご自由にご活用ください。

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

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