CodePipeline を使って AWS CloudFormation スタックを別のアカウントにデプロイする方法を教えてください。

最終更新日: 2022 年 1 月 19 日

AWS CodePipeline を使用して異なる AWS アカウントの AWS CloudFormation スタックをデプロイしたいです。これを設定するにはどうすればよいですか?

簡単な説明

CodePipeline を使用して別の AWS アカウントに CloudFormation スタックをデプロイするには、以下の操作を行います。

注:この手順では、アカウント 1アカウント 2 の 2 つの AWS アカウントがあることを前提としています。

1.    (アカウント 1) 顧客管理の AWS Key Management Service (AWS KMS) キーを作成し、キーの使用権限を以下に付与します。

  • アカウント 1 の CodePipeline サービスロール
  • アカウント 2

2.    (アカウント 1) アカウント 2 にバケットへのアクセス権を付与するバケットポリシーを使用して Amazon Simple Storage Service (Amazon S3) バケットを作成します。

3.    (アカウント 2) 以下を許可するクロスアカウント AWS Identity and Access Management (IAM) ロールを作成します。

  • CloudFormation API アクション
  • アカウント 1 の Simple Storage Service (Amazon S3) バケットへのアクセス
  • アカウント 1 のカスタマーマネージド AWS KMS キーを使用した復号化

4.    (アカウント 1) アカウント 1 の CodePipeline サービスロールに AssumeRole アクセス許可を追加して、アカウント 2 でクロスアカウントロールを引き受けることができるようにします。

5.    (アカウント 2) CloudFormation スタックのサービスロールを作成します。このロールには、スタックによってデプロイされたサービスに必要なアクセス権限が含まれます。

6.    (アカウント 1) アカウント 1 の CodePipeline 設定を更新して、アカウント 2 に関連付けられたリソースを含めます。

解決方法

(アカウント 1) アカウント 1 の CodePipeline サービスロールとアカウント 2 に使用許可を付与する、カスタマーマネージド AWS KMS キーを作成します。

1.    アカウント 1 で、 AWS KMS コンソールを開きます。

2.    ナビゲーションペインから [Customer managed keys] をクリックします。

3.    [キーの作成] を選択します。次に、[対称] を選択します。

注: [アドバンストオプション] セクションで、[オリジン] を KMS のままにします。

4.    [Alias] に、キーの名前を入力します。

5.    (オプション) ユースケースに基づいてタグを追加します。その後、[次へ] を選択します。

6.    [キー管理権限の定義] ページの [キー管理者] で、AWS Identity and Access Management (IAM) ユーザーを選択します。また、そのキーの管理者となる他のユーザーまたはグループも選択します。その後、[次へ] を選択します。

7.    [キー使用権限の定義] ページの [このアカウント] で、キーへのアクセスを許可する IAM ID を追加します。たとえば、CodePipeline サービスロールなどです。

8.    [別の AWS アカウント] セクションで、[別の AWS アカウントを追加する] を選択します。次に、アカウント 2 の IAM ロールの Amazon リソースネーム (ARN) を入力します。

9.    [次へ] を選択します。[完了] をクリックします。

10.    [カスタマーマネージドキー] セクションで、先ほど作成したキーを選択します。次に、キーの ARN をコピーします。

重要:パイプラインの更新や IAM ポリシーを設定するときは、AWS KMS キーの ARN が必要です。

(アカウント 1) アカウント 2 にバケットへのアクセス権を付与するバケットポリシーを使用して Simple Storage Service (Amazon S3) バケットを作成します

1.    アカウント 1 で、Simple Storage Service (Amazon S3) コンソールを開きます。

2.    既存の Simple Storage Service (Amazon S3) バケットを選択するか、新しい S3 バケットを作成して、CodePipeline の ArtifactStore として使用します。

注: アーティファクトには、スタックテンプレートファイルテンプレート設定ファイル、またはその両方を含めることができます。CodePipeline は、これらのアーティファクトを使用して CloudFormation スタックと変更セットを操作します。テンプレート設定ファイルで、テンプレートパラメータ値、スタックポリシー、およびタグを指定する必要があります。

3.    バケットの Amazon S3 詳細ページで、[Permissions] を選択します。

4.    [バケットポリシー] を選択します。

5.    バケットポリシーエディタで、次のポリシーを入力します。

重要: codepipeline-source-artifact を CodePipeline のSourceArtifact のバケット名で置き換えます。ACCOUNT_B_NOアカウント 2 のアカウント番号に置き換えます。

{
  "Id": "Policy1553183091390",
  "Version": "2012-10-17",
  "Statement": [{
      "Sid": "",
      "Action": [
        "s3:Get*",
        "s3:Put*"
      ],
      "Effect": "Allow",
      "Resource": "arn:aws:s3:::codepipeline-source-artifact/*",
      "Principal": {
        "AWS": [
          "arn:aws:iam::ACCOUNT_B_NO:root"
        ]
      }
    },
    {
      "Sid": "",
      "Action": [
        "s3:ListBucket"
      ],
      "Effect": "Allow",
      "Resource": "arn:aws:s3:::codepipeline-source-artifact",
      "Principal": {
        "AWS": [
          "arn:aws:iam::ACCOUNT_B_NO:root"
        ]
      }
    }
  ]
}

6.    [保存] を選択します。

(アカウント 2) クロスアカウント IAM ロールを作成します

以下を許可する IAM ポリシーを作成します。

  • アカウント 2 でクロスアカウント IAM ロールを引き受けるためのアカウント 1 のパイプライン
  • CloudFormation API アクション
  • ソースアーティファクトに関連する Simple Storage Service (Amazon S3) API アクション

1.    アカウント 2 で、IAM コンソールを開きます。

2.    ナビゲーションペインで、[Policies] (ポリシー) を選択します。その後、[Create policy] (ポリシーを作成) を選択します。

3.    [JSON] タブを選択します。その後、JSON エディタに次のポリシーを入力します。

重要:codepipeline-source-artifact をパイプラインの Artifact ストアのバケット名に置き換えます。

{
  "Version": "2012-10-17",
  "Statement": [{
      "Effect": "Allow",
      "Action": [
        "cloudformation:*",
        "iam:PassRole"
      ],
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "s3:Get*",
        "s3:Put*",
        "s3:ListBucket"
      ],
      "Resource": [
        "arn:aws:s3:::codepipeline-source-artifact/*"
      ]
    }
  ]
}

4.    [Review policy] (ポリシーの確認) をクリックします。

5.    [Name] (名前) で、ポリシーの名前を入力します。

6.    [ポリシーの作成] を選択します。

AWS KMS API アクションを許可する 2 つ目の IAM ポリシーを作成します

1.    アカウント 2 で、IAM コンソールを開きます。

2.    ナビゲーションペインで、[Policies] (ポリシー) を選択します。その後、[Create policy] (ポリシーを作成) を選択します。

3.    [JSON] タブを選択します。その後、JSON エディタに次のポリシーを入力します。

重要:arn:aws:kms:REGION:ACCOUNT_A_NO:key/key-id を、先ほどコピーした AWS KMS キーの ARN に置き換えます。

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Action": [
      "kms:DescribeKey",
      "kms:GenerateDataKey*",
      "kms:Encrypt",
      "kms:ReEncrypt*",
      "kms:Decrypt"
    ],
    "Resource": [
      "arn:aws:kms:REGION:ACCOUNT_A_NO:key/key-id"
    ]
  }]
}

4.    [Review policy] (ポリシーの確認) をクリックします。

5.    [Name] (名前) で、ポリシーの名前を入力します。

6.    [ポリシーの作成] を選択します。

作成したポリシーを使用して、クロスアカウント IAM ロールを作成します。

1.    アカウント 2 で、IAM コンソールを開きます。

2.    ナビゲーションペインで [Roles] を選択します。

3.    [ロールの作成] を選択します。

4.    [別の AWS アカウント] を選択します。

5.    [アカウント ID] に、アカウント 1 のアカウント ID を入力します。

6.    [次へ: アクセス許可] を選択します。次に、 IAM ロールを作成するステップを完了します。

7.    クロスアカウントロールポリシー、作成したロールへの KMS キーポリシーをアタッチします。手順については、「IAM ID のアクセス許可の追加および削除」参照してください。

(アカウント 1) アカウント 1 の CodePipeline サービスロールに AssumeRole アクセス許可を追加して、アカウント 2 でクロスアカウントロールを引き受けることができるようにします。

1.    アカウント 1 で、IAM コンソールを開きます。

2.    ナビゲーションペインで [Roles] を選択します。

3.    CodePipeline で使用している IAM サービスロールを選択します。

4.    [Add inline policy] を選択します。

5.    [JSON] タブを選択します。その後、JSON エディタに次のポリシーを入力します。

重要:ACCOUNT_B_NOアカウント 2 のアカウント番号に置き換えます。

{
  "Version": "2012-10-17",
  "Statement": {
    "Effect": "Allow",
    "Action": "sts:AssumeRole",
    "Resource": [
      "arn:aws:iam::ACCOUNT_B_NO:role/*"
    ]
  }
}

6.    [ポリシーの確認] を選択し、続いてポリシーを作成します。

(アカウント 2) CloudFormation スタックのサービスロールを作成します。このロールには、スタックによってデプロイされたサービスに必要なアクセス権限が含まれます。

注: このサービスロールは、アカウント 2 の CloudFormation スタックに直接設定されます。ロールには、スタックによってデプロイされたサービスのアクセス権限が含まれている必要があります。

1.    アカウント 2 で、IAM コンソールを開きます。

2.    ナビゲーションペインで [Roles] を選択します。

3.    お客様に代わってサービスを起動する際に使用する AWS CloudFormation 用のロールを作成します。

4.    ユースケースに応じて、ロールにアクセス許可を適用します。

重要: 信頼ポリシーが AWS CloudFormation 向けであること、およびスタックがデプロイしているサービスにアクセスする権限がロールにあることを確認してください。

(アカウント 1) CodePipeline 設定を更新して、アカウント 2 に関連付けられたリソースを含めます。

注: AWS Command Line Interface (AWS CLI) のコマンド実行中にエラーが発生した場合は、AWS CLI の最新バージョンを使用していることを確認してください

CodePipeline コンソールは、別のアカウントに関連付けられたリソースを使用するパイプラインの作成や編集には使用できません。ただし、コンソールを使用してパイプラインの一般的な構造を作成できます。次に、AWS CLI を使用してパイプラインを編集し、他のアカウントに関連付けられたリソースを追加できます。また、新しいパイプラインのリソースを使用して、現在のパイプラインの更新も可能です。詳細については、CodePipeline でのパイプラインの作成を参照してください。

1.    次の AWS CLI コマンドを実行して、パイプライン JSON 構造を取得します。

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

2.    ローカルの pipeline.json ファイルで、artifactStore の下のencryptionKey ID に AWS KMS キーの ARN を持つ ID が含まれていることを確認します。

注:パイプラインの構造の詳細については、『AWS CLI コマンドリファレンス』の「create-pipeline」を参照してください。

3.    pipeline.json ファイルで、AWS CloudFormation のアクション設定を更新します。

注: パイプラインのアクション設定 JSON 構造内の RoleArn は、CloudFormation スタックのロール (CFN_STACK_ROLE) です。アクション設定 JSON 構造外の roleArn は、パイプラインが CloudFormation スタックの操作を引き受けるクロスアカウントロール (CROSS_ACCOUNT_ROLE) です。

4.    次の両方でロールが更新されていることを確認します。

  • パイプラインのアクション設定 JSON 構造内の RoleArn
  • パイプラインのアクション設定 JSON 構造の外にある roleArn

注: 次のコード例では、RoleArn は、スタックを起動するために AWS CloudFormation に渡されるロールです。CodePipeline は roleArn を使用して AWS CloudFormation スタックを操作します。

{
  "name": "Prod_Deploy",
  "actions": [{
    "inputArtifacts": [{
      "name": "MyApp"
    }],
    "name": "test-cfn-x",
    "actionTypeId": {
      "category": "Deploy",
      "owner": "AWS",
      "version": "1",
      "provider": "CloudFormation"
    },
    "outputArtifacts": [],
    "configuration": {
      "ActionMode": "CHANGE_SET_REPLACE",
      "ChangeSetName": "test",
      "RoleArn": "ARN_FOR_CFN_STACK_ROLE",
      "Capabilities": "CAPABILITY_IAM",
      "StackName": "test-cfn-sam",
      "TemplatePath": "MyApp::template.yaml"
    },
    "roleArn": "ARN_FOR_CROSS_ACCOUNT_ROLE",
    "runOrder": 1
  }]
}

5.    pipeline.json ファイルからメタデータ設定を削除します。例:

"metadata": {
  "pipelineArn": "arn:aws:codepipeline:REGION:ACC:my_test",
  "updated": 1551216777.183,
  "created": 1551207202.964
}

重要: 適切な JSON 形式に合わせるには、メタデータセクションの前のコンマを削除します。

6.    (オプション) パイプラインを作成し、JSON 構造をアップデートするには、次のコマンドを実行して新しい設定ファイルを使用してパイプラインを更新します。

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

7.    (オプション) 現在のパイプラインを使用し、JSON 構造を更新するには、次のコマンドを実行して新しいパイプラインを作成します。

aws codepipeline create-pipeline --cli-input-json file://pipeline.json

重要:pipeline.json ファイルでは、必ず新しいパイプラインの名前を変更してください。