【问题标题】:AWS pipeline with cross-account CodeCommit repo as Source以跨账户 CodeCommit 存储库为源的 AWS 管道
【发布时间】:2020-08-26 17:16:02
【问题描述】:

我需要使用 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。

我怎样才能创建它?

【问题讨论】:

    标签: amazon-web-services amazon-cloudformation aws-codepipeline aws-cdk aws-codecommit


    【解决方案1】:

    如果有人遇到同样的问题,我设法用 CDK 和this example 解决了这个问题。它已经过时了,但我应用了相同的逻辑。由于最近的变化,可能不需要此答案中提到的某些步骤。我找到了一个更新的例子here,但我还没有尝试过。

    重要提示:确保两个帐户中的资源位于同一区域。

    让我们将 ID_ACC_WITH_REPO 调用到具有 CodeCommit 存储库的 AWS 账户 ID,并将 ID_ACC_WITH_PIPELINE 调用到具有管道以及我们想要部署架构的位置的账户 ID。

    管道的 CDK 代码

    ACC_WITH_REPO

    1. 在 ID_ACC_WITH_REPO 中创建一个堆栈。 必须指定区域,因为它是跨账户管道所必需的。
    const repoAccStack = new cdk.Stack(app, 'RepoAccStack', {
        env: {
            account: ID_ACC_WITH_REPO,
            region: REPO_REGION
        }
    });
    
    1. 在 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);
    
    1. 导入存储库。
    const repo = codecommit.Repository.fromRepositoryArn(
      repoAccStack,
      'AppRepository',
      `arn:aws:codecommit:${REPO_REGION}:${ID_ACC_WITH_REPO}:${REPO_NAME}`
    );
    

    ACC_WITH_PIPELINE

    1. 为 ID_ACC_WITH_PIPELINE 中的管道创建堆栈。
    const pipelineAccStack = new cdk.Stack(app, 'PipelineAccStack', {
        env: {
            account: ID_ACC_WITH_PIPELINE,
            region: REGION_WITH_PIPELINE
        }
    });
    
    1. 创建 KMS 密钥。示例中使用的方法EncryptionKey已弃用,请改用Key
    const key = new kms.Key(pipelineAccStack, 'CrossAccountKmsKey');
    

    实际上,我在尝试创建密钥时遇到了kms.model.MalformedPolicyDocumentException 错误,所以我从 AWS 控制台手动完成,然后使用 kms.Key.fromKeyArn 将其导入。我的帐户可能有问题(在使用此解决方案之前我遇到了很多错误),但如果您遇到相同的错误,这是一种解决方法。只需确保将使用权限分配给管道角色即可。

    1. 使用之前创建的 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));
    
    1. 创建管道并添加在第 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);
    
    1. 使用在步骤 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
        })
      ]
    });
    
    1. 最后添加构建阶段
    // 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"
    

    【讨论】:

      【解决方案2】:

      CodePipeline (CP) 由 CC 通过 CloudWatch 事件规则 触发,当两者在同一个帐户中时:

      CC ---> CW Event rule ---> CP
      

      要跨帐户执行此操作,您必须调整 CW 事件。即 CC 账户中的 CW Event 规则必须将事件转发给 CP 账户中的 CW Events:

      CP ---> CW Event rule ---> CW Event bus in CP acc ---> CW rule --> CP 
      

      我没有适合您的代码,但应该这样做。您提供的链接提供了此架构的更多具体细节。

      我猜在使用 CDK 时,您将不得不“手动”创建所有 CW 事件规则,因为这通常不是开箱即用的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-03-16
        • 2022-09-25
        • 1970-01-01
        • 2017-12-12
        • 1970-01-01
        • 2022-01-20
        • 2022-06-29
        • 2022-12-11
        相关资源
        最近更新 更多