8

I have an application which upload ( copy ) some files to a S3 bucket in another AWS account, I use copyObject command from AWS SDK ( Nodejs )

var params = {
      Bucket: "MyBucket_AccountB", 
      CopySource: encodeURI('/Accunt_A_Bocket/file.png'),
      Key: "file.png",
      ACL: 'bucket-owner-full-control'
     };
s3.copyObject(params, function(err, datas) {
    if (err) console.log(err, err.stack); // an error occurred
    else     console.log(datas);           // successful response
});

This code, run from a diffrent AWS Account, let's say, AWS_ACCOUNT_A , and the files uploaded to a S3 bucket in AWS_ACCOUNT_B The thing is, when it upload the files to this bucket, the ownership of this files, are still AWS_ACCOUNT_A.

I want to know what should I do to give ownership of files to AWS_ACCOUNT_B, while uploading them. Anyone here can give me some guidance?

UPDATE :

I used this policy :

{
"Version": "2012-10-17",
"Statement": [
    {
        "Sid": "Permissions",
        "Effect": "Allow",
        "Principal": {
            "AWS": "arn:aws:iam::MY_ACCOUNT_B_ID:root"
        },
        "Action": "s3:*",
        "Resource": [
            "arn:aws:s3:::MYBUCKET_IN_ACCOUNT_A",
            "arn:aws:s3:::MYBUCKET_IN_ACCOUNT_A/*"
        ]
    }
]
}

but the uploaded files are still owned by Account_A, Did I do anything wrong in the policy?

Emad Dehnavi
  • 3,262
  • 4
  • 19
  • 44
  • You asked the same question yesterday and received the correct answer: https://stackoverflow.com/questions/51510472/cross-account-access-between-3-aws-accounts-using-assumerule. If this answer does not meet your goals, edit your question to be more specific. – John Hanley Jul 26 '18 at 03:15
  • That question was about some other issue, which fixed by the answer given by you, this is different, more in coding part. – Emad Dehnavi Jul 26 '18 at 03:21
  • 1
    Where is your code running (cloud, desktop, etc.)? Remember, you do not give ownership of S3 objects. The owner is determined by the credentials that you are using. Use the correct IAM account credentials. This means that you must use Account B's credentials to copy files into Account B's bucket to set the owner to Account B. Account B's credentials will require rights to Account A's bucket (read permissions). – John Hanley Jul 26 '18 at 03:48
  • @John Hanley My code is running in a EC2, but how should I use the assumeRule inside my code? I don't get this part – Emad Dehnavi Jul 26 '18 at 03:49
  • OK, now I understand what you are trying to ask. – John Hanley Jul 26 '18 at 03:51
  • 1
    In this case you do not need to use AssumeRole. In Account A's S3 bucket create a policy allowing Account B to read objects. No code is required, just a bucket policy. Remember to use Account B credentials when you copy objects from Account A. There are lots of examples on the Internet. Here is one from AWS: https://docs.aws.amazon.com/AmazonS3/latest/dev/example-walkthroughs-managing-access-example2.html – John Hanley Jul 26 '18 at 03:56
  • Oh Really? If it works with policy, it would be great, I will try it, thanks – Emad Dehnavi Jul 26 '18 at 03:58
  • Yep, just that simple. Getting the policy correct is the key. I answered a different question today on S3 bucket policies. This does not cover cross accounts but will help you understand the layers: https://stackoverflow.com/questions/51527954/aws-s3-trying-to-understand-permission-given-to-a-policy/51528458#51528458 – John Hanley Jul 26 '18 at 04:05
  • @John Hanley I just update the question, can you check the policy that I used? because it not worked – Emad Dehnavi Jul 26 '18 at 04:13
  • Just to mention again, The copy process, will run in account_A, so Account_A copy objects to a S3 in account_B , but in account_B bucket, the ownership of files are still for Account_A – Emad Dehnavi Jul 26 '18 at 04:18
  • That looks good - except you are giving all permissions to Account B. If you are OK with that ... I would use layers like my other answer and just give Account B list and read rights even if just for practice. – John Hanley Jul 26 '18 at 04:19
  • @JohnHanley Yea, I understand the policy part, but it seems this haveno effect on ownership, because after upload, the ownership of files are still for Account_A – Emad Dehnavi Jul 26 '18 at 04:21
  • You misread my answers. I put emphasis that the copy process must use Account B' s credentials. Think it thru, why are you creating an S3 bucket policy giving Account B read rights if you are going to use Account A's credentials for the copy? – John Hanley Jul 26 '18 at 04:21
  • The key item is that the object owner is determined by the credentials that you use not the permissions that you grant. – John Hanley Jul 26 '18 at 04:22
  • If you must use Account A credentials, then you are back to creating a role in Account B that Account A can assume using AssumeRole. – John Hanley Jul 26 '18 at 04:23
  • I get it now, I will try to go through it a bit more. – Emad Dehnavi Jul 26 '18 at 04:23
  • Using AssumeRole is not difficult. Again this is so common that there are lots of examples to reference. – John Hanley Jul 26 '18 at 04:24
  • @JohnHanley Can we use a Role instead of the credentials? – Emad Dehnavi Jul 26 '18 at 04:26
  • AssumeRole returns new credentials. This will give you the credentials that you need so that you can create objects with the correct owner. Here is a link to help you understand: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html – John Hanley Jul 26 '18 at 04:29
  • Here is another Stack Overflow answer with node.js source code that will work for you. https://stackoverflow.com/a/48530115/8016720 – John Hanley Jul 26 '18 at 05:02
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/176844/discussion-between-emad-dehnavi-and-john-hanley). – Emad Dehnavi Jul 27 '18 at 04:22

1 Answers1

15

If you have to copy a file from account A to account B, then you should have account A assume a role in account B before writing the file. If for some reason you can't assume a role in account B to do it, then you can set the access to allow full control to the bucket owner:

aws s3 cp --acl bucket-owner-full-control localFile s3://bucketname/path/filename

The bucket owner can enforce this requirement with the following rule:

{
    "Sid": "CrossAccountWritePermissionsDenier",
    "Effect": "Deny",
    "Principal": {
        "AWS": "arn-of-account-A-pusher"
    },
    "Action": [
        "s3:PutObject"
    ],
    "Resource": [
        "arn:aws:s3:::bucketname/path/given/access/*",
        "arn:aws:s3:::bucketname/other/path/given/access/*"
    ],
    "Condition": {
        "StringNotEquals": {
            "s3:x-amz-acl": "bucket-owner-full-control"
        }
    }
}

One caveat to this approach is that if you have an account C (reader) which was also granted read privileges by account B (bucket owner) for the path that account A (writer) pushed a file into, then account C will not be able to read files pushed by account A since they aren't actually owned by account B. This is the issue you are facing.

If account A instead assumed a role in account B before pushing, then the file would be owned by account B, and therefore, account C would be able to read it. Otherwise, account B will have to move the file (since account B has full access) and then account C will be able to read the file in its new location.

In theory, you can change ownership by copying the file to itself from the bucket owner's role:

aws s3 cp s3://bucketname/path/filename s3://bucketname/path/filename

It will not let you do this, however, unless you are changing something (such as the owner, metadata, acl, etc). So you can only do this from the bucket owner's role, not from the original (non-bucket-owner) uploader's role.

Shadow Man
  • 3,234
  • 1
  • 24
  • 35