General
Return values of !Ref and !GetAtt are not consistent
Depending upon the used resource, !Ref
and !GetAtt
do return the Name
property, as well as the Arn
:
Service | !Ref | !GetAtt |
---|---|---|
AWS::ECS::Cluster | Name | Arn |
AWS::ECS::Service | Arn | Name |
AWS::ECS::TaskDefinition | Arn | none |
A full list can be found in the !Ref and !GetAtt cheatsheet.
Stacks
Export a list as output and import the list in another stack.
If you need to export a list of resource identifiers, e.g. all subnets of a VPC, as an output in one stack, you can join the subnets:
# environment-stack.yaml
Resources:
# ....
Outputs:
AllSubnets:
Description: All subnets
Value: !Join
- ','
- !GetAtt [ MyVpc, Subnets ]
Export:
Name: !Sub "${AWS::StackName}-AllSubnets"
In your other stack, you can then import the output with the following definition:
# other-stack.yaml
Parameters:
EnvironmentStackName:
Description: "Name of the stack containing VPC, subnets etc."
Type: String
Default: "environment
Resources:
MyCodeBuildProject:
Type: AWS::CodeBuild::Project
VpcConfig:
Subnets:
Fn::Split:
- ","
- Fn::ImportValue:
!Sub "${EnvironmentStackName}-AllSubnets"
Exporting the first entry of a list and referencing it
If you just need the first entry of a list, e.g. the first subnet, you can use the following definition:
# environment-stack.yaml
Resources:
# ....
Outputs:
FirstSubnet:
Description: First subnet
Value: !Select [0, !GetAtt [MyVpc, Subnets]]
Export:
Name: !Sub "${AWS::StackName}-FirstSubnet"
It can then be referenced in the other stack with
# other-stack.yaml
Resources:
MyLambda:
Type: AWS::Lambda::Function
Properties:
VpcConfig:
SubnetIds:
- !ImportValue
'Fn::Sub': '${EnvironmentStackName}-FirstSubnet'
CodeBuild and CodePipeline
Pushing a Docker image into ECR with CodeBuild
If you are using CodeBuild to push a Docker image into ECR, you have set the PrivilegedMode
setting to true
. Otherwise, you'll receive the message
Cannot connect to the Docker daemon at unix:/var/run/docker.sock. Is the docker daemon running?
Resources:
MyBuildProject:
Type: AWS::CodeBuild::Project
Properties:
Name: "my-project"
Environment:
# We need the PrivilegedMode, otherwise the Docker daemon would not be accessible to pull and push the images
PrivilegedMode: true
In addition to that, you need the correct permissions for the CodeBuild service role. If you don't have the permissions, the docker daemon might hang during pulling or pushing the image.
Resources:
MyRepository:
Type: AWS::ECR::Repository
Properties:
ImageTagMutability: IMMUTABLE
RepositoryName: "my-docker-image"
MyBuildProject:
Type: AWS::CodeBuild::Project
ServiceRole: !GetAtt [MyCodeBuildRole, Arn]
MyCodeBuildRole:
Type: AWS::IAM::Role
Properties:
Policies:
- PolicyDocument:
Statement:
# Allow CodePipeline to update the ECRs
- Action:
- ecr:GetDownloadUrlForLayer
- ecr:BatchGetImage
- ecr:CompleteLayerUpload
- ecr:DescribeImages
- ecr:DescribeRepositories
- ecr:UploadLayerPart
- ecr:ListImages
- ecr:InitiateLayerUpload
- ecr:BatchCheckLayerAvailability
- ecr:PutImage
Effect: Allow
Resource:
Fn::Join:
- ""
- - !Sub 'arn:aws:ecr:${AWS::Region}:${AWS::AccountId}:repository'
- "/my-docker-image"
- "/*"
"Insufficient permissions. The provided role does not have sufficient permissions to access ECS"
The error occurs during a CodePipeline build when executing an ECS deployment action. The role of the CodePipeline must allow the permission iam:PassRole
in its PolicyDocument
:
Resources:
# region CodeBuild
CodePipelineRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
# ....
Path: /
Policies:
- PolicyDocument:
Statement:
- Action:
- iam:PassRole
Effect: Allow
Resource: '*'
Lambda
The provided execution role does not have permissions to call DescribeNetworkInterfaces on EC2
The error The provided execution role does not have permissions to call DescribeNetworkInterfaces on EC2
occurs, if your Lambda's service is attached to a VPC and is missing the required ec2:*
permissions.
Resources:
MyLambda:
Type: AWS::Lambda::Function
Properties:
Role: !GetAtt [ MyLambdaRole, Arn ]
MyLambdaRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Action:
- sts:AssumeRole
Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Policies:
- PolicyDocument:
Statement:
- Action:
- ec2:CreateNetworkInterface
- ec2:DeleteNetworkInterface
- ec2:DescribeNetworkInterfaces
Resource: '*'
Effect: Allow
Version: '2012-10-17'