シークレット ローテーションは、パスワード、API キー、暗号鍵などの機密情報(シークレット)を定期的に更新または置き換えるプロセスです。シークレットのローテーションは、特にシークレットが侵害された場合や漏洩した場合に、シークレットに不正アクセスや不正使用が行われるリスクを最小限に抑えることができます。
定期的なローテーションは、次のような点で役立ちます。
-
シークレットの漏洩が発生した場合の影響を制限する。
-
シークレットへのアクセスが不要になった個人に対して、古いシークレット値を使用できないようにする。
-
シークレットを緊急にローテーションする必要がある場合、サービスの中断のリスクを最小限に抑えます。
Secret Manager には、シークレット、シークレット バージョン、ローテーション スケジュールのコンセプトがあります。これは、ローテーションされたシークレットをサポートするワークロードを構築するための基盤となります。
このページでは、Secret Manager に保存されているシークレットのローテーションに関する推奨事項について説明します。以下の操作について学習します。
始める前に、プラットフォームの概要を読んで、Google Cloud の全体像を把握することをおすすめします。また、Secret Manager の概要もご覧ください。
シークレット バージョンをアプリケーションにバインドする
Secret Manager のシークレットには、複数のシークレット バージョンを含めることができます。シークレット バージョンには不変のペイロード(実際のシークレットのバイト文字列)が含まれ、順序と番号が付けられます。シークレットをローテーションするには、既存のシークレットに新しいシークレット バージョンを追加します。
シークレットに最近追加されたシークレット バージョンは、latest
エイリアスを使用して参照できます。latest
エイリアスは、開発には便利ですが、本番環境ワークロードで問題になる可能性があります。これは、不正な値がすぐにロールアウトされ、サービス全体の停止につながる可能性があるためです。次のシナリオでは、シークレット バージョンへのバインディングの代替方法について説明します。
段階的なロールアウト
段階的なロールアウトは、以下のシナリオの指針になります。シークレットのロールアウトをより遅くすることで、破損のリスクを低減できますが、復旧にかかる時間もより遅くなります。一部のシークレットは、外部システム(有効なシークレット値を追跡する API やデータベースなど)で無効になる可能性があります。これらの外部システムは、ロールアウトが必要な場合に、自分で制御と復元ができる場合とできない場合があります。
手動または自動のローテーション中に、不適切なシークレットがロールアウトされる可能性があります。強力なローテーション ワークフローでは、破損(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 で新しいシークレット バージョンを作成します。また、新しく作成されたシークレットを指すように
latest
エイリアスも更新されます。
再試行と同時実行
ローテーション プロセスはいつでも終了できるため、Cloud Run サービスはプロセスを中断した時点から再開できる(リエントラントである)必要があります。
失敗したローテーションまたは中断されたローテーションを再実行できるように、再試行を構成することをおすすめします。さらに、Cloud Run サービスで最大同時実行数と最大インスタンス数を構成して、同時ローテーション実行が相互に干渉する可能性を最小限に抑えます。
リエントラントなローテーション機能を構築するには、ローテーション プロセスを再開できるように状態を保存すると便利です。これに役立つ Secret Manager の機能が 2 つあります。
-
シークレットのラベルを使用して、ローテーション中に状態を保存します。シークレットにラベルを追加して、ローテーション ワークフロー中の最後に正常に追加されたバージョンの数を追跡します(例:
ROTATING_TO_NEW_VERSION_NUMBER=3
)。ローテーションが完了したら、ローテーション トラッキング ラベルを削除します。 -
ETag を使用して、ローテーション ワークフロー中に他のプロセスによってシークレットが同時に変更されていないことを確認します。詳細については、シークレットとシークレット バージョンの ETag をご覧ください。
Identity and Access Management の権限
ローテーション プロセスには、新しいシークレット バージョンを追加するための secretmanager.versions.add
権限が必要です。また、以前のシークレット バージョンを読み取るには secretmanager.versions.access
権限が必要になる場合があります。
ローテーション プロセスには、新しいシークレット バージョンを追加するための 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
新しいシークレット バージョンをワークロードにロールアウトする
新しく有効なシークレット バージョンが外部システムに登録され、Secret Manager に保存されたので、アプリケーションにロールアウトします。このロールアウトは、シークレット バインディングへのアプローチによって異なります。一般的には、手動での操作は必要ありません。
古いシークレット バージョンをクリーンアップする
すべてのアプリケーションで古いシークレット バージョンがローテーションされると、シークレット バージョンを安全にクリーンアップできます。クリーンアップ プロセスはシークレットのタイプによって異なりますが、通常は以下のようになります。
-
新しいシークレット バージョンがすべてのアプリに完全にロールアウトされていることを確認します。
-
Secret Manager の古いシークレット バージョンを無効にし、アプリケーションが破損していないことを確認します(無効の操作でコンシューマが破壊された場合、人が介入できるような合理的な時間待機します)。
-
外部システムから古いシークレット バージョンを削除または登録解除します。
-
Secret Manager で古いシークレット バージョンを破棄する