データベースパスワードが数ヶ月ではなく数分しか生きない世界

チームが3ヶ月ごとにデータベースパスワードをローテーションしているとする。まったくローテーションしていないチームよりは安全だと感じるだろう。しかし、ここで厄介な問いを投げかけたい。ローテーションの2日後にパスワードが漏洩したらどうなるか?そのシークレットはあと88日間も有効だ。見つけた攻撃者は、次のローテーションで無効化されるまでの約3ヶ月間、本番データベースにアクセスし続けられる。

このギャップは理論上の話ではない。シークレットはログファイル、侵害されたCIランナー、開発者のノートPC、設定ミスのバックアップなどを通じて漏れる。有効期間の長い静的シークレットは、攻撃者に広い攻撃時間枠を与える。シークレットの寿命が長ければ長いほど、1回の漏洩で発生する被害は大きくなる。

ここで、短命シークレットという概念がゲームを変える。数ヶ月間有効なパスワードを保存する代わりに、必要なときにその場で認証情報を生成し、1つのタスクにだけ使って、すぐに破棄する。

動的シークレットとは何か

動的シークレットは保存された値ではない。誰かが必要とした瞬間に作成される認証情報であり、寿命は数分または数秒で測られる。タスクが終了すると、その認証情報は消える。後で再利用することは誰にもできない。

次のシナリオを想像してほしい。CIパイプラインがPostgreSQLデータベースに対してマイグレーションを実行する必要がある。静的シークレットの場合、パイプラインはVaultから保存されたパスワードを読み取り、データベースに接続し、マイグレーションを実行し、切断する。そのパスワードは将来も有効なまま残る。もし誰かがパイプラインのログからパスワードを抽出したら、次のローテーションまでいつでもデータベースに接続できる。

次のシーケンス図は、このフローがどのように動作するかを示している。

sequenceDiagram participant CI as CI Pipeline participant V as Vault participant DB as Database CI->>V: マイグレーション用のDBアクセスを要求 V->>DB: 一時ユーザー+パスワードを作成 DB-->>V: 認証情報 V-->>CI: 一時認証情報を返却 CI->>DB: マイグレーションを実行 DB-->>CI: マイグレーション完了 CI->>V: タスク完了を通知 V->>DB: 一時ユーザーを無効化 DB-->>V: 確認

動的シークレットの場合、パイプラインはVaultにリクエストを送る。「このマイグレーションのためにデータベースアクセスが必要だ」と。Vaultは新しいユーザー名とパスワードを生成し、マイグレーションスキーマに対する読み書き権限を付与し、認証情報をパイプラインに返す。パイプラインはそれを使ってマイグレーションを実行し、完了するとVaultが自動的に認証情報を無効化する。その5分間だけ存在したユーザー名とパスワードは、もう使えない。たとえパイプラインのログが漏洩しても、その認証情報は無価値だ。

実際のVaultリクエストは次のようになる。

# Vaultから動的データベース認証情報を要求
VAULT_RESPONSE=$(vault read -format=json database/creds/migration-role)

# 一時的なユーザー名とパスワードを抽出
DB_USER=$(echo "$VAULT_RESPONSE" | jq -r '.data.username')
DB_PASS=$(echo "$VAULT_RESPONSE" | jq -r '.data.password')

# 認証情報を使ってマイグレーションを実行
psql "postgresql://${DB_USER}:${DB_PASS}@db.example.com:5432/production" \
  -f ./migrations/001_initial.sql

# 認証情報はTTL(例:5分)後に自動的に期限切れになる
# 手動での無効化は不要

本質的な違い:寿命

静的シークレットは長い寿命を持つ。保存し、定期的にローテーションし、ローテーションの合間に漏洩しないことを願う。リスクは寿命に比例する。90日ごとにローテーションされるパスワードは、攻撃者に最大90日の攻撃時間枠を与える。

動的シークレットは短い寿命を持つ。特定の目的のために作成され、その目的が完了すると破棄される。悪用可能な時間枠は数ヶ月から数分に縮まる。仮に認証情報が漏洩しても、誰かが見つけた時にはすでに期限切れだ。

このシフトは、シークレット管理の考え方を変える。「誰がこのシークレットを読めるか?」ではなく、「誰が新しいシークレットを要求できるか?」を問うことになる。Vaultが残りの処理を担当する。

動的シークレットがアクセス制御をどう変えるか

静的シークレットは、保存された値へのアクセスを管理することを強制する。誰が特定のパスワードを読めるかを設定し、そのパスワードがコピーされたり共有されたりしないことを願う。開発者がデータベースへの読み取り専用アクセスを必要とする場合、別の静的認証情報を作成するか、全員が同じ認証情報を使うことになる。

動的シークレットでは、リクエストレベルでアクセスポリシーを定義できる。パイプラインがデータベースアクセスを必要とするとき、Vaultはそのパイプラインが必要とする正確な権限を持つ認証情報を作成する。読み取り専用パイプラインには読み取り専用の認証情報。マイグレーションパイプラインには特定のテーブルへの書き込みアクセス。分析パイプラインには特定のスキーマに対するSELECTのみ。

この細粒度により、監査は簡単になる。すべての認証情報は、特定のリクエスト、特定のパイプライン、特定の時間枠に紐づく。何が、いつ、どのような権限で発生したかを正確に追跡できる。

動的シークレットが適さないケース

動的シークレットは強力だが、静的シークレットの完全な代替ではない。長期間有効な認証情報が必要な状況もある。

永続的なデータベース接続を維持するアプリケーションは、数分で期限切れになる認証情報を使えない。コネクションプールを保持するWebサーバーは、接続の存続期間中有効な認証情報を必要とする。この場合、より短いローテーション期間の静的シークレットを使うか、アクティブな接続を切断せずに認証情報を更新できるコネクションプーリングを実装する。

自動化された認証情報作成をサポートしない外部システムも問題になる。手動登録プロセスでトークンを発行するサードパーティAPIに対して認証する必要がある場合、動的認証情報を生成できない。静的トークンを使うしかなく、そのローテーションを慎重に管理する必要がある。

一部のレガシーシステムには、動的認証情報プロビジョニングに必要なAPIがない。データベースがプログラムによるユーザー作成をサポートしていない場合や、クラウドプロバイダーが手動のIAMロール作成を必要とする場合、動的シークレットは選択肢にならない。

動的シークレットを扱うツール

HashiCorp Vaultは、動的シークレット管理で最も一般的なツールだ。PostgreSQL、MySQL、MongoDB、AWS、GCPなど、多くのシステム向けの認証情報生成をサポートする。クライアントが認証情報を要求すると、Vaultはそれを作成し、Time-To-Live(TTL)付きのリースを割り当て、リースが期限切れになると自動的に無効化する。

CyberArk ConjurやAWS Secrets Managerなどの他のツールも動的シークレット機能を提供するが、実装は異なる。探すべき重要な機能は、手動介入なしでの認証情報の自動生成と無効化だ。

動的シークレット導入前の実用的チェックリスト

すべての静的シークレットを動的シークレットに置き換える前に、次のチェックリストを確認する。

  • 対象システムはプログラムによる認証情報作成をサポートしているか?データベースやクラウドプロバイダーに、一時ユーザーやロールを作成するAPIがあるか確認する。
  • アプリケーションは認証情報の期限切れを処理できるか?アプリが長時間接続を維持する場合、接続を切断せずに認証情報を更新する戦略が必要だ。
  • パイプラインはオンデマンドで認証情報を要求しているか?動的シークレットは、各パイプライン実行がキャッシュされた認証情報を再利用するのではなく、独自の認証情報を要求する場合に最も効果的だ。
  • Vaultインフラは信頼性が高いか?Vaultがダウンすると、誰も新しい認証情報を要求できなくなる。高可用性を計画する。
  • 実際に動的シークレットが必要なパイプラインを監査したか?実行頻度が非常に低いパイプラインでは、短いローテーション期間の静的シークレットの方が管理が簡単な場合がある。

具体的な結論

長い寿命を持つ静的シークレットは、ローテーションの間隔が広がるごとにセキュリティギャップを拡大する。動的シークレットは、認証情報を単一タスクの期間だけ有効にすることで、そのギャップを埋める。トレードオフは複雑さだ。動的プロビジョニングをサポートするVault、短命認証情報を処理するアプリケーション、オンデマンドでユーザーを作成できるシステムが必要になる。しかし、自動化パイプラインや短命プロセスで使われる認証情報にとって、動的シークレットは「意味のある漏洩」と「意味のない漏洩」を分ける決定的な違いをもたらす。