I was editing my CloudFormation templates and suddenly AWS tells me I need CAPABILITY_NAMED_IAM
. I am curious as to which change triggers this?
What is a named IAM resource?
Before I already "name" my resources like
RoleName: !Sub '${PipelineName}-codebuild'
I am not asked to add this capability, I think until I add
Parameters:
AppName:
Type: String
Description: Prefix for resources
Resources:
LambdaRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Ref AppName
To my SAM application template. But arent they the "same" except one uses !Ref
? Or maybe some other change triggered this?
For reference, my CodePipeline stack
AWSTemplateFormatVersion : '2010-09-09'
Description: 'Skynet stack for CodePipeline'
Parameters:
PipelineName:
Type: String
Description: Pipeline Name (Lower case only, since S3 bucket names can only have lowercase)
Default: skynet-pipeline
GitHubOwner:
Type: String
Description: GitHub Owner
Default: 2359media
GitHubRepo:
Type: String
Description: GitHub Repo
Default: 'skynet'
GitHubBranch:
Type: String
Description: GitHub Branch
Default: master
GitHubToken:
Type: String
Description: GitHub Token
NoEcho: true
Resources:
Pipeline:
Type: AWS::CodePipeline::Pipeline
Properties:
Name: !Ref PipelineName
RoleArn: !GetAtt [PipelineRole, Arn]
ArtifactStore:
Location: !Ref PipelineArtifactStore
Type: S3
DisableInboundStageTransitions: []
Stages:
- Name: GitHubSource
Actions:
- Name: Source
ActionTypeId:
Category: Source
Owner: ThirdParty
Version: 1
Provider: GitHub
Configuration:
Owner: !Ref GitHubOwner
Repo: !Ref GitHubRepo
Branch: !Ref GitHubBranch
OAuthToken: !Ref GitHubToken
OutputArtifacts:
- Name: SourceCode
- Name: Build
Actions:
- Name: Lambda
InputArtifacts:
- Name: SourceCode
OutputArtifacts:
- Name: LambdaPackage
ActionTypeId:
Category: Build
Owner: AWS
Version: 1
Provider: CodeBuild
Configuration:
ProjectName: !Ref CodeBuildLambda
- Name: CreateChangeSet
Actions:
- Name: Lambda
InputArtifacts:
- Name: LambdaPackage
OutputArtifacts:
- Name: LambdaDeployment
ActionTypeId:
Category: Deploy
Owner: AWS
Version: 1
Provider: CloudFormation
Configuration:
ActionMode: CHANGE_SET_REPLACE
ChangeSetName: !Sub
- '${PipelineName}-lambda'
- {PipelineName: !Ref PipelineName}
RoleArn: !GetAtt [CloudFormationRole, Arn]
StackName: !Sub
- '${PipelineName}-lambda'
- {PipelineName: !Ref PipelineName}
TemplatePath: 'LambdaPackage::SkynetLambdaPackaged.yml'
Capabilities: CAPABILITY_NAMED_IAM
ParameterOverrides: !Sub '{"AppName": "${PipelineName}-lambda"}'
- Name: ExecuteChangeSet
Actions:
- Name: Lambda
ActionTypeId:
Category: Deploy
Owner: AWS
Version: 1
Provider: CloudFormation
Configuration:
ActionMode: CHANGE_SET_EXECUTE
ChangeSetName: !Sub
- '${PipelineName}-lambda'
- {PipelineName: !Ref PipelineName}
StackName: !Sub
- '${PipelineName}-lambda'
- {PipelineName: !Ref PipelineName}
CodeBuildLambda:
Type: AWS::CodeBuild::Project
Properties:
Name: !Sub '${PipelineName}-lambda'
Artifacts:
Type: CODEPIPELINE
Environment:
ComputeType: BUILD_GENERAL1_SMALL
Image: aws/codebuild/nodejs:7.0.0
Type: LINUX_CONTAINER
EnvironmentVariables:
- Name: S3_BUCKET
Value: !Ref PipelineArtifactStore
ServiceRole: !Ref CodeBuildRole
Source:
BuildSpec: 'lambda/buildspec.yml'
Type: CODEPIPELINE
PipelineArtifactStore:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub '${PipelineName}-artifacts'
VersioningConfiguration:
Status: Enabled
CodeBuildRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub '${PipelineName}-codebuild'
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
Effect: Allow
Principal:
Service: codebuild.amazonaws.com
Action: sts:AssumeRole
Policies:
- PolicyName: !Sub '${PipelineName}-codebuild'
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Resource: 'arn:aws:logs:*:*:*'
Action:
- 'logs:CreateLogGroup'
- 'logs:CreateLogStream'
- 'logs:PutLogEvents'
- Effect: Allow
Resource:
- !Sub 'arn:aws:s3:::codepipeline-${AWS::Region}-*/*'
- !Sub
- '${PipelineArtifactStoreArn}/*'
- {PipelineArtifactStoreArn: !GetAtt [PipelineArtifactStore, Arn]}
Action:
- 's3:GetObject'
- 's3:GetObjectVersion'
- 's3:PutObject'
CloudFormationRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub '${PipelineName}-cloudformation'
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service: cloudformation.amazonaws.com
Action:
- sts:AssumeRole
ManagedPolicyArns:
- 'arn:aws:iam::aws:policy/AWSLambdaExecute'
Policies:
- PolicyName: !Sub '${PipelineName}-cloudformation'
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Resource: '*'
Action:
- 's3:GetObject'
- 's3:GetObjectVersion'
- 's3:GetBucketVersioning'
- Effect: Allow
Resource: 'arn:aws:s3:::codepipeline*'
Action:
- 's3:PutObject'
- Effect: Allow
Resource: !Sub 'arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:*'
Action:
- 'lambda:*'
- Effect: Allow
Resource: !Sub 'arn:aws:apigateway:${AWS::Region}::*'
Action:
- 'apigateway:*'
- Effect: Allow
Resource: '*'
Action:
- 'lambda:CreateEventSourceMapping'
- 'lambda:DeleteEventSourceMapping'
- 'lambda:GetEventSourceMapping'
- Effect: Allow
Resource: '*'
Action:
- 'iam:GetRole'
- 'iam:CreateRole'
- 'iam:DeleteRole'
- 'iam:PassRole'
- 'iam:AttachRolePolicy'
- 'iam:DetachRolePolicy'
- 'iam:DeleteRolePolicy'
- 'iam:PutRolePolicy'
- Effect: Allow
Resource: '*'
Action:
- 'iam:PassRole'
- Effect: Allow
Resource: !Sub 'arn:aws:cloudformation:${AWS::Region}:aws:transform/Serverless-2016-10-31'
Action:
- 'cloudformation:CreateChangeSet'
PipelineRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub '${PipelineName}-pipeline'
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Action: ['sts:AssumeRole']
Effect: Allow
Principal:
Service: [codepipeline.amazonaws.com]
Path: /
Policies:
- PolicyName: SkynetPipeline
PolicyDocument:
Version: '2012-10-17'
Statement:
- Action:
- 's3:GetObject'
- 's3:GetObjectVersion'
- 's3:GetBucketVersioning'
Effect: 'Allow'
Resource: '*'
- Action:
- 's3:PutObject'
Effect: 'Allow'
Resource:
- !GetAtt [PipelineArtifactStore, Arn]
- Action:
- 'codecommit:CancelUploadArchive'
- 'codecommit:GetBranch'
- 'codecommit:GetCommit'
- 'codecommit:GetUploadArchiveStatus'
- 'codecommit:UploadArchive'
Effect: 'Allow'
Resource: '*'
- Action:
- 'codedeploy:CreateDeployment'
- 'codedeploy:GetApplicationRevision'
- 'codedeploy:GetDeployment'
- 'codedeploy:GetDeploymentConfig'
- 'codedeploy:RegisterApplicationRevision'
Effect: 'Allow'
Resource: '*'
- Action:
- 'elasticbeanstalk:*'
- 'ec2:*'
- 'elasticloadbalancing:*'
- 'autoscaling:*'
- 'cloudwatch:*'
- 's3:*'
- 'sns:*'
- 'cloudformation:*'
- 'rds:*'
- 'sqs:*'
- 'ecs:*'
- 'iam:PassRole'
Effect: 'Allow'
Resource: '*'
- Action:
- 'lambda:InvokeFunction'
- 'lambda:ListFunctions'
Effect: 'Allow'
Resource: '*'
- Action:
- 'opsworks:CreateDeployment'
- 'opsworks:DescribeApps'
- 'opsworks:DescribeCommands'
- 'opsworks:DescribeDeployments'
- 'opsworks:DescribeInstances'
- 'opsworks:DescribeStacks'
- 'opsworks:UpdateApp'
- 'opsworks:UpdateStack'
Effect: 'Allow'
Resource: '*'
- Action:
- 'cloudformation:CreateStack'
- 'cloudformation:DeleteStack'
- 'cloudformation:DescribeStacks'
- 'cloudformation:UpdateStack'
- 'cloudformation:CreateChangeSet'
- 'cloudformation:DeleteChangeSet'
- 'cloudformation:DescribeChangeSet'
- 'cloudformation:ExecuteChangeSet'
- 'cloudformation:SetStackPolicy'
- 'cloudformation:ValidateTemplate'
- 'iam:PassRole'
Effect: 'Allow'
Resource: '*'
- Action:
- 'codebuild:BatchGetBuilds'
- 'codebuild:StartBuild'
Effect: 'Allow'
Resource: '*'
The part of SAM stack (sam.yml
) changed recently
AWSTemplateFormatVersion : '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: 'Skynet. AWS Management Assistant'
Parameters:
AppName:
Type: String
Description: Prefix for resources
Resources:
LambdaRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Ref AppName
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
- apigateway.amazonaws.com
Action:
- sts:AssumeRole
ManagedPolicyArns:
- 'arn:aws:iam::aws:policy/AmazonEC2FullAccess'
- 'arn:aws:iam::aws:policy/AWSLambdaFullAccess'
- 'arn:aws:iam::aws:policy/AWSXrayWriteOnlyAccess'
- 'arn:aws:iam::aws:policy/AmazonAPIGatewayInvokeFullAccess'
- 'arn:aws:iam::aws:policy/CloudWatchLogsFullAccess'
When are CAPABILITY_IAM
/CAPABILITY_NAMED_IAM
Required
According to CloudFormation CreateStack Parameters, one of these is required when your Template includes any of the following resource types:
AWS::IAM::AccessKey
AWS::IAM::Group
AWS::IAM::InstanceProfile
AWS::IAM::Policy
AWS::IAM::Role
AWS::IAM::User
AWS::IAM::UserToGroupAddition
When to use CAPABILITY_NAMED_IAM
instead of CAPABILITY_IAM
When any of your IAM resources have a custom name, such as a RoleName
then CAPABILITY_NAMED_IAM
is required.
Why are these required?
The Capabilities are there to ensure you realize that you're creating IAM resources, that these will modify the permissions on your account, and that you have reviewed these resources and their permissions as necessary.
You've added a resource of type AWS::IAM::Role to your resources section. This tells CloudFormation to create an IAM Role. In order to create IAM resources, you need to supply CAPABILITY_IAM or CAPABILITY_NAMED_IAM. It's an acknowledgement from you to CloudFormation that you understand that you are creating resources that can affect permissions in your AWS account.
Note on use of CAPABILITY_NAMED_IAM vs CAPABILITY_IAM:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With