こんにちは!
クラウドインテグレーション2部 技術3課の樺澤です。
タイトルの件、意外とややこしかったので記録に残します。
はじめに
IAMポリシーとは
ユーザーやリソースに対してのアクセス権限を制御できるもので、リクエストが許可されるか拒否されるかが決まります。
IAMポリシーの見方はこちらのブログをご参考ください。
【初心者向け】IAMポリシー(JSON)の見方 - サーバーワークスエンジニアブログ
タグベースの制御のユースケース
色々なユースケースがあると思いますが1つとして、
同じアカウントや同じVPC内に、違う会社・違う部署・違うグループのリソースが共存している場合が考えられます。
各自の所属先リソースへのみアクセスを許可し、他のグループに属するリソースへはアクセス不可とするために、タグベースでのアクセス制御が使われます。
今回やりたいこと
A社のユーザーが、自社(A社)のタグが付いたEC2のAMIのみを作成できる。
自社以外のタグが付いたEC2のAMIを作成できないようにする。
今回ポリシーで使用するタグの設定は以下の表のとおりです。
以下、A社タグと表記します。
キー | 値 |
---|---|
company | A |
クイズです
上記「今回やりたいこと」を実現できるポリシーはAとBのどちらでしょうか?
※A社のユーザーに付与するIAMポリシーを想定しています。
※サービス認証リファレンスによると、今回の操作範囲内でCreateImageアクションをリソースレベルで制御する場合InstanceとImageが必須リソースとなります。
公式ドキュメント参考:
A
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "ec2:CreateImage", "Resource": [ "arn:aws:ec2:*:<アカウント番号>:instance/*", "arn:aws:ec2:*::image/*" ] "Condition": { "StringEquals": { "ec2:ResourceTag/company": "A" } } } ] }
B
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "ec2:CreateImage", "Resource": "arn:aws:ec2:*:<アカウント番号>:instance/*", "Condition": { "StringEquals": { "ec2:ResourceTag/company": "A" } } }, { "Effect": "Allow", "Action": "ec2:CreateImage", "Resource": "arn:aws:ec2:*::image/*" } ] }
ステートメントの数が違うところがヒントです!
解説
正解はBです!
Aのポリシーだとステートメントが無効となり、残念ながらアクセス権限は付与されません。
なぜBが正解?
①Condition句が適切なリソースにかかっている
Condition句(=A社タグが付与されているという条件)がInstanceリソースのみに適用されています。
★箇所参考
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "ec2:CreateImage", "Resource": "arn:aws:ec2:*:<アカウント番号>:instance/*", ★Instanceリソースのみ "Condition": { "StringEquals": { "ec2:ResourceTag/company": "A" ★A社タグが付与されているという条件 } } }, { "Effect": "Allow", "Action": "ec2:CreateImage", "Resource": "arn:aws:ec2:*::image/*" } ] }
実際にA社タグが付いているのはInstanceのみであり、Imageにはタグが付いていません(今からイメージを作成するのだから付与してあるはずがない)。
Condition句がInstanceリソースのみにかかるようにします。
②サービス認証リファレンスの条件が反映されている
冒頭でも述べた通り
サービス認証リファレンスによると、CreateImageアクションをリソースレベルで制御する場合InstanceとImageが必須リソース
ということで
リソースレベルでの制御の場合Imageリソースについても明記する必要があります。
正解ポリシーのどこに書いてあるかというと、
Instanceリソースとは別のステートメントにあります!
★箇所参考
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "ec2:CreateImage", "Resource": "arn:aws:ec2:*:<アカウント番号>:instance/*", "Condition": { "StringEquals": { "ec2:ResourceTag/company": "A" } } }, { "Effect": "Allow", "Action": "ec2:CreateImage", "Resource": "arn:aws:ec2:*::image/*" ★Imageリソース } ] }
※ちなみにステートメントを分けるとVisualEditorではエラーが出てしまいますが、JSONでは書けますし反映されるので問題ないです。きっとVisualEditorのスコープ範囲がステートメント単位なのだと考えられます。
まとめ
Condition句はResource句すべてにかかるため、矛盾がないかを確かめる
同じアクションのリソースを別のステートメントに移動しても認識してくれる(ただしVisualEditorではエラーが出る)
最後に
1つのアクションでもステートメントを別にして書いてもいいのか~という新たな発見でした。ちょっと冗長なポリシーにはなりますが、今回のCreateImageのようにイレギュラーなアクションの権限を絞る際にご参考になれば幸いです。サービス認証リファレンスについてはさらっと流してしまいましたので、別途ポイントをまとめたいなと思います。