aws / aws/aws-cdk

aws-codepipeline: CodePipeline/CodeBuild roles don't have necessary access

Open
#28,522 12 comments 0 reactions 0 assignees View on GitHub
@aws-cdk/aws-codepipeline bug effort/medium p2
Dominant language
TypeScript
Stars
12.9k
Forks
4.6k
Avg merge
2d 3h
Merged PRs (30d)
83

Description

### Describe the bug

I am trying to deploy a CDK stack through CodePipeline. I am defining the CodePipeline configuration to automate this as a separate CDK stack. I've tried two different iterations and both of them result in some kind of IAM authorization issue.

**Iteration 1:**

The pipeline stack deploys, but the CodeBuild build job fails.

**Iteration 2:**

I tried to create a custom IAM role with admin access and pass it in to CodeBuild but the CodePipeline stack no longer will deploy.

### Expected Behavior

I would have expected either iteration to have successfully deployed the CodePipeline stack and deployed the the other stack in CodeBuild.

### Current Behavior

Neither iterations work.

**Error with iteration 1:**

```
Deployment failed: Error: example-stack: This CDK deployment requires bootstrap stack version '6', but during the confirmation via SSM parameter /cdk-bootstrap/hnb659fds/version the following error occurred: AccessDeniedException: User: arn:aws:sts::OMITTED:assumed-role/example-testRole34633740-AyqzAsAGDOPz/AWSCodeBuild-b20ef2ed-7da6-49f2-8afd-3604ae3ddc09 is not authorized to perform: ssm:GetParameter on resource: arn:aws:ssm:us-east-2:OMITTED:parameter/cdk-bootstrap/hnb659fds/version because no identity-based policy allows the ssm:GetParameter action
```

**Error with iteration 2:**

```
arn:aws:iam::OMITTED:role/example-automationRole287FA533-Vtj1n51Shw46 is not authorized to perform AssumeRole on role arn:aws:iam::OMITTED:role/example-CodeBuildRole728CBADE-z8z8uvmDfzC (Service: AWSCodePipeline; Status Code: 400; Error Code: InvalidStructureException; Request ID: 176eb989-f485
-49c6-8fe7-d816bf5c6018; Proxy: null)
```

### Reproduction Steps

**Iteration 1:**

```typescript
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as codepipeline from 'aws-cdk-lib/aws-codepipeline';
import * as codepipeline_actions from 'aws-cdk-lib/aws-codepipeline-actions';
import * as codebuild from 'aws-cdk-lib/aws-codebuild';
import * as iam from 'aws-cdk-lib/aws-iam';
import { Secret } from 'aws-cdk-lib/aws-secretsmanager';
import { SecretValue } from 'aws-cdk-lib';

export class PipelineStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);

const githubTokenString = process.env.GITHUB_TOKEN || '';
const githubToken = new Secret(this, 'github-token', {
secretStringValue: SecretValue.unsafePlainText(githubTokenString),
});

const pipeline = new codepipeline.Pipeline(this, 'automation', {});
const sourceOutput = new codepipeline.Artifact();

const sourceAction = new codepipeline_actions.GitHubSourceAction({
actionName: 'Github',
owner: example',
repo: 'example',
oauthToken: githubToken.secretValue,
output: sourceOutput,
branch: 'main',
});

const buildAction = new codepipeline_actions.CodeBuildAction({
actionName: 'Build',
project: new codebuild.PipelineProject(this, 'build', {
buildSpec: codebuild.BuildSpec.fromSourceFilename('buildspec.yaml'),
environment: {
buildImage: codebuild.LinuxBuildImage.STANDARD_7_0,
},
}),
input: sourceOutput,
});

pipeline.addStage({
stageName: 'Source',
actions: [sourceAction],
});

pipeline.addStage({
stageName: 'Build',
actions: [buildAction],
});

}
}
```

**Iteration 2:**

```typescript
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as codepipeline from 'aws-cdk-lib/aws-codepipeline';
import * as codepipeline_actions from 'aws-cdk-lib/aws-codepipeline-actions';
import * as codebuild from 'aws-cdk-lib/aws-codebuild';
import * as iam from 'aws-cdk-lib/aws-iam';
import { Secret } from 'aws-cdk-lib/aws-secretsmanager';
import { SecretValue } from 'aws-cdk-lib';

export class PipelineStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);

const githubTokenString = process.env.GITHUB_TOKEN || '';
const githubToken = new Secret(this, 'github-token', {
secretStringValue: SecretValue.unsafePlainText(githubTokenString),
});

const pipeline = new codepipeline.Pipeline(this, 'automation', {});
const sourceOutput = new codepipeline.Artifact();

const sourceAction = new codepipeline_actions.GitHubSourceAction({
actionName: 'Github',
owner: example',
repo: 'example',
oauthToken: githubToken.secretValue,
output: sourceOutput,
branch: 'main',
});

const buildAction = new codepipeline_actions.CodeBuildAction({
actionName: 'Build',
project: new codebuild.PipelineProject(this, 'build', {
buildSpec: codebuild.BuildSpec.fromSourceFilename('buildspec.yaml'),
environment: {
buildImage: codebuild.LinuxBuildImage.STANDARD_7_0,
},
}),
input: sourceOutput,
role: new iam.Role(this, 'CodeBuildRole', {
assumedBy: new iam.ServicePrincipal('codebuild.amazonaws.com'),
managedPolicies: [
iam.ManagedPolicy.fromAwsManagedPolicyName('AdministratorAccess'),
],
}),

});

pipeline.addStage({
stageName: 'Source',
actions: [sourceAction],
});

pipeline.addStage({
stageName: 'Build',
actions: [buildAction],
});

}
}
```

### Possible Solution

For some reason it appears the CodePipeline CDK stack is creating 3 roles for this stack, when I expected 2. A couple years back I see the addition of an `actionRole` parameter but it since seems to have been removed. I'm not sure what the appropriate solution here is.

### Additional Information/Context

_No response_

### CDK CLI Version

2.117.0 (build 59d9b23)

### Framework Version

_No response_

### Node.js Version

Node.js v20.9.0

### OS

macOS 14.1.2 (23B92)

### Language

TypeScript

### Language Version

typescript@5.2.2

### Other information

_No response_

Contributor guide

Open the contributing guide

Research direction

Start by reproducing the supplied TypeScript examples and inspect the IAM roles generated by PipelineProject and CodeBuildAction. Compare the permissions and trust relationships for the default and custom-role configurations; done means the pipeline stack deploys and the CodeBuild job can deploy the target stack without authorization errors.

Written by the indexing model from the issue text.

Assessment

Tech stack
aws, typescript
Domain
authorization, cloud, devops
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.