AWS Lambda function to grant the bucket owner full control over an S3 object.
This setup assumes two AWS accounts. The main account (Account A) grants
another account (Account B) access to an S3 bucket via
bucket policy,
e.g. the following:
{
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::ACCOUNT_ID:root"
},
"Action": "s3:*",
"Resource": ["arn:aws:s3:::BUCKET_NAME", "arn:aws:s3:::BUCKET_NAME/*"]
}
]
}Ideally this bucket policy would restrict S3 uploads to always set the
bucket-owner-full-control
canned ACL.
A sample bucket policy with this restriction would be the following:
{
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::ACCOUNT_ID:root"
},
"Action": "s3:*",
"Resource": ["arn:aws:s3:::BUCKET_NAME", "arn:aws:s3:::BUCKET_NAME/*"]
},
{
"Effect": "Deny",
"Principal": {
"AWS": "arn:aws:iam::ACCOUNT_ID:root"
},
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::BUCKET_NAME/*",
"Condition": {
"StringNotEquals": {
"s3:x-amz-acl": "bucket-owner-full-control"
}
}
}
]
}A sample
s3 put-object
command with the required bucket-owner-full-control ACL as argument:
aws s3api put-object \
--bucket BUCKET_NAME \
--key test.txt \
--body test.txt \
--acl bucket-owner-full-controlIn cases where this is not possible, e.g. when allowing uploads with an S3 application like Cyberduck, this Lambda function comes in handy.
In Account B, create a new cross-account IAM
role. Fill in the account ID of Account A as account that can use this role.
As role name, choose bucket-owner-full-control-role.
After creating the role, attach the following inline policy, replacing
BUCKET_NAME with the name of your bucket:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:PutObjectAcl",
"Condition": {
"StringEquals": {
"s3:x-amz-acl": "bucket-owner-full-control"
}
},
"Resource": "arn:aws:s3:::BUCKET_NAME/*"
}
]
}In Account A, create a new Lambda service role with the managed
AWSLambdaBasicExecutionRole attached. As role name choose
aws-lambda-bucket-owner-role.
After creating the role, attach the following inline policy, replacing
ACCOUNT_ID with the account ID of Account B:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::ACCOUNT_ID:role/bucket-owner-full-control-role"
}
]
}Add the function code to AWS Lambda with the following configuration options:
| Key | Value |
|---|---|
| Runtime | Node.js 10.x |
| Handler | index.handler |
| Role | aws-lambda-bucket-owner-role |
| Memory | 128 (MB) |
| Timeout | 3 sec |
Set the following required environment variable for the Lambda function:
| Key | Value |
|---|---|
| rolearn | The ARN of the bucket-owner-full-control-role of Account B. |
Add an S3 trigger for your bucket with the PUT event type.
test-event.json contains a sample S3 PUT event.
Released under the MIT license.