top of page
検索
  • 執筆者の写真mon

別アカウントのCodeCommitの変更でCodePipelineからデプロイする

めちゃめちゃ期間をあけてしまいましたが前回の続きです。


前回のあらすじ

  • リポジトリアカウント : CodeCommitのRepositoryがある方のアカウント

  • パイプラインアカウント : CodePipelineがある方のアカウント

リポジトリアカウントにあるCodeCommitの変更をEventBus経由でパイプラインアカウントのEventRuleで検出できるようになりました。


この記事のゴール

リポジトリアカウントのCodeCommitに対して行なった変更がパイプラインアカウントでデプロイされるようになります。


なぜこの記事を書いたか

アカウントを跨いだコードパイプラインの構築についてはWeb上にいくつか記事があります。その通りに構築すれば出来上がったのですが、このIAM Roleはだれのためのものだったっけ?など自分の頭の整理が必要になったので書いてみました。


前提知識

  • CodePipeline, CodeCommit, KMSなどの各サービスがどのようなものか知っている

  • IAM Roleを引き受けるという概念を知っている

  • クロスアカウントアクセスというものを聞いたことがある


CodePipeline V1/V2について

CodePipelineには現在V1とV2という2種類のタイプがあります(知りませんでした)。

適切なパイプラインのタイプの選択 を確認すると今回は特にV2が必要な要件がないのでV1を選択します。


出来上がる構成





今回は説明をシンプルにするため、デプロイはCodePipelineからS3にファイルを配置するのみの構成とします。


大まかな説明

CodePipelineはソース(CodeCommieやS3、Githubなど)から取得したファイルをアーティファクトストアと呼ばれるS3 Bucketに一旦コピーします。

クロスアカウントでCodeCommit/CodePipelineを構成する場合、このアカウントを跨いだアーティファクトストアにファイルを置くための権限をどのように作るかというところがキモになります。




CodePipelineはリポジトリアカウントに用意されたRoleを引き受けてCodeCommitからソースを取得します。

同時にそのRoleを使ってリポジトリアカウントからパイプラインアカウントのアーティファクトストアにファイルをおきます。

この時、KMSカスタママネージドキーによる暗号化が必須です。


  1. パイプラインアカウントにアーティファクトストアを作成する。

  2. リポジトリアカウントにパイプラインアカウントに引き受けさせるIAM Roleを用意する。このRoleはカスタママネージドキーを使ってパイプラインアカウントのアーティファクトストアへの書き込みができるようにする。

  3. パイプラインアカウントにKMSでカスタママネージドキーを作成する

  4. CodePipelineのIAM RoleにリポジトリアカウントにあるIAM Roleを引き受けられるように sts:AssumeRole を許可する。

  5. アーティファクトストアのBuckePolicyでリポジトリアカウントからのアクセスを許可するように設定する。



余談:IAM Roleのアイコンがなぜヘルメットなのかというと、RoleをAssumeする(引き受ける)ことをヘルメットを被ってその役職で振る舞うことに準えているのだということをどこかで聞きました。真偽も記憶も定かではないですが。


作成していく

アーティファクトストア作成


パイプラインアカウントで行う。

アーティファクトストアは普通のS3Bucketです


ポイント

  • バージョニングを有効にする

  • リポジトリアカウントからの書き込みを許可

  • 書き込み時にはKMSを使った暗号化とSecureTransportを必須にする


# pipeline-artifact-store.yml

  PipelineArtifactBucket:
    # DeletionPolicy: Retain
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !Sub "${Environment}-${ResourceNamePrefix}-pipeline-artifact-bucket-${AWS::AccountId}"
      VersioningConfiguration:
        Status: Enabled
  PipelineArtifactBucketPolicy:
    Type: AWS::S3::BucketPolicy
    Properties:
      Bucket: !Ref PipelineArtifactBucket
      PolicyDocument:
        Version: 2012-10-17
        Statement:
        - Action:
          - s3:PutObject
          Effect: Deny
          Principal: "*"
          Resource:
          - !Sub arn:aws:s3:::${PipelineArtifactBucket}/*
          Condition:
            StringNotEquals:
              s3:x-amz-server-side-encryption: aws:kms
        - Action:
          - s3:*
          Effect: Deny
          Principal: "*"
          Resource:
          - !Sub arn:aws:s3:::${PipelineArtifactBucket}/*
          Condition:
            Bool:
              aws:SecureTransport: false
        - Action:
          - s3:Get*
          - s3:Put*
          Effect: Allow
          Principal:
            AWS:
            - !Sub arn:aws:iam::${RepositoryAccountId}:root
          Resource:
          - !Sub arn:aws:s3:::${PipelineArtifactBucket}/*
        - Action:
          - s3:ListBucket
          Effect: Allow
          Principal:
            AWS:
            - !Sub arn:aws:iam::${RepositoryAccountId}:root
          Resource:
          - !Sub arn:aws:s3:::${PipelineArtifactBucket}

CodePipelineに付与するIAM Role作成


パイプラインアカウントで行う。

CodePipelineの実行時のRoleです。


ポイント

  • sts:AssumeRole のところでリポジトリアカウントからのRoleを引き受けられるようにする


# pipeline-role.yml

  # 別アカウントRepositoryをソースにするCodepipelineのRole
  # リポジトリ側のRoleを引き受けられるようにAssumeRoleを許可している
  PipelineRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub "${Environment}-${ResourceNamePrefix}-CodePielineRole"
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
              - codepipeline.amazonaws.com
            Action:
              - sts:AssumeRole
      Path: /
      Policies:
        - PolicyName: Pipeline
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - sts:AssumeRole
                Resource:
                  - !Sub arn:aws:iam::${RepositoryAccountId}:role/*
              - Effect: Allow
                Action:
                  - iam:PassRole
                Resource:
                  - "*"
              - Effect: Allow
                Action:
                  - codecommit:GetBranch
                  - codecommit:GetCommit
                  - codecommit:UploadArchive
                  - codecommit:GetUploadArchiveStatus
                  - codecommit:CancelUploadArchive
                  - cloudformation:CreateStack
                  - cloudformation:DeleteStack
                  - cloudformation:DescribeStacks
                  - cloudformation:UpdateStack
                  - cloudformation:CreateChangeSet
                  - cloudformation:DeleteChangeSet
                  - cloudformation:DescribeChangeSet
                  - cloudformation:ExecuteChangeSet
                  - cloudformation:SetStackPolicy
                  - cloudformation:ValidateTemplate
                  - iam:PassRole
                  - codebuild:BatchGetBuilds
                  - codebuild:StartBuild
                Resource: '*'
              - Effect: Allow
                Action: s3:*
                Resource:
                  - !Sub "${PipelineArtifactBucket.Arn}"
                  - !Sub "${PipelineArtifactBucket.Arn}/*"
              - Effect: Allow
                Action: s3:Put*
                Resource:
                  - !Sub "${DeployTargetBucketArn}"
                  - !Sub "${DeployTargetBucketArn}/*"
              - Effect: Allow
                Action:
                  - kms:DescribeKey
                  - kms:GenerateDataKey*
                  - kms:Encrypt
                  - kms:ReEncrypt*
                  - kms:Decrypt
                Resource: !Ref KmsKeyArn

KMS カスタママネージドキー


パイプラインアカウントで行う。

アーティファクトストアに書き込むときに使うカスタママネージドキーです。


ポイント

  • リポジトリアカウントからの使用を許可する


# kms-key.yml

  Key:
    Type: AWS::KMS::Key
    Properties:
      KeyPolicy:
        Version: 2012-10-17
        Id: key-default-1
        Statement:
        - Effect: Allow
          Principal:
            AWS:
            - !Sub arn:aws:iam::${AWS::AccountId}:root
          Action: kms:*
          Resource: "*"
        - Effect: Allow
          Principal:
            AWS:
            - !Sub "arn:aws:iam::${AWS::AccountId}:group/admin-group-${AWS::AccountId}"
          Action:
          - kms:Create*
          - kms:Describe*
          - kms:Enable*
          - kms:List*
          - kms:Put*
          - kms:Update*
          - kms:Revoke*
          - kms:Disable*
          - kms:Get*
          - kms:Delete*
          - kms:ScheduleKeyDeletion
          - kms:CancelKeyDeletion
          Resource: "*"
        - Effect: Allow
          Principal:
            AWS:
            - !Sub arn:aws:iam::${RepositoryAccountId}:root
            - !GetAtt PipelineRole.Arn
          Action:
          - kms:DescribeKey
          - kms:Encrypt
          - kms:Decrypt
          - kms:ReEncrypt*
          - kms:GenerateDataKey
          - kms:GenerateDataKeyWithoutPlaintext
          Resource: "*"
        - Effect: Allow
          Principal:
            AWS:
            - !Sub arn:aws:iam::${RepositoryAccountId}:root
            - !GetAtt PipelineRole.Arn
          Action:
          - kms:CreateGrant
          - kms:ListGrants
          - kms:RevokeGrant
          Resource: "*"
          Condition:
            Bool:
              kms:GrantIsForAWSResource: true
  Alias:
    Type: AWS::KMS::Alias
    Properties:
      AliasName: alias/CodePipelineArtifact
      TargetKeyId:
        Ref: Key

CodePipelineに渡すリポジトリアカウント側Role


リポジトリアカウントで行う。

CodePipelineが実行されるときにリポジトリアカウントから引き受けるIAM Roleです。


ポイント

  • Principal でリポジトリアカウントを設定する

  • パイプラインアカウントにあるアーティファクトストアとカスタママネージドキーの利用を許可する


  ExternalPipelineExecutionRole:
    Properties:
      RoleName: !Sub "${AWS::StackName}-ExternalPipelineExecutionRole"
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              AWS:
              - !Sub arn:aws:iam::${ExternalAccountId}:root
            Action:
              - sts:AssumeRole
      Path: /
      Policies:
        - PolicyName: source
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - s3:PutObject
                  - s3:PutObjectAcl
                Resource:
                  - !Sub ${PipelineArtifactBucketArn}/*
              - Effect: Allow
                Action:
                  - kms:DescribeKey
                  - kms:GenerateDataKey*
                  - kms:Encrypt
                  - kms:ReEncrypt*
                  - kms:Decrypt
                Resource:
                  - !Ref ExternalKeyArn
              - Effect: Allow
                Action:
                  - codecommit:GetBranch
                  - codecommit:GetCommit
                  - codecommit:UploadArchive
                  - codecommit:GetUploadArchiveStatus
                  - codecommit:CancelUploadArchive
                Resource:
                  - !GetAtt Repo.Arn

CodePipeline


パイプラインアカウントで行う。

CodePipelineの構成自体は今回の本題ではないのでシンプルにS3に配置するだけのものです。


ポイント

  • ArtifactStore の指定でカスタママネージドキーを設定

  • このカスタママネージドキーがリポジトリアカウント側とパイプラインアカウント側の共通の暗号鍵になる

  • Actionの実行時のRoleをリポジトリアカウントから引き受けるIAM Roleにする

  • 2つ目のActionでDeployTargetBucketに release/ というPrefixをつけてデプロイする


  Pipeline:
    Type: AWS::CodePipeline::Pipeline
    Properties:
      Name: !Sub "${AWS::StackName}-${RepositoryName}-pipeline"
      ArtifactStore:
        Location: !Ref PipelineArtifactBucketName
        Type: S3
        EncryptionKey:
          Id: !Ref KmsKeyArn
          Type: KMS
      RoleArn: !Ref PipelineRoleArn
      RestartExecutionOnUpdate: False
      Stages:
        - Actions:
          - ActionTypeId:
              Category: Source
              Owner: AWS
              Provider: CodeCommit
              Version: 1
            Configuration:
              RepositoryName: !Ref RepositoryName
              BranchName: !Ref TargetBranchName
              PollForSourceChanges: false
              OutputArtifactFormat: CODE_ZIP
            Name: Source
            Namespace: SourceVariables
            OutputArtifacts:
              - Name: SourceArtifact
            Region: !Ref AWS::Region
            RunOrder: 1
            # CodeCommit側アカウントに作成したRole
            RoleArn: !Ref RepositoryAccountRoleArn
          Name: Source
        - Actions:
          - ActionTypeId:
              Category: Deploy
              Owner: AWS
              Provider: S3
              Version: 1
            Configuration:
              BucketName: !Ref DeployTargetBucketName
              Extract: true
              ObjectKey: release
            InputArtifacts:
              - Name: SourceArtifact
            Name: Deploy
            Namespace: DeployVariables
            RunOrder: 1
          Name: Deploy

いよいよCodePipeline本体を作ります。


CodePipeline自身には PipelineRole が設定されています。

Source ActionではリポジトリアカウントにあるCodeCommitリポジトリを参照していますが、この時のIAM Roleはリポジトリアカウントに作成しておいた ExternalPipelineExecutionRoleが使われます。


EventBridgeとつなぐ


前回の記事でリポジトリアカウントからパイプラインアカウントにリポジトリ更新が通知されるようにEventBridgeでRuleを作成しました。

今回はRuleのターゲットにCodePIpelineを設定します。



動作確認

ここまでくるとCodePipelineがクロスアカウント動作するようになるので動かしてみましょう。


リポジトリにPushされたCommit


CodePipelineの起動

commit idとメッセージが期待した通り、リポジトリにPushされたCommitのもので起動されています。


まとめ

これでAWSアカウントを跨いだCodeCommit/CodePipelineの連携ができるようになりました。さまざまな事情でGitHub/GitLabや外部CIサービスを使用できない場合でもAWS純正サービスでデプロイメントパイプラインを構築することが可能です。


補足

今回はリポジトリ1に対してパイプライン1でしたが、商用を考えると開発AWSアカウント/本番AWSアカウントが分かれていて、それぞれにパイプラインを配置する構成が考えられます。

その場合、CodeCommitは開発AWSアカウントではなく本番アカウントとも独立したAWSアカウントにした方が良いと思います。なぜなら、開発/本番AWSアカウントでCodePipeline周りの設定が異なっているとトラブルシューティングやメンテナンスが面倒になりそうだからです。

閲覧数:13回0件のコメント

最新記事

すべて表示

データ状態により異なるSQLを実行させたい

はじめに 近頃担当する業務は夜間バッチでのデータ更新処理が多く、特にDWH的にテーブル再構築(TRUNCATE/INSERT)のパターンを多く使用しています。 その中でSQLで処理を組み上げる時、エラー処理などで条件分岐で異なるSQLを実行したくなる事は珍しくありません。 多くのシステムでは呼び出し側でSQLの実行結果を参照し、次に実行するSQLを選択/実行していると思います。 また、SQLだけで

Comments


bottom of page