Create a pipeline in CodePipeline that uses resources from another AWS account - AWS CodePipeline

Create a pipeline in CodePipeline that uses resources from another AWS account

You might want to create a pipeline that uses resources created or managed by another AWS account. For example, you might want to use one account for your pipeline and another for your CodeDeploy resources.

Note

When you create a pipeline with actions from multiple accounts, you must configure your actions so that they can still access artifacts within the limitations of cross-account pipelines. The following limitations apply to cross-account actions:

  • In general, an action can only consume an artifact if:

    • The action is in the same account as the pipeline account OR

    • The artifact was created in the pipeline account for an action in another account OR

    • The artifact was produced by a previous action in the same account as the action

    In other words, you cannot pass an artifact from one account to another if neither account is the pipeline account.

  • Cross-account actions are not supported for the following action types:

    • Jenkins build actions

For this example, you must create an AWS Key Management Service (AWS KMS) key to use, add the key to the pipeline, and set up account policies and roles to enable cross-account access. For an AWS KMS key, you can use the key ID, the key ARN, or the alias ARN.

Note

Aliases are recognized only in the account that created the KMS key. For cross-account actions, you can only use the key ID or key ARN to identify the key. Cross-account actions involve using the role from the other account (AccountB), so specifying the key ID will use the key from the other account (AccountB).

In this walkthrough and its examples, AccountA is the account originally used to create the pipeline. It has access to the Amazon S3 bucket used to store pipeline artifacts and the service role used by AWS CodePipeline. AccountB is the account originally used to create the CodeDeploy application, deployment group, and service role used by CodeDeploy.

For AccountA to edit a pipeline to use the CodeDeploy application created by AccountB, AccountA must:

  • Request the ARN or account ID of AccountB (in this walkthrough, the AccountB ID is 012ID_ACCOUNT_B).

  • Create or use an AWS KMS customer managed key in the Region for the pipeline, and grant permissions to use that key to the service role (CodePipeline_Service_Role) and AccountB.

  • Create an Amazon S3 bucket policy that grants AccountB access to the Amazon S3 bucket (for example, codepipeline-us-east-2-1234567890).

  • Create a policy that allows AccountA to assume a role configured by AccountB, and attach that policy to the service role (CodePipeline_Service_Role).

  • Edit the pipeline to use the customer managed AWS KMS key instead of the default key.

For AccountB to allow access to its resources to a pipeline created in AccountA, AccountB must:

  • Request the ARN or account ID of AccountA (in this walkthrough, the AccountA ID is 012ID_ACCOUNT_A).

  • Create a policy applied to the Amazon EC2 instance role configured for CodeDeploy that allows access to the Amazon S3 bucket (codepipeline-us-east-2-1234567890).

  • Create a policy applied to the Amazon EC2 instance role configured for CodeDeploy that allows access to the AWS KMS customer managed key used to encrypt the pipeline artifacts in AccountA.

  • Configure and attach an IAM role (CrossAccount_Role) with a trust relationship policy that allows the CodePipeline service role in AccountA to assume the role.

  • Create a policy that allows access to the deployment resources required by the pipeline and attach it to CrossAccount_Role.

  • Create a policy that allows access to the Amazon S3 bucket (codepipeline-us-east-2-1234567890) and attach it to CrossAccount_Role.

Prerequisite: Create an AWS KMS encryption key

Customer-managed keys are specific to a Region, as are all AWS KMS keys. You must create your customer managed AWS KMS key in the same Region where the pipeline was created (for example, us-east-2).

To create a customer managed key in AWS KMS
  1. Sign in to the AWS Management Console with AccountA and open the AWS KMS console.

  2. On the left, choose Customer managed keys.

  3. Choose Create key. In Configure key, leave the Symmetric default selected and choose Next.

  4. In Alias, enter an alias to use for this key (for example, PipelineName-Key). Optionally, provide a description and tags for this key, and then choose Next.

  5. In Define Key Administrative Permissions, choose the role or roles you want to act as administrators for this key, and then choose Next.

  6. In Define Key Usage Permissions, under This Account, select the name of the service role for the pipeline (for example, CodePipeline_Service_Role). Under Other AWS accounts, choose Add another AWS account. Enter the account ID for AccountB to complete the ARN, and then choose Next.

  7. In Review and edit key policy, review the policy, and then choose Finish.

  8. From the list of keys, choose the alias of your key and copy its ARN (for example, arn:aws:kms:us-east-2:012ID_ACCOUNT_A:key/2222222-3333333-4444-556677EXAMPLE). You will need this when you edit your pipeline and configure policies.

Step 1: Set up account policies and roles

After you create the AWS KMS key, you must create and attach policies that will enable the cross-account access. This requires actions from both AccountA and AccountB.

Configure policies and roles in the account that will create the pipeline (AccountA)

To create a pipeline that uses CodeDeploy resources associated with another AWS account, AccountA must configure policies for both the Amazon S3 bucket used to store artifacts and the service role for CodePipeline.

To create a policy for the Amazon S3 bucket that grants access to AccountB (console)
  1. Sign in to the AWS Management Console with AccountA and open the Amazon S3 console at https://console.aws.amazon.com/s3/.

  2. In the list of Amazon S3 buckets, choose the Amazon S3 bucket where artifacts for your pipelines are stored. This bucket is named codepipeline-region-1234567EXAMPLE, where region is the AWS Region in which you created the pipeline and 1234567EXAMPLE is a ten-digit random number that ensures the bucket name is unique (for example, codepipeline-us-east-2-1234567890).

  3. On the detail page for the Amazon S3 bucket, choose Properties.

  4. In the properties pane, expand Permissions, and then choose Add bucket policy.

    Note

    If a policy is already attached to your Amazon S3 bucket, choose Edit bucket policy. You can then add the statements in the following example to the existing policy. To add a new policy, choose the link, and follow the instructions in the AWS Policy Generator. For more information, see Overview of IAM Policies.

  5. In the Bucket Policy Editor window, type the following policy. This will allow AccountB access to the pipeline artifacts, and will give AccountB the ability to add output artifacts if an action, such as a custom source or build action, creates them.

    In the following example, the ARN is for AccountB is 012ID_ACCOUNT_B. The ARN for the Amazon S3 bucket is codepipeline-us-east-2-1234567890. Replace these ARNs with the ARN for the account you want to allow access and the ARN for the Amazon S3 bucket:

    { "Version": "2012-10-17", "Id": "SSEAndSSLPolicy", "Statement": [ { "Sid": "DenyUnEncryptedObjectUploads", "Effect": "Deny", "Principal": "*", "Action": "s3:PutObject", "Resource": "arn:aws:s3:::codepipeline-us-east-2-1234567890/*", "Condition": { "StringNotEquals": { "s3:x-amz-server-side-encryption": "aws:kms" } } }, { "Sid": "DenyInsecureConnections", "Effect": "Deny", "Principal": "*", "Action": "s3:*", "Resource": "arn:aws:s3:::codepipeline-us-east-2-1234567890/*", "Condition": { "Bool": { "aws:SecureTransport": false } } }, { "Sid": "", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::012ID_ACCOUNT_B:root" }, "Action": [ "s3:Get*", "s3:Put*" ], "Resource": "arn:aws:s3:::codepipeline-us-east-2-1234567890/*" }, { "Sid": "", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::012ID_ACCOUNT_B:root" }, "Action": "s3:ListBucket", "Resource": "arn:aws:s3:::codepipeline-us-east-2-1234567890" } ] }
  6. Choose Save, and then close the policy editor.

  7. Choose Save to save the permissions for the Amazon S3 bucket.

To create a policy for the service role for CodePipeline (console)
  1. Sign in to the AWS Management Console with AccountA and open the IAM console at https://console.aws.amazon.com/iam/.

  2. In the navigation pane, choose Roles.

  3. In the list of roles, under Role Name, choose the name of the service role for CodePipeline.

  4. On the Permissions tab, choose Add inline policy.

  5. Choose the JSON tab, and enter the following policy to allow AccountB to assume the role. In the following example, 012ID_ACCOUNT_B is the ARN for AccountB:

    { "Version": "2012-10-17", "Statement": { "Effect": "Allow", "Action": "sts:AssumeRole", "Resource": [ "arn:aws:iam::012ID_ACCOUNT_B:role/*" ] } }
  6. Choose Review policy.

  7. In Name, enter a name for this policy. Choose Create policy.

Configure policies and roles in the account that owns the AWS resource (AccountB)

When you create an application, deployment, and deployment group in CodeDeploy, you also create an Amazon EC2 instance role. (This role is created for you if you use the Run Deployment Walkthrough wizard, but you can also create it manually.) For a pipeline created in AccountA to use CodeDeploy resources created in AccountB, you must:

  • Configure a policy for the instance role that allows it to access the Amazon S3 bucket where pipeline artifacts are stored.

  • Create a second role in AccountB configured for cross-account access.

    This second role must not only have access to the Amazon S3 bucket in AccountA, it must also contain a policy that allows access to the CodeDeploy resources and a trust relationship policy that allows the CodePipeline service role in AccountA to assume the role.

    Note

    These policies are specific to setting up CodeDeploy resources to be used in a pipeline created using a different AWS account. Other AWS resources will require policies specific to their resource requirements.

To create a policy for the Amazon EC2 instance role configured for CodeDeploy (console)
  1. Sign in to the AWS Management Console with AccountB and open the IAM console at https://console.aws.amazon.com/iam/.

  2. In the navigation pane, choose Roles.

  3. In the list of roles, under Role Name, choose the name of the service role used as the Amazon EC2 instance role for the CodeDeploy application. This role name can vary, and more than one instance role can be used by a deployment group. For more information, see Create an IAM Instance Profile for your Amazon EC2 Instances.

  4. On the Permissions tab, choose Add inline policy.

  5. Choose the JSON tab, and enter the following policy to grant access to the Amazon S3 bucket used by AccountA to store artifacts for pipelines (in this example, codepipeline-us-east-2-1234567890):

    { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:Get*" ], "Resource": [ "arn:aws:s3:::codepipeline-us-east-2-1234567890/*" ] }, { "Effect": "Allow", "Action": [ "s3:ListBucket" ], "Resource": [ "arn:aws:s3:::codepipeline-us-east-2-1234567890" ] } ] }
  6. Choose Review policy.

  7. In Name, enter a name for this policy. Choose Create policy.

  8. Create a second policy for AWS KMS where arn:aws:kms:us-east-1:012ID_ACCOUNT_A:key/2222222-3333333-4444-556677EXAMPLE is the ARN of the customer managed key created in AccountA and configured to allow AccountB to use it:

    { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "kms:DescribeKey", "kms:GenerateDataKey*", "kms:Encrypt", "kms:ReEncrypt*", "kms:Decrypt" ], "Resource": [ "arn:aws:kms:us-east-1:012ID_ACCOUNT_A:key/2222222-3333333-4444-556677EXAMPLE" ] } ] }
    Important

    You must use the account ID of AccountA in this policy as part of the resource ARN for the AWS KMS key, as shown here, or the policy will not work.

  9. Choose Review policy.

  10. In Name, enter a name for this policy. Choose Create policy.

Now create an IAM role to use for cross-account access, and configure it so that the CodePipeline service role in AccountA can assume the role. This role must contain policies that allow access to the CodeDeploy resources and the Amazon S3 bucket used to store artifacts in AccountA.

To configure the cross-account role in IAM
  1. Sign in to the AWS Management Console with AccountB and open the IAM console at https://console.aws.amazon.com/iam.

  2. In the navigation pane, choose Roles. Choose Create role.

  3. Under Select type of trusted entity, choose Another AWS account. Under Specify accounts that can use this role, in Account ID, enter the AWS account ID for the account that will create the pipeline in CodePipeline (AccountA), and then choose Next: Permissions.

    Important

    This step creates the trust relationship policy between AccountB and AccountA. However, this grants root level access to the account, and CodePipeline recommends scoping it down to the CodePipeline service role in AccountA. Follow step 16 to restrict permissions.

  4. UnderAttach permissions policies, choose AmazonS3ReadOnlyAccess, and then choose Next: Tags.

    Note

    This is not the policy you will use. You must choose a policy to complete the wizard.

  5. Choose Next: Review. Type a name for this role in Role name (for example, CrossAccount_Role). You can name this role anything you want as long as it follows the naming conventions in IAM. Consider giving the role a name that clearly states its purpose. Choose Create Role.

  6. From the list of roles, choose the role you just created (for example, CrossAccount_Role) to open the Summary page for that role.

  7. On the Permissions tab, choose Add inline policy.

  8. Choose the JSON tab, and enter the following policy to allow access to CodeDeploy resources:

    { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "codedeploy:CreateDeployment", "codedeploy:GetDeployment", "codedeploy:GetDeploymentConfig", "codedeploy:GetApplicationRevision", "codedeploy:RegisterApplicationRevision" ], "Resource": "*" } ] }
  9. Choose Review policy.

  10. In Name, enter a name for this policy. Choose Create policy.

  11. On the Permissions tab, choose Add inline policy.

  12. Choose the JSON tab, and enter the following policy to allow this role to retrieve input artifacts from, and put output artifacts into, the Amazon S3 bucket in AccountA:

    { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:GetObject*", "s3:PutObject", "s3:PutObjectAcl" ], "Resource": [ "arn:aws:s3:::codepipeline-us-east-2-1234567890/*" ] } ] }
  13. Choose Review policy.

  14. In Name, enter a name for this policy. Choose Create policy.

  15. On the Permissions tab, find AmazonS3ReadOnlyAccess in the list of policies under Policy Name, and choose the delete icon (X) next to the policy. When prompted, choose Detach.

  16. Select the Trust Relationship tab, and then choose Edit trust policy. Choose the Add a principal option on the left column. For Principal type, choose IAM Roles, and then provide the ARN for the CodePipeline service role in AccountA. Remove arn:aws:iam::Account_A:root from the list for AWS Principals, and then choose Update policy.

Step 2: Edit the pipeline

You cannot use the CodePipeline console to create or edit a pipeline that uses resources associated with another AWS account. However, you can use the console to create the general structure of the pipeline, and then use the AWS CLI to edit the pipeline and add those resources. Alternatively, you can use the structure of an existing pipeline and manually add the resources to it.

To add the resources associated with another AWS account (AWS CLI)
  1. At a terminal (Linux, macOS, or Unix) or command prompt (Windows), run the get-pipeline command on the pipeline to which you want to add resources. Copy the command output to a JSON file. For example, for a pipeline named MyFirstPipeline, you would type something similar to the following:

    aws codepipeline get-pipeline --name MyFirstPipeline >pipeline.json

    The output is sent to the pipeline.json file.

  2. Open the JSON file in any plain-text editor. After "type": "S3" in the artifact store, add the KMS encryptionKey, ID, and type information where codepipeline-us-east-2-1234567890 is the name of the Amazon S3 bucket used to store artifacts for the pipeline and arn:aws:kms:us-east-1:012ID_ACCOUNT_A:key/2222222-3333333-4444-556677EXAMPLE is the ARN of the customer-managed key you just created:

    { "artifactStoreā€¯: { "location": "codepipeline-us-east-2-1234567890", "type": "S3", "encryptionKey": { "id": "arn:aws:kms:us-east-1:012ID_ACCOUNT_A:key/2222222-3333333-4444-556677EXAMPLE", "type": "KMS" } },
  3. Add a deploy action in a stage to use the CodeDeploy resources associated with AccountB, including the roleArn values for the cross-account role you created (CrossAccount_Role).

    The following example shows JSON that adds a deploy action named ExternalDeploy. It uses the CodeDeploy resources created in AccountB in a stage named Staging. In the following example, the ARN for AccountB is 012ID_ACCOUNT_B:

    , { "name": "Staging", "actions": [ { "inputArtifacts": [ { "name": "MyAppBuild" } ], "name": "ExternalDeploy", "actionTypeId": { "category": "Deploy", "owner": "AWS", "version": "1", "provider": "CodeDeploy" }, "outputArtifacts": [], "configuration": { "ApplicationName": "AccountBApplicationName", "DeploymentGroupName": "AccountBApplicationGroupName" }, "runOrder": 1, "roleArn": "arn:aws:iam::012ID_ACCOUNT_B:role/CrossAccount_Role" } ] }
    Note

    This is not the JSON for the entire pipeline, just the structure for the action in a stage.

  4. You must remove the metadata lines from the file so the update-pipeline command can use it. Remove the section from the pipeline structure in the JSON file (the "metadata": { } lines and the "created", "pipelineARN", and "updated" fields).

    For example, remove the following lines from the structure:

    "metadata": { "pipelineArn": "arn:aws:codepipeline:region:account-ID:pipeline-name", "created": "date", "updated": "date" }

    Save the file.

  5. To apply your changes, run the update-pipeline command, specifying the pipeline JSON file, similar to the following:

    Important

    Be sure to include file:// before the file name. It is required in this command.

    aws codepipeline update-pipeline --cli-input-json file://pipeline.json

    This command returns the entire structure of the edited pipeline.

To test the pipeline that uses resources associated with another AWS account
  1. At a terminal (Linux, macOS, or Unix) or command prompt (Windows), run the start-pipeline-execution command, specifying the name of the pipeline, similar to the following:

    aws codepipeline start-pipeline-execution --name MyFirstPipeline

    For more information, see Start a pipeline manually.

  2. Sign in to the AWS Management Console with AccountA and open the CodePipeline console at http://console.aws.amazon.com/codesuite/codepipeline/home.

    The names of all pipelines associated with your AWS account are displayed.

  3. In Name, choose the name of the pipeline you just edited. This opens a detailed view of the pipeline, including the state of each action in each stage of the pipeline.

  4. Watch the progress through the pipeline. Wait for a success message on the action that uses the resource associated with another AWS account.

    Note

    You will receive an error if you try to view details for the action while signed in with AccountA. Sign out, and then sign in with AccountB to view the deployment details in CodeDeploy.