📘

【PostgreSQL】複数ユーザーでDB所有者権限を共有する方法:ロールを使った実践的解決策

に公開

はじめに

新規アプリ開発で AWS RDS Aurora PostgreSQL Serverless v2 を利用していました。
以下の要件がありました。

  • Migration用ユーザー: DBリセットやマイグレーションを実行したい
  • Restore用ユーザー: バックアップからのリストアを行いたい

どちらもテーブル削除やスキーマ再作成が必要=オーナー権限が要る、という状況です。
ただしPostgreSQLでは、**オブジェクトのオーナーは常に1つ(1ユーザーまたは1ロール)**に限定され、直接複数ユーザーへは付与できません。

結論

ロールを仲介させれば解決します。スキーマ等の所有者をロールにし、そのロールを各ユーザーに付与します。

-- ログイン不可の所有者ロール(グループロール)を作る
CREATE ROLE db_owner NOLOGIN;

-- 各ユーザー(=LOGINロール)を作る
CREATE USER migration WITH PASSWORD 'example_password';
CREATE USER restore   WITH PASSWORD 'example_password';

-- スキーマを作成し、所有者をロールにする
CREATE SCHEMA test;
ALTER SCHEMA test OWNER TO db_owner;

-- ロールをユーザーへ付与(メンバーシップ)
GRANT db_owner TO migration;
GRANT db_owner TO restore;

これで migrationrestore は、db_ownerのメンバーとしてオーナー相当の操作を行えます。

オーナー権限は直接複数ユーザーに付与できない

ALTER SCHEMA test OWNER TO migration;
ALTER SCHEMA test OWNER TO restore; -- ❌ 直前の所有者が上書きされるだけ

所有者は常に1つのため、この方法では"共有"になりません。

ユーザーとロールの違い(正しく理解する)

PostgreSQLでは「ユーザー=LOGIN権限を持つロール」です。厳密にはどちらもロールで、違いは属性だけ。

  • 共通点
    • どちらも"ロール"。権限付与・所有・メンバーシップの概念を持つ。
  • ユーザー(=LOGINロール)
    • CREATE USERCREATE ROLE ... LOGIN の別名。
    • パスワード等でログイン可能。アプリや人が使う主体。
  • グループロール(=NOLOGINロール)
    • 直接ログインしない"権限の入れ物"。今回の db_owner がこれ。
    • オブジェクトの所有者にすると、そのメンバーは所有者として振る舞える
  • 継承(INHERIT)と SET ROLE
    • あるユーザーUがロールRのメンバーで、UにINHERITが有効(通常デフォルト)なら、Rに付与された権限は自動的に利用可能。
    • もしUがNOINHERITなら、SET ROLE R; を実行して権限を"借りる"必要がある。
    • SET ROLE を使うと current_user が切り替わり、新規作成オブジェクトの所有者は切り替え先ロール(例:db_owner)になる。

まとめると:ユーザー=ログインできるロール所有はロールに集約メンバーシップ+(必要なら)INHERIT/SET ROLEで権限を使う、が基本線です。

補足:実務で気をつけること

すでにあるテーブルや関数の所有者

  • ロールを作っただけでは、既存のオブジェクトの所有者は変わりません。
  • 所有者がバラバラだと、操作や権限管理がややこしくなります。
-- 特定のテーブルをまとめて所有者変更
ALTER TABLE some_table OWNER TO db_owner;
-- そのユーザーが持つすべてのオブジェクトを一括変更(DBごと)
REASSIGN OWNED BY old_user TO db_owner;

新しく作るテーブルや関数の所有者

  • そのまま作ると「作ったユーザー」が所有者になります。
  • 「常に db_owner が所有者」になるようにしたい場合は次の方法があります。

作業前にロールを切り替える

SET ROLE db_owner;
-- ここから作ったオブジェクトは db_owner が所有者になる

後からまとめて変更する

ALTER TABLE new_table OWNER TO db_owner;

ロールとユーザーの仕組み

  • ロールはクラスタ全体で管理されます。
  • オブジェクトの所有者や権限はデータベースごとに存在します。

まとめ

  • 所有者は常に1つ。所有者をロールにして共有するのが王道。
  • ユーザーは"ログインできるロール"。ロール(NOLOGIN)は権限束ね・所有者役に最適。
  • INHERIT が有効ならそのまま権限が使える。所有を db_owner に揃え、必要に応じて SET ROLE で新規作成物の所有も統一する。
  • 既存/新規の所有者揃え、RDSの制約確認を忘れずに。

Discussion