LoginSignup
3
0

クロスアカウントなCodePipelineとCodeCommitの連携

Posted at

とある事情で AアカウントにあるCodeCommitリポジトリを、BアカウントのCodePipelineで取得する必要がありました。

その際いくつかハマったのでメモとして残しておきます。

CodePipelineのRole

CodePipelineには、StageごとにRoleを指定する機能があります。

AWS::CodePipeline::Pipeline ActionDeclaration

これは、CodePipelineが動作中に、指定されたRoleに AssumeRole してくれる機能です。
そのためCodePipelineのRoleのポリシーに、 sts:AssumeRole を追加しておく必要があります。

CodeCommit

CodeCommitにはリソースベースのポリシーがありません。
そのため、今回はAアカウントに CodeCommitRoleを作成し、そのロールに以下の権限を付けてあります。

Effect: Allow
Action:
  - codecommit:Get*
  - codecommit:GitPull
  - codecommit:UploadArchive
  - codecommit:CancelUploadArchive
Resource:
  - !Ref CodeCommitRepositoryARN

その上で、AssumeRolePolicyとして、BアカウントからのAssumeRoleを許可しました。

AssumeRolePolicyDocument:
  Version: "2012-10-17"
  Statement:
    - Effect: Allow
      Principal:
        AWS: "<Bアカウント>"
      Action:
        - 'sts:AssumeRole'

これだけでは動かない

しかし、残念ながらこれでは動きません。
Bアカウントのパイプラインは、CodeCommitRoleにAssumeRoleしているため、パイプラインのアーティファクトストア(BアカウントのS3)にCodeCommitから取得したソースコードをs3にPutすることができないのです。

そのため、CodeCommitRoleにs3へのPut権限を付ける必要があります。

Effect: Allow
Action:
  - s3:PutObject
  - s3:PutObjectAcl
Resource:
  - !Sub "arn:aws:s3:::${バケットのプレフィックス}-*/*"

※ バケットはCloudFormationで作成しているので、プレフィックスを固定にしています。

無事にPutできた

s3に無事にPutすることができるようになりました。
しかし、Objectをダウンロードしようとすると、復号に失敗するエラーが発生します。

これは、CodeCommitRoleがs3へPutする際に、AアカウントのKMSキーを使って暗号化してs3にPutするために発生しています(おそらく)

KMSで暗号化

それを回避するためにCodePipelineのArtifactStoreの設定で、KMSを明示するようにしました。
(aws/s3 のKMSキーを使用しようとして、それぞれのアカウントにデフォルトで存在するため、それが使用されてしまったという理解をしています)

これはBアカウントで作成するリソースです。

ArtifactStore:
  Type: S3
  Location: !Ref ArtifactBucket
  EncryptionKey:
    Type: KMS
    Id: !GetAtt BucketEncryptionKey.Arn

KMSのキーポリシーには、Aアカウントが使用できるようにする必要があります

BucketEncryptionKey:
  Type: AWS::KMS::Key
  Properties:
    KeyPolicy:
      Version: '2012-10-17'
      Statement:
        - Effect: Allow
          Principal:
            AWS: !Sub 'arn:aws:iam::${AWS::AccountId}:root'
          Action:
            - 'kms:*'
        - Effect: Allow
          Principal:
            AWS: "Aアカウント"
          Action:
            - 'kms:Encrypt'
            - 'kms:Decrypt'
            - 'kms:ReEncrypt*'
            - 'kms:GenerateDataKey'
            - 'kms:DescribeKey'
          Resource:
            - '*'

そして、CodeCommitRoleにこのKeyを使用できるようにします。

- Effect: Allow
  Action:
    - 'kms:Encrypt'
    - 'kms:Decrypt'
    - 'kms:ReEncrypt*'
    - 'kms:GenerateDataKey'
    - 'kms:DescribeKey'
  Resource:
    - !Ref BucketEncryptionKeyARN

こうすることで無事BアカウントのCodePipelineがAアカウントのCodeCommitを取得できるようになりました。

まとめ

クロスアカウントでCodePipelineからCodeCommitのリポジトリを使用する方法を考えました。
クロスアカウントは何をやるにしても大変なのでやらないで済むに越したことはないなと思いました。

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0