Automate the tagging of AWS resources using the AWS CLI

by Hadley Bradley


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:

As a minimum requirement I’d recommend starting with the following tagging strategy.

Using Automation

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.


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

    # 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)

    # tag the TLS certificate in Certificate Manager
    aws acm add-tags-to-certificate --certificate-arn $(acmbase)e414b365-8517-4203-884d-67653e098c18 --tags Key=Name, $(tagkeys) $(region) $(profile)

    # 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)

    # 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)

    # 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)

    # 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)