AWS CodePipeline のパイプライン呼び出し機能を使って別の AWS アカウントのパイプラインをクロスアカウント実行してみた
いわさです。
昨日、AWS CodePipeline が別のパイプラインを実行するための新しいアクションが追加されたことを紹介しました。
このアナウンス内ではクロスアカウントパイプラインの実行も可能になったと言及されていましたが、昨日の記事では同一アカウント内のパイプラインを実行しています。
CodePipeline はリソースベースポリシーの機能がなく、クロスアカウント実行を許可させる仕組みがよくわかっていなかったのですが、API を使うとパイプラインの各アクションごとにroleArnを指定できることがわかりました。
試してみましたので整理しつつ紹介します。
設定方法
主に CodeDeploy のクロスアカウント実行を目的に記載されていますが以下の公式ドキュメントが参考になります。
元が CodeDeploy を対象とした記事でアーティファクトバケットへのアクセスが関係するので KMS やら EC2 インスタンスプロファイルやら色々書いてあるのですが、CodePipeline のクロスアカウント実行の観点で最小構成を整理してみました。次のようになります。お面とかは出てこないです。

CodePipeline はサービスロールを使って実行されます。
そのサービスロールからターゲットアカウントに AssumeRole し、そのロールが StartPipelineExecution できれば OK です。
ポイントとしてこの AssumeRole させるための設定はマネジメントコンソールから行うことが出来ません。AWS API からの設定が必要で、今回は AWS CLI を使いました。
CodePipeline コンソールを使用して、別の AWS アカウントに関連付けられたリソースを使用するパイプラインを作成または編集することはできません。ただし、コンソールを使用してパイプラインの一般的な構造を作成し、AWS CLI を使用してパイプラインを編集し、それらのリソースを追加することはできます。または、既存のパイプラインの構造を使用して、手動でリソースを追加することもできます。
引用元: 他の AWS アカウントからリソースを使用するパイプラインを CodePipeline で作成する方法について説明します。 - AWS CodePipeline
上記記載のとおり、一度 roleArn だけアクションに設定しておけば、パイプラインの編集を行ってもその設定は残ります。
では設定してみましょう。トリガーとなるパイプラインが実行されるのがアカウントA、クロスアカウントで実行したい先をアカウントBとします。
アカウントAのパイプラインがアカウントBのロールを使えるようにする
アカウントB
前述のとおりリソースベースポリシーではなく、AssumeRole の仕組みでクロスアカウント実行されるので AssumeRole できるようにしておきます。
まずはアカウントB にロールを準備しましょう。
アカウントBにアカウントAを信頼するロールを作成します。(実際にはもう少し絞る必要がありますが)

で、このロールが行いたいのはアカウントBのパイプラインの実行です。なのでcodepipeline:StartPipelineExecutionを実行できるようにポリシーを設定します。

アカウントA
アカウントAではパイプラインが使うサービスロールがアカウントBのロールにsts:AssumeRoleします。
サービスロールデフォルトのポリシーだとsts:AssumeRoleは含まれていないので明示的に追加しましょう。

最低限の構成の場合、ロールの設定はこれで OK です。
パイプラインを編集する
ではアカウントAのパイプラインを編集し、アカウントBにAssumeRoleさせるように変更します。
get-pipelineで既存情報を取得し、Assume したいロール情報だけ追記して更新する感じです。
% aws codepipeline get-pipeline --name hoge0315pipeline1 --profile hoge > pipeline.json
pipeline.stages[].actions[].roleArnで、ステージごとアクションごとに設定可能です。
なお、PipelineNameですがクロスアカウントなので ARN を指定するのかなと思っていたのですがそれだと実行時に失敗しました。そのまま名称を設定すれば OK のようです。
% aws codepipeline get-pipeline --name hoge0315pipeline1 --profile hoge
{
    "pipeline": {
        "name": "hoge0315pipeline1",
        "roleArn": "arn:aws:iam::xxxxxxxxxxx1:role/service-role/AWSCodePipelineServiceRole-ap-northeast-1-hoge0315pipeline1",
        "artifactStore": {
            "type": "S3",
            "location": "codepipeline-ap-northeast-1-225279913824"
        },
        "stages": [
            {
                "name": "Source",
                "actions": [
                    {
                        "name": "Source",
                        "actionTypeId": {
                            "category": "Source",
                            "owner": "AWS",
                            "provider": "CodeCommit",
                            "version": "1"
                        },
                        "runOrder": 1,
                        "configuration": {
                            "BranchName": "main",
                            "OutputArtifactFormat": "CODE_ZIP",
                            "PollForSourceChanges": "false",
                            "RepositoryName": "hoge0315code"
                        },
                        "outputArtifacts": [
                            {
                                "name": "SourceArtifact"
                            }
                        ],
                        "inputArtifacts": [],
                        "region": "ap-northeast-1",
                        "namespace": "SourceVariables"
                    }
                ],
                "onFailure": {
                    "result": "RETRY",
                    "retryConfiguration": {
                        "retryMode": "ALL_ACTIONS"
                    }
                }
            },
            {
                "name": "Build",
                "actions": [
                    {
                        "name": "ccc",
                        "actionTypeId": {
                            "category": "Invoke",
                            "owner": "AWS",
                            "provider": "CodePipeline",
                            "version": "1"
                        },
                        "runOrder": 2,
                        "configuration": {
                            "PipelineName": "hoge1005command"
                        },
                        "outputArtifacts": [],
                        "inputArtifacts": [],
                        "roleArn": "arn:aws:iam::xxxxxxxxxxx2:role/hoge0316-crossaccount-pipeline",
                        "region": "ap-northeast-1"
                    }
                ],
                "onFailure": {
                    "result": "RETRY",
                    "retryConfiguration": {
                        "retryMode": "ALL_ACTIONS"
                    }
                }
            }
        ],
        "version": 9,
        "executionMode": "QUEUED",
        "pipelineType": "V2",
        "variables": [
            {
                "name": "val1",
                "defaultValue": "aaa"
            }
        ]
    },
    "metadata": {
        "pipelineArn": "arn:aws:codepipeline:ap-northeast-1:xxxxxxxxxxx1:hoge0315pipeline1",
        "created": "2025-03-15T06:09:03.562000+09:00",
        "updated": "2025-03-16T06:05:13.335000+09:00"
    }
}
ではアカウントAでパイプラインを実行してみます。前回と同様にパイプライン間で変数の受け渡しをついでに行います。
まずパイプラインAが無事実行できました。

こちらアカウントBのパイプラインBの様子です。実行中であり、変数値が受け取れていることが確認出来ます。良さそうじゃないか。

完了後に実行ログも確認してみましたがコマンドアクションで環境変数に設定した値を参照することが出来ていました。

さいごに
本日は AWS CodePipeline のパイプライン呼び出し機能を使って別の AWS アカウントのパイプラインをクロスアカウント実行してみました。
マネジメントコンソールで設定できないのでひと手間ありますが、アクションごとに API だとロールを指定できるという点と、あとは AssumeRole する感じだよというのを覚えておけば問題なく対応できそうです。











