行レベルセキュリティポリシー
ユーザーごとに行を自動でフィルタリングします。
「行レベルセキュリティポリシー」はCoddyKit上の無料SQL Academyレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはSQL Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 SQL Academyコースには全4レッスンが含まれています。
行レベルセキュリティとは
行レベルセキュリティ(RLS)は、特定のデータベースユーザーまたはロールがテーブルのどの行を参照・変更できるかを制御できるPostgreSQLの機能です。すべてのクエリで行をフィルタリングする代わりに、ポリシーを一度定義すれば、PostgreSQLがすべてのSELECT、INSERT、UPDATE、DELETEに対して自動的に適用します。
特定のクエリではなく、テーブル自体に付加された目に見えないWHERE句だと考えると分かりやすいでしょう。
テーブルでのRLSの有効化
RLSはデフォルトでは無効です。各テーブルでALTER TABLE ... ENABLE ROW LEVEL SECURITYを使用して、明示的に有効化する必要があります。有効化すると、少なくとも1つのポリシーを作成するまで、テーブル所有者ではないロールには行が1件も表示されません。
-- Create a sample table
CREATE TABLE orders (
id SERIAL PRIMARY KEY,
owner TEXT NOT NULL,
amount NUMERIC(10,2)
);
-- Enable RLS
ALTER TABLE orders ENABLE ROW LEVEL SECURITY;最初のポリシーの作成
ポリシーはCREATE POLICYで作成します。ポリシー名と対象テーブルを指定し、USING式を記述します。USING句は各行に対して評価されるBoolean式で、式の結果がTRUEになる行だけがユーザーに表示されます。
-- Allow each user to see only their own orders
CREATE POLICY orders_owner_policy
ON orders
FOR SELECT
USING (owner = current_user);USING 句と WITH CHECK 句
ポリシーには、異なる目的を持つ2つのフィルター句があります。
- USING — 読み取り操作(SELECT、UPDATE、DELETE)で行をフィルタリングします。USING が TRUE を返す場合にのみ、その行が表示されます。
- WITH CHECK — 書き込み操作(INSERT、UPDATE)で行を検証します。WITH CHECK が TRUE を返す場合にのみ、書き込みが許可されます。省略した場合は、書き込みのチェックにも USING が再利用されます。
-- Allow users to select and insert only their own rows
CREATE POLICY orders_isolation
ON orders
FOR ALL
USING (owner = current_user)
WITH CHECK (owner = current_user);ポリシーの適用範囲: FOR SELECT、INSERT、UPDATE、DELETE
1つのポリシーで、すべてのコマンド(FOR ALL)または特定のコマンドを対象にできます。コマンドごとにポリシーを分けると、きめ細かな制御が可能になります。たとえば、すべてのユーザーにすべての行の読み取りを許可しつつ、自分の行だけを変更できるようにできます。
-- Everyone can read all orders
CREATE POLICY read_all_orders
ON orders
FOR SELECT
USING (true);
-- But each user can only update their own orders
CREATE POLICY update_own_orders
ON orders
FOR UPDATE
USING (owner = current_user)
WITH CHECK (owner = current_user);session_user と current_user の使用
PostgreSQL には、ポリシー式の中で現在のユーザーを識別する組み込み関数が用意されています。
- current_user — 現在有効な権限を持つロールです(SET ROLE の後に変わる場合があります)。
- session_user — 接続を開始したロールです(セッション中は変わりません)。
多くの RLS ポリシーでは、ロール切り替え後の実効ロールを反映する current_user を使用します。
-- Inspect the current identity inside a query
SELECT current_user, session_user;特定のロールへの RLS の適用
デフォルトでは、ポリシーは PUBLIC(すべてのロール)に適用されます。TO 句を使用すると、特定のロールに制限できます。通常のユーザー向けのポリシーと、管理者ロール向けの別のポリシーを用意したい場合に便利です。
-- Policy only for the 'app_user' role
CREATE POLICY app_user_policy
ON orders
FOR SELECT
TO app_user
USING (owner = current_user);
-- Separate permissive policy for 'admin' role
CREATE POLICY admin_full_access
ON orders
FOR ALL
TO admin
USING (true)
WITH CHECK (true);PERMISSIVE ポリシーと RESTRICTIVE ポリシー
同じテーブルに複数のポリシーを設定した場合、ポリシーは次の2通りの方法で作用します。
- PERMISSIVE(デフォルト) — すべての PERMISSIVE ポリシーを OR で結合します。いずれかの PERMISSIVE ポリシーが許可すれば、その行にアクセスできます。
- RESTRICTIVE — RESTRICTIVE ポリシーを、PERMISSIVE ポリシーの結果に AND で適用します。RESTRICTIVE ポリシーを通過し、かつ少なくとも1つの PERMISSIVE ポリシーが許可した場合にのみ、その行にアクセスできます。
-- Restrictive policy: block access to archived orders for everyone
CREATE POLICY no_archived_rows
ON orders
AS RESTRICTIVE
FOR SELECT
USING (amount > 0);RLS のバイパス: BYPASSRLS とテーブル所有者
テーブル所有者とスーパーユーザーは、デフォルトで RLS をバイパスし、常にすべての行を参照できます。スーパーユーザーにせずに無制限のアクセスを必要とするロールには、BYPASSRLS 属性を付与できます。反対に、FORCE ROW LEVEL SECURITY を使用すると、所有者にも RLS の適用を強制できます。
-- Force the table owner to also obey RLS policies
ALTER TABLE orders FORCE ROW LEVEL SECURITY;
-- Grant BYPASSRLS to a trusted service account
ALTER ROLE service_account BYPASSRLS;ポリシーの変更と削除
既存のポリシーは ALTER POLICY で変更でき、DROP POLICY で完全に削除できます。RLS を有効にしたまますべてのポリシーを削除すると、所有者以外のロールはどの行にもアクセスできなくなります。RLS を完全に解除するには、ALTER TABLE で無効にします。
-- Rename a policy
ALTER POLICY orders_owner_policy ON orders
RENAME TO user_isolation_policy;
-- Update the USING expression
ALTER POLICY user_isolation_policy ON orders
USING (owner = current_user AND amount >= 0);
-- Remove a policy
DROP POLICY admin_full_access ON orders;
-- Disable RLS entirely on the table
ALTER TABLE orders DISABLE ROW LEVEL SECURITY;実例: マルチテナントデータの分離
マルチテナント SaaS アプリでよく使われる RLS パターンでは、すべてのテーブルに tenant_id 列を持たせ、セッションレベルの変数(set_config)を使って接続時にテナント識別子を渡します。その後、ポリシーで各行の tenant_id とその設定値を比較します。
-- Table with tenant isolation column
CREATE TABLE documents (
id SERIAL PRIMARY KEY,
tenant_id TEXT NOT NULL,
title TEXT
);
ALTER TABLE documents ENABLE ROW LEVEL SECURITY;
-- Policy reads the tenant from a session variable
CREATE POLICY tenant_isolation
ON documents
FOR ALL
USING (tenant_id = current_setting('app.tenant_id'))
WITH CHECK (tenant_id = current_setting('app.tenant_id'));
-- Application sets the variable before running queries
SELECT set_config('app.tenant_id', 'tenant_42', true);
-- Now only tenant_42 documents are visible
SELECT * FROM documents;理解度チェック
PostgreSQL の行レベルセキュリティポリシーについての理解度を確認しましょう。
レッスンのまとめ
このレッスンでは、行レベルセキュリティによって、データベースレベルでポリシーに基づく行のフィルタリングを自動的に行う方法を学びました。
- RLS の有効化 — ALTER TABLE ... ENABLE ROW LEVEL SECURITY を使用してテーブルで RLS を有効にします。
- CREATE POLICY で USING 句を使用して読み取り可能な行をフィルタリングし、WITH CHECK 句を使用して書き込まれる行を検証します。
- TO 句を使用して、ポリシーの対象を特定のコマンド(SELECT、INSERT、UPDATE、DELETE、ALL)や特定のロールに限定します。
- PERMISSIVE(OR ロジック)と RESTRICTIVE(AND ロジック)のポリシーを組み合わせて、多層的なアクセス制御を実現します。
- テーブル所有者とスーパーユーザーはデフォルトで RLS をバイパスします。これを上書きするには FORCE ROW LEVEL SECURITY を使用します。
- current_setting() を使用するマルチテナントパターンは、RLS の強力な実用例です。
RLS は、アプリケーションのすべてのクエリに WHERE 句を分散させることなく、データ分離を適切かつ一貫して適用する標準的な方法です。
よくある質問
「行レベルセキュリティポリシー」レッスンは無料ですか?
はい。「行レベルセキュリティポリシー」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、SQL Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 SQL Academyコースには全4レッスンが含まれています。
「行レベルセキュリティポリシー」で何を学びますか?
ユーザーごとに行を自動でフィルタリングします。 ブラウザで直接実行するハンズオンコードでSQL Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
SQL Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのSQL Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。
「行レベルセキュリティポリシー」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このSQL Academyレッスンでコードを書いて実行できますか?
はい。すべてのSQL Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。