メインコンテンツへスキップ
友田 陽大
PostgreSQL 運用・信頼性
PostgreSQL
セキュリティ
アーキテクチャ設計

PostgreSQL セキュリティ堅牢化(ロール・最小権限・pg_hba.conf・SCRAM・TLS/verify-full・OAuth・v18対応)

PostgreSQL を本番品質で守るセキュリティ堅牢化ガイド。スーパーユーザーで動かさない最小権限ロール設計、GRANT/REVOKEとデフォルト権限、public スキーマの落とし穴(PG15の変更)、監視用の定義済みロール、pg_hba.confの認証設計、SCRAMとMD5非推奨、TLS/sslmode=verify-fullで中間者攻撃を防ぐ方法、PostgreSQL 18のOAuth 2.0認証までを公式ドキュメントに忠実に解説します。

公開日
読了時間
10分
著者
友田 陽大
シェア

データベースのセキュリティは「最後に足すもの」ではなく、「最初に設計するもの」です。アプリをスーパーユーザーで動かし、pg_hba.conftrust で開け、TLSを require で済ませている——そのどれもが、情報漏洩への最短経路です。

この記事は、PostgreSQL を本番で守るための堅牢化チェックリストを、公式ドキュメントに忠実に解説します。ロールと最小権限、ネットワーク認証、パスワード方式、暗号化(中間者攻撃対策)まで。発注者が「このDBは安全に作られているか」を判断する材料にもなります。本番運用ガイド §6の深掘りです。

この記事のルール:ロール・権限・認証・暗号化の仕様、PostgreSQL 18 の変更点は PostgreSQL 18 公式ドキュメント(2026年6月時点) に基づきます。行レベルセキュリティ(RLS) によるマルチテナント認可はデータベース・RLS クラスタで詳述しているため、本稿では触れず、ロール・ネットワーク・暗号化に集中します。


1. 最小権限:アプリをスーパーユーザーで動かさない

第一の原則。アプリの実行ロールにスーパーユーザーやテーブル所有者を使わない。公式の警告:

データベーススーパーユーザーは、ログインの権利を除き、すべての権限チェックを迂回する。…これは危険な権限であり、不用意に使うべきではない。スーパーユーザーでない役割で大半の作業を行うのが最善である。

ロールはクラスタ全体(公式:「ロールはデータベースクラスタ全体でグローバル」)で、LOGIN 属性を持つものが「ユーザー」、持たないものが「グループ」として機能します。本番の正解は——アプリ専用の最小権限LOGINロールを作り、必要なDMLだけ与えることです。

-- 1) オブジェクト所有者(マイグレーション用・通常運用では使わない)
CREATE ROLE app_owner NOLOGIN;

-- 2) アプリ実行用の最小権限ロール(必要なDMLだけ。所有者でもスーパーユーザーでもない)
CREATE ROLE app_user LOGIN PASSWORD '***';

-- 3) スキーマと既存テーブルへ、必要な権限だけ付与
GRANT USAGE ON SCHEMA app TO app_user;                  -- スキーマのUSAGEは必須
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA app TO app_user;
GRANT USAGE ON ALL SEQUENCES IN SCHEMA app TO app_user; -- serial/identity を使うなら

-- 4) 将来作られるテーブルにも自動で同じ権限を(重要:付け忘れを防ぐ)
ALTER DEFAULT PRIVILEGES IN SCHEMA app
  GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO app_user;

アプリが乗っ取られても、app_userDROP TABLECREATE ROLE もできなければ、被害は「そのロールが触れるデータ」に封じ込められます。これが最小権限による被害局限です。


2. 権限設計:GRANT、デフォルト権限、public スキーマの罠

所有者・PUBLIC・USAGE

公式:「オブジェクトの所有者は、本質的に全権限を持つ」。新規オブジェクトは作成者が所有し全権限を持ちます。他ロールには GRANT必要な分だけ渡します。

特別な擬似ロール PUBLIC は「全ロール」を意味します。公式:「テーブル・列・シーケンス・スキーマ等に対し、PUBLIC には既定で権限が与えられない」。重要なのは、テーブル権限だけでなくスキーマの USAGE も必要な点——両方揃って初めてアクセスできます。

⚠ public スキーマの落とし穴(PostgreSQL 15 の変更)

歴史的な地雷です。公式:

PostgreSQL 15 以降、既定の構成はこの使い方を支える。それ以前(または旧版からアップグレードしたDB)では、public スキーマから PUBLIC の CREATE 権限を削除する必要がある(REVOKE CREATE ON SCHEMA public FROM PUBLIC を実行)。

旧来は「全ユーザーが public スキーマにオブジェクトを作れる」状態で、公式は「これは決して安全なパターンではない」と断じています。

-- 旧版からアップグレードしたDBでは必ず実行(PG15+で新規作成したDBは既定で対策済み)
REVOKE CREATE ON SCHEMA public FROM PUBLIC;
-- さらに厳格にするなら、public への接続時USAGEも絞る
-- REVOKE ALL ON SCHEMA public FROM PUBLIC;

監視・分析には定義済みロール

「読み取りだけのアナリスト」「監視エージェント」にスーパーユーザーを渡すのは過剰です。公式の定義済みロールを使います。

ロール権限
pg_read_all_data全テーブル/ビュー/シーケンスのSELECT 相当+全スキーマの USAGE(RLSは迂回しない)
pg_monitor監視ビュー/関数の読み取り(pg_read_all_settingspg_read_all_stats 等を含む)
pg_read_all_statspg_stat_* の閲覧
-- アナリストは読み取り専用ロールで(スーパーユーザー不要)
GRANT pg_read_all_data TO analyst;
-- 監視エージェントは pg_monitor で
GRANT pg_monitor TO monitoring_agent;

3. ネットワーク認証:pg_hba.conf

「誰が・どこから・どのDBに・どの方式で」接続できるかを決めるのが pg_hba.conf。公式の最重要ルール:

最初に一致したレコードが認証に使われる。「フォールスルー」や「バックアップ」はない:あるレコードが選ばれて認証に失敗しても、後続のレコードは考慮されない。一致するレコードがなければアクセスは拒否される。

つまり順序が命で、上から評価して最初の一致で決まります。堅牢化の要点:

# TYPE     DATABASE   USER       ADDRESS          METHOD
# ローカルの管理用ソケットのみ peer(OSユーザーと一致)
local      all        postgres                    peer
# アプリは TLS 必須(hostssl)+ SCRAM + 送信元を限定
hostssl    appdb      app_user   10.0.0.0/24      scram-sha-256
# 上記に一致しない全接続を明示的に拒否(デフォルト拒否)
host       all        all        0.0.0.0/0        reject
  • hostssl を使い、TLS接続でなければ一致させないhost はSSL/非SSLどちらも一致)。
  • 認証は scram-sha-256
  • trust は厳禁——公式:「無条件で接続を許可する。…パスワードも認証も不要で、誰でも任意のユーザーとしてログインできる」。ローカルの信頼できるソケット以外で使ってはいけません。
  • 送信元IP(CIDR)・DB・ユーザーでできる限り絞る

4. パスワード:SCRAM、MD5 は非推奨に

公式:password_encryption の既定は scram-sha-256。SCRAM は「現在提供される中で最も安全」です。一方 MD5 は弱い——公式:「MD5 ハッシュアルゴリズムは、今日では執拗な攻撃に対して安全とは見なされない」。

そして PostgreSQL 18 で MD5 は非推奨になりました(公式リリースノート):

MD5 パスワード認証を非推奨化する。…将来のメジャー版でサポートは削除される。CREATE ROLEALTER ROLE は、MD5 パスワードを設定する際に非推奨警告を出す

-- パスワードは SCRAM で保存される(既定)。MD5 ロールが残っていれば SCRAM へ移行
SET password_encryption = 'scram-sha-256';   -- 既定
ALTER ROLE app_user PASSWORD '***';          -- 設定し直すと SCRAM ハッシュで保存される

-- MD5 のまま残っているロールを洗い出す
SELECT rolname FROM pg_authid WHERE rolpassword LIKE 'md5%';

5. 暗号化:sslmode=verify-full で中間者攻撃を防ぐ

通信の暗号化はサーバー設定とクライアント設定の両輪です。サーバーは ssl = on で有効化(server.crt/server.key が必要)。

決定的に重要なのはクライアントの sslmode です。公式の表が示すとおり、暗号化となりすまし(中間者攻撃)防止は別物。

sslmode盗聴防止中間者攻撃(MITM)防止何を検証するか
require暗号化のみ。証明書を検証しない
verify-caCA次第証明書チェーンをルートCAまで検証
verify-full上記+ホスト名が証明書と一致するか検証

公式:「第三者が通信途中でデータを改変できれば、サーバーになりすませる。SSL は証明書検証でこれを防ぐ」。require は暗号化するだけでなりすましを防げません。本番のクライアントは verify-full +ルートCAで接続します。

# アプリの接続文字列:verify-full でなりすましを防ぐ(require では不十分)
DATABASE_URL="postgresql://app_user@db.internal/appdb?sslmode=verify-full&sslrootcert=/etc/ssl/certs/db-ca.pem"
// node-postgres でも明示的に検証を有効化(rejectUnauthorized を切らない)
import { Pool } from "pg";
export const pool = new Pool({
  connectionString: process.env.DATABASE_URL, // sslmode=verify-full を含む
  ssl: { rejectUnauthorized: true, ca: process.env.DB_CA_CERT }, // 証明書を必ず検証
});

やってはいけないrejectUnauthorized: falsesslmode=require で「とりあえず動かす」。それは暗号化しているのになりすましを許す、最悪の中途半端です。


6. PostgreSQL 18 のセキュリティ強化

公式リリースノートより。

  • OAuth 2.0 認証pg_hba.confoauth メソッドが追加。サードパーティのIdP(OAuth 2.0)で認可・認証できる。中央集権的なID管理に有用(--with-libcurl ビルドが必要)。
  • MD5 非推奨(§4)。
  • SCRAM パススルー:クライアントのSCRAM認証を postgres_fdw/dblink に引き継げる(use_scram_passthrough)——FDWの資格情報をDBに保存せずに済む。
  • TLSssl_ecdh_curvessl_groups に改名(複数曲線を指定可、既定に X25519 を含む)。OpenSSL 1.1.1 未満はサポート終了
  • 権限系:pg_get_acl()ALTER DEFAULT PRIVILEGES がラージオブジェクト対応、定義済みロール pg_signal_autovacuum_worker 追加。

7. 堅牢化チェックリスト

  1. アプリは最小権限のLOGINロールで動かす(スーパーユーザー・所有者を使わない)。
  2. ALTER DEFAULT PRIVILEGES で将来のテーブルにも正しい権限を自動付与。
  3. 旧版DBは REVOKE CREATE ON SCHEMA public FROM PUBLIC(PG15+の既定に合わせる)。
  4. 読み取り/監視は pg_read_all_data / pg_monitor(スーパーユーザーを配らない)。
  5. pg_hba.confデフォルト拒否、最初の一致が意図どおりの順序、hostsslscram-sha-256、送信元IP/DB/ユーザーで限定、trust 禁止
  6. パスワードは SCRAM。残った MD5 ロールを移行(PG18で非推奨)。
  7. クライアントは sslmode=verify-full +ルートCA(require は不可)。
  8. 余裕があれば OAuth 2.0(PG18)で中央ID管理、OpenSSL ≥ 1.1.1 を担保。
  9. マルチテナントの行単位の分離は RLSデータベース・RLS クラスタ)で。

8. まとめ

  • 最小権限が出発点。アプリをスーパーユーザー・所有者で動かさない。ALTER DEFAULT PRIVILEGES で付け忘れを防ぐ。
  • public スキーマの罠(PG15の変更)に注意——旧版DBは REVOKE CREATE ... FROM PUBLIC
  • pg_hba.conf は最初の一致。デフォルト拒否・hostsslscram-sha-256・送信元限定。trust 厳禁。
  • SCRAM を使い、MD5 を捨てる(PG18で非推奨)。
  • sslmode=verify-full でなりすましを防ぐ(require は暗号化だけで不十分)。
  • PG18 は OAuth 2.0 認証を追加。

これで PostgreSQL の運用・信頼性シリーズは一巡です。本番運用ガイドを起点に、接続プーリングバックアップ/PITRレプリケーション/HA論理レプリケーション/アップグレード無停止DDLと合わせて、「壊さない・止めない・詰まらせない・守る・進化させる」を満たす PostgreSQL を設計してください。


参考(PostgreSQL 18 公式ドキュメント)

友田

友田 陽大

経済産業大臣賞 受賞プロダクト開発者。TypeScript + Python + AWS で、SaaS・業界DX・ 実用レベルの生成AI(RAG)を、要件定義からインフラ・運用まで一人で完遂します。

この記事で解説した技術の適用事例

木材流通DXのB2B SaaS — PostgreSQL を中核にマルチテナント・多段商流を支えたデータ基盤

ケーススタディを見る