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-control
In 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 6.10 |
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.