Skip to content

Instantly share code, notes, and snippets.

@benjaminjackman
Created December 22, 2017 23:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save benjaminjackman/ca8d7df56ec1bc316cd1dace4c230248 to your computer and use it in GitHub Desktop.
Save benjaminjackman/ca8d7df56ec1bc316cd1dace4c230248 to your computer and use it in GitHub Desktop.
Had a great conversation with AWS support and found my answer for those interested:
Thanks for chatting with me today. As I understand, you have a cross-account scenario in which your intended grantee is not able to access objects stored in the source bucket. After further consideration, I am inclined to suggest option #3 below to meet your requirement with the least administrative overhead.
You have the following setup (keeping generic to comply with cross-account support limitations):
Account A - Uploader account (AWS Cloudtrail Service Account) Account B - Bucket owner Account C - Destination Account/IAM user
The reason Account C can't access the object in this scenario, even though the bucket owner has full control, has to do with the following default behaviors in S3:
S3 sets the owner ID of the object to the account that performed the PUT request. By default, the only ACL set on the object is "full-control" for the owner (uploader). If the canned ACL 'bucket-owner-full-control' is added, the bucket owner can delegate this permission to its own IAM users, but it still doesn't own the object. In the event that a Cloudtrail log is uploaded to any given bucket, the bucket owner will be added as a grantee in the object ACL with full control, but as mentioned, it is not the object owner. Account A owns the object.
You cannot use bucket policies to share the data with Account C since a bucket policy can only affect an object you own.
There are a few different approaches to correct or mitigate this behavior. First, you can do one of the following to correct the issue with existing objects:
1) Overwrite them as a user in Account B to set the ownerID to the correct value. This can be done using something like the AWS CLI Tool.
Ex: aws s3 cp s3://aplptrails/master/AWSLogs/005670278797/CloudTrail/us-east-1/2017/07/21/005670278797_CloudTrail_us-east-1_20170721T0000Z_2WJSxO6C1Hmvg6Is.json.gz s3://aplptrails/master/AWSLogs/005670278797/CloudTrail/us-east-1/2017/07/21/005670278797_CloudTrail_us-east-1_20170721T0000Z_2WJSxO6C1Hmvg6Is.json.gz --storage-class STANDARD
Docs for installing the CLI Tool: https://urldefense.proofpoint.com/v2/url?u=http-3A__docs.aws.amazon.com_cli_latest_userguide_installing.html&d=DwICaQ&c=dbNN4u5swSMqErirwbKEcvcubeovAzUWne5MYBi0r7Y&r=sg0v1cuQBLPlmbnAW-j8tYGo_hZ8sJMOUwPgykG-0X5DSDm5TvADprofgHg5KINt&m=4l2Fw6GuW_vLHvMERYZ-LiPffMUTqeY2G6ozGiH32TA&s=wojeG4MV2NKxr_P_6DolohknsP14hqWUce4jubNgiaw&e= https://urldefense.proofpoint.com/v2/url?u=http-3A__docs.aws.amazon.com_cli_latest_userguide_cli-2Dchap-2Dgetting-2Dstarted.html&d=DwICaQ&c=dbNN4u5swSMqErirwbKEcvcubeovAzUWne5MYBi0r7Y&r=sg0v1cuQBLPlmbnAW-j8tYGo_hZ8sJMOUwPgykG-0X5DSDm5TvADprofgHg5KINt&m=4l2Fw6GuW_vLHvMERYZ-LiPffMUTqeY2G6ozGiH32TA&s=R8zUhU2i8Fitxbf0Kufb3807-e-ye6UUosKf2kGG348&e=
Note: the --recursive parameter can be used to iterate over an entire prefix.
The problem is that this is a one time process, so any newly written files will still have the same permissions issue.
2) Account B can perform a PUT Object acl operation on each object to include a grant for Account C. From the AWS CLI, the command [1] might look like this:
aws s3api put-object-acl --bucket aplptrails --key master/AWSLogs/005670278797/CloudTrail/us-east-1/2017/07/21/005670278797_CloudTrail_us-east-1_20170721T0000Z_2WJSxO6C1Hmvg6Is.json.gz --grant-full-control emailaddress=user1@example.com --grant-read emailaddress=user2@example.com
The values for 'emailaddress' in the above example would be the primary email addresses of Account B and Account C. You could also substitute the canonical user ID of each account, for example: --grant-full-control id=<canonical ID>. The canonical ID for any given account can be retrieved by running 'aws s3api get-bucket-acl --bucket <bucket_name>'.
3) Create a role in Account B, assign it permissions to access the S3 bucket in question, and grant permission to Account C to assume this role. This process is outlined in the following walk-through: https://urldefense.proofpoint.com/v2/url?u=http-3A__docs.aws.amazon.com_AmazonS3_latest_dev_example-2Dwalkthroughs-2Dmanaging-2Daccess-2Dexample4.html&d=DwICaQ&c=dbNN4u5swSMqErirwbKEcvcubeovAzUWne5MYBi0r7Y&r=sg0v1cuQBLPlmbnAW-j8tYGo_hZ8sJMOUwPgykG-0X5DSDm5TvADprofgHg5KINt&m=4l2Fw6GuW_vLHvMERYZ-LiPffMUTqeY2G6ozGiH32TA&s=Mw5PbQwnx8CG-xzPstZLGP92kxlCWYhYWtUrATOzsII&e= .
Another option going forward is to create an S3 event notification to trigger a Lambda function for new PUTs; the Lambda function would then perform the overwrite copy (and effectively "take ownership") automatically. The example Lambda function here first checks the ownership of the object before performing the copy operation so as not to result in an infinite loop: https://urldefense.proofpoint.com/v2/url?u=https-3A__gist.github.com_williamtsoi1_104531c65852a852399a3dc1096a2dcc&d=DwICaQ&c=dbNN4u5swSMqErirwbKEcvcubeovAzUWne5MYBi0r7Y&r=sg0v1cuQBLPlmbnAW-j8tYGo_hZ8sJMOUwPgykG-0X5DSDm5TvADprofgHg5KINt&m=4l2Fw6GuW_vLHvMERYZ-LiPffMUTqeY2G6ozGiH32TA&s=QXSuAXdXpxSMYBZrW0cLzMPe99HgSKHkIJ0G_nO3QEg&e=
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment