チームにシークレットポリシーが必要な理由(単なるVaultだけでは不十分)
あなたがチームの部屋に入り、5人の開発者にデータベースパスワードをどこに保存しているか尋ねたとします。一人はプロジェクトルートの .env ファイルを指さします。別の開発者はパスワードマネージャーのプライベートノートに保存しています。三人目は、APIトークンをコード内のコメントとして、それを使用する関数のすぐ上に貼り付けています。四人目の開発者はVaultに入れたと断言しますが、他の誰も見つけられません。五人目はただ肩をすくめるだけです。
これはセキュリティの失敗ではありません。これは協調の失敗です。どの開発者にも、その選択には理由がありました。.env ファイルは迅速でした。プライベートノートは便利でした。コードコメントは可視性が高かった。Vaultへの登録は技術的には正しかったが、文書化されていませんでした。肩をすくめるのは正直な反応です。
問題はシークレットが存在することではありません。問題は、チーム全体および環境全体でシークレットをどのように管理するかについて、共有されたルールがないことです。ポリシーがなければ、各開発者は自分のワークフローに最適化し、結果として不整合が生じます。不整合があると、本番シークレットが開発シークレットと同じ方法で扱われることを保証できません。ローテーションされたシークレットがすべての環境に確実に届くことも保証できません。元チームメンバーがもはやアクセスできないことも保証できません。
シークレットポリシーとは、一度読んだらしまい込まれる形式的な文書ではありません。これは、Vaultの設定とパイプラインの動作に変換される一連のルールです。目標はシンプルです。どの環境を見ても、シークレットが同じ方法でアクセスされ、管理されていることです。
誰が何にアクセスできるか
最初に確立すべきルールはアクセスに関するものです。開発環境で誰がシークレットを読めるのか?本番環境で誰がシークレットを読めるのか?これらは同じ質問ではありません。
開発環境では、ほとんどのチームメンバーがアプリケーションをローカルマシンで実行するためにシークレットへのアクセスを必要とします。それは問題ありません。リスクは低く、アクセスをブロックすると全員の速度が低下します。しかし、本番環境ではアクセスを制限しなければなりません。すべての開発者が本番データベースのパスワードや決済ゲートウェイのAPIトークンを知る必要はありません。ここでの原則は最小権限です。すべての人またはシステムは、自分の仕事に必要なシークレットのみを取得します。
これを強制する方法は、Vaultポリシーを使用することです。ポリシーは、ユーザーまたはシステムが読み取れるパスを定義します。例えば、secret/development/* はすべてのチームメンバーが読み取り可能ですが、secret/production/* はデプロイパイプラインと指定された数名のシニアエンジニアのみが読み取り可能です。これは手動で守ることが期待される文書化されたルールではありません。Vaultが強制する設定です。開発者が自分のラップトップから本番シークレットを読み取ろうとすると、Vaultは拒否します。監査ログにはその試行が記録されます。
環境を分離する
2つ目のルールは環境の境界に関するものです。本番シークレットを開発環境やステージング環境で使用してはなりません。開発シークレットが本番環境に漏れてはなりません。
これは明白に聞こえますが、実際にはよく発生します。チームが急いでいる時、外部サービスと通信する機能をテストする必要があります。別のテスト用クレデンシャルを作成する代わりに、本番トークンをステージングにコピーします。テストは成功します。誰もそれを削除することを覚えていません。後日、開発者が誤ってステージングの環境変数をログに出力し、本番トークンがチーム全体に見えるログファイルに含まれてしまいます。これにより、ステージングでのショートカットが原因で本番環境が露出します。
ここでの強制は構造的なものです。環境ごとにVaultパスを分離します。開発パイプラインは開発パスにのみアクセスできます。ステージングパイプラインはステージングパスにのみアクセスできます。本番パイプラインは本番パスにのみアクセスできます。パイプラインが異なる環境のシークレットを読み取ろうとすると、Vaultは拒否し、その試行をログに記録します。これは信頼の問題ではありません。誤ったアクションを不可能にすることです。
ローテーションは自動化されなければならない
3つ目のルールはローテーションに関するものです。シークレットはどのくらいの頻度で変更すべきでしょうか?答えは環境によって異なります。
開発シークレットはローテーションの頻度を低くできます。開発データベースのパスワードが漏洩した場合、影響範囲はチーム内に限定されます。3ヶ月ごとのローテーションで通常は十分です。本番シークレットはより頻繁なローテーションが必要です。毎月が妥当なベースラインです。チームメンバーが退職するたびに、そのメンバーがアクセスできた本番シークレットは直ちにローテーションする必要があります。
重要な点は、ローテーションは自動化されなければならないということです。人間は忘れます。人間は忙しくなります。人間は締め切りが近づくと手を抜きます。パイプラインがスケジュールに従ってローテーションを処理すべきです。シークレットが予定日までにローテーションされていない場合、パイプラインはフラグを立てるか、ローテーションが行われるまでデプロイをブロックする必要があります。これはチームを罰するためではありません。ローテーションを覚えておくという認知負荷を取り除くためです。
リカバリに備える
4つ目のルールはリカバリに関するものです。シークレットは失われます。Vaultパスが誤って削除されることがあります。誰かがシークレットをローテーションし、ダウンストリームサービスを更新し忘れることがあります。このような場合、チームはアプリケーション設定を変更せずにリカバリする方法を必要とします。
ほとんどのVaultはバージョン履歴を提供します。削除されたシークレットは以前のバージョンに復元できます。しかし、ポリシーでは、誰がリカバリを実行する権限を持ち、そのプロセスがどのようにログに記録されるかを定義する必要があります。リカバリは誰でも実行できる自由なアクションであってはなりません。承認が必要であり、監査証跡を残す必要があります。そうでなければ、リカバリは他のすべてのルールを迂回するバックドアになります。
強制可能にする
これらすべてのルールは、文書としてのみ存在するなら無意味です。Wikiに存在し、設定に変換されることのないシークレットポリシーは、ポリシーではありません。それは提案です。
シークレットポリシーを現実のものにする3つの要素:
- 環境ごとのアクセスルールを強制するVaultポリシー
- 環境ごとに分離され、パスを越境できないパイプライン
- 定期的にレビューされる監査ログ(単に保存されるだけではない)
これらの3つの要素がなければ、ポリシーは単なる言葉です。これらがあれば、ポリシーはシステムのデフォルトの動作になります。開発者はルールを覚えておく必要はありません。システムが自動的に強制します。
実践的なチェックリスト
チームのシークレットポリシーを設定する場合、以下に取り組むべき短いリストを示します:
- 環境ごとに、どのVaultパスがどのロールによって読み取り可能かを定義する
- それらのルールを文書化するだけでなく、強制するようにVaultポリシーを設定する
- 各環境が自身のシークレットにのみアクセスできるようにパイプラインアクセスを分離する
- 環境ごとにローテーションスケジュールを設定し、パイプラインで自動化する
- 削除されたシークレットを誰がリカバリできるか、およびリカバリがどのようにログに記録されるかを定義する
- 予期しないアクセス試行がないか、少なくとも月に一度は監査ログをレビューする
まとめ
シークレットVaultはツールです。シークレットポリシーは、そのツールを有用にするルールブックです。ポリシーがなければ、Vaultはシークレットが一貫性なく保存されるもう一つの場所に過ぎません。ポリシーがあれば、Vaultはチームが実行するすべての環境にわたって、シークレットがどのようにアクセスされ、ローテーションされ、リカバリされるかを強制するシステムになります。ルールから始め、それらを強制するようにVaultを設定してください。それがシークレット管理ツールを持つことと、実際にシークレットを管理することの違いです。