aws-codepipeline: CodePipeline/CodeBuild roles don't have necessary access
- 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
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