From 47de05957d13164b91a238c4490f84f31b880588 Mon Sep 17 00:00:00 2001 From: Kaixiang Zhao Date: Fri, 7 Jun 2019 16:31:07 -0700 Subject: [PATCH] feat(codebuild): add functionality to allow using private registry and cross-account ECR repository as build image. BREAKING CHANGE: codebuild.LinuxBuildImage.fromDockerHub() has been renamed to fromDockerRegistry() * codebuild.WindowsBuildImage.fromDockerHub() has been renamed to fromDockerRegistry() Fixes #2175 --- allowed-breaking-changes.txt | 2 + packages/@aws-cdk/aws-codebuild/README.md | 7 +- .../@aws-cdk/aws-codebuild/lib/project.ts | 237 ++++++++++++------ packages/@aws-cdk/aws-codebuild/package.json | 4 +- .../test/integ.docker-asset.lit.expected.json | 69 ++--- .../integ.docker-registry.lit.expected.json | 148 +++++++++++ .../test/integ.docker-registry.lit.ts | 36 +++ .../test/integ.ecr.lit.expected.json | 53 ++-- 8 files changed, 423 insertions(+), 133 deletions(-) create mode 100644 packages/@aws-cdk/aws-codebuild/test/integ.docker-registry.lit.expected.json create mode 100644 packages/@aws-cdk/aws-codebuild/test/integ.docker-registry.lit.ts diff --git a/allowed-breaking-changes.txt b/allowed-breaking-changes.txt index 0901892b553ff..3e8001958f05f 100644 --- a/allowed-breaking-changes.txt +++ b/allowed-breaking-changes.txt @@ -1,4 +1,6 @@ removed:@aws-cdk/aws-ec2.Port.toRuleJSON +removed:@aws-cdk/aws-codebuild.LinuxBuildImage.fromDockerHub +removed:@aws-cdk/aws-codebuild.WindowsBuildImage.fromDockerHub change-return-type:@aws-cdk/aws-codebuild.PipelineProject.addSecondaryArtifact change-return-type:@aws-cdk/aws-codebuild.Project.addSecondaryArtifact removed:@aws-cdk/aws-ec2.Connections.allowFromAnyIPv4 diff --git a/packages/@aws-cdk/aws-codebuild/README.md b/packages/@aws-cdk/aws-codebuild/README.md index 9b634febe5fc1..39ce76ce7702d 100644 --- a/packages/@aws-cdk/aws-codebuild/README.md +++ b/packages/@aws-cdk/aws-codebuild/README.md @@ -186,8 +186,7 @@ of the constants such as `WindowsBuildImage.WIN_SERVER_CORE_2016_BASE` or Alternatively, you can specify a custom image using one of the static methods on `XxxBuildImage`: -* Use `.fromDockerHub(image)` to reference an image publicly available in Docker - Hub. +* Use `.fromDockerRegistry(image[, { credentials }])` to reference an image in any public or private Docker registry. * Use `.fromEcrRepository(repo[, tag])` to reference an image available in an ECR repository. * Use `.fromAsset(directory)` to use an image created from a @@ -201,6 +200,10 @@ The following example shows how to define an image from an ECR repository: [ECR example](./test/integ.ecr.lit.ts) +The following example shows how to define an image from a private docker registry: + +[Docker Registry example](./test/integ.docker-registry.lit.ts) + ## Events CodeBuild projects can be used either as a source for events or be triggered diff --git a/packages/@aws-cdk/aws-codebuild/lib/project.ts b/packages/@aws-cdk/aws-codebuild/lib/project.ts index 2d44917c69eac..3a9b764df5656 100644 --- a/packages/@aws-cdk/aws-codebuild/lib/project.ts +++ b/packages/@aws-cdk/aws-codebuild/lib/project.ts @@ -5,6 +5,7 @@ import { DockerImageAsset, DockerImageAssetProps } from '@aws-cdk/aws-ecr-assets import events = require('@aws-cdk/aws-events'); import iam = require('@aws-cdk/aws-iam'); import kms = require('@aws-cdk/aws-kms'); +import secretsmanager = require('@aws-cdk/aws-secretsmanager'); import { Aws, CfnResource, Construct, Duration, IResource, Lazy, PhysicalName, Resource, Stack } from '@aws-cdk/core'; import { IArtifacts } from './artifacts'; import { BuildSpec } from './build-spec'; @@ -797,9 +798,28 @@ export class Project extends ProjectBase { throw new Error("Invalid CodeBuild environment: " + errors.join('\n')); } + if (this.buildImage.repository) { + if (this.buildImage.imagePullCredentialsType === ImagePullCredentialsType.SERVICE_ROLE) { + this.buildImage.repository.grantPull(this); + } else { + const statement = new iam.PolicyStatement({ + principals: [new iam.ServicePrincipal('codebuild.amazonaws.com')], + actions: ['ecr:GetDownloadUrlForLayer', 'ecr:BatchGetImage', 'ecr:BatchCheckLayerAvailability'], + }); + statement.sid = 'CodeBuild'; + this.buildImage.repository.addToResourcePolicy(statement); + } + } + return { type: this.buildImage.type, image: this.buildImage.imageId, + imagePullCredentialsType: this.buildImage.imagePullCredentialsType, + registryCredential: this.buildImage.credentials ? + { + credentialProvider: 'SECRETS_MANAGER', + credential: this.buildImage.credentials.secretArn + } : undefined, privilegedMode: env.privileged || false, computeType: env.computeType || this.buildImage.defaultComputeType, environmentVariables: !hasEnvironmentVars ? undefined : Object.keys(vars).map(name => ({ @@ -924,6 +944,22 @@ export enum ComputeType { LARGE = 'BUILD_GENERAL1_LARGE' } +/** + * The type of credentials AWS CodeBuild uses to pull images in your build. + */ +export enum ImagePullCredentialsType { + /** + * CODEBUILD specifies that AWS CodeBuild uses its own credentials. + * This requires that you modify your ECR repository policy to trust AWS CodeBuild's service principal. + */ + CODEBUILD = 'CODEBUILD', + + /** + * SERVICE_ROLE specifies that AWS CodeBuild uses your build project's service role. + */ + SERVICE_ROLE = 'SERVICE_ROLE' +} + export interface BuildEnvironment { /** * The image used for the builds. @@ -982,6 +1018,27 @@ export interface IBuildImage { */ readonly defaultComputeType: ComputeType; + /** + * The type of credentials AWS CodeBuild uses to pull images in your build. + * {@link ImagePullCredentialsType.CODEBUILD} will be used for CodeBuild images, + * {@link ImagePullCredentialsType.SERVICE_ROLE} will be used for all other images. + */ + readonly imagePullCredentialsType?: ImagePullCredentialsType; + + /** + * The credentials for access to a private registry. + * + * @default no credentials will be used + */ + readonly credentials?: secretsmanager.ISecret; + + /** + * An optional ECR repository that the image is hosted in. + * + * @default no repository + */ + readonly repository?: ecr.IRepository; + /** * Allows the image a chance to validate whether the passed configuration is correct. * @@ -995,6 +1052,17 @@ export interface IBuildImage { runScriptBuildspec(entrypoint: string): BuildSpec; } +interface LinuxBuildImageProps { + readonly imageId: string; + readonly imagePullCredentialsType?: ImagePullCredentialsType; + readonly credentials?: secretsmanager.ISecret; + readonly repository?: ecr.IRepository; +} + +export interface DockerImageOptions { + readonly credentials?: secretsmanager.ISecret; +} + /** * A CodeBuild image running Linux. * @@ -1002,7 +1070,7 @@ export interface IBuildImage { * * You can also specify a custom image using one of the static methods: * - * - LinuxBuildImage.fromDockerHub(image) + * - LinuxBuildImage.fromDockerRegistry(image[, { credentials }]) * - LinuxBuildImage.fromEcrRepository(repo[, tag]) * - LinuxBuildImage.fromAsset(parent, id, props) * @@ -1010,44 +1078,48 @@ export interface IBuildImage { * @see https://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref-available.html */ export class LinuxBuildImage implements IBuildImage { - public static readonly STANDARD_1_0 = new LinuxBuildImage('aws/codebuild/standard:1.0'); - public static readonly STANDARD_2_0 = new LinuxBuildImage('aws/codebuild/standard:2.0'); - public static readonly UBUNTU_14_04_BASE = new LinuxBuildImage('aws/codebuild/ubuntu-base:14.04'); - public static readonly UBUNTU_14_04_ANDROID_JAVA8_24_4_1 = new LinuxBuildImage('aws/codebuild/android-java-8:24.4.1'); - public static readonly UBUNTU_14_04_ANDROID_JAVA8_26_1_1 = new LinuxBuildImage('aws/codebuild/android-java-8:26.1.1'); - public static readonly UBUNTU_14_04_DOCKER_17_09_0 = new LinuxBuildImage('aws/codebuild/docker:17.09.0'); - public static readonly UBUNTU_14_04_DOCKER_18_09_0 = new LinuxBuildImage('aws/codebuild/docker:18.09.0'); - public static readonly UBUNTU_14_04_GOLANG_1_10 = new LinuxBuildImage('aws/codebuild/golang:1.10'); - public static readonly UBUNTU_14_04_GOLANG_1_11 = new LinuxBuildImage('aws/codebuild/golang:1.11'); - public static readonly UBUNTU_14_04_OPEN_JDK_8 = new LinuxBuildImage('aws/codebuild/java:openjdk-8'); - public static readonly UBUNTU_14_04_OPEN_JDK_9 = new LinuxBuildImage('aws/codebuild/java:openjdk-9'); - public static readonly UBUNTU_14_04_OPEN_JDK_11 = new LinuxBuildImage('aws/codebuild/java:openjdk-11'); - public static readonly UBUNTU_14_04_NODEJS_10_14_1 = new LinuxBuildImage('aws/codebuild/nodejs:10.14.1'); - public static readonly UBUNTU_14_04_NODEJS_10_1_0 = new LinuxBuildImage('aws/codebuild/nodejs:10.1.0'); - public static readonly UBUNTU_14_04_NODEJS_8_11_0 = new LinuxBuildImage('aws/codebuild/nodejs:8.11.0'); - public static readonly UBUNTU_14_04_NODEJS_6_3_1 = new LinuxBuildImage('aws/codebuild/nodejs:6.3.1'); - public static readonly UBUNTU_14_04_PHP_5_6 = new LinuxBuildImage('aws/codebuild/php:5.6'); - public static readonly UBUNTU_14_04_PHP_7_0 = new LinuxBuildImage('aws/codebuild/php:7.0'); - public static readonly UBUNTU_14_04_PHP_7_1 = new LinuxBuildImage('aws/codebuild/php:7.1'); - public static readonly UBUNTU_14_04_PYTHON_3_7_1 = new LinuxBuildImage('aws/codebuild/python:3.7.1'); - public static readonly UBUNTU_14_04_PYTHON_3_6_5 = new LinuxBuildImage('aws/codebuild/python:3.6.5'); - public static readonly UBUNTU_14_04_PYTHON_3_5_2 = new LinuxBuildImage('aws/codebuild/python:3.5.2'); - public static readonly UBUNTU_14_04_PYTHON_3_4_5 = new LinuxBuildImage('aws/codebuild/python:3.4.5'); - public static readonly UBUNTU_14_04_PYTHON_3_3_6 = new LinuxBuildImage('aws/codebuild/python:3.3.6'); - public static readonly UBUNTU_14_04_PYTHON_2_7_12 = new LinuxBuildImage('aws/codebuild/python:2.7.12'); - public static readonly UBUNTU_14_04_RUBY_2_5_3 = new LinuxBuildImage('aws/codebuild/ruby:2.5.3'); - public static readonly UBUNTU_14_04_RUBY_2_5_1 = new LinuxBuildImage('aws/codebuild/ruby:2.5.1'); - public static readonly UBUNTU_14_04_RUBY_2_3_1 = new LinuxBuildImage('aws/codebuild/ruby:2.3.1'); - public static readonly UBUNTU_14_04_RUBY_2_2_5 = new LinuxBuildImage('aws/codebuild/ruby:2.2.5'); - public static readonly UBUNTU_14_04_DOTNET_CORE_1_1 = new LinuxBuildImage('aws/codebuild/dot-net:core-1'); - public static readonly UBUNTU_14_04_DOTNET_CORE_2_0 = new LinuxBuildImage('aws/codebuild/dot-net:core-2.0'); - public static readonly UBUNTU_14_04_DOTNET_CORE_2_1 = new LinuxBuildImage('aws/codebuild/dot-net:core-2.1'); + public static readonly STANDARD_1_0 = LinuxBuildImage.codeBuildImage('aws/codebuild/standard:1.0'); + public static readonly STANDARD_2_0 = LinuxBuildImage.codeBuildImage('aws/codebuild/standard:2.0'); + public static readonly UBUNTU_14_04_BASE = LinuxBuildImage.codeBuildImage('aws/codebuild/ubuntu-base:14.04'); + public static readonly UBUNTU_14_04_ANDROID_JAVA8_24_4_1 = LinuxBuildImage.codeBuildImage('aws/codebuild/android-java-8:24.4.1'); + public static readonly UBUNTU_14_04_ANDROID_JAVA8_26_1_1 = LinuxBuildImage.codeBuildImage('aws/codebuild/android-java-8:26.1.1'); + public static readonly UBUNTU_14_04_DOCKER_17_09_0 = LinuxBuildImage.codeBuildImage('aws/codebuild/docker:17.09.0'); + public static readonly UBUNTU_14_04_DOCKER_18_09_0 = LinuxBuildImage.codeBuildImage('aws/codebuild/docker:18.09.0'); + public static readonly UBUNTU_14_04_GOLANG_1_10 = LinuxBuildImage.codeBuildImage('aws/codebuild/golang:1.10'); + public static readonly UBUNTU_14_04_GOLANG_1_11 = LinuxBuildImage.codeBuildImage('aws/codebuild/golang:1.11'); + public static readonly UBUNTU_14_04_OPEN_JDK_8 = LinuxBuildImage.codeBuildImage('aws/codebuild/java:openjdk-8'); + public static readonly UBUNTU_14_04_OPEN_JDK_9 = LinuxBuildImage.codeBuildImage('aws/codebuild/java:openjdk-9'); + public static readonly UBUNTU_14_04_OPEN_JDK_11 = LinuxBuildImage.codeBuildImage('aws/codebuild/java:openjdk-11'); + public static readonly UBUNTU_14_04_NODEJS_10_14_1 = LinuxBuildImage.codeBuildImage('aws/codebuild/nodejs:10.14.1'); + public static readonly UBUNTU_14_04_NODEJS_10_1_0 = LinuxBuildImage.codeBuildImage('aws/codebuild/nodejs:10.1.0'); + public static readonly UBUNTU_14_04_NODEJS_8_11_0 = LinuxBuildImage.codeBuildImage('aws/codebuild/nodejs:8.11.0'); + public static readonly UBUNTU_14_04_NODEJS_6_3_1 = LinuxBuildImage.codeBuildImage('aws/codebuild/nodejs:6.3.1'); + public static readonly UBUNTU_14_04_PHP_5_6 = LinuxBuildImage.codeBuildImage('aws/codebuild/php:5.6'); + public static readonly UBUNTU_14_04_PHP_7_0 = LinuxBuildImage.codeBuildImage('aws/codebuild/php:7.0'); + public static readonly UBUNTU_14_04_PHP_7_1 = LinuxBuildImage.codeBuildImage('aws/codebuild/php:7.1'); + public static readonly UBUNTU_14_04_PYTHON_3_7_1 = LinuxBuildImage.codeBuildImage('aws/codebuild/python:3.7.1'); + public static readonly UBUNTU_14_04_PYTHON_3_6_5 = LinuxBuildImage.codeBuildImage('aws/codebuild/python:3.6.5'); + public static readonly UBUNTU_14_04_PYTHON_3_5_2 = LinuxBuildImage.codeBuildImage('aws/codebuild/python:3.5.2'); + public static readonly UBUNTU_14_04_PYTHON_3_4_5 = LinuxBuildImage.codeBuildImage('aws/codebuild/python:3.4.5'); + public static readonly UBUNTU_14_04_PYTHON_3_3_6 = LinuxBuildImage.codeBuildImage('aws/codebuild/python:3.3.6'); + public static readonly UBUNTU_14_04_PYTHON_2_7_12 = LinuxBuildImage.codeBuildImage('aws/codebuild/python:2.7.12'); + public static readonly UBUNTU_14_04_RUBY_2_5_3 = LinuxBuildImage.codeBuildImage('aws/codebuild/ruby:2.5.3'); + public static readonly UBUNTU_14_04_RUBY_2_5_1 = LinuxBuildImage.codeBuildImage('aws/codebuild/ruby:2.5.1'); + public static readonly UBUNTU_14_04_RUBY_2_3_1 = LinuxBuildImage.codeBuildImage('aws/codebuild/ruby:2.3.1'); + public static readonly UBUNTU_14_04_RUBY_2_2_5 = LinuxBuildImage.codeBuildImage('aws/codebuild/ruby:2.2.5'); + public static readonly UBUNTU_14_04_DOTNET_CORE_1_1 = LinuxBuildImage.codeBuildImage('aws/codebuild/dot-net:core-1'); + public static readonly UBUNTU_14_04_DOTNET_CORE_2_0 = LinuxBuildImage.codeBuildImage('aws/codebuild/dot-net:core-2.0'); + public static readonly UBUNTU_14_04_DOTNET_CORE_2_1 = LinuxBuildImage.codeBuildImage('aws/codebuild/dot-net:core-2.1'); /** * @returns a Linux build image from a Docker Hub image. */ - public static fromDockerHub(name: string): LinuxBuildImage { - return new LinuxBuildImage(name); + public static fromDockerRegistry(name: string, options: DockerImageOptions = {}): LinuxBuildImage { + return new LinuxBuildImage({ + ...options, + imageId: name, + imagePullCredentialsType: ImagePullCredentialsType.SERVICE_ROLE, + }); } /** @@ -1062,9 +1134,11 @@ export class LinuxBuildImage implements IBuildImage { * @param tag Image tag (default "latest") */ public static fromEcrRepository(repository: ecr.IRepository, tag: string = 'latest'): LinuxBuildImage { - const image = new LinuxBuildImage(repository.repositoryUriForTag(tag)); - repository.addToResourcePolicy(ecrAccessForCodeBuildService()); - return image; + return new LinuxBuildImage({ + imageId: repository.repositoryUriForTag(tag), + imagePullCredentialsType: ImagePullCredentialsType.SERVICE_ROLE, + repository, + }); } /** @@ -1072,19 +1146,29 @@ export class LinuxBuildImage implements IBuildImage { */ public static fromAsset(scope: Construct, id: string, props: DockerImageAssetProps): LinuxBuildImage { const asset = new DockerImageAsset(scope, id, props); - const image = new LinuxBuildImage(asset.imageUri); - - // allow this codebuild to pull this image (CodeBuild doesn't use a role, so - // we can't use `asset.grantUseImage()`. - asset.repository.addToResourcePolicy(ecrAccessForCodeBuildService()); + return new LinuxBuildImage({ + imageId: asset.imageUri, + imagePullCredentialsType: ImagePullCredentialsType.SERVICE_ROLE, + repository: asset.repository, + }); + } - return image; + private static codeBuildImage(name: string): LinuxBuildImage { + return new LinuxBuildImage({ imageId: name }); } public readonly type = 'LINUX_CONTAINER'; public readonly defaultComputeType = ComputeType.SMALL; - - private constructor(public readonly imageId: string) { + public readonly imageId: string; + public readonly imagePullCredentialsType?: ImagePullCredentialsType; + public readonly credentials?: secretsmanager.ISecret; + public readonly repository?: ecr.IRepository; + + private constructor(props: LinuxBuildImageProps) { + this.imageId = props.imageId; + this.imagePullCredentialsType = props.imagePullCredentialsType; + this.credentials = props.credentials; + this.repository = props.repository; } public validate(_: BuildEnvironment): string[] { @@ -1120,6 +1204,13 @@ export class LinuxBuildImage implements IBuildImage { } } +interface WindowsBuildImageProps { + readonly imageId: string; + readonly imagePullCredentialsType?: ImagePullCredentialsType; + readonly credentials?: secretsmanager.ISecret; + readonly repository?: ecr.IRepository; +} + /** * A CodeBuild image running Windows. * @@ -1127,20 +1218,24 @@ export class LinuxBuildImage implements IBuildImage { * * You can also specify a custom image using one of the static methods: * - * - WindowsBuildImage.fromDockerHub(image) + * - WindowsBuildImage.fromDockerRegistry(image[, { credentials }]) * - WindowsBuildImage.fromEcrRepository(repo[, tag]) * - WindowsBuildImage.fromAsset(parent, id, props) * * @see https://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref-available.html */ export class WindowsBuildImage implements IBuildImage { - public static readonly WIN_SERVER_CORE_2016_BASE = new WindowsBuildImage('aws/codebuild/windows-base:1.0'); + public static readonly WIN_SERVER_CORE_2016_BASE = new WindowsBuildImage({ imageId: 'aws/codebuild/windows-base:1.0' }); /** * @returns a Windows build image from a Docker Hub image. */ - public static fromDockerHub(name: string): WindowsBuildImage { - return new WindowsBuildImage(name); + public static fromDockerRegistry(name: string, options: DockerImageOptions): WindowsBuildImage { + return new WindowsBuildImage({ + ...options, + imageId: name, + imagePullCredentialsType: ImagePullCredentialsType.SERVICE_ROLE, + }); } /** @@ -1155,9 +1250,11 @@ export class WindowsBuildImage implements IBuildImage { * @param tag Image tag (default "latest") */ public static fromEcrRepository(repository: ecr.IRepository, tag: string = 'latest'): WindowsBuildImage { - const image = new WindowsBuildImage(repository.repositoryUriForTag(tag)); - repository.addToResourcePolicy(ecrAccessForCodeBuildService()); - return image; + return new WindowsBuildImage({ + imageId: repository.repositoryUriForTag(tag), + imagePullCredentialsType: ImagePullCredentialsType.SERVICE_ROLE, + repository, + }); } /** @@ -1165,18 +1262,25 @@ export class WindowsBuildImage implements IBuildImage { */ public static fromAsset(scope: Construct, id: string, props: DockerImageAssetProps): WindowsBuildImage { const asset = new DockerImageAsset(scope, id, props); - const image = new WindowsBuildImage(asset.imageUri); - - // allow this codebuild to pull this image (CodeBuild doesn't use a role, so - // we can't use `asset.grantUseImage()`. - asset.repository.addToResourcePolicy(ecrAccessForCodeBuildService()); - - return image; + return new WindowsBuildImage({ + imageId: asset.imageUri, + imagePullCredentialsType: ImagePullCredentialsType.SERVICE_ROLE, + repository: asset.repository, + }); } + public readonly type = 'WINDOWS_CONTAINER'; public readonly defaultComputeType = ComputeType.MEDIUM; - - private constructor(public readonly imageId: string) { + public readonly imageId: string; + public readonly imagePullCredentialsType?: ImagePullCredentialsType; + public readonly credentials?: secretsmanager.ISecret; + public readonly repository?: ecr.IRepository; + + private constructor(props: WindowsBuildImageProps) { + this.imageId = props.imageId; + this.imagePullCredentialsType = props.imagePullCredentialsType; + this.credentials = props.credentials; + this.repository = props.repository; } public validate(buildEnvironment: BuildEnvironment): string[] { @@ -1238,12 +1342,3 @@ export enum BuildEnvironmentVariableType { */ PARAMETER_STORE = 'PARAMETER_STORE' } - -function ecrAccessForCodeBuildService(): iam.PolicyStatement { - const s = new iam.PolicyStatement({ - principals: [new iam.ServicePrincipal('codebuild.amazonaws.com')], - actions: ['ecr:GetDownloadUrlForLayer', 'ecr:BatchGetImage', 'ecr:BatchCheckLayerAvailability'], - }); - s.sid = 'CodeBuild'; - return s; -} diff --git a/packages/@aws-cdk/aws-codebuild/package.json b/packages/@aws-cdk/aws-codebuild/package.json index 00f927c63ffaf..53b1c87a824fc 100644 --- a/packages/@aws-cdk/aws-codebuild/package.json +++ b/packages/@aws-cdk/aws-codebuild/package.json @@ -90,6 +90,7 @@ "@aws-cdk/aws-kms": "^0.37.0", "@aws-cdk/aws-s3": "^0.37.0", "@aws-cdk/aws-s3-assets": "^0.37.0", + "@aws-cdk/aws-secretsmanager": "^0.37.0", "@aws-cdk/core": "^0.37.0" }, "homepage": "https://github.com/awslabs/aws-cdk", @@ -105,6 +106,7 @@ "@aws-cdk/aws-kms": "^0.37.0", "@aws-cdk/aws-s3": "^0.37.0", "@aws-cdk/aws-s3-assets": "^0.37.0", + "@aws-cdk/aws-secretsmanager": "^0.37.0", "@aws-cdk/core": "^0.37.0" }, "engines": { @@ -118,4 +120,4 @@ ] }, "stability": "stable" -} \ No newline at end of file +} diff --git a/packages/@aws-cdk/aws-codebuild/test/integ.docker-asset.lit.expected.json b/packages/@aws-cdk/aws-codebuild/test/integ.docker-asset.lit.expected.json index d4b6b0e10e84b..5a66818ed4c7f 100644 --- a/packages/@aws-cdk/aws-codebuild/test/integ.docker-asset.lit.expected.json +++ b/packages/@aws-cdk/aws-codebuild/test/integ.docker-asset.lit.expected.json @@ -39,33 +39,6 @@ ] } ] - }, - "PolicyDocument": { - "Statement": [ - { - "Action": [ - "ecr:GetDownloadUrlForLayer", - "ecr:BatchGetImage", - "ecr:BatchCheckLayerAvailability" - ], - "Effect": "Allow", - "Principal": { - "Service": { - "Fn::Join": [ - "", - [ - "codebuild.", - { - "Ref": "AWS::URLSuffix" - } - ] - ] - } - }, - "Sid": "CodeBuild" - } - ], - "Version": "2012-10-17" } }, "DependsOn": [ @@ -262,6 +235,45 @@ "Properties": { "PolicyDocument": { "Statement": [ + { + "Action": [ + "ecr:BatchCheckLayerAvailability", + "ecr:GetDownloadUrlForLayer", + "ecr:BatchGetImage" + ], + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":ecr:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":repository/", + { + "Fn::GetAtt": [ + "MyImageAdoptRepository6CA902F6", + "RepositoryName" + ] + } + ] + ] + } + }, + { + "Action": "ecr:GetAuthorizationToken", + "Effect": "Allow", + "Resource": "*" + }, { "Action": [ "logs:CreateLogGroup", @@ -439,6 +451,7 @@ ] ] }, + "ImagePullCredentialsType": "SERVICE_ROLE", "PrivilegedMode": false, "Type": "LINUX_CONTAINER" }, @@ -455,4 +468,4 @@ } } } -} \ No newline at end of file +} diff --git a/packages/@aws-cdk/aws-codebuild/test/integ.docker-registry.lit.expected.json b/packages/@aws-cdk/aws-codebuild/test/integ.docker-registry.lit.expected.json new file mode 100644 index 0000000000000..b8cd00a66ffb2 --- /dev/null +++ b/packages/@aws-cdk/aws-codebuild/test/integ.docker-registry.lit.expected.json @@ -0,0 +1,148 @@ +{ + "Resources": { + "MyProjectRole9BBE5233": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": { + "Fn::Join": [ + "", + [ + "codebuild.", + { + "Ref": "AWS::URLSuffix" + } + ] + ] + } + } + } + ], + "Version": "2012-10-17" + } + } + }, + "MyProjectRoleDefaultPolicyB19B7C29": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":logs:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":log-group:/aws/codebuild/", + { + "Ref": "MyProject39F7B0AE" + } + ] + ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":logs:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":log-group:/aws/codebuild/", + { + "Ref": "MyProject39F7B0AE" + }, + ":*" + ] + ] + } + ] + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "MyProjectRoleDefaultPolicyB19B7C29", + "Roles": [ + { + "Ref": "MyProjectRole9BBE5233" + } + ] + } + }, + "MyProject39F7B0AE": { + "Type": "AWS::CodeBuild::Project", + "Properties": { + "Artifacts": { + "Type": "NO_ARTIFACTS" + }, + "Environment": { + "ComputeType": "BUILD_GENERAL1_SMALL", + "Image": "my-registry/my-repo", + "ImagePullCredentialsType": "SERVICE_ROLE", + "PrivilegedMode": false, + "RegistryCredential": { + "Credential": { + "Fn::Join": [ + "", + [ + "arn:aws:secretsmanager:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":secret:my-secrets-123456" + ] + ] + }, + "CredentialProvider": "SECRETS_MANAGER" + }, + "Type": "LINUX_CONTAINER" + }, + "ServiceRole": { + "Fn::GetAtt": [ + "MyProjectRole9BBE5233", + "Arn" + ] + }, + "Source": { + "BuildSpec": "{\n \"version\": \"0.2\",\n \"phases\": {\n \"build\": {\n \"commands\": [\n \"ls\"\n ]\n }\n }\n}", + "Type": "NO_SOURCE" + } + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-codebuild/test/integ.docker-registry.lit.ts b/packages/@aws-cdk/aws-codebuild/test/integ.docker-registry.lit.ts new file mode 100644 index 0000000000000..e89391c180b6c --- /dev/null +++ b/packages/@aws-cdk/aws-codebuild/test/integ.docker-registry.lit.ts @@ -0,0 +1,36 @@ +import secretsmanager = require('@aws-cdk/aws-secretsmanager'); +import cdk = require('@aws-cdk/core'); +import codebuild = require('../lib'); + +class TestStack extends cdk.Stack { + constructor(scope: cdk.App, id: string) { + super(scope, id); + + const secrets = secretsmanager.Secret.fromSecretArn(this, "MySecrets", + `arn:aws:secretsmanager:${this.region}:${this.account}:secret:my-secrets-123456`); + + new codebuild.Project(this, 'MyProject', { + buildSpec: codebuild.BuildSpec.fromObject({ + version: "0.2", + phases: { + build: { + commands: [ 'ls' ] + } + } + }), + /// !show + environment: { + buildImage: codebuild.LinuxBuildImage.fromDockerRegistry('my-registry/my-repo', { + credentials: secrets, + }), + }, + /// !hide + }); + } +} + +const app = new cdk.App(); + +new TestStack(app, 'test-codebuild-docker-asset'); + +app.synth(); diff --git a/packages/@aws-cdk/aws-codebuild/test/integ.ecr.lit.expected.json b/packages/@aws-cdk/aws-codebuild/test/integ.ecr.lit.expected.json index 5bac318649a12..ae939917ab996 100644 --- a/packages/@aws-cdk/aws-codebuild/test/integ.ecr.lit.expected.json +++ b/packages/@aws-cdk/aws-codebuild/test/integ.ecr.lit.expected.json @@ -1,37 +1,8 @@ { "Resources": { "MyRepoF4F48043": { - "DeletionPolicy": "Retain", "Type": "AWS::ECR::Repository", - "Properties": { - "RepositoryPolicyText": { - "Statement": [ - { - "Action": [ - "ecr:GetDownloadUrlForLayer", - "ecr:BatchGetImage", - "ecr:BatchCheckLayerAvailability" - ], - "Effect": "Allow", - "Principal": { - "Service": { - "Fn::Join": [ - "", - [ - "codebuild.", - { - "Ref": "AWS::URLSuffix" - } - ] - ] - } - }, - "Sid": "CodeBuild" - } - ], - "Version": "2012-10-17" - } - } + "DeletionPolicy": "Retain" }, "MyProjectRole9BBE5233": { "Type": "AWS::IAM::Role", @@ -65,6 +36,25 @@ "Properties": { "PolicyDocument": { "Statement": [ + { + "Action": [ + "ecr:BatchCheckLayerAvailability", + "ecr:GetDownloadUrlForLayer", + "ecr:BatchGetImage" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "MyRepoF4F48043", + "Arn" + ] + } + }, + { + "Action": "ecr:GetAuthorizationToken", + "Effect": "Allow", + "Resource": "*" + }, { "Action": [ "logs:CreateLogGroup", @@ -186,6 +176,7 @@ ] ] }, + "ImagePullCredentialsType": "SERVICE_ROLE", "PrivilegedMode": false, "Type": "LINUX_CONTAINER" }, @@ -202,4 +193,4 @@ } } } -} \ No newline at end of file +}