📝

CodePipeline の EC2 デプロイアクションではクロスアカウントでのデプロイはサポートされていない

に公開

Amazon EC2 action reference - AWS CodePipeline
AWS に確認したところ、本記事執筆時点ではクロスアカウントでのデプロイはサポートされていませんでした。

ソースアカウントの設定

ソースアカウントに CodeCommit リポジトリを作成し、deployspec.yml および index.html をプッシュしました。

deployspec.yml
# プロジェクトルートに配置
version: 1.0
phases:
  pre_deploy:
    commands:
      - echo "Pre-deployment phase started"
      - sudo yum update -y
      - sudo yum install -y httpd
  deploy:
    commands:
      - echo "Deployment phase started"
      - sudo cp -r . /var/www/html/
      - sudo chown -R apache:apache /var/www/html/
  post_deploy:
    commands:
      - echo "Post-deployment phase started"
      - sudo systemctl start httpd
      - sudo systemctl enable httpd
      - echo "Deployment completed successfully"
index.html
<!-- index.html -->
<!DOCTYPE html>
<html>
  <head>
    <title>CodePipeline Native EC2 Deployment</title>
    <style>
      body {
        font-family: Arial, sans-serif;
        margin: 40px;
      }
      .container {
        max-width: 800px;
        margin: 0 auto;
      }
      .success {
        color: green;
      }
      .timestamp {
        background: #f0f0f0;
        padding: 10px;
        border-radius: 5px;
      }
    </style>
  </head>
  <body>
    <div class="container">
      <h1 class="success">
        🎉 Cross Account Native EC2 Deployment Successful!
      </h1>
      <p>
        This page was deployed using CodePipeline's native EC2 deployment
        feature.
      </p>
      <div class="timestamp">
        <strong>Deployment Time:</strong> <span id="timestamp"></span>
      </div>
      <h2>Deployment Details:</h2>
      <ul>
        <li>Source Account: Account A</li>
        <li>Target Account: Account B</li>
        <li>Deployment Method: CodePipeline Native EC2</li>
        <li>No CodeDeploy Required!</li>
      </ul>
    </div>
    <script>
      document.getElementById("timestamp").textContent =
        new Date().toLocaleString();
    </script>
  </body>
</html>

アーティファクト用の S3 バケットを作成し、以下のバケットポリシーを設定しました。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": [
          "arn:aws:iam::012345678901:role/<Targate EC2 IAM role ARN>",
          "arn:aws:iam::012345678901:role/<Cross Account Access Role ARN>"
        ]
      },
      "Action": ["s3:GetObject", "s3:ListBucket"],
      "Resource": [
        "arn:aws:s3:::<my-bucket-name>",
        "arn:aws:s3:::<my-bucket-name>/*"
      ]
    }
  ]
}

Targate EC2 IAM role ARN および Cross Account Access Role ARN は後述のターゲットアカウント側で作成する IAM ロールです。

KSM キーを作成し、以下のキーポリシーを設定しました。

{
  "Version": "2012-10-17",
  "Id": "key-consolepolicy-3",
  "Statement": [
    {
      "Sid": "Enable IAM User Permissions",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::<source account id>:root"
      },
      "Action": "kms:*",
      "Resource": "*"
    },
    {
      "Sid": "Allow use of the key",
      "Effect": "Allow",
      "Principal": {
        "AWS": [
          "arn:aws:iam::<target account id>:role/<Targate EC2 IAM role ARN>",
          "arn:aws:iam::<target account id>:role/<Cross Account Access Role ARN>"
        ]
      },
      "Action": [
        "kms:Decrypt",
        "kms:Encrypt",
        "kms:GenerateDataKey",
        "kms:ReEncryptTo",
        "kms:DescribeKey"
      ],
      "Resource": "*"
    }
  ]
}

以下の設定で CodePipeline のパイプラインを作成しました。

{
  "pipeline": {
    "name": "makoto",
    "roleArn": "<CodePipeline service role arn>",
    "artifactStore": {
      "type": "S3",
      "location": "<artifact-bucket-name>",
      "encryptionKey": {
        "id": "<kms-key-id>",
        "type": "KMS"
      }
    },
    "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": "<CodeCommit-repository-name>"
            },
            "outputArtifacts": [
              {
                "name": "SourceArtifact"
              }
            ],
            "inputArtifacts": [],
            "region": "ap-northeast-1",
            "namespace": "SourceVariables"
          }
        ],
        "onFailure": {
          "result": "RETRY",
          "retryConfiguration": {
            "retryMode": "ALL_ACTIONS"
          }
        }
      },
      {
        "name": "Deploy",
        "actions": [
          {
            "name": "Deploy",
            "actionTypeId": {
              "category": "Deploy",
              "owner": "AWS",
              "provider": "EC2",
              "version": "1"
            },
            "runOrder": 1,
            "configuration": {
              "DeploySpec": "deployspec.yml",
              "InstanceTagKey": "<EC2-tag-name>",
              "InstanceTagValue": "<EC2-tag-value>",
              "InstanceType": "SSM_MANAGED_NODE"
            },
            "outputArtifacts": [],
            "inputArtifacts": [
              {
                "name": "SourceArtifact"
              }
            ],
            "region": "ap-northeast-1",
            "namespace": "DeployVariables",
            "roleArn": "<Cross Account Access Role ARN>"
          }
        ],
        "onFailure": {
          "result": "ROLLBACK"
        }
      }
    ],
    "version": 1,
    "executionMode": "QUEUED",
    "pipelineType": "V2"
  }
}

ターゲットアカウントの設定

以下の設定で EC2 インスタンスを起動しました。

  • AMI: Amazon Linux 2023
  • AdministratorAccess 権限が付与された IAM インスタンスプロファイル
  • パブリックサブネット

以下の設定で IAM ロールを作成しました。

  • 信頼関係
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::<source-account-id>:root"
            },
            "Action": "sts:AssumeRole",
            "Condition": {}
        }
    ]
}
  • ポリシー: AdministratorAccess

デプロイ

上記設定後、CodePipeline コンソールから変更をリリースしたところ、以下の状況でした。

  • Source アクションは成功
  • Deploy アクションで失敗
    • ターゲットインスタンスは認識できている
    • Systems Manager の Run Command でアーティファクトストアである S3 バケットからのソースの取得で AccessDenied が発生している
2025/06/18 11:25:48 ERROR [Download] Failed to get S3 object <bucket-name>/SourceArti/3Vdlb3u. Error: operation error S3: GetObject, https response error StatusCode: 403, RequestID: 244SYAKB0VJH4XHJ, HostID: +BwWezH2g63MNfYYWBCB2RisM3a06QD3ShueXYI6yMiF0xswD41UQkeMO3jDcGDF09wbpfrFDEg=, api error AccessDenied: Access Denied
failed to run commands: exit status 1

以下の内容を試しましたがエラーは解消しませんでした。

  • アーティファクトストアのブロックパブリックアクセスを無効化
  • KMS のキーポリシーでターゲットアカウントからのすべてのアクションを許可
  • EC2 インスタンスにログインし、デプロイエグゼキューターを直接実行
$ sudo mkdir -p /opt/codepipeline
$ sudo curl "https://d33ue1ndcnyy34.cloudfront.net/ec2-deploy-executor-1/deploy_linux_amd64 " -o /opt/codepipeline/deploy
$ sudo chmod +x /opt/codepipeline/deploy
$ sudo /opt/codepipeline/deploy -event Download -executionId test-execution -bucket <bucket-name> -key test/SourceArti/ih339ZH -accountId 012345678901

AWS に確認

上記検証内容を踏まえて AWS に確認したところ、クロスアカウントでのデプロイはサポートされていない旨の回答でした。
回避策としては従来の CodeDeploy アクションでのクロスアカウントデプロイになる旨の回答もありました。

Create a pipeline in CodePipeline that uses resources from another AWS account - AWS CodePipeline

今後のアップデートに期待です。

まとめ

CodePipeline の EC2 デプロイアクションではクロスアカウントでのデプロイはサポートされていないという内容を紹介しました。
どなたかの参考になれば幸いです。

参考資料

Discussion