Enforcing Tagging Compliance in AWS using Service Control Policies

Below, I go through using Service Control Policies to enforce tagging standards. I do not go over Tagging Policies, but this is the next logical step in cooperation with the enforcement of tagging described herein.

We hear a lot about the importance of tagging within AWS for a multitude of very powerful options that include cost tracking, ownership/responsibility, and ABAC controls — to name a few.

As an organization’s maturity in AWS increases, the need and value for these tags can be realized. In some cases, after it’s too late and Infrastructure has been built. Leaving the Sisyphean task of tagging resources (manually or programmatically) resources as they are spun into and out of existence.

Let’s assume an organization has moved past the first iteration of building resources by hand and has already learned the power of Infrastructure as Code using CloudFormation or Terraform. Adding tags to new items can be done relatively easily with the addition of this work to the deployment. However, what if you aren’t pulling from centrally managed templates? What happens when the code needs to be updated? — How do you ensure various teams are following the (potentially) multitude of compliance and governance controls?

Again, Service Control Policies come to the rescue of compliance. How you choose to implement this is flexible, but there are some considerations around the API calls in each use case. The focus will be on EC2 instances as a part of this explanation.

Here are some important considerations before we begin — including these SCPs on Production accounts should be done with utmost communication and discretion as this could have negative impacts on the business. If separating at an OU level isn’t an option, attaching the SCP to individual accounts to remediate account by account is not only an option, but may be your best course of deployment to reduce unintended consequences. Additionally, the use of these SCPs do not enforce the capitalization of the tag keys. Use of Tagging Policies will assist with this.

Scenario 1: Prevent users from instances that do not have the appropriate tags.

Considerations: The call creates and starts an EC2. The act of starting here is not an additional API call and therefore will allow the starting at time of creation. However, this will prevent the frustration of user attempting to deploy infrastructure through the console — only to have their work lost on the final screen. (If this is something of interest, see Scenario 2.)

Service Control Policy statement:

{
"Sid": "tag1",
"Effect": "Deny",
"Action": [
"ec2:StartInstances"
],
"Resource": [
"*"
],
"Condition": {
"StringNotLike": {
"ec2:ResourceTag/<TagKey>": "?*"
}
}
}

Explanation: The <TagKey> will be required on all EC2 instances before they will start from a stopped status. The “?*” enforces that there is some value for the tag key. Replacing this with “?” doesn’t require the value be present, but still requires the tag key. (See Tagging Policies for additional functionality for further validation of these values.)

Scenario 2: Prevent all users from creating new EC2 instances using the RunInstance permission unless the required tags are present.

Considerations: Each tag will require two separate statements with the needed conditions. (See Explanation below.) Replacing the <TagKey> with the required tag in the policy below will require that the Tag is present, and just like Scenario 1, requires a tag value.

Service Control Policy:

    {
"Sid": "tag1a",
"Effect": "Deny",
"Action": "ec2:RunInstances",
"Resource": [
"arn:aws:ec2:*:*:instance/*",
"arn:aws:ec2:*:*:volume/*"
],
"Condition": {
"ForAllValues:StringNotEquals": {
"aws:Tagkeys": [
"<TagKey>"
]
}
}
},
{
"Sid": "tag1b",
"Effect": "Deny",
"Action": "ec2:RunInstances",
"Resource": [
"arn:aws:ec2:*:*:instance/*",
"arn:aws:ec2:*:*:volume/*"
],
"Condition": {
"StringNotLike": {
"aws:RequestTag/<TagKey>": [
"?*"
]
}
}
}

Explanation: (I started to type of an in-depth explanation of the syntax for these policies, but realized I was rewriting a very helpful article. Credit to the author who put this article in around the time I sent in a flurry of support tickets to get help with this: https://aws.amazon.com/premiumsupport/knowledge-center/iam-policy-tags-deny/)

Hopefully these two snippets (plus some Tagging Policies) can stop the bleeding of non-compliant resources.

Please keep in mind the use of Service Control Policies can have wide reaching (and sometime unintended) consequences. Testing these — in non-production scenarios — should be done extensively.

Feel free to reach out with any questions.

Modernizing companies’ AWS security and governance programs at scale.