📘
【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;
これで migration と restore は、db_ownerのメンバーとしてオーナー相当の操作を行えます。
オーナー権限は直接複数ユーザーに付与できない
ALTER SCHEMA test OWNER TO migration;
ALTER SCHEMA test OWNER TO restore; -- ❌ 直前の所有者が上書きされるだけ
所有者は常に1つのため、この方法では"共有"になりません。
ユーザーとロールの違い(正しく理解する)
PostgreSQLでは「ユーザー=LOGIN権限を持つロール」です。厳密にはどちらもロールで、違いは属性だけ。
-
共通点
- どちらも"ロール"。権限付与・所有・メンバーシップの概念を持つ。
-
ユーザー(=LOGINロール)
-
CREATE USERはCREATE ROLE ... LOGINの別名。 - パスワード等でログイン可能。アプリや人が使う主体。
-
-
グループロール(=NOLOGINロール)
- 直接ログインしない"権限の入れ物"。今回の
db_ownerがこれ。 - オブジェクトの所有者にすると、そのメンバーは所有者として振る舞える。
- 直接ログインしない"権限の入れ物"。今回の
-
継承(INHERIT)と SET ROLE
- あるユーザーUがロールRのメンバーで、Uに
INHERITが有効(通常デフォルト)なら、Rに付与された権限は自動的に利用可能。 - もしUが
NOINHERITなら、SET ROLE R;を実行して権限を"借りる"必要がある。 -
SET ROLEを使うとcurrent_userが切り替わり、新規作成オブジェクトの所有者は切り替え先ロール(例:db_owner)になる。
- あるユーザーUがロールRのメンバーで、Uに
まとめると:ユーザー=ログインできるロール、所有はロールに集約、メンバーシップ+(必要なら)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