特定のCloudFormationスタック名のみに操作を制限するIAMポリシーを試してみた

2024.02.07

はじめに

CloudFormation スタックの操作に対し、特定のスタック名のみ操作権限を与えたいケースがあったので試してみました。 以下のドキュメントを参考に実際に正しく制御できているか確認してみます。

AWS Identity and Access Management によるアクセスの制御 - AWS CloudFormation

作成したポリシー

特定のスタック名に対し削除権限を持つポリシーは以下の通りです。Action のDeleteStackの部分を変更すれば、作成、更新についても制御可能です。 <region><account-id>については環境に併せて変更してください。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": "cloudformation:DeleteStack",
            "Resource": "arn:aws:cloudformation:ap-northeast-1:914661484899:stack/cm-test-stack/*",
            "Effect": "Allow"
        },
        {
            "Action": [
                "ec2:DeleteVpc",
                "ec2:DescribeVpcs"
            ],
            "Resource": "*",
            "Effect": "Allow"
        }
    ]
}

今回はテストで削除するスタックは VPC を作成しているため、削除に必要なec2:DeleteVpcec2:DescribeVpcsの権限を追加しています。この権限がないと、スタック削除の実行はできてもエラーとなります。

やってみる

作成したポリシーを作成、アタッチして動作の確認をしてみます。

ポリシーとロールの作成

操作を制限する IAM ロールとポリシーは以下のテンプレートで作成しました。

AWSTemplateFormatVersion: "2010-09-09"
Description: "IAM Role with Policy to Allow Deletion of a Specific CloudFormation Stack and ReadOnly Access"

Resources:
  MyIAMRole:
    Type: "AWS::IAM::Role"
    Properties:
      RoleName: "RoleWithCFNDeleteStackPermission"
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              AWS: !Sub "arn:aws:iam::${AWS::AccountId}:root"
            Action:
              - "sts:AssumeRole"
      Policies:
        - PolicyName: "DeleteSpecificCFNStackPolicy"
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Action: "cloudformation:DeleteStack"
                Resource: !Sub "arn:aws:cloudformation:${AWS::Region}:${AWS::AccountId}:stack/cm-test-stack/*"
              - Effect: Allow
                Action: 
                 - "ec2:DeleteVpc"
                 - "ec2:DescribeVpcs"
                Resource: "*"

削除のテスト

まずは正常に削除できるか確認してみます。

VPC のみを作成する CFn スタックを作成し、スタック名にはcm-test-stackと付けます。

先ほど作成した IAM ロールにスイッチします。スイッチは以下のコマンドで実施します。{AccountId}{RoleName}は適宜置き換えてください。{SessionName}は任意のものでOKです。

eval $(aws sts assume-role --role-arn "arn:aws:iam::{AccountId}:role/{RoleName}" --role-session-name "{SessionName}" --query 'Credentials.[AccessKeyId,SecretAccessKey,SessionToken]' --output text | awk '{print "export AWS_ACCESS_KEY_ID="$1"\nexport AWS_SECRET_ACCESS_KEY="$2"\nexport AWS_SESSION_TOKEN="$3}')

スタックを削除してみます。

aws cloudformation delete-stack --stack-name cm-test-stack

レスポンスは何も返ってきませんが、コンソールを見ると cm-test-stack が削除されています。

次に他のスタックが削除できないことを確認しましょう。

同じように VPC のみを作成するcm-test-stack2というスタックを作成して、これを対象に削除コマンドを実行してみました。

$ aws cloudformation delete-stack --stack-name cm-test-stack2

An error occurred (AccessDenied) when calling the DeleteStack operation: User: arn:aws:sts::111111111111:assumed-role/RoleWithCFNDeleteStackPermission/CFNDeleteStackSession is not authorized to perform: cloudformation:DeleteStack on resource: arn:aws:cloudformation:ap-northeast-1:111111111111:stack/cm-test-stack2/18dafde0-c573-11ee-8092-0a2b5f946e19 because no identity-based policy allows the cloudformation:DeleteStack action

想定通り、スタック名が一致していないため、AccessDenied となります。これで特定のスタックのみを削除できることが確認できました。

スタック名の制限を部分一致にしてみる

ふとスタック名の部分一致でも制御できるか気になったので試してみます。 スタック名を制御している Resource で*をスタック名の後につけてみました。

]
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "cloudformation:DeleteStack",
            "Resource": "arn:aws:cloudformation:<region>:<account-id>:stack/cm-test-stack*/*"
        }
    ]
}

試しにcm-test-stack2を削除すると、問題なく成功します。

aws cloudformation delete-stack --stack-name cm-test-stack2

スタック名の部分一致も問題ないようなので、命名規則でスタックを運用するケースにも対応できそうです。

まとめ

特定の CloudFormation スタック名のみに操作を制限する IAM ポリシーを試してみました。

注意点としては、スタックに対する操作権限(DeleteStack等)に加えて、操作対象のスタックに含まれるリソースに対する権限も必要な点を押さえておきましょう。