PROD欧州主権の BaaS プラットフォームダッシュボードを開く →

エンジニアリング · 10 分読み取り

RLS とプロジェクトごとの専用データベースの比較

Affane Daylami · Fondateur · 2026年7月27日

ブログに戻る

「RLS マルチテナント postgres」を検索すると、共有データベース、tenant_idcolumn、行をフィルタリングするポリシーなど、ほぼどこでも同じスキーマが見つかります。これは、Aurabase がプロジェクトを相互に分離するために使用するモデルではありません。各プロジェクトは独自の Postgres 16 データベースを受け取り、他のクライアントと共有されることはありません。RLS はそこに残りますが、別のフロア、つまり自分のユーザー用のデータベース内に残ります。

この英語のテキストはフランス語のオリジナルから自動的に生成されたもので、まだレビューされていません。
このページは自動翻訳されました。英語版が正式です。

「RLS」と「マルチテナント」は、この主題に関してすでに公開されているほぼすべてのコンテンツで隣り合って見られます。これは、多くの SaaS アーキテクチャにとって正当な選択ですが、Aurabase が独自のクライアントを互いに分離するために選択したものではありません。この投稿では、簡略化したマーケティングの説明ではなく、実際のプロビジョニング エンジンと実際に適用される RLS ポリシーとの違いについて説明します。 Aurabase のマネージド Postgres エンジンが分離を超えてカバーする内容の概要については、データベースドキュメントを参照してください。

必需品

  • プロジェクト間では、Aurabase は RLS 単独ではなく、専用の Postgres ベースによって分離します。各プロジェクトは、専用の CNPG クラスター (企業レベル) または独自の組織 (フリー/プロ/チーム) の CNPG クラスター上に独自の物理ベースを持ち、他の組織と共有されることはありません。
  • RLS (auth.uid()、 auth.role()、 auth.jwt()) はアクティブなままであり、独自のユーザーを分離するために、 の ベース内に置くことをお勧めします (Supabase と同じ規則)。
  • service_role およびプロジェクト ベースの管理ロールは、設計により RLS をバイパスします (BYPASSRLS)。これは、サーバー操作のための想定されるアーキテクチャ上の選択であり、欠陥ではありません。
  • このリポジトリですでに修正されている回帰 (古い共有スキーマで誤って付与された PUBLIC 権限) は、ベース レベルの境界が純粋なアプリケーション境界よりも耐性がある理由を具体的に示しています。
#
デフォルトのモデル

ほとんどのマルチテナント RLS ガイドが使用するショートカット

マルチテナント Postgres の最も文書化されたパターンは、単一のベース、各テーブルの tenant_id 列、この列を JWT から抽出された値と比較する RLS ポリシー の 3 行で構成されます。これは経済的であり、接続のプール、ダイアグラム、実行する単一のインスタンスが必要であり、テナントが多数で小規模で、個々のステークが低い場合にうまく機能します。

この妥協は現実のものです。2 つのクライアント間の境界は、テーブルごとに評価される SQL 式になります。新しいテーブルで忘れられたポリシー、スーパーユーザー ロールで実行されている接続、ライブで起動されたデバッグ スクリプト。これらの各インシデントは、操作上はどんなに些細なものであっても、すべてのテナントの行を同時にサイレントに公開する可能性があります。したがって、セキュリティ境界と技術境界 (基礎) はまったく同じものになります。

情報

これ自体は悪い選択ではありません。多くの製品にとっては正しい妥協策です。この投稿の要点は別のところにあります。これは、Aurabase が独自のクライアント (異なるコンプライアンス要件を持つ可能性のあるプロジェクト全体) を相互に分離するために行った妥協ではありません。

#
コード内

2 つのアーキテクチャ、プロジェクト間でベースが共有されることはありません

最近のプロビジョナーの統合 (コード内で「タスク 12」としてマークされている) 以降、Aurabase のアクティブな Postgres プロジェクトは、正確に 2 つのアーキテクチャに分類されます。実際に複数のプロジェクト間でベースを共有する古いモデルは、プロビジョニング パスから削除されました。

provisioning/instances.rsrust
pub enum ProjectInstanceKind {
    /// THIS ONLY プロジェクト専用の CNPG クラスター (企業レベル)。
    FullyDedicated,

    /// プロジェクト ORGANIZATION の CNPG クラスター上のデータベース —
    /// 同じ組織の他のプロジェクトと共有、
    /// 第三者機関とは決して協力しません。
    SharedClusterDedicated,
}

プロジェクト レベルによって、2 つのどちらが適用されるかが決まります。そして、それを決定するのはコードであり、ダッシュボードでチェックされたボックスではありません。

provisioning/rules.rsrust
fn should_provision_dedicated(engine: &str, db_url_encrypted: &Option<String>, plan: &str) -> bool {
    matches!(engine, "postgres" | "postgresql")
        && plan == "enterprise"
        && !non_empty(db_url_encrypted)
}

// should_route_to_fleet(): 企業以外の層 (無料/プロ/チーム)
// 自分の組織の CNPG クラスターへのルートではなく、自分の組織の CNPG クラスターへのルート
// 別のアーキテクチャから — 移行 073、2 つのアーキテクチャへの統合を参照してください。
寸法完全専用(企業)SharedClusterD dedicated (無料/プロ/チーム)
CNPGクラスターこの一つのプロジェクトに捧げます共有されますが、2 つの組織間では共有されません
Postgresデータベースアプリ、それに投影するだけproject_<uuid>、クラスター上のプロジェクトごとに 1 つ
PostgreSQL ログインクラスター上の単一プロジェクト: クロスメンバーシップのリスクなしプロジェクトごとにログイン (F-013)、その唯一のロールのメンバー tenant_<uuid>

どちらのアーキテクチャでも、ベースまたはクラスターが 2 つの異なる組織をホストすることはありません。したがって、問題は「データが分離されているか」ではなく、「プロジェクトが CloudNativePG をすべて単独で計算しているか、それとも同じ組織内の他のプロジェクトと共有しているか」です。

この 2 つのアーキテクチャの統合は最近行われたものです。コードには、以前は 2 つの追加パスが含まれていました。それは、複数のプロジェクトが同じデータベース内に共存し、図によってのみ分離されている「共有マスター」と、postgrest_dedicated_shared_dbバリアントです。専用の移行によりこれらが削除され、projects テーブルの制約が残りの 2 つの値のみに強化されました。これは、まさに共有スキーマ モデルが以下で説明するバグの原因であったためです。

#
セキュリティ境界線

専用ベースが顧客間で共有される EPIRB に勝る理由

別個の Postgres データベースは、行レベルの境界ではなく、接続レベルの境界です。プロジェクト A のデータベースに接続されているアプリケーション ロールは、プロジェクト B のテーブルにクエリを実行することはできません。プロジェクト B に対して開いているセッションがありません。この特性は、RLS ポリシーの記述が不十分である場合、テーブルにない場合、または上位ロールによってバイパスされた場合でも当てはまります。最悪のケースは単一データベース内に限定されます。

この堆積物には実際のバグの痕跡もあり、これは逆のリスクを示しています。古い共有スキーマ モデル (廃止以降) では、provision_postgres_schema が誤って各プロジェクト スキーマに GRANT ALL ... TO PUBLIC 権限を付与しました。PUBLIC はメンバーシップ条件なしでデータベース内のすべてのロールに適用され、プロジェクトごとに分離されたログインが別のスキーマで読み書きできる可能性がありました。修正移行 (066) により、これらの権利が既存の権利から削除されました。

学んだ教訓

このパッチでは、リークを塞ぐための RLS ポリシーがもう 1 つ追加されませんでした。2 つのプロジェクトがデータベースを共有する可能性自体が排除されました。現在の 2 つのアーキテクチャについては、provisioning.rs からのコメントが白黒はっきりと文書化しています。「各プロジェクトにはすでに独自の物理 Postgres データベースがあります。」基本レベルの境界により、すべてのポリシーが常に正しく記述されていることに依存するのではなく、そのようなバグのクラス全体が単純に到達不能になります。

2026 年 8 月 23 日のパッチも同じ方向です。プロビジョナーによって無条件に配置された REVOKE ALL ON SCHEMA public は、古い共有データベース モデルで実際の分離のみを提供するため、トポロジに条件付きになりました。現在の 2 つのアーキテクチャでは、 public.<table>を明示的に参照する SQL ダンプのインポートを利益なしにブロックしました。

#
RLSの実践

EPIRB はユーザーのためにデータベース内に常駐します

上記のいずれによっても EPIRB は役に立たなくなります。単にフロアが変更されるだけです。 プロジェクトデータベースに入ると、Aurabase は、 Supabaseによって採用された PostgREST 規約を正確に公開します。 request.jwt.claimsのゲートウェイによって設定された JWT クレームを読み取る 3 つの SQL 関数です。

libs/aura-migrations/golden/auth_global.sqlsql
create function auth.uid() returns uuid
    language sql stable security definer
    set search_path to 'pg_catalog', 'pg_temp'
    as $$
    select nullif(nullif(current_setting('request.jwt.claims', true), '')::json->>'sub', '')::uuid
$$;

これらのヘルパーは、単に文書化されているだけではなく、Aurabase 自体の実際のポリシーで使用されます。リポジトリに配置される storage_objectsを保護するポリシーを次に示します (読み取り用に数行に再フォーマットされます)。

libs/aura-migrations/golden/storage.sqlsql
alter table storage_objects enable row level security;

create policy storage_objects_select on storage_objects
  for select using (
    (owner_id = auth.uid())
    or (
      exists (
        select 1 from storage_buckets b
        where (b.name = storage_objects.bucket_name and b.public)
      )
    )
  );

アプリケーションテーブルを運ぶ独自の project_<uuid>スキーマでは、Aurabase はユーザーに代わってポリシーを意図的に配置しません。コードはそれを「Supabase モデル」として文書化します。テーブルの RLS は、同じ関数、同じ構文を使用して、引き続きユーザーの責任になります。

#
BYPASSRLS を想定

service_role は RLS をバイパスします — 偶然ではなく仕様です

Postgres はネイティブで ロール属性、 BYPASSRLSを提供しますが、これはすべてのポリシーを無視します。 Aurabase は、これを 2 つのロールファミリーで自発的に使用します。 aura_service_role (サーバーロール、ブラウザ側では公開されません) と、 ALTER SCHEMA ... OWNER TOなどの DDL 操作中に使用される、各プロジェクトに固有の管理ロールです。

provisioning/roles.sqlsql
create role aura_service_role nologin bypassrls;
-- サーバーの役割: ブラウザー側で公開されることはなく、メンバーになることもありません
-- 別のプロジェクトからの役割。

リクエストを処理するロール anon/authenticated — tenant_<uuid> — には BYPASSRLSがありません。RLS は例外なく通常どおり適用されます。ボーナスとして、各プロジェクトに固有のシステム ダイアグラム (_auth、 _storage、 _platform) は、ポリシーなしでアクティブ化された RLS を受け取ります。 したがって、バイパス以外のロールはデフォルトで完全に拒否され、アプリケーション パスがある日誤ってアクセスした場合に備えて多層防御になります。

情報

昇格されたサーバーロールによる RLS のバイパスは、Aurabase に固有のものではありません。これは、Supabase 側の service_role と同じ構造です。重要なのは、 BYPASSRLSを避けることではなく、クライアントからアクセスできるロールには決して付与せず、単一のプロジェクトに限定することです。

このサーバーの役割は、事前定義された役割、カスタム RBAC、監査ログなど、より広範な体制の一部であり、セキュリティと RBACページで詳しく説明されています。

#
多層防御

共有クラスターでは、データベースがすべての作業を単独で実行するわけではありません

SharedClusterDedicatedレベルでは、同じ組織の複数のプロジェクトが単一の CNPG クラスター上に共存します。物理データベースはすでにプロジェクトを相互に分離していますが、PostgreSQL ロール (それら) はデータベースではなくクラスターにとってグローバル オブジェクトです。したがって、Aurabase はレイヤー、つまりプロジェクトごとに個別の PostgreSQL ログインを追加します。

libs/aura-core/src/lib.rsrust
pub fn project_authenticator_role(project_id: &str) -> String {
    format!("project_{}_authenticator", project_id.replace('-', '_'))
}

// デフォルトでアクティブ (F013_PER_PROJECT_AUTHENTICATOR)、非アクティブ化可能
// 明らかに緊急避難として。

各プロジェクトは独自のログインで接続し、その独自の tenant_<uuid> / tenant_<uuid>_admin ロールのメンバーのみを使用します。同じクラスター内の別のプロジェクトのメンバーではありません。データベースはすでにデータを分離しています。このプロジェクトごとのログインでは、プロジェクトに接続する ID も分離されるため、プロジェクト上のインシデントによってそのログインに別のメンバーに継承されるメンバーシップが付与されることはありません。

#
あなたのアーキテクチャのために

RLS 単独か専用ベース: 独自の SaaS を決定する方法

Aurabase の選択は普遍的なルールではありません。これは、クライアントが制御できないプラットフォーム上で、潜在的に異なるコンプライアンス要件を持つクライアントを相互に隔離するという、特定のケースに対する妥協です。独自の SaaS を構築している場合、異なるスケールで同じ疑問が生じます。

  • 共有ベース内の tenant_id を使用した RLS — テナントが多数で、個々のステークが低く、テナントごとのベースのコストが不釣り合いになる場合に関連します。例外なく、各テーブルで pg_proveを使用して各ポリシーをテストします。
  • 専用のベースまたは図 — テナントに独自のコンプライアンス問題 (健康、人事、公共部門) がある場合、パフォーマンスの分離を正当化するボリュームがある場合、または 2 つの特定のクライアント間のリークのコストが追加のインフラストラクチャのコストと不釣り合いな場合に関連します。

Aurabase の価格レベルは、これと同じ裁定を独自のクライアントに適用します。デフォルトでは組織によってベースが共有され、プロジェクトの課題が正当化される場合は専用クラスターが適用されます。独自のデータベース内の RLS パターン (所有権、組織別のマルチテナント、ロール階層) については、運用環境の RLS ガイド で、pgTAPテストを使用する 3 つのケースが詳しく説明されています。また、ダイアグラム上の自動生成された API が REST 以外にも興味がある場合は、pg_graphql と Hasura および PostGraphile の比較 は、Aurabase によって公開される Postgres サーフェスの残りの半分をカバーしています。

#
よくある質問

よくある質問

単一の Postgres データベース内のテナントを分離するには、RLS だけで十分ですか?+
各テーブルが正しいポリシーを保持し、非バイパスの役割を逃れる接続がない場合、技術的にはそうです。これはまさに、Aurabase が異なるプロジェクト間で取らないことを選択した運用リスクです。各ポリシー エラーは単一のベースに限定されたままになります。単一プロジェクト内で、独自のテナントの場合、RLS + tenant_id は依然として正当で広く使用されている選択肢です。
無料プロジェクトにはエンタープライズ層のような専用の Postgres クラスターがないのはなぜですか?+
無料プロジェクトを含め、プロジェクトごとに専用の CloudNativePG クラスターを使用すると、その大部分の実際の使用とは関係なく、予約されたコンピューティングが増加します。代わりに、Aurabase は、非エンタープライズプロジェクトのそれぞれに、互いに未知の複数のクライアント間の共通データベース内のスキーマではなく、その組織の CNPG クラスター上にある独自の物理 Postgres データベースを提供します (他の組織と共有されることはありません)。
auth.uid() は技術的にどのようにして私が誰であるかを知るのでしょうか?+
Aurabase ゲートウェイは JWT を検証し、トランザクションの間、そのクレームを Postgres セッションパラメータ request.jwt.claims に配置します。 auth.uid() は、この JSON からサブ フィールドを抽出して uuid にキャストするだけです。クレームが行われない場合 (匿名リクエスト、またはゲートウェイ外への直接接続)、current_setting() は NULL を返し、auth.uid() は NULL を返します。これにより、(owner_id = auth.uid()) を使用したポリシーへのアクセスが閉じられます。

導入の準備はできていますか?

5 分でバックエンドが完成します。

クレジット カードは不要 · 500 MB 無料 · 50,000 MAU