I access a bucket with a lambda function and i get an "Access Denied" error, when i access it with a lambda function via boto3. If i set principal to "*" in the Bucket, all works fine. What is the issue?
"Sid": "DenyIncorrectEncryptionHeader",
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
...
In the bucket policy, the principal to give allow permission to should be the lambda execution role and not the lambda service (lambda.amazonaws.com).
Adding more details, if the lambda execution role is in the same AWS account as the bucket, then an allow permission in the role should suffice. As long as there is no explicit deny in the bucket policy.
However, if the role and bucket are in separate accounts, the role has to have allow permission and the bucket policy has to give allow permission to the role.
The steps would be:
Create an IAM Role with a use-case of Lambda (this creates a Trust Policy that allows the AWS Lambda service to assume the role)
Add a Policy to the IAM Role that grants the required Amazon S3 permissions
Configure the AWS Lambda function to use this IAM Role
There is no need to use an Amazon S3 Bucket Policy for your stated requirements.
As a general rule, Bucket Policies are used when granting permission to everyone, and IAM policies should be used when granting access to specific Users or Groups. (However, there can be other situations for using Bucket Policies, such as granting cross-account access.)
Related
What is (or should be) the relationship between a S3 bucket policy and its designated administrator's user policy?
E.g. suppose I've newly created a bucket:
$ aws --profile admin --endpoint-url http://localhost:4572 s3 mb s3://foo
make_bucket: foo
I want user bucket_admin to be able to administer the bucket (not necessarily exclusively). To do this, should I create/apply a bucket policy along the lines of:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["s3:*"],
"Principal": { "AWS": "arn:aws:iam::000000000000:user/bucket_admin" },
"Resource": "arn:aws:s3:::foo/*"
}
]
}
...or create/apply a user policy along the lines of:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect":"Allow",
"Action":["s3:*"],
"Resource":["arn:aws:s3:::foo/*"]
}
]
}
?
Your bucket policy applies to only one principle, the bucket_admin user. It can't be used by a role, other IAM user or a group, if you want to have more identities being able to administer the bucket.
The IAM policy does not have a principle by definition. It means you have to attach it to an identity, such as IAM role, user or group. This gives you more flexibility on how to distribute the permissions to the bucket. It can be only the bucket_admin, or you can create a group of bucket admins, or have role which can be assumed by an EC2 instance.
Also with IAM policy it is easier to check who/what is using it. You just go to IAM console, and to Policy Usage and you will get a list of all identities which use the policy. With bucket policies, you have to go manually over all buckets and inspect their policies to check who can be admin of buckets.
Good general comparison of resource vs IAM policies is here:
Identity-Based Policies and Resource-Based Policies
Also useful read as IAM policies can be attached to roles:
How IAM Roles Differ from Resource-based Policies
In addition to #Marcin's answer, which is great...
We use bucket policies mostly for bucket-level checks - ensure the traffic is SSL, ensure the traffic originates from a specific VPC, etc.
Using roles attached to IAM users is an easier way of controlling user access.
The exception is where a user is trying to access a bucket in another account - in this case, both a bucket policy and an IAM policy is needed https://docs.aws.amazon.com/AmazonS3/latest/dev/example-walkthroughs-managing-access-example2.html
I have 2 IAM roles in same aws account
IAM_ROLE_1 : which has ec2 launch permission with s3 read permissions
IAM_ROLE_2 : which has only access to lamda with assume trust from IAM_ROLE_1
I am able to assume IAM_ROLE_2 from an instance which has IAM_ROLE_1 attached to it.
Now I want to read a s3 location (which IAM_ROLE_1 has access to) after assuming IAM_ROLE_2 .
My understanding is that I can do that with "iam:passrole"
Is this correct understanding ?
When I am adding below to IAM_ROLE_1 , and assuming IAM_ROLE_2 & accessing s3 bucket it still throwing access denied error.
{
"Sid": "allowpassrole",
"Effect": "Allow",
"Action": "iam:PassRole",
"Resource": [
"arn:aws:iam::00000001:role/IAM_ROLE_2"
]
}
A set of credentials is only associated with one IAM User or IAM Role at any time. Thus, to make a call using permissions associated with IAM Role 1, you would need to use credentials associated with that Role (not IAM Role 2).
To use IAM Role 1, simply create an Amazon S3 client object without specifying credentials. It will then use IAM Role 1 that is associated with the instance.
iam:PassRole is used to permit a service to assume a role on your behalf. For example, when launching the Amazon EC2 instance with the Role set to IAM Role 1, you would need permission to PassRole with IAM Role 1. Without this permission, you would not be able to launch the EC2 instance with that role.
PassRole is not used to pass permissions 'between' roles.
Right now I have my policy defined on my S3 bucket but it seems like the principles I have defined are root and when someone under an account who isn't root isn't falling into the allow part of the policy
"Principal": {
"AWS": [
"arn:aws:iam::123:root",
"arn:aws:iam::456:root",
"arn:aws:iam::789:root",
"arn:aws:iam::101:root"
]
},
I tired to specify it as
"arn:aws:iam::123:*"
but that doesn't work.
I also tried arn:aws:iam::123:user/sample#yahoo.com but that too doesn't seem to be correct as it fails with Invalid principal in policy
When granting cross-account permissions, you need both of:
A bucket policy on Bucket-A in Account-A (as above)
Permissions on the users in their own account to access Bucket-A (which can include wide permissions such as s3:*, but that's rarely a good idea)
Not only does the bucket need to permit access, but the users in the originating account must be granted permission to use S3 for the desired actions (eg s3:GetObject) on Bucket-A (or all buckets).
See: Bucket Owner Granting Cross-Account Bucket Permissions - Amazon Simple Storage Service
If I have an IAM role that gives access to a bucket, does that bucket ALSO need a bucket policy to specify that the role has access? Can I just have one or the other?
Example:
I have an IAM role that says
{
"Action": [
"s3:Get*",
"s3:Put*",
"s3:DeleteObject",
"s3:List*"
],
"Resource": [
"arn:aws:s3:::bucketname/*"
],
"Effect": "Allow"
}
The bucket has a policy attached but it doesn't include anything about the role with the above statement. There are no deny statements in the bucket policy. Should the role be able to access the files?
Typically, you do not need to provide an S3 bucket policy.
Whenever you make a request to S3, the authorization decision depends on the union of all the IAM policies, S3 bucket policies, and S3 ACLs that apply.
The order of policy evaluation is:
Is there an explicit Deny? Result is deny.
Is there an explicit Allow? Result is allow.
(implicit default) Result is deny.
Here is an interesting article from AWS comparing IAM Policy vs Bucket Policy vs ACL
If you’re more interested in “What can this user do in AWS?” then IAM
policies are probably the way to go. You can easily answer this by
looking up an IAM user and then examining their IAM policies to see
what rights they have.
If you’re more interested in “Who can access
this S3 bucket?” then S3 bucket policies will likely suit you better.
You can easily answer this by looking up a bucket and examining the
bucket policy.
https://aws.amazon.com/blogs/security/iam-policies-and-bucket-policies-and-acls-oh-my-controlling-access-to-s3-resources/
Using cloudformation I have launched an EC2 instance with a role that has an S3 policy which looks like the following
{"Statement":[{"Action":"s3:*","Resource":"*","Effect":"Allow"}]}
In S3 the bucket policy is like so
{
"Version": "2012-10-17",
"Id": "MyPolicy",
"Statement": [
{
"Sid": "ReadAccess",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456678:role/Production-WebRole-1G48DN4VC8840"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::web-deploy/*"
}
]
}
When I login to the instance and attempt to curl any object I upload into the bucket (without acl modifications) I receive and Unauthorized 403 error.
Is this the correct way to restrict access to a bucket to only instances launched with a specific role?
The EC2 instance role is more than sufficient to put/read to any of your S3 buckets, but you need to use the instance role, which is not done automatically by curl.
You should use for example aws s3 cp <local source> s3://<bucket>/<key>, which will automatically used the instance role.
There are three ways to grant access to an object in Amazon S3:
Object ACL: Specific objects can be marked as "Public", so anyone can access them.
Bucket Policy: A policy placed on a bucket to determine what access to Allow/Deny, either publicly or to specific Users.
IAM Policy: A policy placed on a User, Group or Role, granting them access to an AWS resource such as an Amazon S3 bucket.
If any of these policies grant access, the user can access the object(s) in Amazon S3. One exception is if there is a Deny policy, which overrides an Allow policy.
Role on the Amazon EC2 instance
You have granted this role to the Amazon EC2 instance:
{"Statement":[{"Action":"s3:*","Resource":"*","Effect":"Allow"}]}
This will provide credentials to the instance that can be accessed by the AWS Command-Line Interface (CLI) or any application using the AWS SDK. They will have unlimited access to Amazon S3 unless there is also a Deny policy that otherwise restricts access.
If anything, that policy is granting too much permission. It is allowing an application on that instance to do anything it wants to your Amazon S3 storage, including deleting it all! It is better to assign least privilege, only giving permission for what the applications need to do.
Amazon S3 Bucket Policy
You have also created a Bucket Policy, which allows anything that has assumed the Production-WebRole-1G48DN4VC8840 role to retrieve the contents of the web-deploy bucket.
It doesn't matter what specific permissions the role itself has -- this policy means that merely using the role to access the web-deploy bucket will allow it to read all files. Therefore, this policy alone would be sufficient to your requirement of granting bucket access to instances using the Role -- you do not also require the policy within the role itself.
So, why can't you access the content? It is because using a straight CURL does not identify your role/user. Amazon S3 receives the request and treats it as anonymous, thereby not granting access.
Try accessing the data via the CLI or programmatically via an SDK call. For example, this CLI command would download an object:
aws s3 cp s3://web-deploy/foo.txt foo.txt
The CLI will automatically grab credentials related to your role, allowing access to the objects.