JosepB
JosepB

Reputation: 2315

Lambda that copy object from one bucket to another in different accounts using AWS SDK copyobject method in javascript

I would like to copy objects from the bucket in account-1 to the other buckets in account-2 using the copyObject method of the AWSJavaScriptSDK in a lambda. Right now it works by allowing the lambda role in account-1 to write in the bucket in account account-2 using the s3 bucket policies. The thing is that in the account-2 we have a lot of buckets and we want to avoid adding permission to each of them every time that we create a lambda that writes or read in one of them.

I'm trying that the lambda in the account-1 assume the role with the permissions to write and read in the account-2 as follows.

  1. In the account-2 I have the role called s3-account-2-full-access with the AmazonS3FullAccess policy and the following trusted relationship:

     "Version": "2012-10-17",
     "Statement": [
       {
         "Effect": "Allow",
         "Principal": {
           "AWS": "arn:aws:iam::11111111111:role/lambda-account-1-role"
         },
         "Action": "sts:AssumeRole",
         "Condition": {}
       }
     ]
    }
    
    
  2. In the account-1 I have the lambda-account-1-role with the following policy attached.

        "Version": "2012-10-17",
        "Statement": [
            {
                "Sid": "VisualEditor0",
                "Effect": "Allow",
                "Action": "sts:AssumeRole",
                "Resource": "arn:aws:iam::22222222222:role/s3-account-2-full-access"
            }
        ]
    }
    
  3. In the lambda I'm assuming the role as follows:

const sts = new AWS.STS();

exports.handler = async (event) => {
    const timestamp = (new Date()).getTime();
    var sts_params = {
        RoleArn: 'arn:aws:iam::22222222222:role/s3-account-2-full-access',
        RoleSessionName: `id-${timestamp}`,
        DurationSeconds: 3600,
     };
    const { Credentials } =  await  sts.assumeRole(sts_params).promise();
    const { AccessKeyId, SecretAccessKey, SessionToken } = Credentials;

    const accessparams2 = {
      accessKeyId: AccessKeyId,
      secretAccessKey: SecretAccessKey,
      sessionToken: SessionToken,
    };
    
    var s3 = new AWS.S3(accessparams2);
    var params = {
        Bucket: "account-2-bucket", 
        CopySource: "/account-1-bucket/file.txt", 
        Key: "file.txt"
    };
    const result = await s3.copyObject(params).promise();

    const response = {
        statusCode: 200,
        body: JSON.stringify(result),
    };
    return response;
};

The thing here is that I'm getting the error AccessDenied during the copyObject. Maybe I'm misunderstanding something, but I can't figure out how I could copy the objects from account-1 to account-2 without having to edit the bucket policy in account-2.

Upvotes: 1

Views: 1896

Answers (1)

RoberMP
RoberMP

Reputation: 1356

You need to execute S3 with the assume role permissions that you just get, I think that you are missing it :)

var s3 = new AWS.S3(accessparams2);

As bonus points:

  • You are assuming role and instantiate the s3 object in every lambda execution, this is not necessary, you can do it out of your handler function to improve performance
  • nodejs SDK use to have a .promise() method for every object so you probably can do something like the following to avoid the ugly Promise/callback thing in your getCrossAccountCredentials function (as you do with your s3 call): const data = await sts.assumeRole(sts_params).promise();

Upvotes: 2

Related Questions