IAM Tag Based Permissions

Without a doubt, security is one of the key aspect to focus in AWS. It is not only authentication is critical, but authorization is a must to consider specially in the production systems where lot of parties (users, resources, services) should be given only the specific permissions in the AWS environment. AWS IAM policies provides great amount of facilities in order to set up granular level of permissions. Tag based permissions are one of the cool feature supported by IAM.

In this blog post, I would discuss how below tag based conditions can be used within AWS IAM policies.

  • ResourceTag
  • RequestTag
  • PrincipalTag
  • TagKeys

Please note: Policy snippets describe below are only a part of a complete IAM policy document extracted only to illustrate the ‘tags’ related conditions, so you will need other necessary permissions to manage the same resources.

ResourceTag

ResourceTag is useful when you need to use the existing tags of a resource to be considered for the permissions. For example, let’s assume there are two ec2 instances where both have tag named stage where one has value dev and the other’s has value production.

And our requirement is to give permissions to stop or terminate ec2 instances only if the ec2 instances has the stage tag value dev. For this purpose, a IAM policy can be used with ResourceTags condition as below:

{
   "Version":"2012-10-17",
   "Statement":[
      {
         "Sid":"AllowStopTerminateOnlyWhenTagStageIsDev",
         "Effect":"Allow",
         "Action":[
            "ec2:TerminateInstances",
            "ec2:StopInstances"
         ],
         "Resource":"arn:aws:ec2:*:*:instance/*",
         "Condition":{
            "StringLike":{
               "ec2:ResourceTag/stage":"dev"
            }
         }
      }
   ]
}

As defined in the Condition section, ec2 which the action going to be applied (the Resource) must have the tag named stage which’s value is dev. Simple yet powerful, isn’t it?

RequestTag

RequestTag conditions can be used to control/validate which tags to be attached with a given resource. For example, let’s assume we need to enforce a user to add his team name TeamX as the team tag when creating a ec2 instance.

For this, we can use below IAM policy document, which checks the incoming/requested tag value.

{
   "Sid":"AllowCreateInstanceOnlyWithTeamTag",
   "Effect":"Allow",
   "Action":[
      "ec2:CreateVolume",
      "ec2:RunInstances",
      "ec2:CreateTags"
   ],
   "Resource":[
      "arn:aws:ec2:*:*:volume/*",
      "arn:aws:ec2:*:*:instance/*"
   ],
   "Condition":{
      "StringEquals":{
         "aws:RequestTag/team":"TeamX"
      }
   }
}
PrincipalTag

PrincipalTag is useful to check if the Principle has a particular tag attached on their identity. Here the Principle can be a user or a role.

Please note: As at now, IAM groups does not support tags. So you cannot apply any tag based permissions for a group directly.

For example, assume there are two users in a AWS account and both have a tag team attached to them. User A has team tag value is TeamX and for User B it is TeamY. And there is an ec2 instance, which should only be allowed to be stopped or terminated only if user has tag value TeamX.

For this requirement, we can use ResourceTag condition as below:

{
   "Version":"2012-10-17",
   "Statement":[
      {
         "Sid":"AllowStopTerminateOnlyIfPrincipleFromTeamX",
         "Effect":"Allow",
         "Action":[
            "ec2:TerminateInstances",
            "ec2:StopInstances"
         ],
         "Resource":"arn:aws:ec2:*:*:instance/*",
         "Condition":{
            "StringLike":{
               "aws:PrincipalTag/team":"TeamX"
            }
         }
      }
   ]
}
TagKeys

TagKeys are useful when you need to allow only a set of specified tags to be used on a resource. For example, if you need a ec2 instance to be tagged only with one or both team and department tags you may use below policy snippet. If you provide any tag other than these two, you are not permitted to create the instance.

Please note: Here, the value of the tag can be anything, it is not validated. Only the tag key is validated

{
   "Sid":"OnlyAllowTagsTeamAndDepartment",
   "Effect":"Allow",
   "Action":[
      "ec2:CreateTags",
      "ec2:RunInstances",
      "ec2:CreateVolume"
   ],
   "Resource":[
      "arn:aws:ec2:*:*:instance/*",
      "arn:aws:ec2:*:*:volume/*"
   ],
   "Condition":{
      "ForAllValues:StringEquals":{
         "aws:TagKeys":[
            "team",
            "department"
         ]
      }
   }
}

Please note: When you don’t provide a tag when creating the resource, still it can be created with above IAM policy as it only check the provided tags and does not enforce having a specific tag.

So, if you need to enforce only a particular tag to be exists, you may do it using a combination of TagKeys and RequestTags as below:

{
   "Sid":"VisualEditor0",
   "Effect":"Allow",
   "Action":[
      "ec2:CreateTags",
      "ec2:RunInstances",
      "ec2:CreateVolume"
   ],
   "Resource":[
      "arn:aws:ec2:*:*:instance/*",
      "arn:aws:ec2:*:*:volume/*"
   ],
   "Condition":{
      "StringLike":{
         "aws:RequestTag/team":"*"
      },
      "ForAllValues:StringEquals":{
         "aws:TagKeys":"team"
      }
   }
}

Here, in the RequestTag condition, we enforce team tag to be exists, still we don’t validate the value as we accept any value with wild card (*). And using TagKeys we enforce only team tag can be used as a tag.