CREATE USERとCREATE 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権限が抜けているケースが多い
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
PostgreSQLの「ロール=ユーザー」という設計思想
PostgreSQLでは、「ロール(ROLE)」がアクセス制御の唯一の主体です。MySQLのCREATE USERに相当する概念がなく、CREATE ROLEだけですべてのアクセス主体を作ります。ロールには大きく2種類の使い方があります。
・ログインロール:アプリやユーザーが直接接続するアカウント。
LOGIN属性を付与する・グループロール:権限をまとめて付与するための入れ物。
LOGIN属性を持たない実務では「アプリ専用ユーザー1個+グループロールで権限をまとめる」設計がよく使われますが、小規模構成では単純にログインロール1個で十分です。
CREATE ROLEとCREATE USERの違い
CREATE USERはCREATE ROLEにLOGIN属性を付けたシュガーシンタックスです。内部では同じ処理が走ります。| コマンド | 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;
実務でよく使うロール設計パターン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';
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 USAGEとGRANT 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日で実務レベルのスキルが身につく【初心者向けハンズオンセミナー】も開催しています。
3,100名以上が実践した「型」を無料で公開中
プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら
- 前のページへ:MySQLの最新バージョンとLTSリリースの選び方|8.0のサポート終了に備えた移行時期の見極めと確認コマンド
- この記事の属するカテゴリ:データーベース管理へ戻る

無料メルマガで学習を続ける
Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。
登録無料・いつでも解除できます