aws:RequestTagの仕様を誤解していた
概要
ドキュメントをちゃんと読んでいればこのような誤解はしないのかもしれませんが、ざっとしか確認しなかったために以下のようにaws:RequestTag
を条件に指定したポリシーが想定通りの挙動をせず悩んでました。
{
"Version": "2012-10-17",
"Statement": {
"Effect": "Allow",
"Action": "ec2:CreateTags",
"Resource": "arn:aws:ec2:*:*:instance/*",
"Condition": {
"StringEquals": {
"aws:RequestTag/environment": [
"preprod",
"production"
]
},
}
}
}
当初の認識
誤解していたのはドキュメント中の次の部分です。
リクエストで渡すことができるタグを制御します。これを行うには、aws:RequestTag/key-name 条件キーを使用して、AWS リソースのタグ付けを行うリクエストで渡すことができるタグキーバリューのペアを指定します。
後半の「リクエストで渡すことができるタグキーバリューのペアを指定」を正しく理解できておらず、
- リクエストではIAMユーザーにアタッチされているタグのキーバリューが渡される
- 上記のポリシーの場合、
environment: preprod or production
が設定されたIAMユーザーにのみCreateTags
を許可する
というような理解をしていました。
そのため、CreateTag
を実行するIAMユーザーに対しenvironment: production
というタグをアタッチし、
※画像に誤りがあります。environment:dev
-> environment:production
で確認しています
既存のEC2インスタンスにOwner: test
という新しいタグを追加しようとしてエラーが発生し、なぜエラーになるのかわからないという事態が起こりました。
※本来はこのようにIAMユーザーのタグと比較したい場合、aws:RequestTag
ではなくaws:PrincipalTag
を使用します。
正しい認識
aws:RequestTag
の正しい挙動は以下です。
-
aws:RequestTag
ではCreateTag
で作成するタグのキーバリューを参照できる - 上記のポリシーの場合、
CreateTag
で作成するタグをキーがenvironment
で値がpreprod or production
のみに制限する
上記の通りaws:RequestTag
はIAMユーザーにアタッチされたタグによりCreateTag
アクションを制限するものではなく、CreateTag
アクションで作成するタグを制限するための条件キーです。
今回のポリシーではIAMユーザーにアタッチされているタグは関係なく、CreateTag
でenvironment: preprod or production
のタグのみ作成できます。
またこのように作成するタグを制限する際のベストプラクティスとして、以下のような条件を追加します。
"ForAllValues:StringEquals": {"aws:TagKeys": "environment"}
IAMのCondition要素では、条件キーで大文字・小文字は区別されません。条件値で大文字・小文字が区別されるかどうかは使用する条件演算子によります。
aws:RequestTag
ではキー名を条件キーに指定するので大文字小文字が区別されません。
その結果aws:RequestTag/environment
ではタグキーとしてenvironment
Environment
の2種類を受け付けます。
aws:TagKeys
は条件値に指定したタグキーとリクエスト内に含まれるタグキーを比較します。
またStringEquals
は条件値の大文字・小文字を区別します。
参考:IAM JSON ポリシー要素: 条件演算子
この条件を追加することにより、タグキーに指定できるキー名をenvironment
のみに制限することができます。
Discussion