What role permissions are required to use get_contents_to_filename? - amazon-s3

I recently setup an IAM role for accessing a bucket with the following policy:
{
"Statement": [
{
"Sid": "Stmt1359923112752",
"Action": [
"s3:*"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::<BUCKET_NAME>"
]
}
]
}
While I can list the contents of the bucket fine, when I call get_contents_to_filename on a particular key, I receive a boto.exception.S3ResponseError: S3ResponseError: 403 Forbidden exception.
Is there a role permission that I need to add to fetch keys from S3? I have checked the permissions on the individual key, and there appears to be nothing that explicitly forbids access to other users; there is only a single permission that grants the owner full permissions.
For completeness, I verified that removing the role policy above prevents access to the bucket completely thus it's not an issue with the policy being applied.
Thanks!

You have to give permission to the objects in the bucket, not just to the bucket. So your resource would have to be arn:aws:s3:::<bucketname>/*. That matches every object.
Unfortunately, that doesn't match the bucket itself. So you either need to give bucket related permissions to arn:aws:s3:::<bucketname> and object permissions to arn:aws:s3:::<bucketname>/*, or just give permissions to arn:aws:s3:::<bucketname>*. Though in that latter case, giving permissions to a bucket named fred would also give the same permissions to one named freddy.

Related

AWS StsClient: User not authorized to perform: sts:AssumeRole on resource

By trying to get s3 object(of account1) from ec2 instance(of account2), the Sts session creation is failed with error:
"User arn:aws:sts::99*804963:assumed-role/i-9B6331541002f46-us-west is not authorized to perform: sts:AssumeRole on resource: arn:aws:iam::85*****15:role/MyS3DataReadRole
To provide access to fetch s3 object:
I've created permission in account2 with GetObject access to the s3 object(arn).
I've provided trust relationship for the role, where Principal.AWS = arn:aws:sts::99*804963:role/i-9B6331541002f46-us-west
The only suspicious point here is "assumed-role" instead of "role" in the user instance arn. AFAIK The user arn is calculated automatically by AWS SDK automatically, but I can't understand why "assumed-" prefix is added before the "role". I.e. in error message is mentioned: "arn:aws:sts::99804963:assumed-role/i-9B6331541002f46-us-west"
but in trust relationship I've provided correct arn, i.e. "arn:aws:sts::99804963:role/i-9B6331541002f46-us-west"
You also have to create the assume role policy and attach it to the EC2 instance role (99*804963) so that EC2 instance role can have permissions to assume the role (85*****15:role) which has read permissions for the S3 object.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::85*****15:role/MyS3DataReadRole"
}
]
}
Please update the account id in the above policy with actual one.

AWS policy evaluation

I have an IAM role to be attached to a microservice in order to limit S3 folder access based on user-agent. The microservice parent account and the bucket owner are the same.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:*"
],
"Resource": [
"arn:aws:s3:::bucket-test/service/${aws:useragent}/*"
]
},
{
"Sid": "AllowListingOfUserFolder",
"Action": [
"s3:ListBucket"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::bucket-test"
],
"Condition": {
"StringLike": {
"s3:prefix": [
"service/${aws:useragent}/*"
]
}
}
}
]
}
The same S3 bucket has a default ACL where the account has R/W on objects and permissions.
Given the ACL and the IAM policy, I don't understand how this policy evaluates. For example, a user with the above role makes a put_object request to bucket-test/service/micro-b/new_object with user agent micro-a. Is this an explicit or implicit deny? Why?
Based on AWS Policy evaluation logic:
When a request is made, the AWS service decides whether a given request should be allowed or denied. The evaluation logic follows these rules:
By default, all requests are denied. (In general, requests made
using the account credentials for resources in the account are
always allowed.)
An explicit allow overrides this default.
An explicit deny overrides any allows.
Now if we look at S3 access policy language documentation:
Effect – What the effect will be when the user requests the specific action—this can be either allow or deny.
If you do not explicitly grant access to (allow) a resource, access is implicitly denied. You can also explicitly deny access to a resource, which you might do in order to make sure that a user cannot access it, even if a different policy grants access.
Now specifying Conditions in S3 policy documentation:
The access policy language allows you to specify conditions when granting permissions. The Condition element (or Condition block) lets you specify conditions for when a policy is in effect.
From these 3 pieces, specially the last one we can say that your case is "Conditional allow", because "Condition element lets you specify conditions for when a policy is in effect" and here the condition in your policy is "Allow".
EDIT:
Here is another interesting blog from AWS on "How does authorization work with multiple access control mechanisms?"
Whenever an AWS principal issues a request to S3, the authorization decision depends on the union of all the IAM policies, S3 bucket policies, and S3 ACLs that apply.
In accordance with the principle of least-privilege, decisions default
to DENY and an explicit DENY always trumps an ALLOW. For example, if
an IAM policy grants access to an object, the S3 bucket policies
denies access to that object, and there is no S3 ACL, then access will
be denied. Similarly, if no method specifies an ALLOW, then the
request will be denied by default. Only if no method specifies a DENY
and one or more methods specify an ALLOW will the request be allowed.

amazon s3 invalid principal in bucket policy

I'm trying to create a new bucket policy in the Amazon S3 console and get the error
Invalid principal in policy - "AWS" : "my_username"
The username I'm using in principal is my default bucket grantee.
My policy
{
"Id": "Policy14343243265",
"Statement": [
{
"Sid": "SSdgfgf432432432435",
"Action": [
"s3:DeleteObject",
"s3:DeleteObjectVersion",
"s3:GetObject",
"s3:GetObjectVersion",
"s3:GetObjectVersionAcl",
"s3:PutObject",
"s3:PutObjectAcl",
"s3:PutObjectVersionAcl"
],
"Effect": "Allow",
"Resource": "arn:aws:s3:::my_bucket/*",
"Principal": {
"AWS": [
"my_username"
]
}
}
]
}
I don;t understand why I'm getting the error. What am I doing wrong?
As the error message says, your principal is incorrect. Check the S3 documentation on specifying Principals for how to fix it. As seen in the example policies, it needs to be something like arn:aws:iam::111122223333:root.
I was also getting the same error in the S3 Bucket policy generator. It turned out that one of the existing policies had a principal that had been deleted. The problem was not with the policy that was being added.
In this instance, to spot the policy that is bad you can look for a principal that does not have an account or a role in the ARN.
So, instead of looking like this:
"Principal": {
"AWS": "arn:aws:iam::123456789101:role/MyCoolRole"
}
It will look something like this:
"Principal": {
"AWS": "ABCDEFGHIJKLMNOP"
}
So instead of a proper ARN it will be an alphanumeric key like ABCDEFGHIJKLMNOP. In this case you will want to identify why the bad principal was there and most likely modify or delete it. Hopefully this will help someone as it was hard to track down for me and I didn't find any documentation to indicate this.
Better solution:
Create an IAM policy that gives access to the bucket
Assign it to a group
Put user into that group
Instead of saying "This bucket is allowed to be touched by this user", you can define "These are the people that can touch this".
It sounds silly right now, but wait till you add 42 more buckets and 60 users to the mix. Having a central spot to manage all resource access will save the day.
The value for Principal should be user arn which you can find in Summary section by clicking on your username in IAM.
It is because so that specific user can bind with the S3 Bucket Policy
In my case, it is arn:aws:iam::332490955950:user/sample ==> sample is the username
I was getting the same error message when I tried creating the bucket, bucket policy and principal (IAM user) inside the same CloudFormation stack. Although I could see that CF completed the IAM user creation before even starting the bucket policy creation, the stack deployment failed. Adding a DependsOn: MyIamUser to the BucketPolicy resource fixed it for me.
Why am I getting the error "Invalid principal in policy" when I try to update my Amazon S3 bucket policy?
Issue
I'm trying to add or edit the bucket policy of my Amazon Simple Storage Service (Amazon S3) bucket using the web console, awscli or terraform (etc). However, I'm getting the error message "Error: Invalid principal in policy." How can I fix this?
Resolution
You receive "Error: Invalid principal in policy" when the value of a Principal in your bucket policy is invalid. To fix this error, review the Principal elements in your bucket policy. Check that they're using one of these supported values:
The Amazon Resource Name (ARN) of an AWS Identity and Access Management (IAM) user or role --
Note: To find the ARN of an IAM user, run the [aws iam get-user][2] command. To find the ARN of an IAM role, run the [aws iam get-role][2] command or just go and check it from the IAM service in your account web console UI.
An AWS account ID
The string "*" to represent all users
Additionally, review the Principal elements in the policy and check that they're formatted correctly. If the Principal is one user, the element must be in this format:
"Principal": {
"AWS": "arn:aws:iam::AWS-account-ID:user/user-name1"
}
If the Principal is more than one user but not all users, the element must be in this format:
"Principal": {
"AWS": [
"arn:aws:iam::AWS-account-ID:user/user-name1",
"arn:aws:iam::AWS-account-ID:user/user-name2"
]
}
If the Principal is all users, the element must be in this format:
{
"Principal": "*"
}
If you find invalid Principal values, you must correct them so that you can save changes to your bucket policy.
Extra points!
AWS Policy Generator
Bucket Policy Examples
Ref-link: https://aws.amazon.com/premiumsupport/knowledge-center/s3-invalid-principal-in-policy-error/
I was facing the same issue when I've created a bash script to initiate my terraform s3 backend. After a few hours I've decided just to put sleep 5 after user creation and that made sense, you can notice it at the line 27 of my script
If you are getting the error Invalid principal in policy in S3 bucket policies, the following 3 steps are the way to resolve it.
1 Your bucket policy uses supported values for a Principal element
The Amazon Resource Name (ARN) of an IAM user or role
An AWS account ID
The string "*" to represent all users
2 The Principal value is formatted correctly
If the Principal is one user
"Principal": {
"AWS": "arn:aws:iam::111111111111:user/user-name1"
}
If the Principal is more than one user but not all users
"Principal": {
"AWS": [
"arn:aws:iam::111111111111:user/user-name1",
"arn:aws:iam::111111111111:user/user-name2"
]
}
If the Principal is all users
{
"Principal": "*"
}
3 The IAM user or role wasn't deleted
If your bucket policy uses IAM users or roles as Principals, then confirm that those IAM identities weren't deleted. When you edit and then try to save a bucket policy with a deleted IAM ARN, you get the "Invalid principal in policy" error.
Read more here.
FYI: If you are trying to give access to a bucket for a region that is not enabled it will give the same error.
From AWS Docs: If your S3 bucket is in an AWS Region that isn't enabled by default, confirm that the IAM principal's account has the AWS Region enabled. For more information, see Managing AWS Regions.
If you are trying to give Account_X_ID access to the my_bucket like below. You need to enable the region of my_bucket on Account_X_ID.
"Principal": {
"AWS": [
"arn:aws:iam::<Account_X_ID>:root"
]
}
"Resource": "arn:aws:s3:::my_bucket/*",
Hope this helps someone.

Why might boto be denied access to S3 with proper IAM keys?

I am trying to access a bucket on S3 with boto. I have been given read access to the bucket and my keys are working when I explore it in S3 Browser. The following code is returning 403 Forbidden Access Denied.
conn = S3Connection('Access_Key_ID', 'Secret_Access_Key')
conn.get_all_buckets()
This also occurs when using the access key and secret access key via the boto config file. Is there something else I need to be doing because the keys are from IAM perhaps? Could this indicate an error in the setup? I don't know much about IAM, I was just given the keys.
Some things to check...
If you are using boto, be sure you are using conn.get_bucket(bucket_name) to access only the bucket you have permission to access.
In your IAM (user) policy, if you are restricting access to a single
bucket, be sure that the policy includes adequate permissions to the
bucket and do not include a trailing slash+asterisks for the ARN name (see example below).
Be sure to set "Upload/Delete" permissions for "Authenticated Users" in S3 for the bucket.
Permissions sample:
IAM policy sample:
NOTE: The SID will be automatically generated when using the policy generator
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"s3:*"
],
"Sid": "Stmt0000000000001",
"Resource": [
"arn:aws:s3:::myBucketName"
],
"Effect": "Allow"
}
]
}
My guess is that it's because you're calling conn.get_all_buckets() instead of conn.get_bucket(bucket_name) for the individual bucket you have access to.
from boto.s3.connection import S3Connection
conn = S3Connection('access key', 'secret access key')
allBuckets = conn.get_all_buckets()
for bucket in allBuckets:
print(str(bucket.name))

How can I make a S3 bucket public (the amazon example policy doesn't work)?

Amazon provides an example for Granting Permission to an Anonymous User as follows (see Example Cases for Amazon S3 Bucket Policies):
{
"Version": "2008-10-17",
"Statement": [
{
"Sid": "AddPerm",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::bucket/*"
}
]
}
Within my policy I've changed "bucket" in ""arn:aws:s3:::bucket/" to "my-bucket".
However, once I try to access an image within a folder of that bucket, I get the following Access denied error:
This XML file does not appear to have any style information associated
with it. The document tree is shown below.
(if I explicitly change the properties of that image to public, then reload its url, the image loads perfectly)
What am I doing wrong?
Update #1: Apparently it has something to do with a third party site that I've given access to. Although it has all of the permissions as the main user (me), and its objects are in the same folder, with the exact same permissions, it still won't let me make them publicly viewable. No idea why.
Update #2: Bucket policies do not apply to objects "owned" by others, even though they are within your bucket, see my answer for details.
Update
As per GoodGets' comment, the real issue has been that bucket policies to do not apply to objects "owned" by someone else, even though they are in your bucket, see GoodGets' own answer for details (+1).
Is this a new bucket/object setup or are you trying to add a bucket policy to a pre-existing setup?
In the latter case you might have stumbled over a related pitfall due to the interaction between the meanwhile three different S3 access control mechanisms available, which can be rather confusing indeed. This is addressed e.g. in Using ACLs and Bucket Policies Together:
When you have ACLs and bucket policies assigned to buckets, Amazon S3
evaluates the existing Amazon S3 ACLs as well as the bucket policy
when determining an account’s access permissions to an Amazon S3
resource. If an account has access to resources that an ACL or policy
specifies, they are able to access the requested resource.
While this sounds easy enough, unintentional interferences may result from the subtle different defaults between ACLs an policies:
With existing Amazon S3 ACLs, a grant always provides access to a
bucket or object. When using policies, a deny always overrides a
grant. [emphasis mine]
This explains why adding an ACL grant always guarantees access, however, this does not apply to adding a policy grant, because an explicit policy deny provided elsewhere in your setup would still be enforced, as further illustrated in e.g. IAM and Bucket Policies Together and Evaluation Logic.
Consequently I recommend to start with a fresh bucket/object setup to test the desired configuration before applying it to a production scenario (which might still interfere of course, but identifying/debugging the difference will be easier in case).
Good luck!
Bucket policies do not apply files with other owners. So although I've given write access to a third party, the ownership remains them, and my bucket policy will not apply to those objects.
I wasted hours on this, the root cause was stupid, and the solutions mentioned here didn't help (I tried them all), and the AWS s3 permissions docs didn't emphasize this point.
If you have Requester Pays setting ON, you cannot enable Anonymous access (either by bucket policy or ACL 'Everyone'). You can sure write the policies and ACL and apply them and even use the console to explicitly set a file to public, but a non signed url will still get a 403 access denied 100% of the time on that file, until you uncheck requester pays setting in the console for the entire bucket (properties tab when bucket is selected). Or, I assume, via some API REST call.
Unchecked Requester Pays and now anonymous access is working, with referrer restrictions, ect. In fairness, the AWS console does tell us:
While Requester Pays is enabled, anonymous access to this bucket is disabled.
The issue is with your Action it should be in array format
Try this:
{
"Version":"2012-10-17",
"Statement":[
{
"Sid":"AddPerm",
"Effect":"Allow",
"Principal": "*",
"Action":["s3:GetObject"],
"Resource":["arn:aws:s3:::examplebucket/*"]
}
]
}
Pass your Bucket name in 'Resource'
If you're having this problem with Zencoder uploads, checkout this page: https://app.zencoder.com/docs/api/encoding/s3-settings/public
The following policy will make the entire bucket public :
{
"Version":"2012-10-17",
"Statement":[
{
"Sid":"AddPerm",
"Effect":"Allow",
"Principal": "*",
"Action":["s3:GetObject"],
"Resource":["arn:aws:s3:::examplebucket/*"]
}
]
}
If you want a specific folder under that bucket to be public using Bucket policies , then you have to explicitly make that folder/prefix as public and then apply the bucket policy as follows :
{
"Version":"2012-10-17",
"Statement":[
{
"Sid":"AddPerm",
"Effect":"Allow",
"Principal": "*",
"Action":["s3:GetObject"],
"Resource":["arn:aws:s3:::examplebucket/images/*"]
}
]
}
The above policy will allow public read to all of the objects under images , but you will not be able to access other objects inside the bucket.
I know it is an old question but I would like to add information that may still be relevant today.
I believe that this bucket should be a static site. Because of this, you must use a specific URL for your rules to be accepted. To do this, you must add a "website" to your URL. Otherwise, it will treat it just like an object repository.
Example:
With the problem pointed out:
https://name-your-bucket.sa-east-1.amazonaws.com/home
Without the problem pointed out:
http://name-your-bucket.s3-website-sa-east-1.amazonaws.com/home
Hope this helps :)
This works.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicRead",
"Effect": "Allow",
"Principal": "*",
"Action": [
"s3:GetObject",
"s3:GetObjectVersion"
],
"Resource": "arn:aws:s3:::example-bucket/*"
}
]
}