aws / aws-cdk

The AWS Cloud Development Kit is a framework for defining cloud infrastructure in code
https://aws.amazon.com/cdk
Apache License 2.0
11.5k stars 3.85k forks source link

(pipelines): add assumeRole parameter to CodeBuildStep #18272

Open bodokaiser opened 2 years ago

bodokaiser commented 2 years ago

Description

Adds an assumeRole property to pipelines.CodeBuildStep which takes an iam.Role object, e.g.,

const role = iam.Role.fromRoleArn(this, 'Role', 'arn:aws:iam::123456789012:role/MyExistingRole')

const step = new CodeBuildStep('Test', {
  // ...
  assumeRole: role,
})

such that commands configured in step are executed under role.

Use Case

When we consider a cross-account deployment pipeline, we need to perform actions on the deployed resources from inside the pipeline. For example:

Proposed Solution

If an assumeRole parameter is provided to a CodeBuildStep, we need to

  1. add a PolicyStatement allowing to assume the role, e.g.,

    new PolicyStatement({
    effect: Effect.ALLOW,
    actions: ['sts:AssumeRole'],
    resources: [role.arn],
    })
  2. assume the role inside the container and change the default AWS profile, e.g.,

aws configure --profile stage set role_arn $AWS_IAM_ROLE
aws configure --profile stage set credential_source EcsContainer

export AWS_PROFILE=stage

Other information

The feature is a pragmatic workaround to https://github.com/aws/aws-cdk/issues/9625.

Acknowledge

rix0rrr commented 2 years ago

It would be a nice feature. In the mean time, you can implement this yourself by making the aws sts assume-role call using the AWS CLI.

volkanunsal commented 2 years ago

I have this use case as well. @rix0rrr You mentioned using SDK. How would you use the SDK it in the CDK construct to assume a role? I've tried using it in a command, but I keep getting errors such as this:

An error occurred (AccessDenied) when calling the AssumeRole operation: User: arn:aws:sts::715222378043:assumed-role/my-pipeline-PipelineDevAcceptanceStageDevRun-1CKZXMADIE7XT/AWSCodeBuild-ac6d538b-5214-4f8b-8811-5756d81e1bf6 is not authorized to perform: sts:AssumeRole on resource: arn:aws:iam::305688118908:role/DevTestUrlRole

Clearly I need to give the execution role permissions to assume that, but it's always the same error.

This is what I've tried:

const actionRole = new Role(this, cbProjectRoleId, {
  assumedBy: new AccountPrincipal(DEPLOYMENT_ENV.account),
});
actionRole.addToPolicy(
  new PolicyStatement({
    effect: Effect.ALLOW,
    resources: ['*'],
    actions: ['sts:AssumeRole'],
  })
);

const step = new CodeBuildStep(cbProjectId, {
  rolePolicyStatements: [
    new PolicyStatement({
      effect: Effect.ALLOW,
      resources: ['*'],
      actions: ['sts:AssumeRole'],
    }),
  ],
  actionRole,
  commands: [
    `sts=$(aws sts assume-role --role-arn $assumedRoleArn --role-session-name "test-profile" --query 'Credentials.[AccessKeyId,SecretAccessKey,SessionToken]' --output text); aws configure set aws_access_key_id $(echo $sts | awk '{print $1}') --profile test-profile; aws configure set aws_secret_access_key $(echo $sts | awk '{print $2}') --profile test-profile; aws configure set aws_session_token $(echo $sts | awk '{print $3}') --profile test-profile; export URL=$(aws ssm get-parameter --name $parameterName --profile test-profile); curl -Ssf $URL`,
  ],
  env: {
    assumedRoleArn,
    parameterName,
  },
});
damnhandy commented 1 year ago

@volkanunsal Assuming this works, I think that might be the best we'll do. CloudFormation doesn't even support something like this now. I've generally relied on using the CLI to do this, but i like what you solution is doing. Again, assuming that is working for you.