Protect Resources Based on Tags

Ever needed to give a user or a group of users permission to only control the EC2 instances that you want them to control? Of course, you have!

Access control is a critical aspect of managing any environment. But, if managing IAM policies in your company's AWS environment falls within your realm of responsibilities, this is something that should not be taken lightly.

OK, so let's say that your company has recently hired a bunch of interns to perform some application testing for you. It will be quite dangerous, and no administrator in their right mind will just create an ‘allow-all’ policy and let the intern loose on the environment unless, of course, there are other security measures in place, i.e. multi-accounts. It is, thus critical to ensure that they (these interns of yours) are only allowed to have access to, and perform the actions, on the resources that they're responsible for. Principle of least privilege and all of that.

AWS is the kind of platform that allows you to achieve the same result in multiple different ways, but if you'd like to limit IAM users based on tag values assigned to resources, you've come to the right place.

Before we go further, what are resource tags?

Tags are key-value pairs assigned to your AWS resources by you the user, and it's a way to add your own metadata to each component within your environment. You can add tags to just about everything in AWS, from an IAM user, an EC2 instance, an EBS volume, that EBS volume's snapshot, subnets, etc. Get a full list of resources that support tags here.

By adding tags to your resources, it allows you to categorise and report on collections of resources. For example, if you add a key of ‘Application’ and a value of ‘App-01’ to all the resources make up that application, you're able to generate a report on the running costs of App-01. And if you are running multiple applications, you can see a split of the running costs of all of them.

This is what it will look like if an EC2 instance is tagged as explained above. We have added 3 tags, ‘Application’, ‘Environment’, and ‘Name’.

Resource tags

OK, now we can take advantage of these tags.

In this example, we're going to limit our test users to start, stop and reboot the EC2 instances that are tagged with the ‘Environment’ key and a value of ‘Test’. The aim of this is to prevent the testers from stopping our production systems.

Let's get started.

Add all your IAM users

Of course, if you already have all your users added, you can skip this step… In the IAM console, we select the ‘Users’ option in the navigation tab, we select the ‘Add user’ button to get started. On the next window that opens, we add all the details that are required for the specific user.

Create our IAM policy

In the IAM console, we navigate to the ‘Policies’ section and select the ‘Create Policy’ button. On the window that opens, we can move forward with one of two methods; we can select all our options via the visual editor, or we can use the JSON editor. Personally, I'm a fan of the JSON editor. I built the below code for my requirement, feel free to edit it as needed.

    "Version": "2012-10-17",
    "Statement": [
            "Sid": "Ec2startstopreboot",
            "Effect": "Allow",
            "Action": [
            "Resource": "*",
            "Condition": {
                "StringEquals": {
                    "ec2:ResourceTag/Environment": "Test"
            "Sid": "Ec2describe",
            "Effect": "Allow",
            "Action": "ec2:Describe*",
            "Resource": "*"

Let's break this down:

The ‘Action’ section defines which actions the users are allowed to perform. I highlight allowed, cause that is what the Effect parameter specifies. If the Effect was ‘Deny’ the policy would block the users from performing those actions. We define all resources, but our tags will come into play in the ‘Condition’ section. Our tags are defined in the StringEquals dictionary, with the following syntax: ec2:ResourceTag/TagKey: TagValue

I also have a second section where we allow the users to list all the EC2 resources. However, later on in this post, I will expand on the possibilities here.

Once the policy is created we select the ‘Review’ button. In the next window, we can provide a name and description for our policy and a summary of our policy is displayed. With the policy created we're able to now create our user group and assign this policy to them.

Create a group for the test users and add the policy we just created to this group.

Still, in the IAM console, we can navigate to the ‘Groups’ menu, and click the ‘Create a New Group’ button. I'm calling my group ‘Testers’ and adding the policy from the previous step.

Add all our intern users to this IAM group

Staying in the Groups menu (in the IAM console), we can add users to the group from here. Select your group, and in the ‘Group Actions’ drop-down, select the ‘Add users to group’ option.

Let's test it out.

Cool, so that should be it. Let's test it. Keep in mind, these users won't be allowed to launch their own instances, so I've launched two EC2 instances and tagged them with the Environment keys, I've given one the value of Test, (our interns will be allowed to start, stop, and reboot this instance), and the other EC2 I've given the tag value of Production, and our interns shouldn't be allowed to start, stop and reboot this instance.

To give you a clearer view of what this will look like once configured:

Ec2 Status

I log into the AWS console with one of the test user's accounts, and I'm able to perform all the allowed actions on the EC2 instance tagged with the Environment/Test tag. But when I try to reboot or stop the instance tagged with the Environment/Production tag, as expected I get the ‘Permission denied’ error.

Stop Instance Error Web-759 is the name of the production instance.

Cool. So that's it… Add more users to this group, and amend the policy as needed.

If you follow the principle of least privilege and only add this policy, the users in this group will not have access to anything else, and only be allowed to start, stop and reboot instances tagged with the Environment/Test tag.

Happy tagging!