Enforce resource tagging on AWS using an IAM policy

2 min read | by Jordi Prats

It is good practice to tag all the resources on AWS to be able to better keep track of them: Using these tags we can have a better understanding of where we are spending our money into. So, we might want to enforce tagging to the resources: This is something we can achieve using an IAM policy

If we want, for example enforce that all the resources should have the tags "app" and "billing" we can create the following policy that Denys the operation if these tags doesn't exists:

{
    "Sid": "AllowLaunchOnlyWithRequiredTags1",
    "Effect": "Deny",
    "Action": "ec2:RunInstances",
    "Resource": "arn:aws:ec2:eu-west-1:123456789123:instance/*",
    "Condition": {
        "Null": {"aws:RequestTag/app": "true"}
    }
},
{
    "Sid": "AllowLaunchOnlyWithRequiredTags2",
    "Effect": "Deny",
    "Action": "ec2:RunInstances",
    "Resource": "arn:aws:ec2:eu-west-1:123456789123:instance/*",
    "Condition": {
        "Null": {"aws:RequestTag/billing": "true"}
    }
}

In this case, the Null operator checks for the presence of a condition key: so here we are denying the operation if either the billing or the app tags are not set. We will have to attach it to the IAM user (or group) that will be used to launch the instances.

If we try to launch an instance with one of the required tags we will get an error with an encoded message that can be read using aws sts decode-authorization-message:

$ aws sts decode-authorization-message --encoded-message '<encoded message>'  --query DecodedMessage --output text | jq '.'
{
  "allowed": false,
  "explicitDeny": true,
  "matchedStatements": {
    "items": [
      {
        "statementId": "AllowLaunchOnlyWithRequiredTags1",
        "effect": "DENY",
        "principals": {
          "items": [
            {
              "value": "A3LRNAR4U6OJ3M4D6JWIO"
            }
          ]
        },
        "principalGroups": {
          "items": []
        },
        "actions": {
          "items": [
            {
              "value": "ec2:RunInstances"
            }
          ]
        },
        "resources": {
          "items": [
            {
              "value": "arn:aws:ec2:*:*:instance/*"
            }
          ]
        },
        "conditions": {
          "items": [
            {
              "key": "aws:RequestTag/billing",
              "values": {
                "items": [
                  {
                    "value": "true"
                  }
                ]
              }
            }
          ]
        }
      },
(...)

Posted on 21/12/2021

Categories