No BS guide to Enforcing Mandatory Tags for AWS EC2 and other services

Grumpy SysAdmin
5 min readMar 7, 2022
Me, a week ago!

Motive:

Who did create the “my-important-ec2” EC2 in our production AWS account with a key-pair name “my-us-east-1-key” which has been running for 6 months? (Thank you whoever you are since you were kind enough to add at least the “Name” tag to your EC2)

Why did you create it? Is it still needed? Do you still work in our company?

Since in default settings Cloudtrail preserves event logs for only 90 days I have almost ran out of ways to find the creator and confront him/her!

Problem:

  • Sometimes IAM users create resources and do not delete them after the requirement is over, or some users do not have IAM access to delete resources and those resources are left without being used and incur to a huge AWS bill. Admins need to keep track of the resources and the owners of them.
  • In an Organization there may be budgetary limitations on a department/team wise basis and respective team leads may need to keep a track of the AWS cost.
  • AWS Admins must have a way to quickly identify the creator of a specific resource, enough data to automate certain tasks such as sending reminders, calculate the cost team wise, project wise, shutdown/restart resources.

Goal

  • No one should be able to create EC2 machines, EKS clusters, Cloudformation stacks without defining the pre-configured tag keys and values.
  • Every existing IAM users/future IAM users must bound to these restrictions.

Plan

  • Using AWS ControlTower to create independent AWS accounts for each department. In this guide we won’t discuss on creating CT accounts, but only the Tag enforcement.
ie: Development, PreSales, Production, Support
  • These tags will be enforced. Users must define below tag keys with the allowed tag values.
Owner = <useremail> Note: The value must end with @example.comProject = {app1, app2, product1}

Prerequisites

  • We can only enable Tag Policies, SCPs only on AWS accounts which are a part of an AWS Organization. And SCPs do not work for the management account of the AWS Organizations. If your company only have one AWS account (Main-Account), what you can do is creating a new AWS account (Dummy-Account) and then creating an AWS Organization using the ‘Dummy-Account’ and then inviting the ‘Main-Account’ to the Organization. The ‘Dummy-Account’ must be the management account of the newly created AWS Organization not the account we intend to enable Tag Policies and SCPs.
  • When creating the AWS Organization ‘All features must be enabled’ which is the default setting.

The Good Stuff , Guide

  1. Log in to the Management Account of your AWS Organization. Go to AWS Organizations Service and go to Policies. Enable Service Control Policies and Tag Policies. First we will config Tag Policies. Once the Tag Polices are configured and enforced on an AWS account, IAM users can not define tags with contradictory Tag values.
Ex: When tag policies are in place a user can create resources without defining any Tags, but can not create a resource with a Tag/ Value pair such as "Project : Test-Project" since we have only allowed {app1, app2, product1} as Tag values for the tag key 'Project'.

Tag Policies

This tag policy is effected for ec2 Instance creation and EBS Volume creation. You can opt out/in resources as your requirement. “Owner” and “Project” tag values are enforced here.

{
"tags": {
"Owner": {
"tag_key": {
"@@assign": "Owner"
},
"tag_value": {
"@@assign": [
"*@example.com"
]
},
"enforced_for": {
"@@assign": [
"ec2:instance",
"ec2:volume"
]
}
},
"Project": {
"tag_key": {
"@@assign": "Project"
},
"tag_value": {
"@@assign": [
"app1",
"app2",
"product1"
]
},
"enforced_for": {
"@@assign": [
"ec2:instance",
"ec2:volume"
]
}
}
}
}

Once the tag policy is created, you can attach this policy to an AWS account or to an OU directly.

AWS Organizations > Policies > Tag policies > Check the Policy you created, Click Actions > Attach Policy > Select the OU or the AWS account you need where the Tag policy to be applied.

Now you can test whether the policy works as expected. Expected results should be like this.

A few Scenarios with Tag Policies Enforced

Service control policies (SCPs)

With Tag Policies we have made sure that users can not violate the tag values, now we need to make sure that users DO SPECIFY TAGS or else the resource won’t be created. We can achieve this by using SCPs.

AWS Organizations > Policies > Service control policies > Create Policy

Specify Policy names and description as you wish. Then we can create the Policy. You can use the UI help wizard or the JSON editor directly.

This policy denies any resource creation with no “aws:RequestTag/Project” and “aws:RequestTag/Owner”: “true” property. (In simple terms the “Project” and “Owner” tags are a must when creating EC2s)

{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyRunInstanceWithNoProjectTag",
"Effect": "Deny",
"Action": "ec2:RunInstances",
"Resource": [
"arn:aws:ec2:*:*:instance/*",
"arn:aws:ec2:*:*:volume/*"
],
"Condition": {
"Null": {
"aws:RequestTag/Project": "true"
}
}
},
{
"Sid": "DenyRunInstanceWithNoOwnerTag",
"Effect": "Deny",
"Action": "ec2:RunInstances",
"Resource": [
"arn:aws:ec2:*:*:instance/*",
"arn:aws:ec2:*:*:volume/*"
],
"Condition": {
"Null": {
"aws:RequestTag/Owner": "true"
}
}
},
{
"Sid": "DenyRunInstanceWithNoNameTag",
"Effect": "Deny",
"Action": "ec2:RunInstances",
"Resource": [
"arn:aws:ec2:*:*:instance/*",
"arn:aws:ec2:*:*:volume/*"
],
"Condition": {
"Null": {
"aws:RequestTag/Name": "true"
}
}
}
]
}

Now You need to attach this SCP to the OU or the AWS account you need where the SCP to be applied. Now you can test whether the policy works as expected. Expected results should be like this.

A few scenarios with both Tag Polices and SCPs Enforced

Congrats! Now you are the arch-nemesis of all the lazy developers who only create AWS resources, but do not even think about them once their requirement is over

--

--