when calling the CreateStack operation: Requires capabilities : [CAPABILITY_IAM]エラーの対応

lambdaの使い方を習得するために、lambdaのハンズオン資料を元に勉強しています。
CloudFormationの勉強も兼ねているので、構築の部分も兼ねて実施しているのですが題記のエラーが出てしまいました。
解決したのでその時の内容を記録します。

この記事で得られる事

  • CloudFormationで「AWS::IAM::Role」Typeのリソースを追加した時に発生する、題記のエラーの解決方法がわかる。

イントロダクション

参考資料、および、構成

下記のスライドを参考に実装しています。
構成についても書いている内容と同じにします。

www.slideshare.net

今回作成したソースについて

github.com

対象のバージョンはv0.1です。

事象

下記の様に、lambdaを許可するロールを追加するリソースを追加。

"Resources": {
    "ExecRole": {
        "Type": "AWS::IAM::Role",
        "Properties": {
            "AssumeRolePolicyDocument": {
                "Version" : "2012-10-17",
                "Statement": [ {
                    "Effect": "Allow",
                    "Principal": {
                        "Service": [ "lambda.amazonaws.com" ]
                    },
                    "Action": [ "sts:AssumeRole" ]
                } ]
            },
            "Path": "/",
        }
    }
}

CloudFormationでスタックを作ろうとすると、エラーが発生します。

$ aws cloudformation create-stack \
    --stack-name myteststack \
    --template-body file://cloudformation.json \
    --capabilities CAPABILITY_IAM
when calling the CreateStack operation: Requires capabilities : [CAPABILITY_IAM]

解決策

公式ドキュメントのAWS Identity and Access Management によるアクセスの制御で次の様に記載されています。

CLI で、aws cloudformation create-stack および aws cloudformation update-stack コマンドを使用する場合は、--capabilities パラメーターに CAPABILITY_IAM または CAPABILITY_NAMED_IAM 値を指定します。テンプレートに IAM リソースがある場合、いずれかの機能を指定できます。テンプレートの IAM リソースにカスタム名がある場合、CAPABILITY_NAMED_IAM を指定する必要があります。

よって、オプションに--capabilities CAPABILITY_IAMを追加します。

$ aws cloudformation create-stack \
    --stack-name myteststack \
    --template-body file://cloudformation.json \
    --capabilities CAPABILITY_IAM

Tips

どうしてcapabilitiesが必要なのか?

公式ドキュメントには次の様に記載されています。

Capabilities.member.N
AWS CloudFormationで特定のスタックを作成する前に指定する必要がある値のリスト。
いくつかのスタックテンプレートには、新しいAWS Identity and Access Management(IAM)ユーザーを作成するなど、AWSアカウントのアクセス許可に影響するリソースが含まれている場合があります。
これらのスタックの場合、このパラメータを指定することによって、明示的にその機能を確認する必要があります。

(曖昧な回答で恐縮ですが)この内容からAWSのアカウントに接続する際のセキュリティの意味を込めているのだと思われます。
「いくつかのスタックテンプレート」というの中にAWS::IAM::Roleが含まれています。
それは次に続きます。

IAMリソースがある場合は、いずれかの機能を指定できます。
カスタム名のIAMリソースがある場合は、指定する必要がありますCAPABILITY_NAMED_IAM。
このパラメーターを指定しない場合、このアクションはInsufficientCapabilities エラーを戻します。

今回、作成するテンプレートでは、ExecRoleUploaerリソースのType属性に「AWS::IAM::Role」と設定しています。 つまり、このTypeのリソースは対象になります。

CAPABILITY_IAMとCAPABILITY_NAMED_IAMの違い

上記の項の説明には下記と書いてあります。

カスタム名のIAMリソースがある場合は、指定する必要がありますCAPABILITY_NAMED_IAM。

例えば、Type属性が「AWS::IAM::Role」だった場合は、リソースにRoleName属性を付与したときに対象になります。

"ExecRoleUploaer": {
    "Type": "AWS::IAM::Role",
    "RoleName": "ロール名"
},

それは、AWS::IAM::RoleのドキュメントのRoleNameの中で明言されています。

名前を指定した場合、テンプレートの機能を承認するために CAPABILITY_NAMED_IAM 値を指定する必要があります。