AWS resources tagging using Serverless framework
An explanation about how AWS resources can be tagged using the Serverless framework. Code sample is available in GitHub.
Resources tagging is an important mechanism in the AWS ecosystem. They can be used for DevOps automation and cost allocation, among other things. A tag is a pair of key and value that can assigned to most resources. A resource can have a maximum of 50 tags. AWS automatically assigns some tags with aws:
prefix.
Whilst you work with the Serverless framework to develop a solution for AWS, the framework provisions the resources on your behalf. Some of those resources are provisioned explicitly, i.e. as a result of CloudFormation script inside the resources
section of serverless.yml
. Other resources are provisioned implicitly, as part of the conventional abstraction of the framework, e.g. API Gateway, Lambda, S3 bucket used for deployment.
Serverless framework gives you full control when it comes to tagging both explicit and implicit resources by updating the serverless.yml
configuration file. Different methods are explained as follows:
1. Using provider.stackTags
All the tags specified under provider.stackTags
section will be:
- Applied to the stack which contains all the resources that the framework will create for a service
- Applied to most of the resources created directly or indirectly by the framework. The reason it’s most and not all is detailed in the last section of this article.
This is the place you should use to tag your resources. It is centralised in one place and is cascaded down to most resources.
provider:
stackTags:
stackTag1: value1
stackTag2: value2
2. Using provider.tags
The provider.tags
node provides a quick way to tag those resources. All tags specified under this node will be applied to all those API Gateway’s APIs and Lambdas.
provider:
tags:
provTag1: value1
provTag2: value2
3. Using provider.deploymentBucket.tags
This node is only used to tag the S3 bucket that the framework uses to deploy code to AWS.
provider:
deploymentBucket:
tags:
depBucketTag1: value1
depBucketTag2: value2
4. Using tags property for each function
Each function declaration in serverless.yml
has a tags node. Those tags will be applied for the Lambda but not the API Gateway’s API.
functions:
hello:
handler: handler.hello
tags:
funcTag1: value1
5. Tags property in CloudFormation
For resources created explicitly inside serverless.yml, you can make uses of CloudFormation syntax to tag them individually.
For example, an S3 bucket:
resources:
Resources:
s3Bucket:
Type: AWS::S3::Bucket
Properties:
Tags:
- Key: directS3Tag1
Value: value1
- Key: directS3Tag2
Value: value2
or a DynamoDB table:
resources:
Resources:
dynamodbTable:
Type: AWS::DynamoDB::Table
Properties:
BillingMode: PAY_PER_REQUEST
AttributeDefinitions:
- AttributeName: postcode
AttributeType: S
KeySchema:
- AttributeName: postcode
KeyType: HASH
Tags:
- Key: directDdbTag1
Value: value1
- Key: directDdbTag2
Value: value2
6. Some exceptions
AWS Cognito’s CloudFormation syntax for tagging is weird. Firstly, it’s under UserPoolTags
property, instead of the usual Tags
for other resources. Secondly, the input value must be a JSON value inside YAML 🤦♂.
The provider.stackTags
does not apply to AWS Cognito. It’s likely to be a 🐛 that can be mitigated by writing extra CloudFormation as follows:
resources:
Resources:
UserPool3:
Type: AWS::Cognito::UserPool
DeletionPolicy: Delete
Properties:
UserPoolTags:
{
"directPoolTag1": "value",
"directPoolTag2": "value"
}
UserPoolClient does not even support tagging at all.
The most likely explanation for the exceptions is the AWS engineering team ran out of time whilst developing the feature and the adoption of Cognito has yet been widespread enough to justify the additional development efforts.