PostgreSQL: PostgreSQLのユーザー、ロール、権限管理

最終更新:2026-08-26

1. 学習目標


2. ストーリー

CharlieはSaaS ECプラットフォームのDBAで、5つのチームのデータ��ース権限を設定する必要があります。

チーム 必要な権限
dev(開発) 全ビジネステーブルの読み��き、テストテーブル作成
analytics(分析) 全ビジネステーブル読み取り専用、マテリアライズドビュー作成
ops(運用) ユーザー管理、データベース監視
audit(監査) 監査ログのみ読み取り、ビジネスデータ不可
app(アプリケーションサービス) ビジネステーブル読み書き、DDL不可

Charlieはロール継承とRLSを使用して最小権限の原則を実装します。


3. 概念: ロールとユーザー

(1) CREATE ROLE と CREATE USER

コマンド LOGIN権限 同等の形式
CREATE ROLE r1; なし(ログイン不可)
CREATE USER u1; あり(ログイン可能) CREATE ROLE u1 LOGIN;

PGではユーザーとロールは同じ概念です。USERはLOGIN属性を持つROLEに過ぎません。

(2) ロール属性の概要

属性 説明 作成構文
LOGIN データベースへの接続を許可 LOGIN / NOLOGIN
SUPERUSER スーパーユーザー、すべての権限をバイパス SUPERUSER
CREATEDB データベース作成可能 CREATEDB
CREATEROLE ロールの作成/管理可能 CREATEROLE
INHERIT 所属ロールの権限を自動継承 INHERIT(デフォルト)
NOINHERIT 自動継承しない。SET ROLEが必要 NOINHERIT
PASSWORD パスワード設定 PASSWORD 'xxx'
VALID UNTIL パスワード有効期限 VALID UNTIL 'timestamp'

▶ サンプル: ロールとユーザーの作成

SQL
-- グループロール(ログイン不可)
CREATE ROLE dev_team NOINHERIT;
CREATE ROLE analytics_team NOINHERIT;
CREATE ROLE ops_team NOINHERIT;
CREATE ROLE audit_team NOINHERIT;

-- ログインユーザー
-- ⚠️ 本番環境ではパスワードをハードコードせず、環境変数やシークレット管理を使用してください
CREATE USER alice_dev PASSWORD 'SecureP@ss1' IN ROLE dev_team;
CREATE USER bob_dev PASSWORD 'SecureP@ss2' IN ROLE dev_team;
CREATE USER charlie_analyst PASSWORD 'SecureP@ss3' IN ROLE analytics_team;
CREATE USER diana_ops PASSWORD 'SecureP@ss4' IN ROLE ops_team INHERIT;

Output:

TEXT 📖 参照専用
CREATE TABLE

▶ サンプル: ロール属性の変更

SQL
-- opsチームリーダーにCREATEDB権限を追加
ALTER ROLE diana_ops CREATEDB;

-- パスワード有効期限を設定
ALTER ROLE charlie_analyst VALID UNTIL '2025-12-31';

-- ロール名を変更
ALTER ROLE dev_team RENAME TO engineering_team;

-- 一時的にログインを無効化
ALTER ROLE bob_dev NOLOGIN;

Output:

TEXT 📖 参照専用
CREATE TABLE

4. 概念: GRANT / REVOKE権限

(1) 権限階層

100%
flowchart TD
    A[データベース<br/>CONNECT / CREATE / TEMP] --> B[スキーマ<br/>CREATE / USAGE]
    B --> C[テーブル<br/>SELECT / INSERT / UPDATE / DELETE / TRUNCATE / REFERENCES / TRIGGER]
    C --> D[カラム<br/>SELECT / INSERT / UPDATE / REFERENCES]
    B --> E[関数<br/>EXECUTE]
    B --> F[シーケンス<br/>USAGE / SELECT / UPDATE]
    A --> G[ロール<br/>MEMBER / SET]

    style A fill:#e1f5fe
    style B fill:#bbdefb
    style C fill:#c8e6c9
    style D fill:#fff9c4

(2) 一般的な権限キーワード

オブジェクト 付与可能な権限 説明
DATABASE CONNECT, CREATE, TEMP 接続、スキーマ作成、一時テーブル
SCHEMA CREATE, USAGE オブジェクト作成、オブジェクトアクセス
TABLE SELECT, INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER 完全なCRUD + 外部キー参照
COLUMN SELECT, INSERT, UPDATE, REFERENCES カラムレベル制御
FUNCTION EXECUTE 関数呼び出し
SEQUENCE USAGE, SELECT, UPDATE シーケンス使用

▶ サンプル: GRANTテーブルレベル権限

SQL
-- Devチーム: ビジネステーブルに対する完全CRUD
GRANT SELECT, INSERT, UPDATE, DELETE ON products TO dev_team;
GRANT SELECT, INSERT, UPDATE, DELETE ON orders TO dev_team;
GRANT SELECT, INSERT, UPDATE, DELETE ON customers TO dev_team;
GRANT SELECT, INSERT, UPDATE, DELETE ON order_items TO dev_team;

-- Analyticsチーム: 読み取り専用
GRANT SELECT ON products TO analytics_team;
GRANT SELECT ON orders TO analytics_team;
GRANT SELECT ON customers TO analytics_team;

-- Auditチーム: 監査ログのみ
GRANT SELECT ON price_audit_log TO audit_team;
GRANT SELECT ON ddl_audit_log TO audit_team;

Output:

TEXT 📖 参照専用
INSERT 0 1

▶ サンプル: GRANTスキーマおよびデータベース権限

SQL
-- Devチームが開発スキーマでオブジェクト作成可能
GRANT CREATE, USAGE ON SCHEMA dev TO dev_team;

-- Analyticsチームがpublicスキーマを使用可能(作成不可)
GRANT USAGE ON SCHEMA public TO analytics_team;

-- Analyticsが自身のスキーマでマテリアライズドビュー作成を許可
GRANT CREATE, USAGE ON SCHEMA analytics TO analytics_team;

-- アプリサービスがデータベースに接続
GRANT CONNECT ON DATABASE shop_db TO app_service;

Output:

TEXT 📖 参照専用
CREATE TABLE

▶ サンプル: REVOKE権限

SQL
-- DevチームからproductsのDELETEを取り消し
REVOKE DELETE ON products FROM dev_team;

-- テーブルから全権限を取り消し
REVOKE ALL PRIVILEGES ON orders FROM public;

-- スキーマ作成権限を取り消し
REVOKE CREATE ON SCHEMA dev FROM dev_team;

-- カスケード: 権限と依存する付与を取り消し
REVOKE SELECT ON products FROM analytics_team CASCADE;

Output:

TEXT 📖 参照専用
DELETE 2

(3) GRANT ALL と GRANT SELECT ALL TABLES

コマンド 効果
GRANT ALL ON t TO r; テーブルtの全権限を付与
GRANT ALL ON SCHEMA s TO r; スキーマsの全権限を付与
GRANT SELECT ON ALL TABLES IN SCHEMA s TO r; スキーマsの全テーブルにSELECTを付与
GRANT USAGE ON ALL SEQUENCES IN SCHEMA s TO r; 全シーケンスにUSAGEを付与

5. 概念: DEFAULT PRIVILEGES

(1) デフォルト権限が必要な理由

単純なGRANTは既に存在するオブジェクトにのみ影響します。将来作成されるテーブルには自動的に権限が付与されません。DEFAULT PRIVILEGESがこれを解決します。

コマンド 効果
ALTER DEFAULT PRIVILEGES IN SCHEMA s GRANT SELECT ON TABLES TO r; s内の新規テーブルに自動付与
ALTER DEFAULT PRIVILEGES FOR ROLE owner GRANT ... 特定の作成者向けデフォルト権限

▶ サンプル: デフォルト権限の設定

SQL
-- publicスキーマの将来の全テーブルをanalytics_teamが読み取り可能に
ALTER DEFAULT PRIVILEGES IN SCHEMA public
  GRANT SELECT ON TABLES TO analytics_team;

-- app_serviceが作成する将来の全テーブルをdev_teamが書き込み可能に
ALTER DEFAULT PRIVILEGES FOR ROLE app_service IN SCHEMA public
  GRANT SELECT, INSERT, UPDATE ON TABLES TO dev_team;

-- publicスキーマの将来の全シーケンス
ALTER DEFAULT PRIVILEGES IN SCHEMA public
  GRANT USAGE, SELECT ON SEQUENCES TO dev_team;

-- 将来の全関数
ALTER DEFAULT PRIVILEGES IN SCHEMA public
  GRANT EXECUTE ON FUNCTIONS TO analytics_team;

Output:

TEXT 📖 参照専用
INSERT 0 1

▶ サンプル: 現在のデフォルト権限を表示

SQL
SELECT
  pg_get_userbyid(defaclrole) AS grantor,
  pg_get_userbyid(defaclnamespace) AS namespace_owner,
  n.nspname AS schema,
  defaclobjtype AS object_type,
  defaclacl AS acl
FROM pg_default_acl d
JOIN pg_namespace n ON n.oid = d.defaclnamespace;

Output:

TEXT 📖 参照専用
 id | name     | value 
----+----------+-------
  1 | example  | 42
(1 row)

6. 概念: 行レベルセキュリティポリシー(RLS)

(1) RLSの仕組み(PGの機能)

RLSを使用すると行レベルでデータアクセスを制御できます。同じテーブルでも異なるロールからは異なる行が見えます。

ステップ コマンド 説明
1. RLSを有効化 ALTER TABLE t ENABLE ROW LEVEL SECURITY; テーブルで行レベルセキュリティを有効化
2. ポリシー作成 CREATE POLICY ... ON t ...; 行レベルのルールを定義
3. スーパーユーザーバイパス SUPERUSERはデフォルトでRLSの対象外
4. テーブル所有者バイパス テーブル所有者はデフォルトで対象外。FORCEで強制

(2) ポリシーの種類

ポリシー種別 キーワード 説明
SELECT FOR SELECT 可視行を制御
INSERT FOR INSERT 挿入可能行を制御
UPDATE FOR UPDATE 更新可能行を制御(BEFORE/AFTER含む)
DELETE FOR DELETE 削除可能行を制御
ALL FOR ALL 全操作で共有

▶ サンプル: RLSを有効化してポリシーを作成

SQL
-- ordersテーブルでRLSを有効化
ALTER TABLE orders ENABLE ROW LEVEL SECURITY;

-- アナリストは完了注文のみ表示可能
CREATE POLICY pol_analytics_completed
  ON orders FOR SELECT
  TO analytics_team
  USING (order_status = 'completed');

-- Devチームは全行を表示可能
CREATE POLICY pol_dev_all
  ON orders FOR ALL
  TO dev_team
  USING (true)
  WITH CHECK (true);

Output:

TEXT 📖 参照専用
CREATE TABLE

▶ サンプル: 現在のユーザーに基づくRLS

SQL
-- customersテーブルでRLSを有効化
ALTER TABLE customers ENABLE ROW LEVEL SECURITY;

-- 各カスタマーサービスユーザーは担当リージョンのみ表示
CREATE POLICY pol_region_access
  ON customers FOR SELECT
  USING (region = current_setting('app.region', true));

-- テーブル所有者にもRLSを強制
ALTER TABLE orders FORCE ROW LEVEL SECURITY;

Output:

TEXT 📖 参照専用
CREATE TABLE

▶ サンプル: INSERT/UPDATEのWITH CHECK

SQL
-- 営業チームは自身のリージョンの注文のみ挿入可能
CREATE POLICY pol_sales_insert
  ON orders FOR INSERT
  TO dev_team
  WITH CHECK (region = current_setting('app.region', true));

-- 営業チームは自身のリージョンの注文のみ更新可能
CREATE POLICY pol_sales_update
  ON orders FOR UPDATE
  TO dev_team
  USING (region = current_setting('app.region', true))
  WITH CHECK (region = current_setting('app.region', true));

Output:

TEXT 📖 参照専用
INSERT 0 1

(3) USING と WITH CHECK

役割 適用対象
USING 可視行を絞り込む(SELECT/UPDATE/DELETEのWHERE) SELECT/UPDATE/DELETE
WITH CHECK 新しい行が許可されるか検証(INSERT/UPDATEの新しい値) INSERT/UPDATE

7. 概念: ロール継承とシステムビュー

(1) INHERIT と NOINHERIT

属性 動作 シナリオ
INHERIT(デフォルト) 所属ロールの権限を自動的に取得 通常のユーザー
NOINHERIT 権限を使用するにはSET ROLE rが必要 一時的な権限昇格、監査分離

▶ サンプル: NOINHERITとSET ROLE

SQL
-- NOINHERITで強力なロールを作成
CREATE ROLE admin_role NOINHERIT;
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO admin_role;

-- Dianaはadmin_roleに所属するが管理権限を自動では使用不可
CREATE USER diana PASSWORD 'SecureP@ss5' IN ROLE admin_role NOINHERIT;

-- Dianaは管理権限を使用するために明示的に切り替える必要がある
SET ROLE admin_role;
-- これでDianaは管理操作を実行可能
RESET ROLE;
-- 通常の権限に戻る

Output:

TEXT 📖 参照専用
CREATE TABLE

(2) システムビュー

ビュー 内容
pg_roles 全ロールとその属性
pg_auth_members ロールとメンバーの関係
information_schema.role_table_grants テーブルレベル権限
information_schema.role_usage_grants スキーマ/関数▶限

▶ サンプル: ロールと権限のクエリ

SQL
-- 全ロールとその属性を一覧表示
SELECT rolname, rolsuper, rolcreatedb, rolcanlogin, rolinherit
FROM pg_roles
WHERE rolname NOT LIKE 'pg_%'
ORDER BY rolname;

-- ロールメンバーシップを一覧表示
SELECT
  r1.rolname AS member,
  r2.rolname AS role
FROM pg_auth_members m
JOIN pg_roles r1 ON r1.oid = m.member
JOIN pg_roles r2 ON r2.oid = m.roleid
ORDER BY r2.rolname, r1.rolname;

-- ロールのテーブル権限を確認
SELECT table_name, privilege_type
FROM information_schema.role_table_grants
WHERE grantee = 'analytics_team'
ORDER BY table_name, privilege_type;

Output:

TEXT 📖 参照専用
CREATE TABLE

8. フローチャート: 権限設定の判断

100%
flowchart TD
    A[権限を設定] --> B{行レベル制御が必要?}
    B -->|はい| C[RLSを有効化<br/>CREATE POLICY]
    B -->|いいえ| D{権限の粒度は?}
    D -->|テーブル全体| E[GRANT ON TABLE]
    D -->|特定のカラム| F[GRANT column_name ON TABLE]
    D -->|スキーマ内の全テーブル| G[GRANT ALL TABLES IN SCHEMA]
    E --> H{新規テーブルに自動付与が必要?}
    G --> H
    H -->|はい| I[ALTER DEFAULT PRIVILEGES]
    H -->|いいえ| J[手動GRANT]
    C --> K{テーブル所有者も制限が必要?}
    K -->|はい| L[FORCE ROW LEVEL SECURITY]
    K -->|いいえ| M[所有者はデフォルトでRLSをバイパス]
    I --> N{ユーザーが一時的な昇格を必要とする?}
    J --> N
    N -->|はい| O[NOINHERIT + SET ROLE]
    N -->|いいえ| P[INHERITがデフォルト]

    style C fill:#fff9c4
    style I fill:#c8e6c9
    style O fill:#ffcdd2

9. 総合サンプル

Charlieが5チーム向けに完全な権限システムを設定します。

SQL
-- Step 1: グループロールを作成
CREATE ROLE dev_team NOINHERIT;
CREATE ROLE analytics_team NOINHERIT;
CREATE ROLE ops_team INHERIT;
CREATE ROLE audit_team NOINHERIT;
CREATE ROLE app_service LOGIN PASSWORD 'AppSecRet!';

-- Step 2: スキーマ権限を付与
GRANT CREATE, USAGE ON SCHEMA public TO dev_team;
GRANT USAGE ON SCHEMA public TO analytics_team;
GRANT CREATE, USAGE ON SCHEMA analytics TO analytics_team;
GRANT USAGE ON SCHEMA public TO ops_team;
GRANT USAGE ON SCHEMA audit TO audit_team;

-- Step 3: テーブル権限を付与
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO dev_team;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO analytics_team;
GRANT SELECT ON ALL TABLES IN SCHEMA audit TO audit_team;
GRANT SELECT, INSERT, UPDATE, DELETE ON products, orders, order_items, customers TO app_service;

-- Step 4: 将来のテーブルに対するデフォルト権限
ALTER DEFAULT PRIVILEGES IN SCHEMA public
  GRANT SELECT ON TABLES TO analytics_team;
ALTER DEFAULT PRIVILEGES IN SCHEMA public
  GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO dev_team;
ALTER DEFAULT PRIVILEGES IN SCHEMA audit
  GRANT SELECT ON TABLES TO audit_team;

-- Step 5: シーケンスと関数の権限
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO dev_team;
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO app_service;
ALTER DEFAULT PRIVILEGES IN SCHEMA public
  GRANT USAGE, SELECT ON SEQUENCES TO dev_team;

-- Step 6: RLS - アナリストは完了注文のみ表示
ALTER TABLE orders ENABLE ROW LEVEL SECURITY;
CREATE POLICY pol_analytics_orders
  ON orders FOR SELECT
  TO analytics_team
  USING (order_status = 'completed');

-- Step 7: RLS - 監査チームはauditスキーマのみ表示
ALTER TABLE price_audit_log ENABLE ROW LEVEL SECURITY;
CREATE POLICY pol_audit_read
  ON price_audit_log FOR SELECT
  TO audit_team
  USING (true);

-- Step 8: ログインユーザーを作成してロールを割り当て
CREATE USER alice_dev PASSWORD 'DevP@ss1' IN ROLE dev_team;
CREATE USER bob_dev PASSWORD 'DevP@ss2' IN ROLE dev_team;
CREATE USER charlie_analyst PASSWORD 'AnlP@ss3' IN ROLE analytics_team;
CREATE USER diana_ops PASSWORD 'OpsP@ss4' IN ROLE ops_team CREATEROLE;
CREATE USER eve_audit PASSWORD 'AudP@ss5' IN ROLE audit_team;

❓ よくある質問

Q CREATE USERとCREATE ROLEの違いは何ですか?
A CREATE USERはCREATE ROLE ... LOGINと同等です。PGではユーザーとロールは同じ概念です。USERはデフォルトでLOGIN属性を持つロールに過ぎません。
Q GRANT SELECT ON ALL TABLESは将来作成されるテーブルも含みますか?
A いいえ。ALL TABLESは現在存在するテー��ルにのみ付与されます。将来のテーブルにはALTER DEFAULT PRIVILEGESで自動付与するか、手動でGRANTする必要があります。
Q RLSはスーパーユーザーに影響しますか?
A デフォルトでは影響しません。SUPERUSERはすべてのRLSポリシーをバイパスします。強制するにはALTER TABLE ... FORCE ROW LEVEL SECURITYを使用しますが、これはテーブル所有者にのみ適用され、SUPERUSERは依然としてバイパスします。
Q NOINHERITロールが一時的に権限を取得するに��?
A SET ROLE target_roleを使用して対象ロールに切り替えて権限を取得します。完了後、RESET ROLEで元の権限に戻します。SET ROLEは現在のセッションにのみ影響します。
Q REVOKEにCASCADEが必要ですか?
A 取り消す権限が別のロールにさらに付与されている(依存付与)場合、一括で取り消すにはCASCADEが必要です。デフォルトのRESTRICTは依存があるとエラーになります。
Q ユーザーが実際に持っている権限を確認するには?
A information_schema.role_table_grantsビューをクエリするか、psqlの\dpおよび\du+コマンドを使用します。INHERITロールは所属するロールの権限を自動的に取得することに注意してください。
Q RLSのUSINGとWITH CHECKは別々に記述できますか?
A はい。USINGのみを記述した場合、WITH CHECKはデフォルトでUSINGと同じになります。ALLポリシーでは、制御を明確にするために両方を明示的に記述することを推奨します。
Q スキーマのUSAGEだけではテーブルにアクセスできないのはなぜですか?
A USAGEはスキーマに「入って」オブジェクト一覧を見ることを許可するだけです。特定のテーブルに対するSELECTなどの権限も別途必要です。両方の権限層が満たされる必要があります。

📖 まとめ


📝 練習問題

  1. ⭐ ロールreadonlyとユーザーreport_userを作成し、readonlyにpublicスキー��の全テーブルへのSELECTを付与し、新規作成テーブルにも自動付与されるようにデフォルト権限を設定してください。

  2. ⭐⭐ ordersテーブルでRLSを有効化し、ポリシーを作成してください。sales_teamは自身のリージョンの注文のみ表示可能(region = current_setting('app.region'))。audit_teamorder_status = 'completed'の注文のみ表示可能。

  3. ⭐⭐⭐ 完全な権限システ��を設計してください。3つのグループロール(backend_devdata_analystdb_admin)を作成し、それぞれ異なるレベルの権限(スキーマ/テーブル/カラム/関数/シーケンス)を付与し、DEFAULT PRIVILEGESを設定し、salaryカラムを別途付与(アナリストは見られない)、pg_rolesinformation_schemaを使用して設定結果をクエリして検証してください。

Web-Tutorial.com

Web-Tutorial 技術チーム

複数の開発者によって共同維持されているプログラミングチュートリアルプラットフォーム。各チュートリアルは専門分野の開発者が執筆・レビューしています。正確で信頼性の高いコンテンツを目指しています — 問題を見つけた場合はお知らせください。

100%