I want to use ec2 instance profile to allow my python program to access a DynamoDb table. I have tested a policy by directly assigning to the user. Now I assign this same policy as a Instance Profile to ec2 instance where my job is running.
This is the policy.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"dynamodb:*"
],
"Resource": "arn:aws:dynamodb:us-east-2:913580688765:table/users"
}
]
}
Additionally I assigned a policy to the user to be able to Pass the ec2 role.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ec2:AssociateIamInstanceProfile",
"ec2:ReplaceIamInstanceProfileAssociation"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": "ec2:DescribeIamInstanceProfileAssociations",
"Resource": "*"
},
{
"Effect": "Allow",
"Action": "iam:PassRole",
"Resource": "*"
}
]
}
But this does not work.
What am I missing here?
I don't have the exact answer for you but I have advice on how you can progress. First off, lets recap (and can you please double check all this):
1) You have an EC2 instance running, it's assigned to an IAM role.
2) The IAM Role trust relationship contains ec2.amazonaws.com.
3) The policy granting "dynamodb:*" is attached to the role.
If this is done, that means everything should be configured properly.
At this point, i would suggest you ssh to the EC2 instance and test out the permissions. This can be done by using the AWS CLI's dynamodb API to make a list/describe/get API calls to confirm they work on the instance. If they works, it means the instance has permissions to access dynamodb and there might be something wrong with how you're using the instance profile.
It's worthy to note that not all operations are going to work on "arn:aws:dynamodb:us-east-2:913580688765:table/users" since it's a specific table rather than all the tables e.g. "arn:aws:dynamodb:us-east-2:913580688765:table/*". API calls such as list-tables won't work if the resource is a specific table. You can find a list of dynamodb api calls and weather or not they support a specific table or not in the documentation here.
Related
I want to restrict access for a specific user to see just few EC2 instances. I created a new user in IAM Roles and I attached a new Policy to it. The content of that Policy is attached below. I tried to look over documentation and to do it myself like this:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "ec2:*",
"Resource": [
"arn:aws:ec2:eu-west-1:ACCOUNT_ID:instance/i-INSTANCE_ID1",
"arn:aws:ec2:eu-west-1:ACCOUNT_ID:instance/i-INSTANCE_ID2"
]
}
]
}
I placed my region,ACCOUNT_ID(the owner id, not of the new user created) and instance-id, but when I connect with that user and I go to list all Instances I got this An error occurred fetching instance data: You are not authorized to perform this operation..
After I placed the code in JSON editor, in Policy Review step I got this message:
This policy defines some actions, resources, or conditions that do not
provide permissions. To grant access, policies must have an action
that has an applicable resource or condition. For details, choose Show
remaining Learn more
The AWS documentation mention exactly the same configuration or these examples.
I assume you connect as that user in the console (but it would be the same with CLI) Here is what I think is happening:
To list all the instances, the console most probably calls the DescribeInstances API. As per the list of action/resources/tags that can be used in IAM policy, this API does not support the resource filter in IAM.
This means your user has no authorization to list instances and they will not be shown in the console. You can validate this theory by using the CLI to request the details of a specific instance id, if my hypothesis is correct, it will be authorized.
As DescribeInstances can not be restricted by resource or tags, I don't think it is possible to filter the instance list for a user.
To have the console working, you'll need to add the following statement in your IAM policy
"Statement": [
{ your existing statement },
{
"Effect": "Allow",
"Action": "ec2:DescribeInstances",
"Resource": "*"
}
]
Please report if I was right :-) The example you mentioned in your question shows exactly that : Resources = * on DescribeInstances and Resources specific InstanceId on other operations.
The previous answer is wrong, you can Conditionally allow access to ec2:DescribeInstances by tag names. It's an AWS best practice as well. Also explicitly deny access to the ec2:CreateTags and ec2:DeleteTags actions to prevent users from creating or deleting tags to take control of the instance.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "ec2:DescribeInstances",
"Resource": "*",
"Condition": {
"StringEquals": {
"ec2:ResourceTag/UserName": "${aws:username}"
}
}
},
{
"Effect": "Deny",
"Action": [
"ec2:CreateTags",
"ec2:DeleteTags"
],
"Resource": "*"
}
]
}
DescribeInstances action does not support condition.
https://docs.aws.amazon.com/service-authorization/latest/reference/list_amazonec2.html
On AWS member of Administrators group is unable to launch EC2 instances with IAM role. The same user can create IAM roles and even manage users in IAM console.
User seems to have all possible permissions. What could be missing?
The documentation states you need ec2:RunInstances, ec2:AssociateIamInstanceProfile, ec2:ReplaceIamInstanceProfileAssociation and iam:PassRole. Do they have all of those?
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ec2:RunInstances",
"ec2:AssociateIamInstanceProfile",
"ec2:ReplaceIamInstanceProfileAssociation"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": "iam:PassRole",
"Resource": "*"
}
]
}
Apparently rights were OK. The mistake was made when creating the role. For instance roles EC2 had to be selected on the first step (not the desired access). Permissions were available on the next step.
Created an AWS IAM policy for a user to give permission for only stopping and starting instance but if I give a particular instance ARN resource then it doesn’t work. Default EC2 Read only permission has been given to the user to describe EC2 instances and on top of that added customized sample policy as follows:
Sample policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"ec2:Describe*",
"ec2:StopInstances",
"ec2:RunInstances",
"ec2:StartInstances"
],
"Effect": "Allow",
"Resource": "*"
This works
"Resource": "arn:aws:ec2:<region>:<account id>:instance/<instance id>"
"Resource": "arn:aws:ec2:<region>:<account id>:instance/*"
"Resource": "arn:aws:ec2:<region>::instance/*"
"Resource": "arn:aws:ec2:::instance/*"
"Resource": "arn:aws:ec2:::*"
These doesn’t work
}
]
}
Edited on 23rd January (To Show what exactly I have done)
Objective: Start and stop instance permission on a single EC2 instance to a user.
Tested different combo policies but none of them worked except "Resource": "*":
Logged in: admin_user (Full access)
Created an instance as follows:
Region: Oregon
Availability zone: us-west-2c
Instance Id: i-xxx3dxxx32xxxxxxe
Owner: xxx23xxx11
Created a user: testec2_user
Permissions given to the user:
EC2 read only (available policy)
Customized policy to permit only stop and start i-xxx38xxx32xx45 instance as follows:
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"ec2:Describe*",
"ec2:RunInstances"
],
"Effect": "Allow",
"Resource": "*"
},
{
"Action": [
"ec2:StopInstances",
"ec2:StartInstances"
],
"Effect": "Allow",
"Resource": "arn:aws:ec2:us-west-2c:xxx23xxx11:instance/i-xxx3dxxx32xxxxxxe"
}
] }
Logged in as testec2_user and tried starting up the stopped instance and received following error:
You are not authorized to perform this operation. Encoded authorization failure message
I have a plan for decoding the message received using sts decode authorization message of AWS.
DescribeInstances does not support resource-level permissions. (See Unsupported Resource-Level Permissions).
If an Amazon EC2 API action does not support resource-level
permissions, you can grant users permission to use the action, but you
have to specify a * for the resource element of your policy statement.
Read more
So, you could re-write your policy as:
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"ec2:Describe*",
"ec2:RunInstances"
],
"Effect": "Allow",
"Resource": "*"
},
{
"Action": [
"ec2:StopInstances",
"ec2:StartInstances"
],
"Effect": "Allow",
"Resource": "arn:aws:ec2:<region>:<account>:instance/<instance-id>"
}
]
}
EDIT
RunInstances needs access to several resource types besides Instance (Such as Image, Key pair, Network interface, Placement group, Security group, Snapshot, Subnet and Volume) and accepts a specific ARN format for each resource type. So, arn:aws:ec2:<region>:<account id>:instance/* would not be enough and you'll get an UnauthorizedOperation error. The "Resource" element should either be:
"Resource": "*"
Which is the easiest way, or:
"Resource": [
"arn:aws:ec2:<region>:<account>:instance/*",
"arn:aws:ec2:<region>::image/*",
"arn:aws:ec2:<region>:<account>:key-pair/*",
"arn:aws:ec2:<region>:<account>:network-interface/*",
"arn:aws:ec2:<region>:<account>:placement-group/*",
"arn:aws:ec2:<region>:<account>:security-group/*",
"arn:aws:ec2:<region>::snapshot/*",
"arn:aws:ec2:<region>:<account>:subnet/*",
"arn:aws:ec2:<region>:<account>:volume/*"
]
Which is more complex but provides fine-grained control on each resource. For example, you can allow RunInstances execution for a specific EC2 image ID or subnet ID only. For more details, see the RunInstances section here.
Additional note on PassRole Permission
When executing RunInstances, if the EC2 instance should include an instance profile, the user who launches the EC2 instance must also have the IAM PassRole permission in order to associate a role with the instance during launch. For example:
{
"Version": "2012-10-17",
"Statement": [
...
{
"Action": "iam:PassRole",
"Effect": "Allow",
"Resource":"arn:aws:iam::<account>:role/<role-name>"
}
]
}
This way, you make sure that a user doesn't pass a role to an EC2 instance where the role has more permissions than you want the user to have.
For more info on granting permission to launch EC2 instances with IAM roles, see this AWS blog article.
This is how you specify multiple resources:
…
"Effect": "Allow",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::BUCKET-NAME/home/${aws:username}",
"arn:aws:s3:::BUCKET-NAME/home/${aws:username}/*"
]
}
]
}
Source:
http://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_examples.html
EDIT:
You can also use Conditions if you want to filter out instead of including all the required resources manually.
I want to be able to apply tags only to instances running in EC2 on a particular VPC (vpc-11111111).
I tried to use the policy
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "EC2TagNonresourceSpecificActions",
"Effect": "Allow",
"Action": [
"ec2:CreateTags",
"ec2:DeleteTags",
"ec2:DescribeTags"
],
"Condition": {
"StringEquals": {
"ec2:vpc": "arn:aws:ec2:<myRegion>:<myCustomerId>:vpc/vpc-11111111"
}
},
"Resource": "*"
}
]
}
but the user with this policy cannot modify the tags unless I remove the condition.
What have I done wrong?
Tags do not support conditions, according to Amazon docs and support.
This is a long standing feature request for several years!
Normally, if given some particular AWS user rights, the Tag rights is inside the policies.
Mistake in your new policies will overwrite those default access. You should try it out using AWS policy simulator.
Try add a principal and try it out.
"Principal": {
"AWS": "arn:aws:iam::<myCustomerId>:user/*"
}
IAM policy variables are quite cool and let you create generic policys to, for example, give users access to paths in an S3 bucket based on their username, like this:
{
"Version": "2012-10-17",
"Statement": [
{
"Action": ["s3:GetObject","s3:PutObject","s3:DeleteObject"],
"Effect": "Allow",
"Resource": "arn:aws:s3:::fooCorp-user-files/${aws:username}/*"
},
{
"Action": "s3:ListBucket",
"Effect": "Allow",
"Resource": "arn:aws:s3:::fooCorp-user-files"
}
]
}
My question is, how can this be done using roles (attached to EC2 instances) instead of user accounts?
I have a number of app servers with unique IAM user accounts that are linked to a generic policy similar to the one above. This isolates the files accessible by each user/app without creating multiple policies.
I want switch these servers to use roles instead but there doesn't seem to be an equivalent IAM variable like aws:rolename.
The docs indicate that when using a role assigned to an EC2 instance the aws:username variable isn't set and aws:userid is [role-id]:[ec2-instance-id] (which isn't helpful either).
This really seems like something you should be able to do.. or am I coming at this the wrong way?
I've been looking for the same and after a lot of searching my conclusion was that it is not possible to use the role name as a variable in a IAM policy (I'd love to be proven wrong though).
Instead, I tagged my role with a name and ended up with this:
{
"Version": "2012-10-17",
"Statement": [
{
"Action": ["s3:GetObject","s3:PutObject","s3:DeleteObject"],
"Effect": "Allow",
"Resource": "arn:aws:s3:::fooCorp-user-files/${aws:PrincipalTag/name}/*"
},
{
"Action": "s3:ListBucket",
"Effect": "Allow",
"Resource": "arn:aws:s3:::fooCorp-user-files"
}
]
}
(Cross-posted to AWS S3 IAM policy for role for restricting few instances to connect to S3 bucket based in instance tag or instance id)
Instead of using aws:SourceArn, use aws:userid!
The Request Information That You Can Use for Policy Variables documentation that you mentioned has a table showing various values of aws:userid including:
For Role assigned to an Amazon EC2 instance, it is set to role-id:ec2-instance-id
Therefore, you could use the Role ID of the role that is used to launch the Amazon EC2 instance to permit access OR the Instance ID.
For example, this one is based on a Role ID:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "SID123",
"Effect": "Allow",
"Action": [
"s3:*"
],
"Resource": [
"*"
],
"Condition": {
"StringLike": {
"aws:userid": [
"AROAIIPEUJOUGITIU5BB6*"
]
}
}
}
]
}
Of course, if you are going to assign permission based on a Role ID, then you can just as easily grant permissions within the Role itself.
This one is based on an Instance ID:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "SID123",
"Effect": "Allow",
"Action": [
"s3:*"
],
"Resource": [
"*"
],
"Condition": {
"StringLike": {
"aws:userid": [
"*:i-03c9a5f3fae4b630a"
]
}
}
}
]
}
The Instance ID will remain with the instance, but a new one will be assigned if a new instance is launched, even from the same Amazon Machine Image (AMI).