AWS pseudo parameters
What makes these parameters special? Well, the fact that they are obtained from AWS itself.
The current list of these parameters is as follows:
- AWS::AccountId
- AWS::NotificationARNs
- AWS::NoValue
- AWS::Region
- AWS::StackId
- AWS::StackName
- AWS::URLSuffix
- AWS::Partition
We're not going to cover all of them, only the most widely used ones.
AWS::AccountId
One of the use cases where we need to use AccountId is when we are using an IAM principal.
If you are familiar with IAM, then you know that we can set the AWS account ID as a principal element. If you need to refresh your memory regarding IAM, you can read a great blog series at https://medium.com/@thomas.storm/aws-iam-deep-dive-chapter-1-essentials-a9cfb1931a01.
At the same time, it is dangerous to expose your AWS account ID; we should always stick to using AWS pseudo parameters when we specify this kind of sensitive information.
An example usage of AWS::AccountId is as follows:
Resources:
MyIamRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- sts:AssumeRole
Principal:
AWS: !Ref "AWS::AccountId"
Sid: "AllowRoleAssume"
# The rest of the IAM role properties...
As with any other parameter, pseudo parameters can be used in conjunction with intrinsic functions. The following is an example (you probably remember it from Chapter 1, CloudFormation Refresher) where we specify all users within an account in Principal:
MyIamRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Sid: AllowAssumeRole
Effect: Allow
Principal:
AWS:
- !Join
- ""
- - "arn:aws:iam::"
- !Ref "AWS::AccountId"
- ":user/${aws.username}"
Action: "sts:AssumeRole"
Note the ${aws.username} variable. This variable is not a part of CloudFormation, but a part of IAM policy variables.
When we initiate stack deployment, CloudFormation will replace the pseudo parameter with an actual value. For AWS::AccountId, the value will be the account where the stack is being created.
AWS::NoValue
The AWS::NoValue phrase is an equivalent of the null value. There is not much practical usage for it, unless you want to combine it with conditional functions. It is important to know that if you supply your resource property with AWS::NoValue, it will act as if you hadn't specified this property at all.
One use case of this would be using it to create a database from a snapshot or from scratch:
Resources:
MyDB:
Type: AWS::RDS::DBInstance
Properties:
AllocatedStorage: "5"
DBInstanceClass: db.t3.micro
Engine: MySQL
EngineVersion: "5.7"
DBSnapshotIdentifier:
Fn::If:
- UseDBSnapshot
- Ref: DBSnapshotName
- Ref: AWS::NoValue
In the last few lines, we can see that if the condition is not met, then the DBSnapshotIdentifier property will not be used.
AWS::Region
Some resources require you to specify the AWS region. Hardcoding the region might not be a security issue, but will cause us trouble when we deploy the same stack in different regions. It is a best practice to use this pseudo parameter, even if you don't plan to deploy multi-regional applications.
For example, when we create an ECS task definition and want to use CloudWatch logs as a log driver, we need to specify a log group and AWS region:
Resources:
EcsTaskDefinition:
Type: AWS::ECS::TaskDefinition
Properties:
# Some properties...
ContainerDefinition:
- Name: mycontainer
# Some container properties...
LogConfiguration:
LogDriver: awslogs
Options:
awslogs-group: myloggroup
awslogs-region: !Ref "AWS::Region"
awslogs-stream-prefix: ""
When this stack is created, CloudFormation will create a CloudWatch log group in the same region where the stack resources were provisioned.
AWS::StackId and AWS::StackName
The AWS::StackId and AWS::StackName pseudo parameters are handy when you need to specify tags for your resources. An example usage is giving an application name to the name of the stack and reusing it in Tags:
Resources:
SomeResource:
Type: # any, that supports tags
Properties:
# Some properties..
Tags:
- Key: Application
Value: !Ref "AWS::StackName"
Referring to AWS::StackName in the Tags value will indicate the CloudFormation stack that this resource belongs to.
AWS::URLSuffix
The AWS::URLSuffix pseudo parameter is needed for specifying AWS URLs. In 99% of cases, it's going to be amazonaws.com, but if you plan to deploy your application to a special region, such as China or AWS GovCloud, you will have to use their own URL suffixes.
You need a URL suffix for services such as IAM roles if this role has to be assumed by AWS—for instance, ECS's task execution role:
Resources:
EcsTaskExecutionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Sid: AllowAssumeRole
Effect: Allow
Principal:
Service: !Join ["." [ "ecs-tasks",!Ref "AWS::URLSuffix" ] ]
Action: "sts:AssumeRole"
# Some role properties...
Using pseudo parameters will make your template recyclable and flexible. If you have to deploy your application in another region or even account, the amount of refactoring will be minimal.
AWS::Partition
When we need to define an ARN of the resource manually, we often write it in the following manner: arn:aws:service:region:account_id:...
The word aws here refers to a partition – which we can refer to as a namespace. For most of the cases, you will see "aws", but you want to know that there are other partitions as well. For example, regions in China have a partition aws-cn, and GovCloud regions have a partition aws-us-gov.
This said, let's continue with another important topic – dynamic referencing in the templates.
Let's move on to the last bit of this chapter, which is about using dynamic references for your stacks with AWS SSM Parameter Store and AWS Secrets Manager.