Fixing permissions on CloudTrail S3 objects
Where I work we aggregate all of our AWS CloudTrail logs from separate accounts into a single S3 bucket in a central account.
Yesterday, I ran into a weird problem where I noticed that our Logging solution, ELK, would not process files dating before a certain time.
Upon further investigation, I discovered that the date period missing was before we moved all of our existing files into the bucket from the AWS account it was originally in. So, “simple!” I thought to myself, “I’ll just update the permissions and allow ELK access to the files!”.
I was wrong, not simple. I had to fix this anyway…
To simplify this explanation, I will continue like this:
Account-A – original account where the files originally came from
Account-B – second account where files went to (bucket is here)
As I discovered, there are a few issues at play here:
- The files were pushed to the bucket in Account-B, not pulled from Account-A. This means the files are still owned by account-A.
- The files show no ‘grantee’ permissions.
- AWS has an
retardedingenious policy/process where the owner of the files is not the owner of the bucket, but the entity/account/service that created the files.
As a result Account-B (And all users/roles within) cannot forcefully take control of the files, and is unable to modify the permissions.
I also had to consider that I am working with tens of thousands of files here, so fixing this manually is not an option. I’ll have to script this for batch processing.
So, there was a few things I had to do:
- Modify the S3 bucket policy to allow Account-A to access the bucket.
- Grant a user/role within Account-A to access the files, using a user policy.
- The granted user in Account-A will need to add permissions for Account-B on every affected file in the bucket (Not every file is affected).
- Account-B should take ownership of the files, for future use.
- Remove Account-A’s access to the bucket.
- Win?
S3 Bucket Policy updated with additional access:
{ "Sid": "AllowAccountAAccess", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::ACCOUNT-A_ID:root" }, "Action": "s3:*", "Resource": [ "arn:aws:s3:::my-cloudtrail-bucket/*", "arn:aws:s3:::my-cloudtrail-bucket" ] }
Added an IAM policy for the user/role in Account-A:
{ "Version": "2012-10-17", "Statement": [ { "Sid": "Example", "Effect": "Allow", "Action": [ "s3:*" ], "Resource": [ "arn:aws:s3:::my-cloudtrail-bucket" ] } ] }
I wrote a PowerShell file to take care of this problem (Note that this uses the AWS PowerShell tools!), and thought I would share it online too:
$region = "eu-west-1" $accountAcreds = "profileacreds" $accountBcreds = "profilebcreds" $s3cloudtrailbucket = "my-cloudtrail-bucket" $s3folder = "AWSLogs/ACCOUNT-B_ID/CloudTrail/AWS_REGION_HERE/2015/01/01/" Set-DefaultAWSRegion $region $files = Get-S3Object -BucketName $s3cloudtrailbucket -KeyPrefix $s3folder | select key foreach ($file in $files) { # Cleanup 'key' virtual paths $oldfile = ${file}.key $newfile = "newfolder/"+${file}.key # Using PowerShell # Using Account-A credentials, set the ACL on objects in remote bucket (Sets bucket owner Account-B full access, not ownership) Set-S3ACL -BucketName $s3cloudtrailbucket -Key $oldfile -CannedACLName "bucket-owner-full-control" -StoredCredentials $accountAcreds # Using Account-B credentials, copy files to new location in same bucket (Take ownership of new files) Copy-S3Object -BucketName $s3cloudtrailbucket -DestinationBucket $s3cloudtrailbucket -Key $oldfile -DestinationKey $newfile -StoredCredentials $accountBcreds # OPTIONAL: # Using Account-B credentials, copy files to SAME LOCATION in same bucket, OVERWRITING. (Take ownership of new files) #Copy-S3Object -BucketName $s3cloudtrailbucket -DestinationBucket $s3cloudtrailbucket -Key $oldfile -DestinationKey $oldfile -StoredCredentials $accountBcreds # Same thing Using S3 CLI, not required if only using PowerShell CLI # Set ACL on objects in remote bucket #aws s3api put-object-acl --bucket $s3cloudtrailbucket --key $oldfile --acl bucket-owner-full-control --profile $accountAcreds # Copy files to new location #aws s3 cp s3://evision-logs-cloudtrail/$oldfile s3://evision-logs-cloudtrail/$newfile --profile $accountBcreds # Final cleanup of objects. # Using Account-B credentials, copy newly owned files back to old/original object location Copy-S3Object -BucketName $s3cloudtrailbucket -DestinationBucket $s3cloudtrailbucket -Key $newfile -DestinationKey $oldfile -StoredCredentials $accountBcreds # Using Account-B credentials, delete 'new' object Remove-S3Object -BucketName $s3cloudtrailbucket -Key $newfile -StoredCredentials $accountBcreds -Confirm -Force }
So did it work?
Yes it did, I processed tens of thousands of CloudTrail files (Bucket total is 110000+ objects) in a few hours and now they show up in ELK, ready for use.
I hope this is useful to someone.
Leave a comment if you found this and found it useful.