キー管理と
フェデレーション
鍵を配って守るか、身元を短命のトークンに替えるか。
5S LABのWebアプリの構成で比べる。
鍵は、持っている人なら誰でも使える。
盗まれた鍵と本物の鍵を、相手のサービスは見分けられない。
2025年に、公開GitHubへ新たに漏れたシークレット(前年比34%増)
2022年に見つかった、まだ使えたシークレットのうち、2026年1月の時点でも使えたもの
だから各社は、長く使う鍵より短命の資格情報を勧めている
2024年5月3日以降に作った組織では、サービスアカウントキーの作成を既定で止めている
本番でクライアントシークレットを使わないよう求めている
いずれも、外部の身元を短命の資格情報に替える方式を用意している
合鍵を配るか、受付で入館証をもらうか。
鍵を保管して使う = 合鍵
- 管理人が合鍵を作り、使う人に配る
- 誰が持っていても、扉は開く
- なくしたら、鍵を替えて全員に配り直す
フェデレーション = 入館証
- 受付で社員証を見せ、その日だけ使える入館証をもらう
- 社員証は、会社(発行元)が保証している
- 入館証は夕方には切れる。なくしても翌日は使えない
アプリの身元(実行ロール)を、実行環境のクラウドが証明する
相手側に登録する、受け入れる身元
既定で1時間ほどで切れる
鍵は、発行・保管・配布・取り替えを、使うあいだ続ける。
身元のIDトークンを、相手が短命のトークンに替える。
- 実行ロールの資格情報で、AWS STSに相手向けのIDトークンを頼む
- AWSが「誰が・誰に向けて・いつまで」を署名して返す。長く使う秘密ではないが、期限内は持っている人が使えるので、ログや応答に出さない
- IDトークンを、相手の交換窓口に渡す
- 相手は署名を確かめ、登録した信頼の設定と照らす。一致すれば短命のトークンを返す
- そのトークンを付けてAPIを呼ぶ
- 結果が返る。切れる前に1から取り直す(5S LABは期限の5分前まで使い回す)
漏れたときの被害と、続く手間が違う。
| 観点 | 鍵を保管して使う | フェデレーション |
|---|---|---|
| 漏れたら | 消すまで、誰でも使える | 既定で1時間ほどで切れる |
| アプリが持つ物 | 長く使える鍵の写し | 身元だけ。盗まれる長期の値が無い |
| 取り替え | 使うあいだ、ずっと続く | 要らない |
| 絞り方 | 持つ人を区別できないので、APIや送信元で絞る | 環境・身元ごとに絞れる(stgだけ止める、もできる) |
| 最初の手間 | 小さい。発行して配るだけ | 相手ごとに信頼の設定を作る。作り方は相手ごとに違う |
| ローカル開発 | 鍵を渡せば動く | 手元に実行環境の身元が無い。開発者のログインや開発用の鍵を使う |
漏れたあと使える時間が、桁で違う。
シークレット
シークレット
寿命は相手ごとに決められる
AWSのロールは15分〜12時間(既定1時間)、Anthropicは60秒〜24時間(既定1時間)。5S LABはAWSのIDトークンを1時間で頼み、実行ロールの権限で1時間より長くは頼めないようにしている。
取り消せないトークンもある
Googleのサービスアカウントのトークンは、期限の前に取り消せない。だから寿命は短く、権限は小さく保つ。
同じ構成でも、アプリが持つ秘密の数が変わる。
対応した3社(Google Cloud・Microsoft・AWS)の鍵に、対応していない相手の鍵とアプリ自身の鍵の3個(DB・Googleログイン・セッション)を足して6個。配備のため、GitHubにもAWSのアクセスキーを置く。
身元のIDトークンはAWS STSがその場で発行する。Googleログインはform_postで受け取り、シークレットを持たない。残る2個はDBとセッションの署名鍵。
渡す身元は1つ。交換のしかたは相手ごとに違う。
身元は、環境ごとの実行ロール。人ではなくアプリ(Lambda)に割り当てる、AWSのIAMロールのこと。
| 相手 | 交換のしかた | 返ってくる物 | 許可を決める所 |
|---|---|---|---|
| AWSSES・Secrets Manager | 交換しない。Lambdaが引き受けた実行ロールの資格情報で直接呼ぶ | 一時的な資格情報 | 実行ロールの権限送信元は no-reply@5slab.jp に限る |
| Google CloudGemini・TTS・地図 | Google STSで交換し、サービスアカウント(SA)になりすますSA:Google Cloudでアプリに割り当てる身元 | SAのアクセストークン | WIFの条件(prodの実行ロールだけ)とSAのロール |
| Microsoftログイン | Entra IDのFICで交換。シークレットの代わりにIDトークンでアプリを証明する | ログインした人のトークン | FIC(発行元・subject・audience)subjectはprodの実行ロールのARN |
| GitHub Actions配備 | GitHubのIDトークンで、AWSの配備ロールを引き受ける(AssumeRoleWithWebIdentity) | 一時的な資格情報 | 5slab/universal の environment aws-prod(mainからだけ) |
信頼の設定は、身元をぴったり指す。
IDトークンの中身
相手側の信頼の設定
- 発行元が、このAWSアカウントの発行元と一致する
- subject が、この環境の実行ロールのARNだけに一致する
- audience が、自分宛ての値と一致する
!subjectとaudienceを固定する
発行元が同じなら、ほかの身元も同じ形のトークンを持てる。GitHubは発行元が全員共通なので、subjectをリポジトリとenvironmentまで固定する。
!環境ごとに分ける
stgとprodで、実行ロール・WIFのプロバイダとSA・FICを別にする。片方だけ止められる。
!権限を最小にし、見張る
実行環境を乗っ取られると、その身元で呼ばれる。フェデレーションは鍵の漏えいを防ぐが、アプリの脆弱性は防がない。
残るのは、相手が対応していない鍵と、ブラウザで使う鍵。
| 鍵 | なぜ残るか | どう守るか |
|---|---|---|
| 地図のキーブラウザ | ブラウザに置かないと地図が動かない | 参照元・使えるAPI・1日の上限・8割で通知文字列はAWSに置かず、Google Cloudから実行時に読む |
| DBのパスワードPlanetScale | パスワード認証しか無い | Secrets Manager。この配備先専用のDBロールにし、PrivateLinkでつなぐ(インターネットを通らない) |
| セッションの署名鍵アプリ自身 | 外部の認証ではない(減らす対象ではない) | 環境ごとに生成し、Secrets Manager |
Googleログインは、交換の窓口を使わずに鍵をなくす
Googleのトークン窓口はクライアントシークレットでしか認証できない。そこで認可コードを交換せず、IDトークンをform_post(ブラウザからサーバーへのPOSTの本文)で直接受け取り、Googleの公開鍵で署名を確かめる。
見られる前提の鍵は、使い道と量で絞る。
地図(Maps JavaScript API)は、ブラウザにキーを置かないと動かない(2026年10月時点)。キーの文字列はAWSに置かず、Google CloudからWIFで読んでブラウザへ渡す。
それでも残ること
スクリプトからなら参照元は偽装できる。ただし上限があるので費用は増えない。残る被害は、上限を使い切られてその日はGoogleの地図が止まる(OpenStreetMapに切り替わる)ことだけ。
Firebase App Checkは入れていない
偽装まで防げるが、読み込みの重さ・プライバシー・設定の手間に見合わないと判断した。
対応していればフェデレーション。鍵は残すものだけ。
対応している?
鍵を守る仕事を、身元の設定に置き換える。
- 相手が対応していれば、鍵ではなくフェデレーション。アプリは秘密の値を持たず、トークンは既定で1時間ほどで切れる。
- 信頼の設定は、発行元・subject・audienceで身元をぴったり指し、環境ごとに分ける。
- 残す鍵は、絞る・隠す・取り替える・見張るを重ね、どこで使っているかを記録する。
- Googleサービスアカウントキーの扱い
- Google安全な既定の組織
- GoogleほかのIdPからのWIF
- Microsoftアプリ登録のセキュリティ
- MicrosoftワークロードIDフェデレーション
- AWSGetWebIdentityToken・AssumeRoleWithWebIdentity
- AnthropicWorkload identity federation
- GitHubOpenID Connect
- GoogleMaps APIのセキュリティ
- GitGuardianThe State of Secrets Sprawl 2026
- IETFRFC 8693・RFC 7523