如果有人遇到同样的问题,我设法用 CDK 和this example 解决了这个问题。它已经过时了,但我应用了相同的逻辑。由于最近的变化,可能不需要此答案中提到的某些步骤。我找到了一个更新的例子here,但我还没有尝试过。
重要提示:确保两个帐户中的资源位于同一区域。
让我们将 ID_ACC_WITH_REPO 调用到具有 CodeCommit 存储库的 AWS 账户 ID,并将 ID_ACC_WITH_PIPELINE 调用到具有管道以及我们想要部署架构的位置的账户 ID。
管道的 CDK 代码
ACC_WITH_REPO
- 在 ID_ACC_WITH_REPO 中创建一个堆栈。 必须指定区域,因为它是跨账户管道所必需的。
const repoAccStack = new cdk.Stack(app, 'RepoAccStack', {
env: {
account: ID_ACC_WITH_REPO,
region: REPO_REGION
}
});
- 在 ACC_WITH_REPO 中创建一个跨账户角色,并附加 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 不是必需的,类实现中使用的几种方法现在已弃用。
const artifactsBucket = new s3.Bucket(pipelineAccStack, "ArtifactsBucket", {
bucketName: BUCKET_NAME,
encryptionKey: key,
encryption: s3.BucketEncryption.KMS
});
artifactsBucket.grantReadWrite(new iam.ArnPrincipal(crossAccRole.roleArn));
- 创建管道并添加在第 5 步中创建的跨账户角色。
// 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 切换帐户。
有三个堆栈,而不是两个。 CDK 会自动生成 EventBusPolicy 堆栈以创建事件总线。其他两个事件由 CDK 在 PipelineAccStack 和 RepoAccStack 中添加(也自动添加)。 Marcin 的回答解释了如何配置跨账户事件。 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"