Trying to isolate IAM user to have AmazonEC2ReadOnlyAccess to only select instances using python boto3

0

Ok so the policy arn:aws:iam::aws:policy/AmazonEC2ReadOnlyAccess looks like this:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "ec2:Describe*",
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": "elasticloadbalancing:Describe*",
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "cloudwatch:ListMetrics",
                "cloudwatch:GetMetricStatistics",
                "cloudwatch:Describe*"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": "autoscaling:Describe*",
            "Resource": "*"
        }
    ]
}

This works to allow the IAM user to perform most ec2 read functions.

Problem is that this is too permissive. What I need to do is allow all the same functionality as this but ONLY for certain instances. So what I attempted to do is isolate this given a list of instance ids instanceids (using python boto3):

ResourceIds = [ f"arn:aws:ec2:{REGION_NAME}:{AWS_ACCOUNTID}:instance/{iid}" for iid in instanceids]
Ec2ReadOnlyPolicy = {
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "ec2:Describe*",
            "Resource": ResourceIds
        },
        {
            "Effect": "Allow",
            "Action": "elasticloadbalancing:Describe*",
            "Resource": ResourceIds
        },
        {
            "Effect": "Allow",
            "Action": [
                "cloudwatch:ListMetrics",
                "cloudwatch:GetMetricStatistics",
                "cloudwatch:Describe*"
            ],
            "Resource": ResourceIds
        },
        {
            "Effect": "Allow",
            "Action": "autoscaling:Describe*",
            "Resource": ResourceIds
        }
    ]
}
response = iam_client.put_group_policy(
    PolicyDocument=json.dumps(Ec2ReadOnlyPolicy),
    PolicyName=EC2_RO_POLICY_NAME,
    GroupName=UserGroupName,
)

Problem is that this doesn't seem to allow the user to list instances they have access to:

$ aws ec2 describe-instances
An error occurred (UnauthorizedOperation) when calling the DescribeInstances operation: You are not authorized to perform this operation.

What am I doing wrong?

2 Answers
2
Accepted Answer

Hi!

Good question. When crafting IAM Policies, keep in mind that some actions do not support resource-level permissions. If those do not support resource-level permissions, you must specify all resources ("*") in the Resource element of the policy for it to work.

You can determine if actions support resource-level permissions by the actions page (example below). If there are no values in the Resource types column, that means it does not support resource-level permissions.

In your case with DescribeInstances, that action does not support resource-level permissions and must come with all resources specified.

What you can do is separate out the actions that do not support resource-level permissions into 1 block and the ones that do into another block to achieve more granular IAM policies like you're trying to do above.

https://docs.aws.amazon.com/service-authorization/latest/reference/list_amazonec2.html

jsonc
answered 2 years ago
  • Awesome thanks so much for that I had no clue. Ill give that a try real fast and let you know how that goes.

1

You could also limit access based on tags instead of instance IDs. As an example, below statement gives access to all resources where resource either doesn't have "owner" -tag OR "owner" -tag has the same value as pricipals (=IAM user or role) "owner" -tag has. Untagged resources are accessible for everyone using this policy, but once "owner" tag is attached, only the user (or role) with the same owner -tag value can modify it (including changening the tag).

          - Sid: 'AllowUnlessOwnedBySomeoneElse'
            Effect: Allow 
            Action: '*'
            Resource: '*'
            Condition:
              StringEqualsIfExists:
                'aws:RequestTag/owner': ${aws:PrincipalTag/owner}
                'aws:ResourceTag/owner': ${aws:PrincipalTag/owner}

You can then limit Actions same way you did to EC2s etc. There are also other variables you can use in place of aws:PrincipalTag. https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_variables.html

Above statement is part of longer story how you can isolate multiple teams working on single account, and yet allow them to create their own IAM policies. https://carriagereturn.nl/aws/iam/policy/boundary/2021/10/07/iambound.html

profile picture
EXPERT
Kallu
answered 2 years ago
  • Oh dang that looks really promising. Ill give it a try. If this works, it would really help me isolate this even further.

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions