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

最終更新日: 2020 年 11 月 2 日

AWS CodePipeline を使用して異なるアカウントの AWS CloudFormation スタックをデプロイしたいです。

簡単な説明

異なるアカウントに AWS CloudFormation スタックをデプロイするには、以下を完了する必要があります。

  1. 1 つのアカウント、アカウント A でパイプラインを作成します。このアカウントには、顧客管理 AWS Key Management Service (AWS KMS) キー、アーティファクト用の Amazon Simple Storage Service (Amazon S3) バケット、他のアカウント アカウント B からのアクセスを許可する S3 バケットポリシーが含まれている必要があります。
  2. アカウント B で、以下を許可するクロスアカウントサービスロールを設定します: 1) AWS CloudFormation アクション、2) アカウント A の S3 バケットへのアクセス、3) アカウント A の顧客管理 KMS キーによる復号化。
  3. アカウント A で、パイプラインサービスのロールがアカウント B でクロスアカウントロール (AssumeRole を使用) になることを許可します。

解決方法

アカウント A で、顧客管理キーを作成します

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

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

3.    [Create key] (キーの作成) を選び、続いて、[Symmetric] (対称) を選択します。

注意: [Advanced options] (高度なオプション) セクションで、[オリジン] を KMS のままにします。

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

5.    (オプション) タグを追加し、続いて [Next] を選択します。

6.    [Define key administrative permissions] (主な管理者のアクセス許可を定義する) ページの [Key administrators] (主な管理者) で、AWS Identity and Access Management (IAM) ユーザーと、キーの管理者の役割を担う他のユーザーまたはグループを選択し、[Next] (次へ) を選択します。

7.    [Define key usage permissions] (キーの使用許可を定義する) ページの [This account] (このアカウント) では、キーにアクセスできるアカウント (CodePipeline サービスロールなど) に IAM ユーザーを追加します。

8.    [Other AWS accounts] (その他の AWS アカウント) セクションで、[Add another AWS account] (別の AWS アカウントの追加) を選択し、アカウント B に IAM ロールの Amazon リソースネーム (ARN) を入力します。

9.    [Next] を選択してから [Finish] を選択します。

10.    [Customer managed keys] (顧客管理キー) セクションで、先ほど作成したキーを選択し、そのキーの ARN をコピーします。

注意: パイプラインを編集し、ポリシーを設定するときに、キーの ARN が必要になります。

アカウント A で、SourceArtifact バケットのパイプラインとして Amazon S3 バケットを選択または作成し、バケットポリシーを作成します。

アカウント A の S3 バケットポリシーは、アカウント B へのアクセスを許可する必要があります。

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

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

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

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

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

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

{
  "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.    前述のコードでは、codepipeline-source-artifact を CodePipeline の SourceArtifact のバケット名で置き換えます。

7.    前述のコードでは、ACCOUNT_B_NOアカウント B のアカウント番号で置き換えます。

8.    [Save] (保存) を選択します。

クロスアカウントロールポリシーは、アカウント A のパイプラインがアカウント B でのロールの引き継ぎを許可します。このポリシーは、AWS CloudFormation アクション、および SourceArtifact および AWS KMS に関連するオペレーションへのアクセスを有効にします。

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

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

3.    [Create policy] を選択します。

4.    [JSON] ビューを選択し、続いてコードエディタに次のポリシーを入力します。

{
  "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/*"
      ]
    }
  ]
}

5.    前述のコードでは、codepipeline-source-artifact をパイプラインの ArtifactStore のバケット名で置き換えます。

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

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

8.    [Create policy] を選択します。

9.    [JSON] ビューを選択し、続いてコードエディタに次のポリシーを入力します。

{
  "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"
    ]
  }]
}

10.    前述のコードでは、arn:aws:kms:REGION:ACCOUNT_A_NO:key/key-id を、先にアカウント A の顧客管理キーの作成セクションで作成したキーの ARN で置き換えます。

11.    [Review policy] (ポリシーの確認) を選択し、続いてポリシーを作成します。

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

13.    [Create role] を選択します。

14.    [Another AWS account] を選択します。

15.    [Account ID] に、アカウント A のアカウント ID を入力します。

16.    [Next: Permissions] を選択し、続いてロールを作成するステップを完了します。

17.    クロスアカウントロールポリシー、作成したロールへの KMS キーポリシーをアタッチします。

アカウント A で、CodePipeline サービスロールに AssumeRole アクセス許可を追加する

ポリシーは、アカウント A の CodePipeline サービスロールが、アカウント B で以前に作成したクロスアカウントロールを引き継げるようにします。

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

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

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

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

5.    [JSON] ビューを選択し、続いてコードエディタに次のポリシーを入力します。

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

6.    前述のコードでは、ACCOUNT_B_NOアカウント B の数値で置き換えます。

7.    [Review policy] (ポリシーの確認) を選択し、続いてポリシーを作成します。

アカウント B で、AWS CloudFormation スタック (CFN_STACK_ROLE) 用のロールを作成する

このサービスロールは、アカウント B の AWS CloudFormation スタックに直接設定され、スタックによってデプロイされるサービスのアクセス許可を含める必要があります。

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

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

3.    AWS CloudFormation 用のロールを作成して、代理でサービスを起動するときに使用します。

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

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

アカウント A で CodePipeline の設定を更新する

注意: AWS コマンドラインインターフェイス (AWS CLI) のコマンド実行時にエラーが発生した場合は、AWS CLI の最新バージョンを使用するようにしてください

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

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

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

2.    ローカル pipeline.json ファイルで、encryptionKey ID に、前に作成したキーの ARN の ID が含まれていることを確認します。

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

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

4.    RoleArnroleArn の両方のロールが更新されたことを確認します。

次のコード例では、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 ファイルでは、新しいパイプラインの名前を変更してください。