Automate the tagging of AWS resources using the AWS CLI
Why use tagging?. If your company has an Amazon Web Services (AWS) account hosting several different workloads, tagging helps you to catagories which workloads belong to which departments or cost centres within your organisation. Tagging increases the visibility into your actual AWS spend, broken down by project or third party supplier. If your AWS account is managed for you, then usually the management company will grant access to billing information through a web portal like Cloud Health. Products like Cloud Health use these tags to drive and populate the various dashboards and charts.
Tagging Best Practices
AWS have published a PDF file which outlines some tagging best practices. The main takeaways are:
- Use tags consistently
- Use automation
- Define a corporate minium standard for tags which are required
- Start small; less is more
- Standardize names for AWS resources
- Regularly audit resources that aren’t tagged
As a minimum requirement I’d recommend starting with the following tagging strategy.
- Name — The name of the AWS resource
- Workload — The common name of the workload or project as known internally within your organisation
- Owner — The name of the department or budget code that is responsible for funding the workload
- Environment — Used to distinguish between production, testing and development environments
- Criticality — To assist a management company understand the importance of the different workloads. For example, Tier 1, Tier 2.
For me, the most important best practices is using tags consistently. To ensure consistency across your cloud infrastructure make use of the tagging capabilities of your infrastructure as code DevOps pipeline. Using an infrastructure provisioning tool like Terraform or AWS’s own Cloud Development Kit allows you to enforce such consistency.
However, what about if you’ve built the AWS resources manually through the AWS web console?.
Luckily it’s not too late to take back control of tagging your resources. Sure it will take a bit of work, auditing and a commitment from your staff to implement; but the benefits to understanding your costs will be the reward. If you find yourself in this situation then the AWS Command Line Interface (CLI) makes a good choice.
Using AWS CLI
The Command Line Interface is a unified tool to manage your AWS services. With just one tool to download and configure, you can control multiple AWS services from the command line and automate them through scripts. There are versions for Windows, Linux and MacOS and there are clear instructions on how to install the tool for your operating system of choice.
The fact it can be automated through scripts makes it ideal for tagging existing resources. Once you’ve invested the time to write a tagging script for each workload it becomes trivial to then reassign a tag value. A typical web application workload could contain many resources, upwards of a hundred, depending on the complexity of the architecture. Let’s say the owner tag needed to be changed from one department to another. Changing each and every resource manually through the web console would be hard and you’re almost guaranteed to lose consistency. By using a script like the one shown below, you can change the owner tag once and then let the script do it’s magic.
Likewise, if you wanted to add a completely new tag, you’d add it to the start of the script and then deploy to update all your resources.
The script shown below is commented and shows the slight differences in adding tags to the different services. It covers typical things like application load balancers, TLS certificates, EC2 instances, RDS databases, VPC items and Lambda functions.
However, if you need any help in using or defining such a script then please get in touch.
Example CLI Tagging Script
# define reuseable variables region = --region eu-west-2 profile = --profile tag-deployment acmbase = arn:aws:acm:eu-west-2:0123456789:certificate/ lambdabase = arn:aws:lambda:eu-west-2:0123456789:function: # define common required tags tagkeys = Key=Workload,Value="WebApp" Key=Owner,Value=Finance Key=Criticality,Value="Tier 2" Key=Environment,Value=Pre-Production lambdatags = Workload=WebApp,Owner=Finance,Criticality=Tier 2,Environment=Pre-Production taggall: alb acm ec2 lambdas alb: # tag application load balancer aws elbv2 add-tags --resource-arns arn:aws:elasticloadbalancing:eu-west-2:0123456789:loadbalancer/app/web-application-alb/c1c7bf58295e65d4 --tags Key=Name,Value=web-application-alb $(tagkeys) $(region) $(profile) acm: # tag the TLS certificate in Certificate Manager aws acm add-tags-to-certificate --certificate-arn $(acmbase)e414b365-8517-4203-884d-67653e098c18 --tags Key=Name,Value=finance.domain.com $(tagkeys) $(region) $(profile) rds: # tag the RDS database aws rds add-tags-to-resource --resource-name arn:aws:rds:eu-west-2:747808398410:cluster:finance-database --tags Key=Name,Value=finance-database $(tagkeys) $(region) $(profile) vpc: # tag VPC items such as VPC endpoints, Transit Gateways, NAT's, ACL's aws ec2 create-tags --resources vpce-07208a942196187dd --tags Key=Name,Value=web-application-ssm $(tagkeys) $(region) $(profile) aws ec2 create-tags --resources nat-005e8420d36be9722 --tags Key=Name,Value=web-application-ngw $(tagkeys) $(region) $(profile) aws ec2 create-tags --resources acl-031742aa66305a8c2 --tags Key=Name,Value=web-application-acl $(tagkeys) $(region) $(profile) aws ec2 create-tags --resources tgw-attach-0f2c3b9b89fcdae35 --tags Key=Name,Value=web-application-tgw $(tagkeys) $(region) $(profile) aws ec2 create-tags --resources vgw-0ba9f36b042d9d2d2 --tags Key=Name,Value=web-application-vgw $(tagkeys) $(region) $(profile) ec2: # tag ec2 servers and their attached ebs volumes (disks) aws ec2 create-tags --resources i-0f385fbcd41fa358e vol-051cea7bb5e03bd5e --tags Key=Name,Value=web-app-a $(tagkeys) $(region) $(profile) aws ec2 create-tags --resources i-0e603c118516a1f24 vol-0336ecd1334b85190 --tags Key=Name,Value=web-app-b $(tagkeys) $(region) $(profile) lambdas: # tag all serverless functions aws lambda tag-resource --resource $(lambdabase)web-app-assets --tags "Name=web-app-assets,$(lambdatags)" $(region) $(profile) aws lambda tag-resource --resource $(lambdabase)web-app-authentication --tags "Name=web-app-authentication,$(lambdatags)" $(region) $(profile)