Reputation: 11
I am using a private Github repo in my CodePipeline build, as our Docker container involves using poetry install
to pull dependencies during the creation of the image that gets uploaded to ECR.
I am also using a Docker build secret to "inject" the private key required to read the git repo during this step.
This all works correctly with a local build of the docker image; if I specify the --secret on the docker build commandline, I get a healthy image out.
But I am struggling to understand how to set up the CodePipeline steps in CDK such that I can:
--secret
command doesn't fail to find the file.My attempt involved a pipeline Stage whose only stack is producing the DockerImageAsset, and when adding this stage to the pipeline, I specify a pre
step, which is the ShellStep that retrieves the AWS secret.
This is the snippet that adds the docker stage and secret-retrieval step to the pipeline:
addArtifactBuildStage(props: SelfUpdatingPipelineStackProps): DockerBuildStage {
const pathToReaderSecret = './secret.dat'
const getPrivkeyStep = new pipelines.ShellStep('extractPrivkeyStep', {
commands: [
`aws secretsmanager get-secret-value --secret-id ${privkeySecretName} >${pathToReaderSecret}`,
],
})
getPrivkeyStep.addOutputDirectory('.')
const dockerBuildStage = new DockerBuildStage(this, 'BuildDeployableArtifactStage', {
env: props.env!,
apiSourcePath: this.apiSourcePath,
pathToReaderSecret,
})
this.codePipeline.addStage(dockerBuildStage, {
stackSteps: [
{
pre: [getPrivkeyStep],
stack: dockerBuildStage.artifactStack,
},
],
})
return dockerBuildStage
}
And here is the docker stage:
export interface DockerBuildStageProps extends cdk.StageProps {
env: cdk.Environment
apiSourcePath: string
pathToReaderSecret: string
}
export class DockerBuildStage extends cdk.Stage {
readonly artifactStack: DeployableArtifactStack
constructor(scope: Construct, id: string, props: DockerBuildStageProps) {
super(scope, id, {
...props,
stageName: 'Api-BuildFetch',
})
const pathToApiTaskDockerfile = `${props.apiSourcePath}/Dockerfile`
const { base: file, dir: directory } = parse(pathToApiTaskDockerfile)
const { pathToReaderSecret } = props
this.artifactStack = new DeployableArtifactStack(this, 'DeployedArtifactStack', {
stackName: `Api-DeployedArtifact`,
file,
directory,
pathToReaderSecret,
})
}
}
Finally, the DeployableArtifactStack:
export interface DeployableArtifactProps extends StackProps {
directory: string
file: string
pathToReaderSecret: string
}
export class DeployableArtifactStack extends Stack {
readonly dockerImageAsset: DockerImageAsset
constructor(scope: Construct, id: string, props: DeployableArtifactProps) {
super(scope, id, props)
const { directory, file, pathToReaderSecret } = props
this.dockerImageAsset = new DockerImageAsset(this, 'DockerImageAsset', {
directory,
file,
platform: Platform.LINUX_AMD64,
networkMode: NetworkMode.HOST,
buildSecrets: {
readerkey: DockerBuildSecret.fromSrc(pathToReaderSecret),
},
})
}
}
Upvotes: 0
Views: 288