Techfirm Cloud Architect Blog

テックファーム株式会社クラウドインフラグループのブログ

AWS CodePipelineから別AWSアカウントのAWS CodeCommitリポジトリを参照する

はじめに

以前、環境毎にAWSアカウントを分離している環境で、各環境にあるパイプラインから特定AWSアカウントのAWS CodeCommitリポジトリをクロスアカウントで参照する構成を構築しました。
今回は、構築する際に分かりにくかった箇所が具体的にどういった値になるのかをまとめます。
※実環境ではAWS CodeBuildやAWS CodeDeployといったサービスとも連携してCI/CD環境を構成しておりますが、本記事では説明省略しています。

全体像

今回ご紹介する例では、以下のような構成になっています。

構築

AssumeRole用のロール作成(開発環境のみ)

まず、以下権限を持つIAMポリシーを作成します。
ここではポリシー名を「dev-codecommit-cross-account-policy」とします。

{
    "Statement": [
        # 各環境へArtifactを格納するためのS3権限
        {
            "Action": [
                "s3:PutObject",
                "s3:PutObjectAcl"
            ],
            "Effect": "Allow",
            "Resource": [
                "arn:aws:s3:::<開発環境S3バケット名>/*",
                "arn:aws:s3:::<検証環境S3バケット名>/*",
                "arn:aws:s3:::<本番環境S3バケット名>/*"
            ]
        },
        # S3をKMSで暗号化している場合は、KMSの権限を付与する(任意)
        {
            "Action": [
                "kms:DescribeKey",
                "kms:GenerateDataKey*",
                "kms:Encrypt",
                "kms:ReEncrypt*",
                "kms:Decrypt"
            ],
            "Effect": "Allow",
            "Resource": [
                "arn:aws:kms:ap-northeast-1:<開発環境アカウントID>:key/*",
                "arn:aws:kms:ap-northeast-1:<検証環境アカウントID>:key/*",
                "arn:aws:kms:ap-northeast-1:<本番環境アカウントID>:key/*"
            ]
        },
        # AWS CodeCommitへ参照権限を付与する
        {
            "Action": [
                "codecommit:GetBranch",
                "codecommit:GetCommit",
                "codecommit:UploadArchive",
                "codecommit:GetUploadArchiveStatus",
                "codecommit:CancelUploadArchive"
            ],
            "Effect": "Allow",
            "Resource": [
                "arn:aws:codecommit:ap-northeast-1:<開発環境アカウントID>:<リポジトリ名>"
            ]
        }
    ],
    "Version": "2012-10-17"
}

次ぎにAssumeRole先のロールを作成します。
各環境からAssumeRoleできるように、各環境のAWSアカウントを信頼ポリシーに記述します。
ここではロール名を「dev-codecommit-cross-account-role」とします。

信頼ポリシーとして以下を設定し、

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "",
            "Effect": "Allow",
            "Principal": {
                "AWS": [
                    "arn:aws:iam::<開発環境アカウントID>:root",
                    "arn:aws:iam::<検証環境アカウントID>:root",
                    "arn:aws:iam::<本番環境アカウントID>:root"
                ]
            },
            "Action": "sts:AssumeRole"
        }
    ]
}

IAMポリシーは、「dev-codecommit-cross-account-policy」をアタッチします。

CodePipelineサービスロールの作成(全環境)

AWS CodePipelineを作成する各環境に、以下権限を持つIAMポリシーを作成します。
ここではポリシー名を「<環境識別子>-codepipeline-cross-account-policy」とします。

{
    "Statement": [
        {
            "Action": [
                "sts:AssumeRole"
            ],
            "Effect": "Allow",
            "Resource": [
                "arn:aws:iam::<開発環境アカウントID>:role/dev-codecommit-cross-account-role"
            ]
        }
    ],
    "Version": "2012-10-17"
}

次ぎに、以下信頼ポリシーを持つIAMロールを作成します。
ここではロール名を「<環境識別子>-codepipeline-service-role」とします。

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

「<環境識別子>-codepipeline-cross-account-policy」と、デプロイ、ビルド権限など、AWS CodePipeline実行に必要な任意のIAMポリシーをアタッチします。

KMSキーポリシーの修正(任意)

Artifact格納用のS3バケットをKMSで暗号化している場合は、各環境のKMSキーポリシーに以下を追記し開発環境から使えるようにします。

        {
            "Sid": "Allow from CodeCommit Account",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::<開発環境アカウントID>:root"
            },
            "Action": [
                "kms:ReEncrypt*",
                "kms:GenerateDataKey*",
                "kms:Encrypt",
                "kms:DescribeKey",
                "kms:Decrypt"
            ],
            "Resource": "*"
        }

パイプラインの作成(全環境で作成)

コンソール上からでは指定できない項目がいくつかあるため、AWS CLIからパイプラインを作成します。
以下内容と他に必要なステージ設定をjsonファイルに記述し保存します。
ここではファイル名を「codepipeline.json」とします。

{
    "pipeline": {
        "name": "cross-account-pipeline", 
        "roleArn": "arn:aws:iam::<各環境のアカウントID>:role/<環境識別子>-codepipeline-service-role", 
        "artifactStore": {
            "type": "S3", 
            "location": "<S3バケット名>", 
            "encryptionKey": {
                "id": "<KMSの暗号化キーのARN>", 
                "type": "KMS"
            }
        }, 
        "stages": [
            {
                "name": "Source", 
                "actions": [
                    {
                        "name": "Source", 
                        "actionTypeId": {
                            "category": "Source", 
                            "owner": "AWS", 
                            "provider": "CodeCommit", 
                            "version": "1"
                        }, 
                        "runOrder": 1, 
                        "configuration": {
                            "RepositoryName": "<開発環境のリポジトリ名>",
                            "BranchName": "<各環境用のブランチ名>"
                        }, 
                        "outputArtifacts": [
                            {
                                "name": "SourceCode"
                            }
                        ],
                        "roleArn": "arn:aws:iam::<開発環境アカウントID>:role/dev-codecommit-cross-account-role"
                    }
                ]
            },
            # 省略

以下コマンドを実行することでパイプラインが作成されます。

aws codepipeline create-pipeline --cli-input-json file://codepipeline.json --profile <プロファイル名>

おわりに

AWS CodePipelineの設定に慣れていないと分かりにくかったポイントをまとめてみました。
よくある構成だと思いますので、これから作ろうとしている方の参考になれば幸いです。

蛇足

本番環境のAWS CodePipelineが誤って他環境のブランチ(「develop」ブランチ等)を見てしまわないようにIAMポリシーで制限しようとしたところ、
以下のように「GitPull」操作に「条件キー」が対応しておらず、ブランチ毎への制限ができませんでした。

AWS CodeCommitのアクション、リソース、および条件キー https://docs.aws.amazon.com/ja_jp/service-authorization/latest/reference/list_awscodecommit.html