aws / aws/aws-cdk

Pipeline: Value of CfnOutput is different if used in a PolicyStatement vs a property of `envFromCfnOutputs`

Open
#21,645 13 comments 0 reactions 1 assignee Claimed by @rix0rrr View on GitHub
@aws-cdk/pipelines bug effort/small p2
Dominant language
TypeScript
Stars
12.9k
Forks
4.6k
Avg merge
2d 3h
Merged PRs (30d)
83

Description

### Describe the bug

I'm creating a bucket in a Pipeline stage and saving the bucketName property as a `CfnOutput`. I use that output in a stage poststep in a shell command (using `envFromCfnOutputs`) and to generate a new PolicyStatement. The value of the name in the policy statement is different than the value of the ENV variable in the shell.

### Expected Behavior

The values should be the same no matter where the output is used.

### Current Behavior

The CfnOutput displays different values depending on where used.

### Reproduction Steps

Create a new bucket:

```
export class MyStack extends Stack {
public readonly bucketName: CfnOutput

constructor(scope: Construct, id: string, props: StackProps) {
const bucket = new Bucket(this, 'myBucket', {
removalPolicy: RemovalPolicy.DESTROY,
autoDeleteObjects: true,
});

this.bucketName = new CfnOutput(this, 'bucketName', {
value: bucket.bucketName
});
}
}
```

'Hoist' the value up the pipeline stage:

```
export class MyStage extends Stage {
public readonly bucketName: CfnOutput;

constructor(scope: Construct, id: string, props: StageProps) {
super(scope, id, props);
const stack = new MyStack(this, 'myStack', props);
this.bucketName = stack.bucketName
}
}
```

Create the pipeline and use the stage, add a poststep

```
export class MyPipeline extends Stack {
constructor(scope: Construct, id: string, props: StackProps) {
super(scope, id, props);

const source = CodePipelineSource.connection(...);
const stage = new MyStage(this, 'stage');
const synth = new CodeBuildStep('Synth', {
input: source,
commands: ['npm ci', 'npm run build', 'npm run cdk synth']
});

// generate a post step that builds my frontend and moves to the bucket
// I have to do this later, because I use some other values such as the URL
// to an API gateway in my React Code, so I can't use bucketDeploy in the stage

const frontend = this.getFrontendStep(source, stage.bucketName);

const pipeline = new CodePipeline(this, 'pipeline', {
pipelineName: 'myPipeline',
synth
});

const pipelineStage = pipeline.addStage(stage);
pipelineStage.addPost(frontend);
}

getFrontendStep(source: CodePipelineSource, bucketName: CfnOutput) {
// notice the echo shell command this value is CORRECT
// the CfnOutput value in the policy statement is INCORRECT

return new CodeBuildStep('frontend', {
input: source,
commands: [
'echo $AWS_FRONTEND_BUCKET_NAME',
'cd frontend',
'npm ci',
'npm run build',
'aws s3 sync ./dist/ s3://$AWS_FRONTEND_BUCKET_NAME/ --delete'
],
rolePolicyStatements: [
new PolicyStatement({
effect: Effect.ALLOW,
actions: ["S3:*"],
resources: [
`arn:aws:s3:::${bucketName.value}`,
`arn:aws:s3:::${bucketName.value}/*`
]
})
],
primaryOutputDirectory: 'frontend/dist',
envFromCfnOutputs: {
AWS_FRONTEND_BUCKET_NAME: bucketName
}
})
}
}
```

### Possible Solution

_No response_

### Additional Information/Context

_No response_

### CDK CLI Version

2.37.0

### Framework Version

_No response_

### Node.js Version

16.16.0

### OS

Mac

### Language

Typescript

### Language Version

Typescript 4.7.4

### Other information

_No response_

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.