How to hide instances in EC2 based on tag - using IAM?

user2434877 picture user2434877 · Sep 5, 2013 · Viewed 8.3k times · Source

I want to create a new user in IAM, and allow him to be able to create new EC2 instances, but be able to view/administer only those instances that he creates.

Is this possible with IAM?

This is the group policy I tried:

{
"Statement": 
[
{
  "Effect": "Allow",
  "Action": 
  [
    "ec2:DescribeImages",
    "ec2:DescribeKeyPairs", "ec2:DescribeSecurityGroups",
    "ec2:DescribeAvailabilityZones"
  ],
  "Resource": "*"
},

{
  "Effect": "Allow",
  "Action": 
  [
    "ec2:DescribeInstances","ec2:RunInstances", "ec2:TerminateInstances",
     "ec2:StartInstances", "ec2:StopInstances", "DescribeInstanceAttribute", "DescribeInstanceStatus"
  ],
  "Resource": "*",
  "Condition": 
  {
    "StringEquals": 
    {
      "ec2:ResourceTag/tag": "TheValueOfTheTag"
    }
  }

}
]
}

Answer

Steffen Opel picture Steffen Opel · Sep 5, 2013

Unfortunately this isn't yet available, at least not in the automatic fashion you are probably looking for - your use case has two aspects:

Resource-Level Permissions

The recent introduction of Resource-Level Permissions for EC2 and RDS Resources finally allows to constrain Amazon EC2 API actions to specific instances indeed, thus enabling your use case from that angle, e.g.:

  • Allow users to act on a limited set of resources within a larger, multi-user EC2 environment.
  • [...]
  • Control which users can terminate which instances.

The Example IAM Policies feature one showing how to Allow a user all actions on an Amazon DynamoDB table whose name matches the user name, demonstrating the use of the policy variable ${aws:username} (see IAM Policy Variables Overview for details):

{
  "Version": "2012-10-17",
  "Statement": [{
      "Effect": "Allow",
      "Action": ["dynamodb:*"],
      "Resource": "arn:aws:dynamodb:us-east-1:123456789012:table/${aws:username}"
    }
  ]
}

Caveat

This resource-level permissions aren't available for all API actions yet:

This is a complex and far-reaching feature and we'll be rolling it out in stages. In the first stage, the following actions on the indicated resources now support resource-level permissions:

Instances - Reboot, Start, Stop, Terminate.
EBS Volumes - Attach, Delete, Detach.

EC2 actions not listed above will not be governed by resource-level permissions at this time. We plan to add support for additional APIs throughout the rest of 2013.

Notably it lacks the ec2:Describe*actions you seem to be looking for as well.

Audit Trail

However, AWS has yet to publicly release any kind of auditing feature (which must be available internally due to the way Amazon IAM works), which means that there is no option to find out which particular IAM user has created a specific resource.

Update

As expected, AWS has meanwhile released AWS CloudTrail, which is a web service that records AWS API calls for your account and delivers log files to you:

The recorded information includes the identity of the API caller, the time of the API call, the source IP address of the API caller, the request parameters, and the response elements returned by the AWS service.

See my related answer to Logs for actions on amazon s3 / other AWS services for a few details and initial constraints.

Partial Workaround

I'm not aware of any self contained workaround - within a cooperative environment, you might be able to approximate what you want by applying respective monitoring and automation as follows:

1) you need to mandate that users only ever run EC2 instances with some kind of tagging scheme, e.g. owner=<username>

2) with that scheme in place, you could apply a ${aws:username} based policy as outlined above, resp. a slight variation based on tags - the AWS security blog has a comprehensive post Resource-level Permissions for EC2 – Controlling Management Access on Specific Instances illustrating this approach - your policy might look as follows:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": [
        "ec2:StartInstances",
        "ec2:StopInstances",      
        "ec2:RebootInstances",
        "ec2:TerminateInstances"
      ],
      "Condition": {
        "StringEquals": {
          "ec2:ResourceTag/owner":"${aws:username}"
        }
      },
      "Resource": [
        "arn:aws:ec2:your_region:your_account_ID:instance/*"
      ],
      "Effect": "Allow"
    }
  ]
}

3) please note that this means a user won't be able to manage his instances if he forgets to start them with the correct tag, so in addition you could use something like the Netflix' Conformity Monkey to enforce the policy on a heuristic basis, i.e. once an instance is detected without the required tag, whoever is in charge gets a notification and can try to enforce this by inquiring the users or shutting down the instance (which could also be done automatically of course).