PostgreSQLでユーザー(ロール)を作成しデータベース単位で権限を絞る手順|CREATE ROLEとGRANTの実務

宮崎智広 この記事の監修:宮崎智広(Linux実務・教育歴20年以上・受講者3,100名超)
HOMELinux技術 リナックスマスター.JP(Linuxマスター.JP)Linuxtipsデーターベース管理 > PostgreSQLでユーザー(ロール)を作成しデータベース単位で権限を絞る手順|CREATE ROLEとGRANTの実務
「PostgreSQLに接続するアプリ専用のユーザーを作りたいが、CREATE USERCREATE ROLEのどちらを使えばよいか分からない」
GRANT SELECTを付与したのに、まだ permission denied for table になる。テーブルごとに設定が必要なのか、データベース単位で一括付与できるのか迷う」

PostgreSQLの権限管理は、MySQLとは設計が根本的に異なります。PostgreSQLには「ユーザー」という専用の概念がなく、すべての主体が「ロール(ROLE)」として統一されています。ログイン属性を与えれば一般ユーザーとして、与えなければグループロールとして機能します。

この記事では、PostgreSQL 16環境(RHEL 9.4 / Rocky Linux 9.4で動作確認済み)を前提に、CREATE ROLEでアプリ専用ユーザーを作成し、特定データベースだけに読み書き権限を絞る手順を解説します。読み取り専用・読み書き・管理者ロールの3パターンと、REVOKEによる権限剥奪、permission deniedのトラブルシュートまで、実務でそのまま使えるSQL例を中心にまとめます。

この記事のポイント

・CREATE ROLE 名前 LOGIN PASSWORD 'パスワード' でアプリ専用ユーザーを作成できる
・権限はDB接続→スキーマ使用→テーブル操作の3段階で付与する必要がある
・GRANT ON ALL TABLESで既存テーブルを一括付与、DEFAULT PRIVILEGESで新規テーブルに自動付与
・permission denied for tableはスキーマのUSAGE権限が抜けているケースが多い


「このままじゃマズい」と感じていませんか?
参考書を開く気力もない、同年代に取り残される不安——
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

PostgreSQLの「ロール=ユーザー」という設計思想

PostgreSQLでは、「ロール(ROLE)」がアクセス制御の唯一の主体です。MySQLのCREATE USERに相当する概念がなく、CREATE ROLEだけですべてのアクセス主体を作ります。

ロールには大きく2種類の使い方があります。

ログインロール:アプリやユーザーが直接接続するアカウント。LOGIN属性を付与する
グループロール:権限をまとめて付与するための入れ物。LOGIN属性を持たない

実務では「アプリ専用ユーザー1個+グループロールで権限をまとめる」設計がよく使われますが、小規模構成では単純にログインロール1個で十分です。

CREATE ROLEとCREATE USERの違い

CREATE USERCREATE ROLELOGIN属性を付けたシュガーシンタックスです。内部では同じ処理が走ります。

コマンド LOGINデフォルト 用途
CREATE ROLE 名前 なし(NOLOGIN) グループロール・権限テンプレート
CREATE ROLE 名前 LOGIN あり アプリ接続用ユーザー
CREATE USER 名前 あり(LOGIN込み) CREATE ROLE 名前 LOGIN と同義

統一性の観点から、本記事ではCREATE ROLE ... LOGIN形式で統一します。どちらを使っても動作は同じです。

アプリ専用ロールを作成してデータベース単位で権限を付与する手順

実際にアプリ専用ユーザー(appuser)を作成し、myappデータベースにある全テーブルへの読み書き権限を付与するまでの流れを、順番に解説します。

1. ロール(ユーザー)を作成する

まずpostgresスーパーユーザーで接続し、ロールを作成します。

-- postgres ユーザーで psql を起動 $ sudo -u postgres psql -- ロールを作成(LOGIN と PASSWORD を指定する) CREATE ROLE appuser LOGIN PASSWORD 'your_secure_password';

実行結果の確認:

postgres=# CREATE ROLE appuser LOGIN PASSWORD 'your_secure_password'; CREATE ROLE

CREATE ROLEと返れば成功です。パスワードはSCRAM-SHA-256でハッシュ化されてpg_authidシステムカタログに格納されます。

2. データベースへの接続を許可する

ロールを作成しただけでは、まだどのデータベースにも接続できません。GRANT CONNECTでデータベースへの接続権限を付与します。

-- myapp データベースへの接続を許可する GRANT CONNECT ON DATABASE myapp TO appuser;

3. スキーマの使用権限を付与する

接続できるようになっても、テーブルにアクセスするにはスキーマへのUSAGE権限が必要です。デフォルトスキーマはpublicです。

-- myapp データベースに切り替えてから実行する \c myapp -- public スキーマの使用権限を付与する GRANT USAGE ON SCHEMA public TO appuser;

このステップを忘れると、テーブル権限を付与してもpermission denied for schema publicになります。

4. テーブルへの操作権限を付与する

ON ALL TABLES IN SCHEMAを使うと、スキーマ内の既存テーブルすべてに一括付与できます。テーブルごとにGRANTを繰り返す必要はありません。

-- 読み書き権限を付与する(SELECT・INSERT・UPDATE・DELETE) GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO appuser; -- シーケンスの更新権限も付与する(SERIAL / BIGSERIAL 列がある場合に必要) GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO appuser;

シーケンス権限を付与しないと、SERIAL型(自動採番)を使ったINSERTでpermission denied for sequenceが発生します。

5. DEFAULT PRIVILEGESで今後のテーブルにも自動付与する

ON ALL TABLESはコマンド実行時点で存在するテーブルにしか効きません。今後CREATE TABLEで追加されるテーブルへの権限は、ALTER DEFAULT PRIVILEGESで設定します。

-- postgres ユーザーが今後作成するテーブルにも自動でアクセス権を付与する ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO appuser; ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT USAGE, SELECT ON SEQUENCES TO appuser;

これで今後追加されるテーブルにも自動的に権限が付与されるため、テーブル追加のたびにGRANT文を手動で実行する手間がなくなります。

実務でよく使うロール設計パターン3つ

読み取り専用ロール(レポート・分析用)

-- 接続先データベース: myapp で実行 CREATE ROLE readonly_user LOGIN PASSWORD 'your_secure_password'; GRANT CONNECT ON DATABASE myapp TO readonly_user; \c myapp GRANT USAGE ON SCHEMA public TO readonly_user; GRANT SELECT ON ALL TABLES IN SCHEMA public TO readonly_user; ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO readonly_user;

読み書きロール(アプリケーション接続用)

CREATE ROLE appuser LOGIN PASSWORD 'your_secure_password'; GRANT CONNECT ON DATABASE myapp TO appuser; \c myapp GRANT USAGE ON SCHEMA public TO appuser; GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO appuser; GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO appuser; ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO appuser; ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT USAGE, SELECT ON SEQUENCES TO appuser;

管理用ロール(DDLまで許可・スーパーユーザーを使わない運用)

本番サーバーではスーパーユーザー(postgres)を直接使い続けるのはリスクがあります。DDL権限を持つ管理者ロールを作り、最小権限で運用するのが現場の鉄則です。

CREATE ROLE db_admin LOGIN PASSWORD 'your_secure_password' CREATEDB; GRANT CONNECT ON DATABASE myapp TO db_admin; \c myapp -- スキーマ内のオブジェクト作成・変更を許可する GRANT ALL PRIVILEGES ON SCHEMA public TO db_admin; GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO db_admin; GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO db_admin; ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL PRIVILEGES ON TABLES TO db_admin; ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL PRIVILEGES ON SEQUENCES TO db_admin;

ロールと権限の確認方法

設定した権限を確認するには、psqlのメタコマンドを使います。

-- 全ロール一覧を表示する \du -- テーブルの権限一覧を表示する \dp テーブル名 -- またはすべてのテーブルの権限を表示する \dp -- ロールのログイン属性などを確認する SELECT rolname, rolcanlogin, rolcreatedb, rolsuper FROM pg_roles WHERE rolname = 'appuser';

実行例(\duの出力):

myapp=# \du List of roles Role name | Attributes ------------+------------------------------------------------------------ appuser | db_admin | Create DB postgres | Superuser, Create role, Create DB, Replication, Bypass RLS readonly_user |

権限を剥奪する(REVOKE)

付与した権限を剥奪するにはREVOKEを使います。GRANTの逆順で実行するのが基本です。

-- テーブル権限を剥奪する REVOKE SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public FROM appuser; -- スキーマ使用権限を剥奪する REVOKE USAGE ON SCHEMA public FROM appuser; -- データベース接続権限を剥奪する REVOKE CONNECT ON DATABASE myapp FROM appuser; -- ロール自体を削除する(権限をすべて剥奪してから実行する) DROP ROLE appuser;

権限が残ったままロールを削除しようとするとERROR: role "appuser" cannot be dropped because some objects depend on itが出ます。REVOKEで権限をすべて剥奪してからDROP ROLEを実行してください。

またALTER DEFAULT PRIVILEGESで設定したデフォルト権限も別途ALTER DEFAULT PRIVILEGES ... REVOKEで削除する必要があります。

ALTER DEFAULT PRIVILEGES IN SCHEMA public REVOKE SELECT, INSERT, UPDATE, DELETE ON TABLES FROM appuser;

「permission denied for table」が出たときの対処法

1. スキーマのUSAGE権限が抜けている

テーブル権限を付与してもスキーマのUSAGE権限がないと、以下のエラーが出ます。

ERROR: permission denied for schema public

対処:

GRANT USAGE ON SCHEMA public TO appuser;

2. ON ALL TABLESを付与した後に新規テーブルを作成した

GRANT ON ALL TABLESはコマンド実行時点の既存テーブルにしか効きません。後から追加したテーブルには権限がありません。

対処:

-- 新規テーブルに対してもう一度 GRANT を実行するか、 -- ALTER DEFAULT PRIVILEGES を設定して自動付与にする ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO appuser;

3. 別のスキーマのテーブルにアクセスしている

public以外のスキーマにテーブルを作成している場合は、そのスキーマに対してもGRANT USAGEGRANT ON ALL TABLESを実行してください。

本記事のまとめ

やりたいこと SQL
ログイン可能なロールを作成する CREATE ROLE 名前 LOGIN PASSWORD 'パスワード'
データベースへの接続を許可する GRANT CONNECT ON DATABASE DB名 TO ロール名
スキーマの使用を許可する GRANT USAGE ON SCHEMA スキーマ名 TO ロール名
既存テーブルに一括付与する GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO ロール名
新規テーブルにも自動付与する ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO ロール名
テーブル権限を剥奪する REVOKE SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public FROM ロール名
ロールを削除する DROP ROLE ロール名
ロール一覧を確認する \du
テーブルの権限を確認する \dp テーブル名

PostgreSQLの権限設計は「DB接続→スキーマ使用→テーブル操作」の3段階を意識することがポイントです。ALTER DEFAULT PRIVILEGESを忘れずに設定しておくと、テーブルを追加するたびにGRANTを手動実行する手間を省けます。

PostgreSQLのユーザー管理を覚えたら、Linuxサーバー全体のセキュリティ設計を体系的に固めませんか?

データベースの権限設計は「最小権限の原則」の実践そのものです。ネットの切れ端の情報をコピペするだけでなく、現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、『Linuxサーバー構築入門マニュアル(図解60P)』を完全無料でプレゼントしています。

「独学の時間がもったいない」「プロから直接、現場の技術を最短で学びたい」という本気の方には、2日で実務レベルのスキルが身につく【初心者向けハンズオンセミナー】も開催しています。

無料メルマガで学習を続ける

Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。

登録無料・いつでも解除できます

暗記不要・1時間後にはサーバーが動く

3,100名以上が実践した「型」を無料で公開中

プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。

姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

Linux無料マニュアル(図解60P) 名前とメールで30秒登録
宮崎 智広

この記事を書いた人

宮崎 智広(みやざき ともひろ)

株式会社イーネットマーキュリー代表。現役のLinuxサーバー管理者として20年以上の実務経験を持ち、これまでに累計3,100名以上のエンジニアを指導してきたLinux教育のプロフェッショナル。「現場で本当に使える技術」を体系的に伝えることをモットーに、実践型のLinuxセミナーの開催や無料マニュアルの配布を通じてLinux人材の育成に取り組んでいる。

趣味は、キャンプにカメラ、トラウト釣り。好きな食べ物は、ラーメンにお酒。休肝日が作れない、酒量を減らせないのが悩み。最近、ドラマ「フライトエンジェル」を観て涙腺が崩壊しました。