AWS STS to list buckets gives access denied - amazon-web-services

I have a bucket with empty bucket policy, block public access turned ON (ACLs and Bucket) and trying to list buckets using IAM policy tied to user using STS AssumeRole with following attached policy.
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"s3:GetObject",
"s3:GetBucket*",
"s3:ListBucket*",
"s3:ListAllMyBuckets"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::my-test-bucket/*"
]
}
]
}
The assumed role credentials are used during the STS session in python (boto3)
s3c = boto3.client('s3',
aws_access_key_id=credentials['AccessKeyId'],
aws_secret_access_key=credentials['SecretAccessKey'],
aws_session_token=credentials['SessionToken'])
s3c.list_buckets()
I get this exception:
botocore.exceptions.ClientError: An error occurred (AccessDenied) when calling the ListBuckets operation: Access Denied
When I tried to use IAM Policy simulator, it indicates "Implicitly denied". Im thinking if I need to access a bucket policy for this user? My understanding has been if both IAM and Bucket policy, it is an intersection. If either is not present, the other takes precedence.

Calling list_buckets() uses the s3:ListAllMyBuckets permission.
This permission cannot be restricted to a specific bucket. A user can either list all of the buckets in the account, or none of them.
Calling operations on a bucket (ListBucket, GetBucket*) requires permission for the bucket itself.
Operations on objects requires permission for the objects (or /* after the bucket name to permit actions on all objects).
Therefore, you can change your policy to:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:ListAllMyBuckets",
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"s3:ListBucket",
"s3:GetBucket*"
],
"Resource": "arn:aws:s3:::my-test-bucket"
},
{
"Effect": "Allow",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::my-test-bucket/*"
}
]
}

This is a pretty common issue because people tend to miss the difference between a "bucket" resource and an "object" resource. A bucket ends in the name of the bucket (arn:aws:s3:::my-test-bucket) whereas an object includes the bucket and key, and is often granted with a star after the initial slash. So, just change your policy to the following.
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"s3:ListAllMyBuckets"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::my-test-bucket"
]
},
{
"Action": [
"s3:GetObject",
"s3:GetBucket*",
"s3:ListBucket*"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::my-test-bucket/*"
]
}
]
}

Related

Deploy Lambda with code source from another accounts s3 bucket

I store my Lambda zip files in an S3 bucket in Account A. In Account B I have my Lambda. I am trying to have my Lambda use the zip file in Account A's bucket but I keep getting:
Your access has been denied by S3, please make sure your request credentials have permission to GetObject for bucket/code.zip. S3 Error Code: AccessDenied. S3 Error Message: Access Denied
I have followed guides I have found online but I am still facing issues.
Here is my current config:
Account A's S3 Bucket Policy:
{
"Version": "2012-10-17",
"Id": "ExamplePolicy",
"Statement": [
{
"Sid": "ExampleStmt",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::AccountBID:role/MyLambdaRole"
},
"Action": [
"s3:GetObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::bucket",
"arn:aws:s3:::bucket/*"
]
}
]
}
Account B's Lambda Execution Role Policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::bucket/*",
"arn:aws:s3:::bucket"
]
}
]
}
The principal in your bucket policy is the role that AWS Lambda uses during execution, which is not used when deploying your function. You could easily just allow the entire B account principal in the bucket policy and then use IAM policies in account B to allow access to the bucket that way.
A bucket policy allowing an entire account looks like this:
{
"Version": "2008-10-17",
"Statement": [
{
"Sid": "ProductAccountAccess",
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::XXXX-account-number:root"
]
},
"Action": [
"s3:Get*",
"s3:List*"
],
"Resource": [
"arn:aws:s3:::bucket",
"arn:aws:s3:::bucket/*"
]
}
]
}
This means that the IAM policies in account B depend on how you do your deployment. Meaning that whatever credentials are used for the deployment need to have S3 permissions for that bucket.

AWS AccessDenied when calling sts:AssumeRole

I'm trying to allow a set of users in a group access to a role through which they can upload objects to an s3 bucket.
The group as the policy:
{
"Version": "2012-10-17",
"Statement": {
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::ACCOUNTID:role/Clinic_Sync"
}
}
The role "Clinic_Sync" has the policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "SyncReqs",
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:DeleteObject",
"s3:PutObjectAcl"
],
"Resource": "arn:aws:s3:::*/*"
},
{
"Sid": "SyncReqs2",
"Effect": "Allow",
"Action": [
"s3:ListBucket",
"s3:GetBucketLocation"
],
"Resource": "arn:aws:s3:::*"
}
]
}
The bucket has the policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::ACCOUNTID:role/Clinic_Sync"
},
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::mydata"
},
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::ACCOUNTID:role/Clinic_Sync"
},
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject"
],
"Resource": "arn:aws:s3:::mydata/*"
},
{
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::mydata",
"arn:aws:s3:::mydata/*"
],
"Condition": {
"StringNotLike": {
"aws:userId": [
"ADMINUSERID:*",
"ACCOUNTNO"
]
}
}
}
]
}
The idea being that no one can access the bucket except through assuming this role (other than the admin). I have created the credentials files as follows:
[default]
aws_access_key_id = ACCESSID1
aws_secret_access_key = SECRETKEY1
[csync]
role_arn = arn:aws:iam::ACCOUNTID:role/Clinic_Sync
source_profile = default
And the config file:
[default]
output = json
region = eu-west-2
[profile csync]
role_arn = arn:aws:iam::ACCOUNTID:role/Clinic_Sync
source_profile = default
The bucket policy seems to work, as running the command "aws s3 cp hello.txt s3://mydata" gives the error: Upload failed. An error occured when calling the PutObject operation: Access Denied.
But when I try to use the role, using the command "aws s3 cp hello.txt s3://run3d-data --profile csync", it gives this error:
upload failed: .\hello.txt to s3://mydata/hello.txt An error occurred (AccessDenied) when calling the AssumeRole operation: User: arn:aws:iam::ACCOUNTID:user/TestAcc2 is not authorized to perform: sts:AssumeRole on resource: arn:aws:iam::ACCOUNTID:role/Clinic_Sync
I've been searching the web for an answer for ages and can't find any answers. The aws documentation is frankly unintelligible to me. If anyone can help me find a solution to this I'd be much appreciated as I'm tearing my hair out here.
To reiterate, I just want the users in a particular group to have access to a role that grants them permission to use an s3 bucket, but block all other access to the bucket.
Your bucket policy seems to say: "Deny access to the bucket unless aws:userId is a given Admin User ID or Account Number. It does not reference the Role.
Therefore, accessing the bucket via the Role will be denied. This is because Deny always overrides Allow.
Writing policies with Deny can be quite difficult, as seen in this situation.
If you really want to keep a bucket secure, it is easier to put the bucket in a separate AWS Account and only grant cross-account access to the entities that should have access. This way, no Deny policy is required.
If you receive a not authorised to perform sts:AssumeRole error, make sure the Trust Policy grants access to users by selecting the Another AWS account option when creating the role. The policy should look similar to:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::111111111111:root"
},
"Action": "sts:AssumeRole",
"Condition": {}
}
]
}

AWS policy to allow access only to a specific bucket folder

I am trying to create an IAM policy to allow a user access only to a specific folder in an S3 bucket.
How do I do this using visual policy editor?
In the resource section if I mention the arn for the folder, the user is being denied access to the whole bucket.
Here is a policy that grants access to a specific folder within a bucket:
{
"Version": "2012-10-17",
"Statement": [
{
"Action": ["s3:ListBucket"],
"Effect": "Allow",
"Resource": ["arn:aws:s3:::mybucket"],
"Condition": {"StringLike": {"s3:prefix": ["folder1/*"]}}
},
{
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Effect": "Allow",
"Resource": ["arn:aws:s3:::mybucket/folder1/*"]
}
]
}
Things to note:
The ListBucket operation that allows listing a bucket is a permission on the bucket itself (not a path). To restrict which folders they can list, the folder must be specified via the s3:prefix.
The GetObject and PutObject operations operate on objects, so the folder can be referenced in the ARN.
It is also possible to use IAM Policy Elements: Variables and Tags to refer to a username. This policy can be applied to an IAM Group and will allow each user access to a folder with their own name:
{
"Version": "2012-10-17",
"Statement": [
{
"Action": ["s3:ListBucket"],
"Effect": "Allow",
"Resource": ["arn:aws:s3:::mybucket"],
"Condition": {"StringLike": {"s3:prefix": ["${aws:username}/*"]}}
},
{
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Effect": "Allow",
"Resource": ["arn:aws:s3:::mybucket/${aws:username}/*"]
}
]
}

S3 replication: Access denied: Amazon S3 can't detect whether versioning is enabled on the destination bucket

I'm configuring a replication between two s3 buckets. but I get the error
Access denied: Amazon S3 can't detect whether versioning is enabled on
the destination bucket.
The destination bucket is in another account, different region.
Here is the bucket policy in the destination bucket:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::destination",
"arn:aws:s3:::destination/*"
],
"Condition": {
"StringNotLike": {
"aws:userId": [
"AROAS3AHCETXXDF5Z5GVG:*",
"AROAS3AHCETXX2DMH4JPY:*",
"AROAS3AHCEXXX4SNCNTNV:*",
"AROAVJZZXXXXXZBBR7PN6L:*"
]
}
}
},
{
"Sid": "S3ReplicationPolicyStmt1",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::XXXXXXXXXXX:root"
},
"Action": [
"s3:GetBucketVersioning",
"s3:GetObjectVersionForReplication",
"s3:PutBucketVersioning",
"s3:ReplicateObject",
"s3:ReplicateDelete",
"s3:PutObjectAcl",
"s3:ObjectOwnerOverrideToBucketOwner"
],
"Resource": [
"arn:aws:s3:::destination",
"arn:aws:s3:::destination/*"
]
}
]
}
My buckets are highly confidential, so I first deny all access except for some roles: So in the condition, I have the replication role ID excluded too.
Why the replication role is still not allowed to replicate? What is wrong with this bucket policy ?
In the above policy I actually authorize the replication role twice. in both statements.
Here is the replication IAM role policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"s3:Get*",
"s3:ListBucket"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::source",
"arn:aws:s3:::source/*"
]
},
{
"Action": [
"s3:ReplicateObject",
"s3:ReplicateDelete",
"s3:ReplicateTags",
"s3:GetBucketVersioning",
"s3:GetObjectVersionTagging",
"s3:ObjectOwnerOverrideToBucketOwner"
],
"Effect": "Allow",
"Resource": "arn:aws:s3:::destination/*"
}
]
}
I tried deleting the explicite deny statement and test the replication, the source bucket gets the Versioning and I had no access denied, but objects are not replicated.
For my experience, AWS S3 policies follow a white-list approach, meaning that you first need to add statements for the actions you want to allow, and then a final statement to deny everything else.
So in your case, try to just switch the statements.
The solution was to white list the replication role in the source bucket as well. Both buckets have similar policy so It was necessary to allow the replication role to access the source.

S3 Policy to Allow Lambda

I have the following policy on an S3 bucket created with the AWS policy generator to allow a lambda, running with a specific role, access to the files in the bucket. However, when I execute the Lambda, I get 403 permission denied:
"errorMessage": "Access Denied (Service: Amazon S3; Status Code: 403; Error Code: AccessDenied; Request ID: <requestId>)",
"errorType": "com.amazonaws.services.s3.model.AmazonS3Exception",
The Policy on the S3 bucket:
{
"Version": "2012-10-17",
"Id": "Policy<number>",
"Statement": [
{
"Sid": "Stmt<number>",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::<account>:role/<roleName>"
},
"Action": "s3:*",
"Resource": "arn:aws:s3:::<bucketName>/*"
}
]
}
What is wrong with the policy? The Lamba is running with the role configured in the policy.
A role assigned to an AWS Lambda function should be created with an AWS Lambda role (that is selected when creating a Role in the IAM console).
Roles do not have a Principal since the permissions are assigned to whichever service (in this case, Lambda function) is using the role.
Also, you should assign permissions on the bucket itself (e.g. to list contents) and on the contents of the bucket (e.g. to GetObject).
It would be something like this:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowS3Access",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123XXX:role/service-role/LAMBDA_ROLE_NAME"
},
"Action": [
"s3:*"
],
"Resource": [
"arn:aws:s3:::my-bucket",
"arn:aws:s3:::my-bucket/*"
]
}
]
}
After looping for I while i could make it work, the process is:
create the s3 bucket.
create the IAM policy (bucket name needed)
Create IAM role (IAM policy needed)
Create lambda Function (IAM Role needed)
Create s3 bucket policy (lambda function name needed)
IAM Policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt*******",
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:PutObjectAcl",
"s3:PutObjectTagging",
"s3:PutObjectVersionAcl",
"s3:PutObjectVersionTagging"
],
"Resource": [
"arn:aws:s3:::<bucket-name>"
]
}
]
}
and I use this policy on the s3 Bucket
{
"Id": "Policy************",
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt********",
"Action": [
"s3:PutObject",
"s3:PutObjectAcl",
"s3:PutObjectTagging",
"s3:PutObjectVersionAcl",
"s3:PutObjectVersionTagging"
],
"Effect": "Allow",
"Resource": "arn:aws:s3:::<bucket-name>/*",
"Principal": {
"AWS": [
"arn:aws:iam::*********:role/<lambda-function-name>"
]
}
}
]
}