CI2-1の松田です。こんにちは。
今回はタグを活用したIAMでの権限制御のざっくりした方法と、設計してみた時の備忘を書いていきます。
やりたいこと
今回やりたいことは、「IAMユーザーが特定のリソースだけを操作できるようにしたい」です。
このような場合、真っ先に思い浮かぶ方法は「タグを活用した権限の制御」ではないでしょうか。タグさえ付与すれば、今後新たに作成するリソースに対する権限も自動的に割り当てることができるため、IAMポリシー修正の手間を大幅に削減できます。
超簡単に図解しておきますと、下図のようなイメージです。
ざっくりやりかた
このような場合は、IAMのグローバル条件キーであるaws:ResourceTag/tag-key
を活用するといい感じに制御できます。今回はApplication
というタグを参照して制御するので、以下のような記述になります。
{ "Version": "2012-10-17", "Statement": [ { "Sid": "AllowEC2Operations", "Effect": "Allow", "Action": "ec2:*", "Resource": "*", "Condition": { "StringEquals": { "aws:ResourceTag/Application": "app01" } } } ] }
ポイントは9~11行目ですね。ここの記述は「リソースのApplication
タグの値がapp01
と等しければ」という意味で、言うなればIf文です。
そしてこのIf文が真であれば、6~8行目の権限(EC2に対するフルアクセス権限)が適用されます。
より詳細なお話は、以下の公式ドキュメントを参照ください。
余談的な備忘録的な何か
今回IAMでタグを使った権限分離を設計してみて、いくつか重要だなと思ったポイントや小ネタを備忘録的に書いていきます。ちなみに要件は以下としておきます。
- IAMユーザーには、
Application
:app01
タグが付与されているリソースに限り、以下の権限を与えること。- EC2インスタンスの起動・停止・再起動
- CloudFrontのキャッシュ時間の編集権限
- AWS WAFの編集権限
ちなみにIAMユーザーにはAWS管理ポリシーであるReadOnlyAccess
を付与することにしていますので、読み取り権限については特に言及しません。
EC2に対する権限
ここではAction
ブロックの書き方を中心に話したいと思います。
結論から行くと、要件は「EC2インスタンスの起動・停止・再起動ができること」なので、最終的には以下のStatement
を作成することで実現できます。
{ "Sid": "AllowEC2Operations", "Effect": "Allow", "Action": [ "ec2:StartInstances", "ec2:StopInstances", "ec2:RebootInstances" ], "Resource": "*", "Condition": { "StringEquals": { "aws:ResourceTag/Application": [ "app01" ] } } }
で、このAction
ブロックのec2:StartInstances
とかってどこから探すの?って話なんですが、私はIAMポリシーのビジュアルエディタを使って探すことが多いです(IAMポリシーの作成ウィザードで出てくるコレ)。
APIリファレンスでもいいんですが、ビジュアルエディタだと「読み込み」とか「書き込み」といった権限のレベルに応じてアクションが分類されているので、ノイズを予め除去できるという意味でこちらの方が好みです。
ちなみにEC2のAPIリファレンスはこちら。ここから探すの大変そうですよね。
AWS WAFに対する権限
AWS WAFでは、AWS WAF(v2)に対するフルアクセス権限を付与します。
ところがAWS WAFにはマネジメントコンソールにタグの項目がなく、一見タグが付与できないように見えます。しかしAWS CLIを使用することでタグの付与が可能です。
コマンドのサンプルを載せておきます。
aws wafv2 tag-resource --resource-arn "WebACLのARN" --tags "Key=Application,Value=app01" --region us-east-1
ちなみにこのコマンドはWebACLが存在するリージョンを--region
オプションで指定する必要があります(CloudFront用のWebACLは北部バージニアリージョン)。
なおWebACLのARNはコンソールでは確認できないため、list-web-acls
コマンドなどを使って調べる必要があります。いちいちめんどい...。
IAMの話ではないのですが、このようなケースもありますよということで紹介でした。
CloudFrontに対する権限
CloudFrontでは、キャッシュ時間の編集権限を付与します。
なぜこんな仮想要件を持ってきたのかというと、CloudFrontのキャッシュ時間を定義する「キャッシュポリシー」にはタグが付与できないためです。
こんな時は、下記の公式ドキュメントを漁って代替案を探すのが良いかと思います。
こちらのドキュメントには、各AWSサービスで使用できる「条件キー」と「リソースタイプ」の一覧が載っています。言い換えると、タグの代替として使える条件キーやリソースタイプ(ARN)があるかもしれないということです。
とはいえ、ユーザーが任意に指定できるものでなければタグの代替として使うことは難しいです。例えばリソース名であれば、「プレフィックスにapp01
を付与する」などの命名規則を定めておき、「プレフィックスにapp01
が含まれていれば許可」というようにCondition
ブロックを記述します。これで、リソース名をタグの代替として活用できます。
"Condition": { "StringLike": { "xxxx:ResourceName": "app01_*" } }
ただし確認した限りでは、条件キーでリソース名を指定できるケースは非常に少ないようでしたので、あればラッキーくらいに考えておいたほうが良いかもしれません。
最終手段としては、Resource
ブロックに操作を許可するリソースのARNを全て書くことになりますが、リソースが追加されればポリシーも修正する必要があるので、できれば避けたいところですね。
"Resource": [ "arn:aws:cloudfront::123456789012:cache-policy/aaaa-aaaa-aaaa", "arn:aws:cloudfront::123456789012:cache-policy/bbbb-bbbb-bbbb", ... "arn:aws:cloudfront::123456789012:cache-policy/zzzz-zzzz-zzzz" ]
余談ですが、キャッシュポリシーに限って言うと、裏技的な方法でタグ制御することも可能です。
キャッシュ設定をキャッシュポリシーではなく「Legacy cache settings」で定義することで、「CloudFrontディストリビューションの一部」として扱うことができます。キャッシュ設定の一元管理というメリットは失われますが、これによりタグでの制御が効くようになりますので、このような回避案も手かと思います。
サンプルポリシー
先述の要件に対して設計したポリシーを、サンプルとして載せておきます。
{ "Version": "2012-10-17", "Statement": [ { "Sid": "AllowEC2Operations", "Effect": "Allow", "Action": [ "ec2:StartInstances", "ec2:StopInstances", "ec2:RebootInstances" ], "Resource": "*", "Condition": { "StringEquals": { "aws:ResourceTag/Application": "app01" } } }, { "Sid": "AllowAWSWAFOperations", "Effect": "Allow", "Action": [ "wafv2:*" ], "Resource": "*", "Condition": { "StringEquals": { "aws:ResourceTag/Application": "app01" } } }, { "Sid": "AllowCloudFrontOperations", "Effect": "Allow", "Action": [ "cloudfront:UpdateDistribution" ], "Resource": "*", "Condition": { "StringEquals": { "aws:ResourceTag/Application": "app01" } } } ] }
まとめ
タグで権限制御って簡単そうですけど、やってみると色々ハマりポイントはあるなーという感じでした。 最後までお付き合いいただきありがとうございました。
松田 渓(記事一覧)
2021年10月入社。散歩が得意です。