4

Background:

I have two accounts A and B. Account A owns a bucket my-bucket. I have given account B access to this bucket -- account B can read objects from and write objects to this bucket. This is working as expected.

However, account A can only read those objects in my-bucket that it has written on its own. Although it can list even those objects that account B has written, it cannot read those.

Below is what I see when I try to download all objects from my-bucket using AWS CLI with AWS configuration of account A.

download: s3://my-bucket/PN1492646400000.csv to tp/PN1492646400000.csv
download: s3://my-bucket/PN1491264000000.csv to tp/PN1491264000000.csv
download: s3://my-bucket/PN1493942400000.csv to tp/PN1493942400000.csv
download failed: s3://my-bucket/PN1503346865232.csv to tp/PN1503346865232.csv An error occurred (AccessDenied) when calling the GetObject operation: Access Denied
download: s3://my-bucket/PN1495389670000.csv to tp/PN1495389670000.csv
download: s3://my-bucket/PN1496685403000.csv to tp/PN1496685403000.csv
download: s3://my-bucket/PN1497945130000.csv to tp/PN1497945130000.csv
download: s3://my-bucket/PN1500508800000.csv to tp/PN1500508800000.csv

As one can see, I could download all files, but PN1503346865232.csv (this was written by account B using a java method putObject).

What I tried so far:

I have looked into the following two questions:

  1. Amazon S3 file 'Access Denied' exception in Cross-Account: One of the comment asks to do a putObject with acl, but does not specify what acl.
  2. S3: User cannot access object in his own s3 bucket if created by another user: This talks about stopping account B from putting objects into my-bucket without giving ownership access. Does just putting this constraint help me get full access?

This is how I tried to put the ACL while putting the object in the java code.

AccessControlList acl = new AccessControlList();
acl.grantPermission(new CanonicalGrantee(S3_BUCKET_OWNER_ID), Permission.FullControl);
PutObjectRequest putObjectRequest = new PutObjectRequest(S3_BUCKET, remoteCleanedPrismFilename, fileStream, null)
                        .withAccessControlList(acl);
s3Client.putObject(putObjectRequest);

It throws exception saying: com.amazonaws.services.s3.model.AmazonS3Exception: Invalid id

Questions:

  1. I wonder how am I supposed to get this ID. Is it not the aws account ID i.e. a 10-12 digit number?
  2. Even if I find this ID, will giving this ACL same as bucket-owner-full- control?
Sonu Mishra
  • 1,659
  • 4
  • 26
  • 45

1 Answers1

4

This post got so many views, but not a single answer!

To help others, I am posting some workarounds that I found from my research so far. After these workarounds, account A is able to access the objects created by account B.

In the java code that is running in account B, I explicitly set the ACL on the object that is to be created.

AccessControlList acl = new AccessControlList();
acl.grantPermission(new CanonicalGrantee(S3_BUCKET_OWNER_ID), Permission.FullControl);
PutObjectRequest putObjectRequest = new PutObjectRequest(S3_BUCKET, remoteCleanedPrismFilename, fileStream, null)
                        .withAccessControlList(acl);
s3Client.putObject(putObjectRequest);

Here S3_BUCKET_OWNER_ID is the canonical ID of account A. Please note that it is not the AWS account ID that we know and I do not know a better way, to find this out, than the following

aws s3api get-object-acl --bucket my-bucket --key PN1491264000000.csv --output text --profile accountA

This is still not an elegant solution according to me and I believe something better exists. I will edit this answer once I find something better.

Edit:

Canonical ID of the bucket owner can be found more elegantly as follows:

String s3BucketOwnerId = s3Client.getBucketAcl(S3_BUCKET).getOwner().getId();
Sonu Mishra
  • 1,659
  • 4
  • 26
  • 45