Limit AWS S3 Bucket to only Lambda access - amazon-web-services

I am using an AWS S3 bucket to hold configuration files for Java AWS Lambdas. How do I configure the bucket to only allow access to any lambda function and nothing else?

You need to add s3 bucket policy for account 123456789012 in region us-east-1 -
{
"Id": "Policy1498253351771",
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1498253327847",
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Effect": "Allow",
"Resource": "arn:aws:s3:::<bucket_name>/<prefix>",
"Principal": {
"AWS": [
"arn:aws:lambda:us-east-1:123456789012:function:*"
]
}
}
]
}
Above is a general policy for all lambda functions.
If you need to generate a more granular policy as per your usecase , you can try AWS Policy Generator

Related

How to only allow one Service Role to PutObjects to an Amazon S3 bucket

I have an Amazon S3 bucket "my-bucket" on a AWS account. Right now everyone on the account can download and put objects to "my-bucket. However, I would like everyone to be able to download/delete objects from the bucket, and only one service role (lambda) to be able to put objects to the bucket.
The lambda role already have access to PutObjects to the bucket, so I guess I would want to make a bucket policy to only allow my lambda role to PutObjects but still allow everyone else to download/delete objects on the bucket. I am however not sure how that bucket policy would look like. I guess I have to use a condition? Something like?
{
"Version":"2012-10-17",
"Statement":[
{
"Sid":"MyRule",
"Effect": "Deny",
"Action":["s3:PutObject"],
"Resource": ["arn:aws:s3:::my-bucket/*", "arn:aws:s3:::my-bucket*"],
"Condition":{"NOT EQUAL TO LAMBDA ROLE???"}
}
]
}
Bucket policy is resourced based policy so principle can be used to restrict the access to specific identity
you can prepare policy like below for everyone to download and delete object
{
"Version":"2012-10-17",
"Statement":[
{
"Sid":"PublicReadDelete",
"Effect":"Allow",
"Principal": "*",
"Action":["s3:GetObject","s3:DeleteObject"],
"Resource":["arn:aws-cn:s3:::/*"]
}
]
}
below policy for lambda to put objects
{
"Version":"2012-10-17",
"Statement":[
{
"Sid":"LambdaUpload",
"Effect":"Allow",
"Principal": "<your lambda function ARN>",
"Action":["s3:PutObject"],
"Resource":["arn:aws-cn:s3:::/*"]
}
]
}
you can combine both statement in same policy. you just need replace your lambda function ARN and S3 bucket ARN or name
You can achieve this in two ways:
By using Principal, where you will explicitly list your Lambda role arn
By using a Deny statement with a Condition (the method you are suggesting).
With option 1, you will have something like:
"Sid": "AllowPutForLambda",
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::01234567890:role/my-lambda-role"
]
},
"Action": [
"s3:PutObject"
],
"Resource": "arn:aws:s3:::my-bucket/*"
}
With Option 2, it will look like this:
{
"Sid": "DenyAllExceptMyPreciousLambda",
"Effect": "Deny",
"Principal": "*",
"Action": [
"s3:PutObject"
],
"Resource": [
"arn:aws:s3:::my-bucket/*",
"arn:aws:s3:::my-bucket"
],
"Condition": {
"StringNotLike": {
"aws:userid": [
"AROAID1GMAMBDAROLEID:*",
]
}
}
where the "AROAID1GMAMBDAROLEID" string is the unique identifier of the calling entity (in this case the IAM UserId for the Lambda IAM role).
You can get the unique ID of your lambda role by using the get-role aws-cli command:
aws iam get-role --role-name MyLambdaRoleName

Uploading to AWS S3 bucket from a profile in a different environment

I have access to one of two AWS environments and I've created a protected S3 bucket in it to upload files to from an account in the one that I do not. The environment and the account that I don't have access to are what a project's CI uses.
environment I have access to: env1
environment I do not have access to: env2
account I do not have access to: user/ci
bucket name: content
S3 bucket policy:
{
"Version": "2008-10-17",
"Id": "PolicyForCloudFrontPrivateContent",
"Statement": [
{
...
},
{
"Sid": "Allow access to bucket from profile in env1",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::111122223333:user/ci"
},
"Action": [
"s3:GetBucketLocation",
"s3:ListBucket*"
],
"Resource": "arn:aws:s3:::content"
},
{
"Sid": "Allow access to bucket items from profile in env1",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::111122223333:user/ci"
},
"Action": [
"s3:Get*",
"s3:PutObject",
"s3:ListMultipartUploadParts"
],
"Resource": [
"arn:aws:s3:::content",
"arn:aws:s3:::content/*"
]
}
]
}
From inside a container that's configured for env1 and user/ci I'm testing with the command
aws s3 sync content/ s3://content/
and I get the error:
fatal error: An error occurred (AccessDenied) when calling the ListObjectsV2 operation: Access Denied
I have two questions:
Am I even using the correct aws command to upload the data to the bucket?
Am I missing something from my bucket policy?
For the latter, I've basically followed what a load of examples and answers online have suggested.
To test your policy, I did the following:
Created an IAM User with no policies
Created an Amazon S3 bucket
Attached your Bucket Policy to the bucket, and updated the ARN and bucket name
Tested access to the bucket with:
aws s3 ls s3://bucketname
aws s3 sync folder/ s3://bucketname/folder/
It worked fine.
Therefore, the policy you display appears to be giving all necessary permissions. It is possible that you have something else that is Denying access on the bucket.
The solution was to given the ACL
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:PutObjectAcl"
],
"Resource": [
"arn:aws:s3:::content",
"arn:aws:s3:::content/*"
]
}
]
}
to user/ci in env1.

Cross-Account IAM Access Denied with GUI Client, but permitted via CLI

I am stuck with provisioning end-user access into a cross account shared bucket, and need help figuring out if there are specific policy requirements for using clients to access the bucket, vs straight CLI.
IAM User Accounts are managed in our "Core" AWS Account.
S3 Bucket is provisioned in our "Dev" AWS Account.
S3 Bucket in Dev account is encrypted with KMS key in Dev Account.
We have configured our Bucket Policy to permit the user access.
We have configured user policies to permit access to the S3 bucket.
We have configured user policies to permit use of the KMS key.
When using the CLI our user account can succesfully access and use the S3 bucket. When attempting to connect with a GUI Client (Win-SCP, CyberDuck, MAC ForkLift) we receive permission denied errors.
BUCKET POLICY
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ListObjectsInBucket",
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::[DEVACCOUNT#]:role/EC2-ROLE-FOR-APP-ACCESS",
"arn:aws:iam::[COREACCOUNT#]:user/end.user"
]
},
"Action": "s3:List*",
"Resource": [
"arn:aws:s3:::dev-mybucket",
"arn:aws:s3:::dev-mybucket/*"
]
},
{
"Sid": "AllObjectActions",
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::[DEVACCOUNT#]:role/EC2-ROLE-FOR-APP-ACCESS",
"arn:aws:iam::[COREACCOUNT#]:user/end.user"
]
},
"Action": [
"s3:GetObject",
"s3:Put*"
],
"Resource": "arn:aws:s3:::dev-mybucket/*"
}
]
}
User Policy - access KMS
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowUseOfDevAPPSKey",
"Effect": "Allow",
"Action": [
"kms:Encrypt",
"kms:Decrypt",
"kms:ReEncrypt*",
"kms:GenerateDataKey*",
"kms:Describe*"
],
"Resource": [
"arn:aws:kms:ca-central-1:[DEVACCOUNT#]:key/[redacted-key-number]"
]
},
{
"Sid": "AllowAttachmentOfPersistentResources",
"Effect": "Allow",
"Action": [
"kms:CreateGrant",
"kms:List*",
"kms:RevokeGrant"
],
"Resource": [
"arn:aws:kms:ca-central-1:[DEVACCOUNT#]:key/[redacted-key-number]"
],
"Condition": {
"Bool": {
"kms:GrantIsForAWSResource": true
}
}
}
]
}
User policy - Access S3 Bucket
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowAccessToMyBucket",
"Effect": "Allow",
"Action": [
"s3:*"
],
"Resource": [
"arn:aws:s3:::dev-mybucket/",
"arn:aws:s3:::dev-mybucket/*"
]
}
]
}
From aws s3 commands we can 'ls' content and 'cp' content from local to remote and from remote to local.
When configuring access with the GUI Clients we always receive somewhat generic 'permission denied' or 'access denied' type errors.
The GUI client is probably making a call that is not List*, Put* or GetObject.
For example, it might be calling GetObjectVersion, GetObjectAcl or GetBucketAcl.
Try adding Get* permissions in addition to List*.
You might also be able to look at the events in your AWS CloudTrail trail to see what specific API calls were denied.
For details, see: Specifying Permissions in a Policy - Amazon Simple Storage Service
Access to an S3 bucket via a GUI such as the AWS web console or SFTP clients with s3 functionality(FileZilla, Cyberduck, ForkLift, etc.) requires the s3:ListAllMyBuckets action in a policy attached to that IAM user. This is very unfortunate as the user will now have access to see ALL your bucket names in that account even if they just have read, write, and or List access to just one bucket in that account.
https://docs.aws.amazon.com/AmazonS3/latest/API/API_Operations.html
https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListBuckets.html
One other option is to go to the bucket URL directly. The user/role will require access via that bucket's Bucket policy.
https://s3.console.aws.amazon.com/s3/buckets/dev-mybucket

AWS IAM Policy Issues writing to s3 bucket for Grafana alerts

Having some issues with AWS permissions and policies for grafana to be able to upload images. First off I tried with a custom policy attached to my user based on the requirements here https://grafana.com/docs/installation/configuration/#access-key.
Here's the policy:
custom policy with locked down permissions and bucket name
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:PutObjectAcl"
],
"Resource": "arn:aws:s3:::myclient-grafana-images"
}
]
}
This unfortunately didn't work and can see an access denied error in my grafana logs. The user is trying to write an image to the bucket and ended up adding the AWS predefined policy for s3 full access. This managed to get it working
s3 full access policy
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:*",
"Resource": "*"
}
]
}
The question is trying to lock the policy down just to the bucket that I need. I've tried creating a new policy with the full access policy and updated the wildcard to reference the s3 arn but that didn't work either.
Any suggestions on the best way to lock down the policies.
The PutObject and PutObjectAcl actions work on objects, not buckets.
This means that your Resource key should represent objects. ARN for objects start with the bucket name but are followed by a / and a path.
You should adapt your policy in the following way if you want to be able to put any object in your bucket (note the /*):
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:PutObjectAcl"
],
"Resource": "arn:aws:s3:::myclient-grafana-images/*"
}
]
}

Cross account role granting S3 bucket access - Permission Denied

I have two accounts, account ACCOUNTAAAA, and ACCOUNTBBBB. A bucket (BUCKETAAAA) exists in account ACCOUNTAAAA and an instance with a role (ROLEBBBB) in ACCOUNTBBBB needs to be able to read from it.
I have adding the following permissions to the bucket:
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::ACCOUNTBBBB:role/ROLEBBBB"
},
"Action": [
"s3:*"
],
"Resource": "arn:aws:s3:::BUCKETAAAA/*"
}
I have the following permissions on the role in ACOUNTBBBB:
"Sid": "",
"Effect": "Allow",
"Action": [
"s3:*"
],
"Resource": [
"arn:aws:s3:::BUCKETAAAA/",
"arn:aws:s3:::BUCKETAAAA/*"
]
}
My assumption is I should be able to run aws s3 ls s3://BUCKETAAAA on the EC2 instance with the IAM role attached, and see the contants of BUCKETAAAA. When I try this, I get An error occurred (AccessDenied) when calling the ListObjects operation: Access Denied.
What am I missing here?
To reproduce your situation, I did the following:
Created Role-B in Account-B with EC2 as the Trusted Entity ("Allows EC2 instances to call AWS services on your behalf") and a policy granting access to Bucket-A
Created Bucket-A in Account-A
Added a Bucket Policy to Bucket-A, which grants access to Role-B
Assigned Role-B to an Amazon EC2 instance
The Bucket Policy on Bucket-A was:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AddPerm",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::<account>:role/role-b"
},
"Action": [
"s3:*"
],
"Resource": [
"arn:aws:s3:::bucket-a",
"arn:aws:s3:::bucket-a/*"
]
}
]
}
The permissions on Role-B were:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "BucketA",
"Effect": "Allow",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::bucket-a",
"arn:aws:s3:::bucket-a/*"
]
}
]
}
I was able to successfully use aws s3 ls s3://bucket-a and was able to copy files to Bucket-A.
The main difference I see with your attempt was that your Bucket Policy only granted permissions for:
"Resource": "arn:aws:s3:::BUCKETAAAA/*"
This means "anything within Bucket-A" but does not include Bucket-A itself. The command aws s3 ls s3://BUCKETAAAA operates on the bucket, for which the role has no permissions.
Thus, you should also add permissions for the bucket itself:
"Resource": [
"arn:aws:s3:::BUCKETAAAA",
"arn:aws:s3:::BUCKETAAAA/*"