How do I deploy artifacts to Amazon S3 in a different account using CodePipeline with a canned ACL?

Last updated: 2020-06-24

I want to deploy artifacts to Amazon Simple Storage Service (Amazon S3) in a different account using AWS CodePipeline with an S3 deploy action provider and a canned Access Control List (ACL).

Short description

The following resolution is based on an example scenario that assumes the following:

  • You have two accounts: a development (dev) account and a production (prod) account.
  • The input bucket in the dev account is called codepipeline-input-bucket (with versioning enabled).
  • The default artifact bucket in the dev account is called codepipeline-us-east-1-0123456789.
  • The output bucket in the prod account is called codepipeline-output-bucket.
  • You're deploying artifacts from the dev account to an S3 bucket in the prod account.
  • You're using canned ACL to provide the bucket owner in the prod account with access to the objects owned by the dev account. To deploy artifacts and set the prod account as object owner, see How do I deploy artifacts to Amazon S3 in a different account using CodePipeline?

Resolution

Create a CodePipeline in the dev account

1.    Open the CodePipeline console, and then choose Create pipeline.

2.    For Pipeline name, enter crossaccountdeploy.

Note: Replace crossaccountdeploy with the name of your pipeline.

The Role name text box is auto populated with the service role name AWSCodePipelineServiceRole-us-east-1-crossaccountdeploy. You can also choose an existing service role.

3.    Expand the Advanced settings section.

4.    For Artifact store, select Default location.

Note: You can select Custom location if that's required for your scenario.

5.    For Encryption key, select Default AWS Managed Key.

6.    Choose Next.

7.    On the Add source stage page, for Source provider, choose Amazon S3.

8.    For Bucket, enter codepipeline-input-bucket.

Note: Replace codepipeline-input-bucket with the name of your input bucket.

Important: The input bucket must have versioning enabled to work with CodePipeline.

9.    For S3 object key, enter sample-website.zip.

Important: To use an example AWS website instead of your own website, see Tutorial: Create a Pipeline That Uses Amazon S3 as a Deployment Provider. Then, search for "sample static website" in the Prerequisites of the 1: Deploy Static Website Files to Amazon S3 section.

10.    For Change detection options, choose Amazon CloudWatch Events (recommended).

11.    Choose Next.

12.    On the Add build stage page, choose Skip build stage, and then choose Skip.

13.    On the Add deploy stage page, for Deploy provider, choose Amazon S3.

14.    For Region, choose US East (N. Virginia).

Important: Replace US East (N. Virginia) with the AWS Region of your output bucket.

15.    For Bucket, enter the name of the prod bucket codepipeline-output-bucket.

Note: Replace codepipeline-output-bucket with the name of your output bucket.

16.    Select the Extract file before deploy check box.

Note: If needed, enter a path for Deployment path.

17.    Expand Additional configuration.

18.    For Canned ACL, choose bucket-owner-full-control.

Note: The bucket-owner-full-control gives the bucket owner in the target prod account full access to the objects deployed and owned by the dev account. For more information, see Canned ACL.

19.    Choose Next.

20.    Choose Create pipeline.

Now, your pipeline is triggered, but the source stage fails. Then, you receive the following error:

The object with key 'sample-website.zip' does not exist.

The Upload the sample website to the input bucket section shows you how to resolve this error later on.

Configure a CodePipeline service role with an AWS Identity and Access Management (IAM) policy that adds S3 access for the output bucket of the prod account

1.    Open the IAM console in the dev account.

2.    In the navigation pane, choose Policies, and then choose Create policy.

3.    Choose the JSON tab, and then enter the following policy in the JSON editor:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "s3:*",
            "Resource": "arn:aws:s3:::codepipeline-output-bucket/*"
        },
        {
            "Effect": "Allow",
            "Action": "s3:ListBucket",
            "Resource": "arn:aws:s3:::codepipeline-output-bucket"
        }
    ]
}

Note: Replace codepipeline-output-bucket with the name of your output bucket.

4.    Choose Review policy.

5.    For Name, enter prodbucketaccess.

Note: Replace prodbucketaccess with your own policy name.

6.    Choose Create policy.

7.    In the navigation pane, choose Roles.

8.    From the list of roles, choose AWSCodePipelineServiceRole-us-east-1-crossaccountdeploy. This is the service role used by CodePipeline.

Note: Replace AWSCodePipelineServiceRole-us-east-1-crossaccountdeploy with your own service role if applicable.

9.    Choose Attach polices.

10.    Select the prodbucketaccess policy that you created earlier, and then choose Attach policy.

CodePipeline now has access to the output bucket in the prod account.

Configure the output bucket in the prod account to allow access from the dev account

1.    Open the Amazon S3 console in the prod account.

2.    In the Bucket name list, choose codepipeline-output-bucket.

Note: Replace codepipeline-output-bucket with the name of your output bucket.

3.    Choose Permissions, and then choose Bucket Policy.

4.    In the text editor, enter the following policy:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::dev-account-id:root"
            },
            "Action": "s3:Put*",
            "Resource": "arn:aws:s3:::codepipeline-output-bucket/*"
        },
        {
            "Sid": "",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::dev-account-id:root"
            },
            "Action": "s3:ListBucket",
            "Resource": "arn:aws:s3:::codepipeline-output-bucket"
        }
    ]
}

Note: Replace dev-account-id with the account ID of your dev environment. Replace codepipeline-output-bucket with your output bucket name.

5.    Choose Save.

Upload the sample website to the input bucket

1.    Open the Amazon S3 console in the dev account.

2.    In the Bucket name list, choose codepipeline-input-bucket.

Note: Replace codepipeline-input-bucket with the name of your input bucket.

3.    Choose Upload, and then choose Add files.

4.    Select the sample-website.zip file that you downloaded earlier.

5.    Choose Upload.

Now, CodePipeline is triggered and the following happens:

1.    The source action selects the sample-website.zip from codepipeline-input-bucket, and then places the zip file as a source artifact inside the codepipeline-us-east-1-0123456789 artifact bucket.

2.    In the deploy action, the CodePipeline service role AWSCodePipelineServiceRole-us-east-1-crossaccountdeploy uses its access to deploy to codepipeline-output-bucket in the prod account and apply the canned ACL bucket-owner-full-control.

The dev account is now the owner of the extracted objects in codepipeline-output-bucket, but the bucket owner in the prod account also has full access to the deployed artifacts.


Did this article help you?

Anything we could improve?


Need more help?