【CI/CD】別のアカウントのCodeCommitを利用したCodePipeline構成について

記事タイトルとURLをコピーする

こんにちは。AWS CLIが好きな福島です。

今回は、別のアカウントのCodeCommitを利用したCodePipeline構成を作成する方法をご紹介します。

参考

https://docs.aws.amazon.com/ja_jp/prescriptive-guidance/latest/patterns/use-aws-codecommit-and-aws-codepipeline-to-deploy-a-ci-cd-pipeline-in-multiple-aws-accounts.html

概要図

ポイント

  • 別のアカウントのCodeCommitの変更を検知できるようにEventBridgeのルールを作成し、イベントをリポジトリアカウントからパイプラインアカウントに送信します。

  • パイプラインアカウントでは、イベントを受信できるようカスタムのイベントバスを作成します。

  • パイプラインアカウントでは、CodePipelineを起動できるように、EventBridgeのルールを作成します。

  • CodePipelineの中身は、CodeCommitのソースコードをS3にデプロイするだけの簡単な内容になります。

  • CodePipelineで利用するIAMロールは、マネジメントコンソールで指定できますが、特定のステージで利用(AssumeRole)するIAMロールの設定は、APIを使う必要があります。

  • CodePipelineのソースステージでは、リポジトリアカウントのIAMロールを利用するため、このIAMロールにパイプラインアカウントのs3とkmsにアクセスできるよう権限を付与します。

  • また、リポジトリアカウントからパイプラインアカウントのs3とkmsにアクセスできるように、s3とkmsのリソースベースのポリシーを設定します。

  • 今回はパイプラインアカウントが1つですが、環境ごとにアカウントを用意し、 ブランチごとにデプロイ先を変更する構成を組むことも可能です。

    • mainブランチ→本番アカウント
    • devブランチ→開発アカウント

補足

参考にしたドキュメントには、KMSをリポジトリアカウントに作成する構成でしたが、 その場合、パイプラインアカウント上でS3を確認するために リポジトリアカウントに存在するKMSにアクセスできる権限が必要となります。

ドキュメントの構成では、権限周りが複雑になりそうと感じたため、今回は、パイプラインアカウント上にKMSを作成します。

手順

リポジトリアカウントで実施

①CodeCommitの作成
②EventBridgeのルール作成
③パイプラインアカウントのCodePipelineがAssumeRoleする用のIAMロールの作成

パイプラインアカウントで実施

④EventBridgeのカスタムバスを作成
⑤KMSキーの作成
⑥CodePipeline用のIAMロール作成
⑦CodePipeline用のS3作成およびバケットポリシーの設定
⑧デプロイ先となるS3作成
⑨CodePipelineの作成
⑩CodePipelineを起動するEventBridgeルールの作成

両方のアカウントで実施

⑪動作確認

①CodeCommitの作成(リポジトリアカウントで実施)

「リポジトリを作成」を押下

名前(sample-codecommit)を入力し、「作成」を押下

②EventBridgeのルール作成(リポジトリアカウントで実施)

「ルールを作成」を押下

名前(send-event-to-pipeline-account-rule) を入力、「次へ」を押下

「作成のメソッド」をカスタムパターンにイベントパターンにJSONを入力し、「次へ」を押下

リポジトリのアカウントIDのsample-codecommitのmainブランチの変更を検知するルールになります。 ブランチ名を変更したい場合は、referenceNameの設定を変更します。

{
  "source": ["aws.codecommit"],
  "detail-type": ["CodeCommit Repository State Change"],
  "resources": ["arn:aws:codecommit:ap-northeast-1:【リポジトリアカウントのID】:sample-codecommit"],
  "detail": {
    "event": ["referenceCreated", "referenceUpdated"],
    "referenceType": ["branch"],
    "referenceName": ["main"]
  }
}

ターゲットの設定を行い、「レビューと作成にスキップ」を押下

  • ターゲットタイプ: EventBridgeイベントバス
  • ターゲットのタイプ: 別のアカウントまたはリージョンのイベントバス
  • ターゲットとしてのイベントバス: arn:aws:events:ap-northeast-1:【パイプラインアカウントのID】:event-bus/recieve-event-from-repo-account-custom-bus
  • ロール名: (任意) send-event-to-pipeline-account-role

レビューを確認し、問題なければ「ルールの作成」を押下し、作成できればOKです。

③パイプラインアカウントのCodePipelineがAssumeRoleする用のIAMロールの作成(リポジトリアカウントで実施)

IAMロールを作成する画面に移動し、信頼されたエンティティを設定

信頼されたエンティティタイプ: AWSアカウント
アカウント ID: パイプラインアカウントのID

AWSCodeCommitFullAccessを付与し、「次へ」を押下

今回は、AWSCodeCommitFullAccessを付与しておりますが、 本番環境の場合は、最小権限を与えましょう。

ロール名(sample-codepipeline-assume-role)を入力し、「ロールを作成」を押下

作成したロールを表示、「インラインポリシーを作成」を押下

インラインポリシーを追加

パイプラインアカウントのKMSとS3にアクセスできる権限を付与します。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "kms:DescribeKey",
                "kms:GenerateDataKey*",
                "kms:Encrypt",
                "kms:ReEncrypt*",
                "kms:Decrypt"
            ],
            "Resource": [
                "arn:aws:kms:ap-northeast-1:【パイプラインアカウントのID】:key/*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetObject*",
                "s3:PutObject",
                "s3:PutObjectAcl"
            ],
            "Resource": [
                "arn:aws:s3:::sample-codepipeline-artifacts-【パイプラインアカウントのID】/*"
            ]
        }
    ]
}

補足

今回は、アカウントの行き来を減らすためにKMSを作成する前にポリシーを設定しています。 そのため、この時点ではKMSのARNが不明のため、*(パイプラインアカウントの全てのKMS)で設定します。

*で設定した場合でも、実際にはKMSのキーポリシー側でもアクセス許可の設定しなければ、 リポジトリアカウントからパイプラインアカウントのKMSにアクセスすることはできません。

つまり必ずしも、*で設定したからといって、パイプラインアカウントの全てのKMSにアクセスできる訳ではありませんが、 セキュリティ面が気になる場合は、KMSを作成後に本ポリシーを更新する必要があります。

ポリシー名(sample-codepipeline-assume-policy)を入力、「ポリシー作成」を押下

ポリシーが作成できればOKです。

④EventBridgeのカスタムバスを作成(パイプラインアカウントで実施)

「イベントバスの作成」を押下

名前(recieve-event-from-repo-account-custom-bus)を入力

リソースベースのポリシーを設定し、末尾の「作成」を押下

  {
    "Version": "2012-10-17",
    "Statement": [{

        "Sid": "AllowAccountToPutEvents",
        "Effect": "Allow",
        "Principal": {
          "AWS": "arn:aws:iam::【リポジトリアカウントのID】:root"
        },
        "Action": "events:PutEvents",
        "Resource": "arn:aws:events:ap-northeast-1:【パイプラインアカウントのID】:event-bus/recieve-event-from-repo-account-custom-bus"
      }

    ]
  }

以下の通り、イベントバスの作成ができればOKです。 また、後続の設定に作成したイベントバスのARNを利用するため、メモしておきます。

⑤KMSキーの作成(パイプラインアカウントで実施)

「キーの作成」を押下

「次へ」を押下

エイリアス(sample-codepipeline-artifacts-kms)を設定し、「次へ」を押下

「次へ」を押下

「別の AWS アカウント」にリポジトリアカウントのIDを設定し、「次へ」を押下

プレビューを確認し、問題なければ「完了」を押下し、KMSが作成できればOKです。 また、後続の設定に作成したKMSのARNを利用するため、メモしておきます。

⑥CodePipeline用のIAMロール作成(パイプラインアカウントで実施)

IAMロール作成の画面に移動し、カスタム信頼ポリシーを設定

codepipelineからAssumeRoleできる設定を追加します。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "codepipeline.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}

S3FullAccessを付与し、「次へ」を押下

今回は、S3FullAccessを付与しておりますが、 本番環境の場合は、最小権限を与えましょう。

名前(sample-codepipeline-role)を入力し、「ロールを作成」を押下

作成したロールを表示、「インラインポリシーを作成」を押下

インラインポリシーを追加

リポジトリアカウントのIAMロールにAssumeRoleできる権限とKMSにアクセスできる権限を付与します。

{
    "Version": "2012-10-17",
    "Statement": [
        {
        "Effect": "Allow",
        "Action": "sts:AssumeRole",
        "Resource": [
            "arn:aws:iam::【リポジトリアカウントのID】:role/sample-codepipeline-assume-role"
        ]
    },
    {
        "Effect": "Allow",
        "Action": [
            "kms:DescribeKey",
            "kms:GenerateDataKey*",
            "kms:Encrypt",
            "kms:ReEncrypt*",
            "kms:Decrypt"
        ],
        "Resource": [
            "【⑤で作成したKMSのARN】"
        ]
    }]
}

ポリシー名(sample-codepipeline-policy)を入力、「ポリシー作成」を押下

ポリシーが作成できればOKです。

⑦CodePipeline用のS3作成およびバケットポリシーの設定(パイプラインアカウントで実施)

「バケットを作成」を押下

バケット名(sample-codepipeline-artifacts-【アカウントID】)を入力し、「バケットを作成」を押下

S3の詳細を表示し、「アクセス許可」タブを押下し、バケットポリシーの編集を押下

バケットポリシーを設定

SidがDenyUnEncryptedObjectUploads, DenyInsecureConnectionsは、CodePipelineが自動でS3を作成する際に付与されるポリシーを参考しております。 そこに加え、リポジトリアカウントからアクセスできる権限を付与します。

{
    "Version": "2012-10-17",
    "Id": "SSEAndSSLPolicy",
    "Statement": [
        {
            "Sid": "DenyUnEncryptedObjectUploads",
            "Effect": "Deny",
            "Principal": "*",
            "Action": "s3:PutObject",
            "Resource": "arn:aws:s3:::sample-codepipeline-artifacts-【パイプラインアカウントID】/*",
            "Condition": {
                "StringNotEquals": {
                    "s3:x-amz-server-side-encryption": "aws:kms"
                }
            }
        },
        {
            "Sid": "DenyInsecureConnections",
            "Effect": "Deny",
            "Principal": "*",
            "Action": "s3:*",
            "Resource": "arn:aws:s3:::sample-codepipeline-artifacts-【パイプラインアカウントID】/*",
            "Condition": {
                "Bool": {
                    "aws:SecureTransport": "false"
                }
            }
        },
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::【リポジトリアカウントのID】:root"
            },
            "Action": [
                "s3:Get*",
                "s3:Put*"
            ],
            "Resource": "arn:aws:s3:::sample-codepipeline-artifacts-【パイプラインアカウントID】/*"
        },
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::【リポジトリアカウントのID】:root"
            },
            "Action": "s3:ListBucket",
            "Resource": "arn:aws:s3:::sample-codepipeline-artifacts-【パイプラインアカウントID】"
        }
    ]
}

バケットポリシーの設定が完了すればOKです。 また、後続の設定に作成したS3のARNを利用するため、メモしておきます。

⑧デプロイ先となるS3作成(パイプラインアカウントで実施)

「バケットを作成」を押下

バケット名(sample-deploy-s3-【アカウントID】)を入力し、「バケットを作成」を押下

⑨CodePipelineの作成(パイプラインアカウントで実施)

CodePipeline画面に移動し、「パイプラインを作成する」を押下

パイプラインの設定を行う

パイプライン名: (任意)sample-codepipeline
サービスロール: 既存のサービスロール
ロールの ARN: sample-codepipeline-role

高度な設定を行い、「次へ」を押下

アーティファクトストア: カスタムローケーション
バケット: sample-codepipeline-artifacts-【パイプラインアカウントID】
暗号化キー: カスタマーマネージド型キー
KMS カスタマーマスターキー: sample-codepipeline-artifacts-kms

「ソース」の設定を行い、「次へ」を押下

ソースプロバイダー: AWS CodeCommit
リポジトリ名: sample-codecommit
ブランチ名: main

「ビルドステージをスキップ」を押下

「デプロイ」の設定を行い、「次へ」を押下

デプロイプロバイダー: Amazon S3
バケット: sample-deploy-s3-【パイプラインアカウントID】
S3 オブジェクトキー: SampleApp.zip

「パイプラインの作成」を押下後、パイプラインが実行されますが、エラーになります。

これは権限のないパイプラインアカウントのsample-codepipeline-roleが使用されているためで、 リポジトリアカウントのsample-codepipeline-assume-roleを利用するように設定変更する必要があります。

そのため、次の項目から変更方法を記載します。(マネジメントコンソールからの変更はできないため、CLIを使います。)

CodePipelineの設定値の取得

aws codepipeline get-pipeline --name sample-codepipeline > sample-codepipeline.json

「ソース」で利用するIAMロールを追記

"roleArn": "arn:aws:iam::【リポジトリアカウントのID】:role/sample-codepipeline-assume-role",

metadataの削除

CodePipelineの設定を更新するにあたり、metadataの項目があるとエラーになるため、削除します。

CodePipelineの設定更新

aws codepipeline update-pipeline \
--cli-input-json file://sample-codepipeline.json

エラーが出なければOKです。

⑩CodePipelineを起動するEventBridgeルールの作成(パイプラインアカウントで実施)

実は、CodePipelineを作成する際に裏側でEventBridgeが作成されています。 ただし、イベントバスがデフォルトで設定されているため、作り直します。

イベントバスを作成したバスに変更し、「ルールを作成」を押下

名前(sample-codepipeline-start-rule)を入力し、「次へ」を押下

「作成のメソッド」をカスタムパターンにイベントパターンにJSONを入力し、「次へ」を押下

リポジトリのアカウントIDのsample-codecommitのmainブランチの変更を検知するルールになります。 ブランチ名を変更したい場合は、referenceNameの設定を変更します。

{
  "source": ["aws.codecommit"],
  "detail-type": ["CodeCommit Repository State Change"],
  "resources": ["arn:aws:codecommit:ap-northeast-1:【リポジトリアカウントのID】:sample-codecommit"],
  "detail": {
    "event": ["referenceCreated", "referenceUpdated"],
    "referenceType": ["branch"],
    "referenceName": ["main"]
  }
}

ターゲットの設定を行い、「レビューと作成にスキップ」を押下

  • ターゲットタイプ: AWSのサービス
  • ターゲットを選択: CodePipeline
  • パイプライン ARN: arn:aws:codepipeline:ap-northeast-1:【パイプラインアカウントのID】:sample-codepipeline
  • ロール名: (任意) sample-codepipeline-start-role

内容を確認し、「ルールの作成」を押下

⑪動作確認(両方のアカウントで実施)

対象のCodeCommitにアクセスし、「ファイルを作成」を押下(リポジトリアカウントで実施)

コミットする内容を入力し、「変更のコミット」を押下(リポジトリアカウントで実施)

コードエディター: test
ファイル名: test.txt
作成者名: test
E メールアドレス: test

CodePipelineの確認(パイプラインアカウントで実施)

CodePipelineが正常終了すればOKです。

デプロイ先のS3の確認(パイプラインアカウントで実施)

S3を確認すると、アーティファクトがデプロイされていることが分かります。

解答して中を覗くとtest.txtファイルが保存されていることが分かります。

終わりに

今回は、別のアカウントのCodeCommitを利用したCodePipeline構成を作成する方法をご紹介しました。

どなたかのお役に立てれば幸いです。

福島 和弥 (記事一覧)

2019/10 入社

AWS CLIが好きです。