問題とコンテキスト
あなたのチームは、マルチテナント分析プラットフォームを PostgreSQL 18 にアップグレードしており、長期有効なパスワードの代わりに OAuth 2.0 ベアラートークンを使用してアプリケーションを接続したいと考えています。PostgreSQL 18 の OAuth 境界、接続ハンドシェイク、ロールマッピング、およびロールアウト計画を説明してください。認可が意図せず拡大したり、発行者(issuer)の取り違えが発生したりする可能性がある箇所を指摘してください。
面接官が評価するポイント
- OAuth クライアント、認可サーバー、リソースサーバー、およびデータベースロールを明確に区別できているか。
pg_hba.conf、バリデータ、スコープ、マップ、および libpq 設定を 1 つのデータフローに統合できるか。- ディスカバリ、厳密な発行者一致、TLS、およびトークンの有効期間に関するリスクを認識しているか。
- 単に「パスワードをトークンに置き換える」と言うだけでなく、可逆的な移行計画を提案できるか。
明確化のための質問
- 呼び出し元は人間ですか、バックエンドサービスですか、それとも両方ですか?プリンシパルの種類はパブリッククライアントとコンフィデンシャルクライアントの選択に影響します。
- 各テナントは個別のデータベースロールにマッピングされますか?1 つのトークンで複数のロールを表すことはありますか?
- プロバイダーは標準のディスカバリドキュメントとベアラートークンバリデータを公開していますか?
- レガシーなクライアントは SCRAM を使い続けることができますか?また、監査とロールバックの期間はどのくらいですか?
30秒の回答
PostgreSQL をリソースサーバー、libpq/psql を OAuth クライアント、外部アイデンティティシステムを認可サーバーとして扱い、データベース自身はトークンを発行しない構成にします。サーバー側では、pg_hba.conf 内で厳密な発行者、スコープ、バリデータを指定して oauth を有効にし、外部アイデンティティをデータベースロールにマッピングする必要がある場合は map を使用します。クライアントはディスカバリを利用してベアラートークンを提示し、バリデータが署名、発行者、オーディエンス、有効期限、スコープを検証します。テナントごとの段階的なロールアウト中は SCRAM を維持し、拒否理由を計測して、ロールバック時は OAuth ルールを削除します。
詳細解説
1. 信頼境界の定義
PostgreSQL 18 は OAuth 認証方式を追加するものであり、認可サーバーを提供するわけではありません。プロバイダーがユーザーを認可してトークンを発行し、PostgreSQL はトークンを検証して接続がデータベースロールを引き受けてよいかを判断します。データベースをログイン UI として扱ったり、リフレッシュトークンをデータベースに保存したりすると、その責任範囲が過度に拡大してしまいます。
2. サーバー・ルールの構成
対象のネットワークとデータベースに対して pg_hba.conf に oauth ルールを追加し、issuer、scope、オプションの validator、およびオプションの map を設定します。発行者はディスカバリドキュメントと 1 文字ずつ完全に一致する必要があります。複数のバリデータがインストールされている場合は、明示的に 1 つ選択します。リクエストが意図しない認証方式にフォールスルーしないよう、このルールは広範なパスワードルールの前に配置します。
3. ディスカバリとハンドシェイクの処理
libpq は oauth_issuer を使用してディスカバリメタデータを取得し、サーバーの要求に応じてトークンを取得します。クライアント側の発行者は、HBA で指定された発行者と一致しなければなりません。PostgreSQL では、この厳密な比較をミックアップ攻撃(mix-up attacks)に対する防御策として文書化しています。ベアラートークンを接続ログ、プロセス引数、または永続的な設定ファイルに含めてはなりません。
4. トークンとロールの検証
バリデータは署名、発行者、有効期間、オーディエンス、および必須スコープを検証し、監査可能な外部アイデンティティを返す必要があります。map を使用しない場合、検証されたユーザー名は要求されたロールと完全に一致しなければなりません。マルチテナンシーの場合は、デフォルト拒否(deny-by-default)の動作を備えた明示的な最小特権マップを使用します。delegate_ident_mapping は標準の pg_ident.conf マッピングをバイパスするため、バリデータ自体が完全なロール認可を実行する場合にのみ使用してください。
5. ロールアウトとロールバック
ディスカバリ、TLS、スコープ、および期限切れトークンの挙動を本番環境外で検証します。SCRAM を維持したまま、小規模なサービスグループに対して OAuth HBA ルールを追加します。成功、期限切れ、発行者不一致、およびマッピング拒否を個別に計測します。コネクションプール、ジョブ、および運用スクリプトがトークンをリフレッシュできるようになったら対象を拡大します。ロールバックは、OAuth ルールを削除するか、すべてのプールが切り替わるまで古い認証情報を保持しつつ SCRAM を復元することで行います。
高品質な回答例
私は 4 つのアクターを想定します。サービスがクライアント、アイデンティティプラットフォームが認可サーバー、PostgreSQL がリソースサーバー、そしてデータベースロールがローカルの認可対象です。HBA の oauth 方式で発行者、スコープ、バリデータを指定し、トークンのアイデンティティをテナントロールにマッピングします。バリデータ自身がロール認可を証明できる場合を除き、delegate_ident_mapping の使用は避けます。クライアントは oauth_issuer ディスカバリを使用し、TLS を強制して、トークンがログに出力されないようにします。テナントごとのロールアウト中は SCRAM を利用可能なまま維持し、ダッシュボードで発行者、スコープ、期限切れ、マッピングの失敗を分類します。OAuth ルールを削除することで即時ロールバックが可能です。これにより、トークン発行、データベース認可、および移行制御を分離したまま、PostgreSQL 18 のネイティブ機能を活用できます。
よくある間違い
- PostgreSQL が OAuth トークンを発行すると主張し、リソースサーバーと認可サーバーを混同する。
- JWT 署名のみをチェックし、発行者、オーディエンス、有効期限、またはスコープのチェックを省略する。
- 同一ドメインの発行者であれば十分であると思い込み、ディスカバリの完全一致を無視する。
- バリデータ側でのロール認可について説明せずに
delegate_ident_mappingを有効にする。 - ベアラートークンを接続ログ、トレース、または長期的な環境変数に出力する。
- 1 段階で SCRAM を削除してしまい、プールやバッチジョブにロールバックパスを残さない。
フォローアップ質問と回答
なぜ発行者は厳密に一致しなければならないのですか?
クライアントは発行者からディスカバリ URL を構築し、返された発行者と自身の設定を比較します。大文字小文字、フォーマット、パスの差異により接続が失敗する可能性があります。また、厳格な比較を行うことで、クライアントが意図しない認可サーバーにリダイレクトされるのを防ぎます。
マップがない場合、ロールはどのように選択されますか?
バリデータによって返されたユーザー名は、接続によって要求されたロールと完全に一致しなければなりません。マルチテナント環境では、アイデンティティが自動的に特権ロールに割り当てられないよう、通常はデフォルト拒否の明示的なマップが必要です。
OAuth が失敗した場合、可用性をどのように維持しますか?
ロールバック用に短期間有効な SCRAM 認証情報を保持し、プールを段階的に移行します。障害をタイプ別に監視し、ディスカバリ、スコープ、またはバリデータの挙動に問題がある場合は、OAuth HBA ルールを削除して以前のルールを復元します。