はじめに
少し前にポストした、この件が解決したので記事にしました!
一度はそれぞれのアカウントにCodePipelineを配置し、クロスアカウントで利用可能なS3をトリガーとする構成としてましたが、きちんとした形ができたと思いますので共有します!
構成
目指す構成は以下のような形です。
今回はCodeDeployを使っていますが、BeanStalk等、他のデプロイ方法でも応用できると思います。
また、この記事で出てくるアカウントは以降、以下2つの記載の仕方をします。
- DEV環境(
888877776666
)- CodePipelineを配置する環境
- STG / PROD環境(
111122223333
)- CodeDeployのみを配置する環境
構築手順
手順はクロスアカウント構成のために必要な設定のみとし、基本的なところは省略させていただきます。
最初にポイント!
この記事のポイントを先に書いておきます。
マネージメントコンソール単体では設定できない場所がある!
私の見落としかもしれませんが、一度作成済みのパイプラインの暗号化キーの指定や、ステージ単位のロールの指定ができないです。
クロスアカウントロールの指定が正しくできていても、マネージメントコンソール上で、CodeDeployのアプリケーションが選択できない。といった事象にかなり悩まされました。
KMSのカスタマーマスターキーが必要
AWSマネージドなaws/s3
エイリアスのキーは、他アカウントでは利用できません。
そのため、複数のアカウントでアーティファクトを共有する場合、クロスアカウントで利用可能なカスタマーマスターキーを利用する必要があります。
1.カスタマーマスターキーの作成
なぜ必要?
CodePipeline上で作成したアーティファクトはアーティファクトストアと呼ばれるS3に格納されます。
この時、CodePipelineのデフォルト動作はエイリアスaws/s3
のマネージドキーを利用しますが、キーボリシーの設定ができないことから、他のアカウントからは複合化ができないためです。
(aws/s3
を使ったSSE-KMS
はSSE-S3
とは違うのか?)
設定
以下のような感じに、CodePipelineがあるアカウント側に作成します。
大切なことは、ここで今回デプロイを行う別のアカウント(888877776666
)に対し、アクセス許可を付与ことです。
この設定後にキーポリシーを見てみると、STG/PRDOアカウント経由の暗号化が許可されていることがわかります。
{
"Version": "2012-10-17",
"Id": "auto-s3-2",
"Statement": [
{
"Sid": "Allow access through S3 for all principals in the account that are authorized to use S3",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": [
"kms:Encrypt",
"kms:Decrypt",
"kms:ReEncrypt*",
"kms:GenerateDataKey*",
"kms:DescribeKey"
],
"Resource": "*",
"Condition": {
"StringEquals": {
"kms:ViaService": "s3.ap-northeast-1.amazonaws.com",
"kms:CallerAccount": "111122223333"
}
}
},
{
"Sid": "Allow direct access to key metadata to the account",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::111122223333:root"
},
"Action": [
"kms:Describe*",
"kms:Get*",
"kms:List*"
],
"Resource": "*"
}
]
}
2.アーティファクトストアのバケットポリシーの設定
なぜ必要?
アーティファクトストアを他のアカウントから参照する際に必要なアクセス権限をバケットポリシーに付与します。
設定
{
"Version": "2012-10-17",
"Id": "SSEAndSSLPolicy",
"Statement": [
{
"Sid": "AllowCrossAccountAccess",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::111122223333:root"
},
"Action": [
"s3:GetBucketLocation",
"s3:ListBucket",
"s3:GetObject",
"s3:PutObject",
"s3:GetObjectVersion"
],
"Resource": [
"arn:aws:s3:::codepipeline-ap-northeast-1-888877776666",
"arn:aws:s3:::ccodepipeline-ap-northeast-1-888877776666/*"
]
}
]
}
3.各種ロールの設定(STG/PROD環境)
EC2のインスタンスプロファイル
アーティファクトストアからの資材の取得は、EC2内のCodeDeploy Agent経由で動作するので、インスタンスプロファイルにアーティファクトストア、KMSへのアクセス権限が必要です。
アーティファクトストア用KMSへのアクセス許可ポリシー
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowUseOfKMSKey",
"Effect": "Allow",
"Action": [
"kms:Decrypt"
],
"Resource": [
"arn:aws:kms:ap-northeast-1:888877776666:key/cb99b732-473c-4ebb-aa94-bfba54805081"
]
}
]
}
アーティファクトストアへのアクセス許可ポリシー
マネージドポリシーAmazonEC2RoleforAWSCodeDeploy
を今回は使います。
CodeDeployの信頼ポリシー
DEV環境でCodeDeployをトリガーするための信頼ポリシー。
この信頼ポリシーを引き受けたステージがアーティファクトストアにアクセスする必要もあるので、そのポリシーも付与しておきます。
- AWSCodeDeployDeployerAccess(マネージドポリシー)
- CodeDeployに必要なロール
- AmazonEC2RoleforAWSCodeDeploy(マネージドポリシー)
- アーティファクトストアがあるS3へのアクセスに必要
4.各種ロールの設定(DEV環境)
CodePipelineのサービスロール
STG/PROD環境で作成したCodeDeployの信頼ポリシーをAssumeRoleする権限を付与します。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::111122223333:role/CrossAccountForCodeDeploy"
}
]
}
5.CodePipelineの設定
ここが一番詰まったのですが、一部の設定がマネージメントコンソールからできず、別の方法で設定する必要があります。
今回はCLIで実施しましたが、おそらくIaCツールでも設定できるはずです。
まずは、現状のPipelineの設定をJSONにエクスポート。
$ aws codepipeline get-pipeline --name web > webpipeline.json
必要な設定をJSONファイルに追記
以下のような感じにマネージメントコンソール上で編集できないところを編集しています。
{
"pipeline": {
"name": "web",
"roleArn": "arn:aws:iam::853835738220:role/service-role/AWSCodePipelineServiceRole-ap-northeast-1-web",
"artifactStore": {
"type": "S3",
"location": "codepipeline-ap-northeast-1-111122223333",
+ "encryptionKey": {
+ "id": "arn:aws:kms:ap-northeast-1:853835738220:alias/CodePipelineArtifacts",
+ "type": "KMS"
+ }
},
"stages": [
{
"name": "Source",
"actions": [
{
"name": "Source",
"actionTypeId": {
"category": "Source",
"owner": "AWS",
"provider": "S3",
"version": "1"
},
"runOrder": 1,
"configuration": {
"PollForSourceChanges": "false",
"S3Bucket": "chel-artifact-backet",
"S3ObjectKey": "app.zip"
},
"outputArtifacts": [
{
"name": "SourceArtifact"
}
],
"inputArtifacts": [],
"region": "ap-northeast-1",
"namespace": "SourceVariables"
}
]
},
{
"name": "Development",
"actions": [
{
"name": "Deploy",
"actionTypeId": {
"category": "Deploy",
"owner": "AWS",
"provider": "CodeDeploy",
"version": "1"
},
"runOrder": 1,
"configuration": {
"ApplicationName": "Web",
"DeploymentGroupName": "Web"
},
"outputArtifacts": [],
"inputArtifacts": [
{
"name": "SourceArtifact"
}
],
"region": "ap-northeast-1",
"namespace": "DeployStgVariables"
}
]
},
+ {
+ "name": "Staging",
+ "actions": [
+ {
+ "name": "Deploy",
+ "actionTypeId": {
+ "category": "Deploy",
+ "owner": "AWS",
+ "provider": "CodeDeploy",
+ "version": "1"
+ },
+ "runOrder": 1,
+ "configuration": {
+ "ApplicationName": "Web",
+ "DeploymentGroupName": "Web"
+ },
+ "outputArtifacts": [],
+ "inputArtifacts": [
+ {
+ "name": "SourceArtifact"
+ }
+ ],
+ "region": "ap-northeast-1",
+ "namespace": "DeployVariables",
+ "roleArn": "arn:aws:iam::111122223333:role/CrossAccountForCodeDeploy"
+ }
]
}
],
"version": 1,
"executionMode": "QUEUED",
"pipelineType": "V2"
- },
+ }
- "metadata": {
- "pipelineArn": "arn:aws:codepipeline:ap-northeast--1:888877776666:web",
- "created": "2024-10-12T20:07:31.782000+00:00",
- "updated": "2024-10-12T21:53:31.662000+00:00"
- }
}
1.暗号化キーの指定
pipeline
->artifactStore
->encryptionKey
を追加し、アーティファクトストアのデータ暗号化時に利用するカスタマーマスターキーを指定します。
これから新規にパイプラインを作成する場合には、高度な設定のところから設定が可能です。
2.STG/PROD環境向けのステージを追加
上記の例でいうと、Staging
のステージを追加します。
大切なところは、roleArn
でこのステージ用のロールを指定するところです。
ここで指定するロールは、STG/PROD環境で作成したクロスアカウントロールです。
このロールを指定することで、このパイプラインがSTG/PROD環境のCodePipelineをトリガーすることが可能になります。
また既に記載済みですが、ステージ用のロールにクロスアカウントロールを利用できるようにするため、CodePipilneのサービスロールにクロスアカウントをAssumeRoleできるポリシーを付与することが必要です。
3.metadataの削除
metadata
が残っているとインポートに以下のエラーがでるので、削除しておきます。
Parameter validation failed:
Unknown parameter in input: "metadata", must be one of: pipeline
修正したJSONをPipelineにインポート
最後にインポートしたら完成です!
$ aws codepipeline update-pipeline --cli-input-json file://webpipeline.json
最後に
いろいろ詰まったけど、CodePipeline周りに少し自信が出てきました!
また、ロールの設定も細かく検証でき、とっても勉強になった検証でした〜!