以跨账户 CodeCommit 存储库作为源的 AWS 管道
AWS pipeline with cross-account CodeCommit repo as Source
我需要使用 CDK 创建一个管道,该管道将基于 CodeCommit 存储库中的分支触发 CloudFormation 中的部署。如果 CodeCommit 存储库与管道在同一个帐户中,我会使用如下内容:
const codecommitRepo = codecommit.Repository.fromRepositoryName(
this,
'AppRepository',
'REPO_NAME'
);
pipeline.addStage({
stageName: 'Source',
actions: [
new codepipeline_actions.CodeCommitSourceAction({
actionName: 'Source',
repository: codecommitRepo,
branch: 'BRANCH_NAME',
output: sourceArtifact,
}),
],
});
但是,如果 CodeCommit 存储库在不同的帐户中怎么办?
我尝试重新创建的架构类似于 this article(下图)中显示的架构,但使用了 CDK 和 CloudFormation。
我该如何创建它?
CodePipeline (CP) 由 CC 通过 CloudWatch 事件规则 触发,当两者都在同一帐户中时:
CC ---> CW Event rule ---> CP
要跨帐户执行此操作,您必须调整 CW 事件。即,CC 账户中的 CW 事件规则必须将事件转发到 CP 账户中的 CW 事件:
CP ---> CW Event rule ---> CW Event bus in CP acc ---> CW rule --> CP
我没有适合您的代码,但应该这样做。您提供的 link 提供了此架构的更多具体细节。
我想当使用 CDK 时,您将不得不“手动”创建所有 CW 事件规则,因为这不是通常开箱即用的事情。
如果有人有同样的问题,我设法用CDK和this example. It's outdated but I applied the same logic. Probably some of the steps mentioned in this answer are not necesary because of recent changes. I found a more recent example here解决了,但我还没有尝试过。
重要提示:确保两个账户中的资源在同一地区。
让我们调用 ID_ACC_WITH_REPO 到带有 CodeCommit 存储库的 AWS 账户 ID 和 ID_ACC_WITH_PIPELINE 到带有管道的账户 ID 以及我们想要部署架构的位置。
流水线的 CDK 代码
ACC_WITH_REPO
- 在 ID_ACC_WITH_REPO 中创建堆栈。必须指定区域 ,因为 cross-account 管道需要它。
const repoAccStack = new cdk.Stack(app, 'RepoAccStack', {
env: {
account: ID_ACC_WITH_REPO,
region: REPO_REGION
}
});
- 在 ACC_WITH_REPO 中创建一个 cross-account 角色并附加 S3(用于存储工件)、CodeCommit 和 KMS(加密)的完整访问策略。该角色将由 ACC_WITH_PIPELINE 中的管道和源阶段中的 CodeCommit 源操作使用。我想您可以对它们进行更多限制以更加安全。
// Create role
const crossAccRole = new iam.Role(repoAccStack, 'OtherAccRole', {
roleName: 'CrossAccountRole',
assumedBy: new iam.AccountPrincipal(pipelineAcc),
});
// Attach policies
const policy = new iam.PolicyStatement();
policy.addAllResources();
policy.addActions('s3:*', 'codecommit:*', 'kms:*');
crossAccRole.addToPolicy(policy);
- 导入存储库。
const repo = codecommit.Repository.fromRepositoryArn(
repoAccStack,
'AppRepository',
`arn:aws:codecommit:${REPO_REGION}:${ID_ACC_WITH_REPO}:${REPO_NAME}`
);
ACC_WITH_PIPELINE
- 为 ID_ACC_WITH_PIPELINE 中的管道创建堆栈。
const pipelineAccStack = new cdk.Stack(app, 'PipelineAccStack', {
env: {
account: ID_ACC_WITH_PIPELINE,
region: REGION_WITH_PIPELINE
}
});
- 创建 KMS 密钥。示例中使用的方法
EncryptionKey
已弃用,请改用 Key
。
const key = new kms.Key(pipelineAccStack, 'CrossAccountKmsKey');
实际上我在尝试创建密钥时遇到了 kms.model.MalformedPolicyDocumentException
错误,所以我从 AWS 控制台手动完成,然后使用 kms.Key.fromKeyArn
导入它。我的帐户可能有问题(在使用此解决方案之前我遇到了很多错误),但如果您遇到相同的错误,这是一种解决方法。只需确保为管道角色分配使用权限即可。
- 使用之前创建的 KMS 在 ACC_WITH_PIPELINE 中创建 S3 存储桶。需要存储桶名称。示例中使用的
HackyIdentity
不是必需的,class 实现中使用的几种方法现已弃用。
const artifactsBucket = new s3.Bucket(pipelineAccStack, "ArtifactsBucket", {
bucketName: BUCKET_NAME,
encryptionKey: key,
encryption: s3.BucketEncryption.KMS
});
artifactsBucket.grantReadWrite(new iam.ArnPrincipal(crossAccRole.roleArn));
- 创建管道并添加在步骤 5 中创建的 cross-account 角色。
// Create pipeline
const pipeline = new codepipeline.Pipeline(pipelineAccStack, 'Pipeline', {
pipelineName: 'CrossAccountPipeline',
artifactBucket: artifactsBucket
});
// Add cross-account role
const policy = new iam.PolicyStatement();
policy.addResources(crossAccRole.roleArn)
policy.addActions('s3:*', 'codecommit:*', 'kms:*');
pipeline.addToRolePolicy(policy);
- 使用步骤 3 中导入的 CodeCommit 存储库将源阶段添加到管道。
// Create artifact for source code
const sourceArtifact = new codepipeline.Artifact();
// Create source stage with role
pipeline.addStage({
stageName: 'Source',
actions: [
new codepipeline_actions.CodeCommitSourceAction({
actionName: 'CodeCommit_Source',
repository: repo,
output: sourceArtifact,
branch: 'dev',
role: crossAccRole
})
]
});
- 最后添加构建阶段
// Create CodeBuild project
const buildProject = new codebuild.PipelineProject(this, 'Build', {
environment: { buildImage: codebuild.LinuxBuildImage.AMAZON_LINUX_2_2 }
});
// Create artifact for build
const buildArtifact = new codepipeline.Artifact();
// Add build stage
pipeline.addStage({
stageName: 'Build',
actions: [
new codepipeline_actions.CodeBuildAction({
actionName: 'Build',
project: buildProject,
input: sourceArtifact,
outputs: [buildArtifact],
}),
],
});
部署
当 CDK 应用程序包含多个堆栈时,您不能只 cdk deploy
。 here 中对此进行了解释。但是,如果您尝试 cdk deploy '*'
,则会出现另一个错误:Need to perform AWS calls for account ACCOUNT_ID, but the current credentials are for ACCOUNT_ID
.
我设法使用 cdk deploy -e
部署堆栈并使用 aws configure
切换帐户。
有三个堆栈,而不是两个。 EventBusPolicy 堆栈由 CDK 自动生成以创建事件总线。另外两个事件由 CDK 添加(也自动)在 PipelineAccStack 和 RepoAccStack 中。 Marcin 的回答解释了 cross-account 事件是如何配置的。 EventBusPolicy 堆栈应在 ACC_WITH_PIPELINE 中创建。要获取堆栈的确切名称,请使用 cdk list
.
考虑到所有这些,在这个例子中我将部署:
# with aws configure in ACC_WITH_PIPELINE
cdk deploy -e "PipelineAccStack"
cdk deploy -e "EventBusPolicy-$ID_ACC_WITH_REPO-$REGION-$ID_ACC_WITH_PIPELINE"
# switch aws configure to ACC_WITH_REPO
cdk deploy -e "RepoAccStack"
我需要使用 CDK 创建一个管道,该管道将基于 CodeCommit 存储库中的分支触发 CloudFormation 中的部署。如果 CodeCommit 存储库与管道在同一个帐户中,我会使用如下内容:
const codecommitRepo = codecommit.Repository.fromRepositoryName(
this,
'AppRepository',
'REPO_NAME'
);
pipeline.addStage({
stageName: 'Source',
actions: [
new codepipeline_actions.CodeCommitSourceAction({
actionName: 'Source',
repository: codecommitRepo,
branch: 'BRANCH_NAME',
output: sourceArtifact,
}),
],
});
但是,如果 CodeCommit 存储库在不同的帐户中怎么办?
我尝试重新创建的架构类似于 this article(下图)中显示的架构,但使用了 CDK 和 CloudFormation。
我该如何创建它?
CodePipeline (CP) 由 CC 通过 CloudWatch 事件规则 触发,当两者都在同一帐户中时:
CC ---> CW Event rule ---> CP
要跨帐户执行此操作,您必须调整 CW 事件。即,CC 账户中的 CW 事件规则必须将事件转发到 CP 账户中的 CW 事件:
CP ---> CW Event rule ---> CW Event bus in CP acc ---> CW rule --> CP
我没有适合您的代码,但应该这样做。您提供的 link 提供了此架构的更多具体细节。
我想当使用 CDK 时,您将不得不“手动”创建所有 CW 事件规则,因为这不是通常开箱即用的事情。
如果有人有同样的问题,我设法用CDK和this example. It's outdated but I applied the same logic. Probably some of the steps mentioned in this answer are not necesary because of recent changes. I found a more recent example here解决了,但我还没有尝试过。
重要提示:确保两个账户中的资源在同一地区。
让我们调用 ID_ACC_WITH_REPO 到带有 CodeCommit 存储库的 AWS 账户 ID 和 ID_ACC_WITH_PIPELINE 到带有管道的账户 ID 以及我们想要部署架构的位置。
流水线的 CDK 代码
ACC_WITH_REPO
- 在 ID_ACC_WITH_REPO 中创建堆栈。必须指定区域 ,因为 cross-account 管道需要它。
const repoAccStack = new cdk.Stack(app, 'RepoAccStack', {
env: {
account: ID_ACC_WITH_REPO,
region: REPO_REGION
}
});
- 在 ACC_WITH_REPO 中创建一个 cross-account 角色并附加 S3(用于存储工件)、CodeCommit 和 KMS(加密)的完整访问策略。该角色将由 ACC_WITH_PIPELINE 中的管道和源阶段中的 CodeCommit 源操作使用。我想您可以对它们进行更多限制以更加安全。
// Create role
const crossAccRole = new iam.Role(repoAccStack, 'OtherAccRole', {
roleName: 'CrossAccountRole',
assumedBy: new iam.AccountPrincipal(pipelineAcc),
});
// Attach policies
const policy = new iam.PolicyStatement();
policy.addAllResources();
policy.addActions('s3:*', 'codecommit:*', 'kms:*');
crossAccRole.addToPolicy(policy);
- 导入存储库。
const repo = codecommit.Repository.fromRepositoryArn(
repoAccStack,
'AppRepository',
`arn:aws:codecommit:${REPO_REGION}:${ID_ACC_WITH_REPO}:${REPO_NAME}`
);
ACC_WITH_PIPELINE
- 为 ID_ACC_WITH_PIPELINE 中的管道创建堆栈。
const pipelineAccStack = new cdk.Stack(app, 'PipelineAccStack', {
env: {
account: ID_ACC_WITH_PIPELINE,
region: REGION_WITH_PIPELINE
}
});
- 创建 KMS 密钥。示例中使用的方法
EncryptionKey
已弃用,请改用Key
。
const key = new kms.Key(pipelineAccStack, 'CrossAccountKmsKey');
实际上我在尝试创建密钥时遇到了 kms.model.MalformedPolicyDocumentException
错误,所以我从 AWS 控制台手动完成,然后使用 kms.Key.fromKeyArn
导入它。我的帐户可能有问题(在使用此解决方案之前我遇到了很多错误),但如果您遇到相同的错误,这是一种解决方法。只需确保为管道角色分配使用权限即可。
- 使用之前创建的 KMS 在 ACC_WITH_PIPELINE 中创建 S3 存储桶。需要存储桶名称。示例中使用的
HackyIdentity
不是必需的,class 实现中使用的几种方法现已弃用。
const artifactsBucket = new s3.Bucket(pipelineAccStack, "ArtifactsBucket", {
bucketName: BUCKET_NAME,
encryptionKey: key,
encryption: s3.BucketEncryption.KMS
});
artifactsBucket.grantReadWrite(new iam.ArnPrincipal(crossAccRole.roleArn));
- 创建管道并添加在步骤 5 中创建的 cross-account 角色。
// Create pipeline
const pipeline = new codepipeline.Pipeline(pipelineAccStack, 'Pipeline', {
pipelineName: 'CrossAccountPipeline',
artifactBucket: artifactsBucket
});
// Add cross-account role
const policy = new iam.PolicyStatement();
policy.addResources(crossAccRole.roleArn)
policy.addActions('s3:*', 'codecommit:*', 'kms:*');
pipeline.addToRolePolicy(policy);
- 使用步骤 3 中导入的 CodeCommit 存储库将源阶段添加到管道。
// Create artifact for source code
const sourceArtifact = new codepipeline.Artifact();
// Create source stage with role
pipeline.addStage({
stageName: 'Source',
actions: [
new codepipeline_actions.CodeCommitSourceAction({
actionName: 'CodeCommit_Source',
repository: repo,
output: sourceArtifact,
branch: 'dev',
role: crossAccRole
})
]
});
- 最后添加构建阶段
// Create CodeBuild project
const buildProject = new codebuild.PipelineProject(this, 'Build', {
environment: { buildImage: codebuild.LinuxBuildImage.AMAZON_LINUX_2_2 }
});
// Create artifact for build
const buildArtifact = new codepipeline.Artifact();
// Add build stage
pipeline.addStage({
stageName: 'Build',
actions: [
new codepipeline_actions.CodeBuildAction({
actionName: 'Build',
project: buildProject,
input: sourceArtifact,
outputs: [buildArtifact],
}),
],
});
部署
当 CDK 应用程序包含多个堆栈时,您不能只 cdk deploy
。 here 中对此进行了解释。但是,如果您尝试 cdk deploy '*'
,则会出现另一个错误:Need to perform AWS calls for account ACCOUNT_ID, but the current credentials are for ACCOUNT_ID
.
我设法使用 cdk deploy -e
部署堆栈并使用 aws configure
切换帐户。
有三个堆栈,而不是两个。 EventBusPolicy 堆栈由 CDK 自动生成以创建事件总线。另外两个事件由 CDK 添加(也自动)在 PipelineAccStack 和 RepoAccStack 中。 Marcin 的回答解释了 cross-account 事件是如何配置的。 EventBusPolicy 堆栈应在 ACC_WITH_PIPELINE 中创建。要获取堆栈的确切名称,请使用 cdk list
.
考虑到所有这些,在这个例子中我将部署:
# with aws configure in ACC_WITH_PIPELINE
cdk deploy -e "PipelineAccStack"
cdk deploy -e "EventBusPolicy-$ID_ACC_WITH_REPO-$REGION-$ID_ACC_WITH_PIPELINE"
# switch aws configure to ACC_WITH_REPO
cdk deploy -e "RepoAccStack"