3
votes

AWS just released required tag support for EC2/EBS: New – Tag EC2 Instances & EBS Volumes on Creation.

However, the example given only checks if tags have a fixed value which isn't useful to us because our users can enter free form values for required tags. How can a policy be written to check tags are present?

For example, we need something like this:

"Statement": [
    {
      "Sid": "DenyMissingTags",
      "Effect": "Deny",
      "Action": "ec2:RunInstances",
      "Resource": "arn:aws:ec2:us-east-1:accountid:instance/*",
      "Condition": {
        "StringExists": [
          "aws:RequestTag/costcenter",
          "aws:RequestTag/stack",
         ]
       }
     }
]

Obviously, I made up StringExists

3

3 Answers

3
votes

AWS support provided a solution I confirmed to work. Two separate condition blocks are needed to ensure the action is denied when only 1 tag is present:

{
    "Sid": "AllowLaunchOnlyWithRequiredTags1",
    "Effect": "Deny",
    "Action": "ec2:RunInstances",
    "Resource": "arn:aws:ec2:us-east-1:accountid:instance/*",
    "Condition": {
        "Null": {"aws:RequestTag/costcenter": "true"}
    }
},
{
    "Sid": "AllowLaunchOnlyWithRequiredTags2",
    "Effect": "Deny",
    "Action": "ec2:RunInstances",
    "Resource": "arn:aws:ec2:us-east-1:accountid:instance/*",
    "Condition": {
        "Null": {"aws:RequestTag/stack": "true"}
    }
}
0
votes

That page actually lists the tag enforcement as:

  "Condition": {
    "StringEquals": {
      "aws:RequestTag/costcenter": "115",
      "aws:RequestTag/stack": "prod"
     },
     "ForAllValues:StringEquals": {
         "aws:TagKeys": ["costcenter","stack"]
     }
   }

The documentation for ForAllValues says:

the ForAllValues qualifier requires all requested values to be listed in the policy

So, that part probably enforces the presence of a tag, without enforcing the actual contents.

-1
votes

You could do something using StringLike or StringNotLike, but it's limited to wildcards if that works for you.

String Conditional Operators

StringLike - Case-sensitive matching. The values can include a multi-character match wildcard (*) or a single-character match wildcard (?) anywhere in the string.

Example:

"Statement": [
{
  "Sid": "DenyMissingTags",
  "Effect": "Deny",
  "Action": "ec2:RunInstances",
  "Resource": "arn:aws:ec2:us-east-1:accountid:instance/*",
  "Condition": {
    "StringLike": [
      "aws:RequestTag/costcenter": "*",
      "aws:RequestTag/stack": "*"
      ]
    }
  }
]

I haven't tested it, but it should work.