応用読了目安 14 分#秘密情報#API キー#ローテーション#Secrets Manager
秘密情報の扱い — 消したコミットの中に、鍵はまだ残っている
誤ってコミットしたアクセスキーを次のコミットで消した。半年後にリポジトリを公開した数時間後、そのキーで高額なサーバーが大量に立ち上がった。漏れた鍵に効くのは削除ではなく、無効化。
先に読んでおくとよい記事
この記事の進み方
What — 秘密情報は、どこから漏れるか
秘密情報(API キー、パスワード、署名用の鍵)は、書いた場所だけでなく、その値が通った場所すべてに残ります。
- 1Git の履歴消したコミットの前に残る重い
- 2コンテナイメージの層後の層で消しても、前の層に残る重い
- 3ビルドとデプロイのログecho や設定の表示中
- 4設定と構成の定義環境変数、テンプレート、状態ファイル中
- 5ブラウザに配るコードバンドルに入れば公開と同じ重い
- 6エラーと会話例外メッセージ、チャット、AI への貼り付け中
冒頭の事故は 1。消すコミットを積んでも、追加したコミットは履歴に残る。
1/6
Git の履歴 — ファイルを消すコミットを積んでも、追加したコミットは履歴に残り、clone すれば誰でも取り出せる。フォーク、手元の clone、CI のキャッシュにも写しがある。
どれも「書いたつもりのない場所」に値が残る形。ソースコードに直接書かないだけでは、半分しか塞がない。
- ローテーション
- 鍵を新しいものに差し替え、古い鍵を無効にすること。漏れていなくても定期的に行う。
- 無効化
- 発行元で鍵を使えない状態にすること。漏れた鍵に対して唯一効く対処。
- シークレット管理サービス
- 秘密情報を暗号化して保管し、権限を持つ処理にだけ実行時に渡すサービス。
- 最小権限
- その処理に必要な操作だけを許した鍵や権限にすること。漏れたときの被害を小さくする。
確認 — ここまで読めたか
API キーを書いたファイルを誤ってコミットし、プッシュしました。次のコミットでファイルを削除してプッシュしました。これで安全になりましたか?
Why — なぜ「消す」では済まないのか
ファイルやログから値を消すのは、これから先に見つかる確率を下げる操作です。すでに誰かが読んだかどうかは変えられません。そして、読まれたかどうかは多くの場合確かめようがありません。
だから、漏れた可能性がある鍵への対処は**「読まれた前提で、使えなくする」**しかありません。
消す: これから見つかる確率を下げる → 読まれた鍵は使われ続ける
無効化: 読まれていても使えなくする → 被害が止まる
値を置く場所
「どこにも残らない場所」は存在しません。値が見える人と経路を、できるだけ少なくするのが目標です。
履歴に永久に残る
const apiKey = "sk_live_…"- 見える人
- **リポジトリを読めるすべての人**
- 残る場所
- **Git の履歴、すべての clone**
- 差し替え
- コードの変更とデプロイ
- 環境ごとの切り替え
- できない
- 読み取りの記録
- —
- –冒頭の事故の入口
- –消すコミットを積んでも、追加したコミットは残る
- –本番と検証で違う鍵を使う、ということもできない
下に行くほど、値が見える人と経路が減る。代わりに、取り出す仕組みと権限の設計が要る。
このサイト自身の判断
このサイトは決済に Stripe を使い、そのキーを シークレット管理サービスに置いて、実行時に読んでいます。インフラの定義(CDK)が作るのは空の入れ物だけで、値は定義にも、リポジトリにも、テンプレートにも入れていません。値は、デプロイ後に人が自分の端末から入れます。
作ってみて分かった注意点が2つあります。
- 差し替えは、すぐには効かない。 関数は読んだ値を一定時間キャッシュしているので、差し替えてもその時間ぶん古い値が使われる。ローテーションでは、古い鍵を少なくともその時間は有効にしておく必要がある
- テンプレートから参照する形は、差し替えを拾わない。 デプロイ時に値を解決する参照は、参照の文字列が変わらない限り、値が変わっても更新されない。差し替えのたびに、参照先の版を明示してデプロイし直している
確認 — ここまで読めたか
Dockerfile で .env を COPY し、依存関係のインストールに使ったあと、次の RUN で rm .env しました。できあがったイメージに鍵は残りますか?
演習 — まず自分で判断する
解説を読む前に、まず自分で判断してみてください。ここで一度詰まっておくと、 次の節の判断軸が「なるほど」ではなく「そう来たか」に変わります。
演習 — 設計判断を問う
サーバーレスの API で、秘密情報をどこにどう置きますか?
与えられた条件
- 扱う秘密情報は、決済サービスの API キー、DB のパスワード、メール配信サービスの API キー
- インフラは IaC で定義し、リポジトリに入っている
- 環境は開発・検証・本番の3つ
- 開発者は5人で、全員が本番の管理画面を閲覧できる
- 監査の要件で、鍵は年1回以上差し替える必要がある
この軸で考える
- · 値が見える人と経路を、どこまで絞れるか
- · 差し替えのたびに、何を変更しデプロイする必要があるか
- · 1本の鍵が漏れたとき、どこまで被害が及ぶか
演習 — 説明できるか
誤ってコミットした API キーを「削除コミットを積んだので対応済みです」と報告してきた後輩に、何が足りないかを伝えてください
与えられた条件
- 相手は入社1年目で、すぐに自分から報告してくれた
- リポジトリは非公開
- キーは本番の決済サービスのもの
- 責めずに、次の一手を一緒に進めたい
読み終わりましたか?
読了にすると、これを前提とする記事がロードマップで開放されます。