Cross Account access for Code Pipeline in CDK

Viewed 1469

I am trying to set up a cross account deployment pipeline with CDK and CodePipeline.

I built the sample CodePipeline example from the AWS Docs and was able to deploy successfully with cdk into a single account. (https://docs.aws.amazon.com/cdk/latest/guide/codepipeline_example.html)

$ cdk deploy PipelineDeployingLambdaStack --profile=111111111111

This returns successfully.

Then using the cross-account instructions in the cdk-codepipeline-actions docs, I added the account attribute to my deploy action. (https://docs.aws.amazon.com/cdk/api/latest/docs/aws-codepipeline-actions-readme.html#cross-account-actions)

        {
          stageName: 'Deploy',
          actions: [
            new codepipeline_actions.CloudFormationCreateUpdateStackAction({
              account: '222222222222',   // introduce cross-account deployment
              ......
            }),
          ],
        },

After this change and running cdk synth again it generates a new stack called cross-account-support-stack-222222222222.template.json as expected.

So far so good.

When I try to run cdk deploy though it immediately throws a cross-account reference error:

$ cdk deploy PipelineDeployingLambdaStack --profile=111111111111
Including dependency stacks: cross-account-support-stack-222222222222
cross-account-support-stack-222222222222 (PipelineDeployingLambdaStack-support-222222222222)
cross-account-support-stack-222222222222 (PipelineDeployingLambdaStack-support-222222222222): deploying...

 ❌  cross-account-support-stack-222222222222 (PipelineDeployingLambdaStack-support-222222222222) failed: Error: Need to perform AWS calls for account 222222222222, but the current credentials are for 111111111111.

I don't understand how this is ever supposed to work since I can only provide one set of credentials at a time. I can't find any documentation about it which makes me think it should be obvious.

What am I missing?

2 Answers

The key is in that line in your output:

Including dependency stacks: cross-account-support-stack-222222222222

You can use the -e / --exclusively command-line switch when deploying the support stack, and then the main CodePipeline stack, and you can use the --profile option to switch the credentials for those different cdk deploy invocations.

Just to add to @adam-ruka's answer (because the solution wasn't initially clear to me), this is how you split the deployment of the support-stack from the main stack:

# deploy cross-account support stack
cdk deploy cross-account-support-stack-222222222222 --profile=222222222222 -e

# deploy main stack
cdk deploy PipelineDeployingLambdaStack --profile=111111111111 -e

The important thing to be aware of (which is what caught me out and added to my confusion) is if your stack environment is being configured implicitly using the CDK CLI environment variables, e.g.

new PipelineDeployingLambdaStack (app, 'pipeline', { 
  env: { 
    account: process.env.CDK_DEFAULT_ACCOUNT, 
    region: process.env.CDK_DEFAULT_REGION 
}});

then the command to setup the support stack will fail to find the stack with the error:

No stacks match the name(s) cross-account-support-stack-222222222222

This is because CDK_DEFAULT_ACCOUNT becomes 222222222222 instead of 111111111111. The solution here is to setup the stack so the environment can be explicitly defined:

new PipelineDeployingLambdaStack (app, 'pipeline', { 
  env: { 
    account: process.env.CDK_DEPLOY_ACCOUNT || process.env.CDK_DEFAULT_ACCOUNT, 
    region: process.env.CDK_DEPLOY_REGION || process.env.CDK_DEFAULT_REGION 
}});

then pass in the account on the CLI:

CDK_DEPLOY_ACCOUNT=111111111111 cdk deploy cross-account-support-stack-222222222222 --profile=222222222222 -e
Related