このトピックでは、シークレットのローテーションのコンセプトについて説明します。始める前に、プラットフォームの概要を確認して、Google Cloud の全体像を把握することをおすすめします。また、Secret Manager プロダクトの概要もご覧ください。
はじめに
定期的なローテーションは、次のことに役立ちます。
- シークレットの漏洩が発生した場合の影響を制限する。
- シークレットへのアクセスが不要になった個人に対して、古いシークレット値の使用を継続できないようにする。
- ローテーション フローを継続的に実施し、緊急ローテーションが発生した場合の停止の可能性を軽減する。
Secret Manager には、シークレット、シークレット バージョン、ローテーション スケジュールのコンセプトがあります。これは、ローテーションされたシークレットをサポートするワークロードを構築するための基盤となります。
このトピックでは、Secret Manager に保存されているシークレットのローテーションに関する推奨事項について説明します。以降のセクションでは、次のメリットとトレードオフについて説明します。
シークレット バージョンへのバインディング
Secret Manager のシークレットには、複数のシークレット バージョンを含めることができます。シークレット バージョンには不変のペイロード(実際のシークレットのバイト文字列)が含まれ、順序と番号が付けられます。シークレットをローテーションするには、既存のシークレットに新しいシークレット バージョンを追加します。
シークレットに最近追加されたシークレット バージョンは、latest
エイリアスを使用して参照できます。latest
エイリアスは、開発には便利ですが、本番環境ワークロードで問題になる可能性があります。これは、不正な値がすぐにロールアウトされ、サービス全体の停止につながる可能性があるためです。次のシナリオでは、シークレット バージョンへのバインディングの代替方法について説明します。
段階的なロールアウト
段階的なロールアウトは、以下のシナリオの指針になります。シークレットのロールアウトをより遅くすることで、破損のリスクを低減できますが、復旧にかかる時間もより遅くなります。一部のシークレットは、外部システム(有効なシークレット値を追跡する API やデータベースなど)で無効になる可能性があります。これらの外部システムは、ロールアウトが必要な場合に、自分で制御と復元ができる場合とできない場合があります。
手動または自動のローテーション中に、不適切な Secret がロールアウトされる可能性があります。強力なローテーション ワークフローでは、破損(HTTP エラー率など)を自動的に検出し、(以前の構成のデプロイによって)古いシークレット バージョンを使用するようにロールバックできる必要があります。
新しいシークレット バージョンのロールアウトは、シークレットがアプリケーションにバインドされる方法によって異なります。
アプローチ 1: 既存のリリース プロセス中に解決する
シークレット バージョンを解決して、アプリケーションのリリースにバインドします。ほとんどのデプロイの場合、これには、最新のシークレット バージョンを完全なシークレット バージョンのリソース名に解決し、フラグとしてアプリケーションで、または構成ファイルでロールアウトすることが含まれます。ローテーション時にシークレット バージョンの名前を解決して、リソース名を耐久性のある場所(Git への commit など)に保存し、デプロイがブロックされるのを防ぐために、push 時にバージョン名をデプロイ構成に入れることをおすすめします。
アプリケーションの起動時に、特定のシークレット バージョン名を指定して Secret Manager を呼び出し、シークレット値にアクセスします。
この方法には次のメリットがあります。
- 再起動後も同じシークレット バージョンが使用されるため、予測可能性が向上し、運用の複雑さが軽減されます。
- ロールアウトとロールバックの既存のチェンジ マネジメント プロセスを、シークレットのローテーションとシークレット バージョンのデプロイに再利用できます。
- 値を段階的にロールアウトして、不正な値のデプロイの影響を軽減できます。
アプローチ 2: アプリの起動時に解決する
アプリケーションの起動時に最新のシークレット ペイロードを取得し、アプリケーションの存続期間中は、そのシークレットの使用を継続します。
このアプローチの利点は、シークレット バージョンの解決に CI/CD パイプラインを変更する必要がないことですが、不正なシークレットがロールアウトされると、インスタンスの再起動時やサービスのスケールアップ時にアプリケーションの起動に失敗し、サービス停止につながる可能性があります。
アプローチ 3: 継続的に解決する
アプリケーションで最新のシークレット バージョンに対して継続的にポーリングし、新しいシークレット値をすぐに使用します。
このアプローチでは、新しいシークレット値を段階的に採用しないため、サービス全体がすぐに停止するリスクがあります。
シークレットをローテーションする
シークレットを動的に更新できる場合(たとえば、シークレットを検証する外部システムが Admin API を提供する場合)は、定期的に実行するローテーション ジョブを設定することをおすすめします。一般的な手順については、次のセクションでサンプルのコンピューティング環境として Cloud Run を使用して、概要を説明します
シークレットにローテーション スケジュールを構成する
シークレットのローテーション スケジュールを設定します。シークレットをローテーションするときに、通知を受け取るように、シークレットに Pub/Sub トピックを構成する必要があります。シークレットにトピックを構成するには、イベント通知のガイドをご覧ください。
Cloud Run を起動して新しいシークレット バージョンを作成する
ローテーション通知を受信してローテーション手順を実施するには、Cloud Run サービスを作成して構成します。
外部システム(データベース、API プロバイダなど)で新しいシークレットを取得または作成します。
既存のワークロードが影響を受けないように、この操作によって既存のシークレットが無効化されないようにしてください。
新しいシークレットを使用して Secret Manager を更新します。
Secret Manager で新しい
SecretVersion
を作成します。これにより、latest
エイリアスが更新され、新しく作成されたシークレットを参照するようになります。
再試行と同時実行
ローテーション プロセスはいつでも終了できるため、Cloud Run サービスはプロセスを中断した時点から再開できる(リエントラントである)必要があります。
失敗したローテーションまたは中断されたローテーションを再実行できるように、Pub/Sub で再試行を構成することをおすすめします。さらに、Cloud Run サービスで最大同時実行数と最大インスタンス数を構成して、同時ローテーション実行が相互に干渉する可能性を最小限に抑えます。
リエントラントなローテーション ファンクションを構築するには、ローテーション プロセスを再開できるように状態を保存すると便利です。これに役立つ Secret Manager の機能が 2 つあります。
- シークレットのラベルを使用して、ローテーション中に状態を保存します。シークレットにラベルを追加して、ローテーション ワークフロー中の最後に正常に追加されたバージョン(例:
ROTATING_TO_NEW_VERSION_NUMBER=3
)の数を追跡します。ローテーションが完了したら、ローテーション トラッキング ラベルを削除します。 - ETag を使用して、ローテーション ワークフロー中に他のプロセスによってシークレットが同時に変更されていないことを確認します。詳細については、シークレットとシークレット バージョンの ETag をご覧ください。
Identity and Access Management の権限
ローテーション プロセスには、新しいシークレット バージョンを追加するための secretmanager.versions.add
権限が必要です。また、以前のシークレット バージョンを読み取るには secretmanager.versions.access
が必要になる場合があります。
デフォルトの Cloud Run サービス アカウントには編集者のロールがあります。このロールには、シークレット バージョンの追加権限が含まれていますが、アクセス権限はありません。最小権限の原則に沿って、デフォルトのサービス アカウントは使用しないことをおすすめします。代わりに、必要に応じて付与された Secret Manager のロール(1 つまたは複数でもかまいません)を使用して、Cloud Run サービスの個別のサービス アカウントを設定します。
roles/secretmanager.secretVersionAdder
roles/secretmanager.secretVersionManager
roles/secretmanager.secretAdmin
roles/secretmanager.secretAccessor
新しい SecretVersion
をワークロードにロールアウトする
新しく有効な SecretVersion
が外部システムに登録され、Secret Manager に保存されたので、アプリケーションにロールアウトします。このロールアウトは、シークレット バインディングへのアプローチによって異なります(シークレット バージョンへのバインディングを参照)。一般的には、手動での操作は必要ありません。
古いシークレット バージョンをクリーンアップする
すべてのアプリケーションで古いシークレット バージョンがローテーションされると、シークレット バージョンを安全にクリーンアップできます。クリーンアップ プロセスはシークレットのタイプによって異なりますが、通常は以下のようになります。
- 新しいシークレット バージョンがすべてのアプリに完全にロールアウトされていることを確認します。
- Secret Manager の古いシークレット バージョンを無効にし、アプリケーションが破損していないことを確認します(無効の操作でコンシューマが破壊された場合、人が介入できるような合理的な時間待機します)。
- 外部システムから古いシークレット バージョンを削除または登録解除します。
- Secret Manager で古いシークレット バージョンを破棄します。