この記事は個人ブログと同じ内容です
はじめに
新規アプリ開発で 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の制約確認を忘れずに。