I'm trying to use the EcsDeployAction and I understand for a cross account deployment I must provide a role that's created in the account with the ECS cluster:
const service = ecs.BaseService.fromServiceArnWithCluster(this, 'Service', `arn:aws:ecs:${this.region}:${ACCOUNTS.dev}:service/${CLUSTER_NAME}/${SERVICE_NAME}`);
const deploymentRole = iam.Role.fromRoleArn(this, 'DeploymentRole', `arn:aws:iam::${ACCOUNTS.dev}:role/${DEPLOYMENT_ROLE_NAME}`)
const deploymentAction = new codepipelineActions.EcsDeployAction({
actionName: 'deploy',
service,
input: buildOutputFromDockerBuildInCodeBuild,
role: deploymentRole,
});
deploymentRole
) with CDK(or CLI or other IAAC but not manually through console) that Codepipeline can do a deployment in another account?I found a few examples of cross account deployments on the web but couldn't find one with ECS deployment in this way that documents the IAM role creation. Codepipeline own documentaion and a few other examples of cross account deployments show a role that only has access to S3 which not what I'm deploying to.
I did this a few weeks ago in Terraform so happy to assist. I found this article on codepipeline the most comprehensive example I could find on how to do this. You need both a codepipeline role that can be assumed by the account your codepipeline is located in, as well as a codedeploy role that can be assumed by the codedeploy service. I am not using S3 to deploy either but the permissions are there nonetheless.
Below is my Terraform code:
resource "aws_iam_role" "codepipeline_cross_account" {
name = "codepipeline-cross-account"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = "sts:AssumeRole"
Effect = "Allow"
Sid = ""
Principal = {
AWS = "arn:aws:iam::<account_id_of_codepipeline_acct>:root"
}
}
]
})
inline_policy {
name = "codedeploy"
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect : "Allow",
Action : [
"codedeploy:GetDeploymentConfig",
"codedeploy:GetApplicationRevision",
"codedeploy:RegisterApplicationRevision",
"codedeploy:GetApplication",
"codedeploy:GetDeployment",
"codedeploy:CreateDeployment"
],
Resource : "*"
},
{
Effect : "Allow",
Action : [
"kms:DescribeKey",
"kms:GenerateDataKey*",
"kms:Encrypt",
"kms:ReEncrypt*",
"kms:Decrypt"
],
Resource : "<kms_arn>"
},
{
Effect : "Allow",
Action : [
"s3:GetObject",
"s3:GetObjectVersion",
"s3:GetObjectTagging",
"s3:GetObjectVersionTagging"
],
Resource : "<s3_arn>/*"
},
{
Effect : "Allow",
Action : [
"ecs:RegisterTaskDefinition"
],
Resource : "*"
},
{
Effect : "Allow",
Action : [
"iam:PassRole"
],
Resource : <ecs_task_execution_role_arn_goes_here>
}
]
})
}
}
resource "aws_iam_role" "ecs_deploy" {
name = "ecs-deploy"
managed_policy_arns = ["arn:aws:iam::aws:policy/AWSCodeDeployRoleForECS"]
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = "sts:AssumeRole"
Effect = "Allow"
Sid = ""
Principal = {
Service = "codedeploy.amazonaws.com"
}
}
]
})
}
resource "aws_codedeploy_app" "app" {
compute_platform = "ECS"
name = "app"
}
resource "aws_codedeploy_deployment_group" "example" {
app_name = aws_codedeploy_app.app.name
deployment_config_name = terraform.workspace == "prod" ? "CodeDeployDefault.ECSLinear10PercentEvery1Minutes" : "CodeDeployDefault.ECSAllAtOnce"
deployment_group_name = "example"
service_role_arn = aws_iam_role.ecs_deploy.arn
..rest of code
}
Then when you create your deployment group in your application account, you will reference the ECS deployment role above as the service role. That will allow your pipeline to deploy to it.