TT Lab
はじめる
学ぶ 学習パス コース

クラウド権限設計

長期キーなしで権限を渡す

TT Labで続きを見る

目標

ロールが長期のキーより安全なのは確かですが、信頼ポリシーを緩く書くと、その安全がまるごと消えます。このラボは、クラウドアカウントなしで、信頼ポリシーを自分で書き、危険な形を見つける検査器を手で作って、その場所を確認します。

信頼ポリシーと権限ポリシー

2つのドキュメントを混同すると、何も合いません。

このラボで使うのは、信頼ポリシーのほうです。最後のステップ1つだけが、権限ポリシーです。

条件

文法の確認

ポリシーはたいてい、コンソールではなくコードで入ります。JSONが壊れていると、エラーメッセージがポリシーの内容と無関係に出るので、毎回確認するほうが速いです。

python3 -m json.tool /root/roles/trust-ec2.json

作るもの

ファイル 内容
/root/roles/trust-ec2.json インスタンスが引き受けるロール
/root/roles/trust-partner.json 外部アカウントに開けるロール
/root/roles/trust-ci.json フェデレーションで引き受けるロール
/root/roles/lint_trust.py 危険な信頼ポリシーの検査器
/root/roles/passrole.json ロールを渡す権限
/root/roles/06-session.md セッション時間の計算
/root/roles/07-notes.md まとめ

参考

ステップ4の検査器は、隠してある4つのポリシーと、自分が作った3つのポリシーの両方で実行されます。危険なものを見逃しても失敗で、安全なものを検出しても失敗です。

インスタンスが自分で資格情報を受け取るようにする

EC2インスタンスが引き受けられるロールの信頼ポリシーを、/root/roles/trust-ec2.jsonに書いてください。Versionは2012-10-17です。

信頼ポリシーは、「誰がこのロールを引き受けられるか」だけを決めます。何ができるかは、別の権限ポリシーにあります。

プリンシパルが人ではなくサービスであることが核心です。PrincipalにServiceを書き、アクションは、ロールを引き受けるその操作1つです。

このロールをインスタンスに付けると、その中で動くプログラムが、キーファイルなしで資格情報を得ます。期限切れの前に自動で更新されるので、人が手を加えることはありません。

外部アカウントに開けるときは、もう1欄を埋める

協力会社のアカウント210987654321が引き受けられるロールの信頼ポリシーを、/root/roles/trust-partner.jsonに書いてください。アカウント番号だけを書いてはいけません。

アカウント番号だけを書くと、そのアカウントの中の誰でもこのロールを引き受けられます。協力会社の社員1人の資格情報が漏れたら、こちらのロールが開きます。

そのため、双方だけが知る値を条件として一緒にかけます。sts:ExternalIdをStringEqualsで比較し、値は推測しにくいように8文字以上にしてください。

この条件がないと、その協力会社に仕事を任せた第三者が、協力会社を経由して、こちらのロールに届いてしまいます。

CIからキーをなくす

CIランナーがOIDCで引き受けるロールの信頼ポリシーを、/root/roles/trust-ci.jsonに書いてください。リポジトリacme/platformのrefs/heads/mainからだけ引き受けられる必要があります。

フェデレーションで引き受けるときは、アクションがsts:AssumeRoleではなくsts:AssumeRoleWithWebIdentityで、プリンシパルは、Principal.Federatedに書くIDプロバイダーです。

条件を抜かすと、そのCIサービスを使うどのリポジトリでも、こちらのロールを引き受けます。最もよく出るミスで、条件1行で防げます。

:subをStringEqualsで固定し、:audも一緒に確認してください。StringLikeに*を使って、リポジトリだけを書くと、そのリポジトリのどのブランチからでも引き受けられるので、条件がないのと大きく変わりません。

危険な信頼ポリシーを見つける検査器

/root/roles/lint_trust.pyを作成してください。python3 /root/roles/lint_trust.py <정책.json>(プレースホルダーはポリシーJSONです)で呼び出すと、危険なポリシーは何が危険かを出力して終了コード1、安全なポリシーは終了コード0で終わる必要があります。

3つを見ます。

  1. プリンシパルが開いているか。Principal自体が*であるか、Principal.AWSが*であるもの
  2. 外部アカウントをPrincipal.AWSに置いているのに、sts:ExternalIdの条件がないもの
  3. sts:AssumeRoleWithWebIdentityなのに、:subの条件がないか、値に*があるもの

採点ツールは、前の3つのステップで作ったポリシーも、この検査器に入れてみます。安全なものを検出しても失敗です。誤警報が出始めると、人は検査器をオフにします。

ロールを渡す権限を絞る

開発者がECSタスクを作るときに、タスクロールを付けられる必要があります。その権限を/root/roles/passrole.jsonに書き、付けられるロールと渡す先のサービスまで絞ってください。

リソースを作るときに、そのリソースにロールを付ける操作は、実質的に、「自分にはできないことを代わりにやらせられる」権限です。Resourceを*にすると、低い権限のユーザーが、管理者ロールを付けたリソースを作って、権限を引き上げられます。

Resourceには、付けてよいロールのARNを書きます。名前の前半だけを決めて、後半を開ける方式でもかまいません。

iam:PassedToService条件で、どのサービスに渡すときだけ許可するかも固定してください。そうすれば、同じロールを別のサービスに渡す道が塞がれます。

セッション時間がそのまま対応速度になる

資格情報が発行された直後に漏れたとします。気づくまでに3時間、対応を決めるまでに1時間かかります。セッションが12時間のときと1時間のときで、権限を取り消したあとも残る時間をそれぞれ計算して、/root/roles/06-session.mdに3行以上書いてください。

ロールの権限を減らしても、すでに発行されたセッションは取り消されません。残りの有効時間の分は、そのまま使えます。

取り消しまで3 + 1時間かかります。12時間のセッションなら、そのあと何時間残りますか。1時間のセッションならどうなりますか。

数字を書いておけば、「セッションは短く」という言葉が、好みではなく計算になります。

3つをまとめる

/root/roles/07-notes.mdに3行以上。長期キーと一時的な資格情報の違い、信頼ポリシーが決めるもの、外部とフェデレーションで抜かしてはいけないもの。

本文に만료、신뢰 정책、조건が含まれている必要があります(韓国語で、順に「有効期限切れ」「信頼ポリシー」「条件」を意味する語です)。