背景

大型企业中代码仓库通常存放在各部门开发账户中,而流水线则位于独立 DevOps 账户中。

本文我们将介绍如何创建跨账号访问 Codecommit 代码仓库的 Codepipeline 流水线,即 CodePipeline 调用另一个账号中的 Codecommit 代码仓库。

亚马逊云科技开发者社区 为开发者们提供全球的开发技术资源。这里有技术文档、开发案例、技术专栏、培训视频、活动与竞赛等。帮助中国开发者对接世界最前沿技术,观点,和项目,并将中国优秀开发者或技术推荐给全球云社区。如果你还没有关注/收藏,看到这里请一定不要匆匆划过,点这里 让它成为你的技术宝库!

部署架构图

image.png

权限配置

  1. CodePipeline 执行 role – CodePipelineServiceRole,关键 IAM Policy:允许 CodePipeline assume account B 中的角色 “AssumeAdminRole”。
  2. AssumeAdminRole – CodePipeline-SourceStage 实际执行 role, 添加 policy 以具有以下权限
  • 允许被 Account A 中 CodePipeline Assume
  • 允许访问本账户中的 CodeCommit
  • 允许访问 Account A 中的 S3桶(存放 sourceArtifact)
  • 允许访问 Account A 中的 KMS
  1. 配置 KMS Policy, 允许 CodePipelineServiceRole 和 AssumeAdminRole 访问 kms 中相应的key
  2. 配置 S3 Bucket Policy,允许 AssumeAdminRole 访问 S3中相应的bucket
  3. CodeBuild 执行 role,可配置为自动生成,不是本文重点

流水线执行过程

  1. 触发流水线
  2. SourceStage 中首先 assume AssumeAdminRole,获得访问 CodeCommit 权限
  3. 从 AccountB CodeCommit 代码仓库拉取代码
  4. 将放 sourceArtifact 存入 S3桶
  5. S3服务端加密
  6. 执行 Build Stage: CodeBuild

账号准备

选择您所在的 region,本文以北京 Region 为例。

准备两个 Amazon 主账号:

  • 代码仓库账号 B:提供 Codecommit 服务,源代码放在这里。
  • pipeline 账号 A:提供 Codepipeline 服务,以及相关联的codebuild、kms 密钥和 s3桶

代码仓库账号 B

一、创建跨账号 IAM Role

该 Role 命名为 assume-admin-role,使用权限如下:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "kms:Decrypt",
                "kms:Encrypt",
                "kms:DescribeKey",
                "s3:GetObject*",
                "s3:PutObjectAcl",
                "kms:ReEncrypt*",
                "kms:GenerateDataKey*"
            ],
            "Resource": [
                " arn:aws-cn:kms:cn-north-1:<Account_A_ID>:key/XXX-XXX-XXX-XXX ",
                "arn:aws-cn:s3:::codecommit-sdv-cross-account/*"
            ]
        },
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": [
                "codecommit:List*"
            ],
            "Resource": "arn:aws-cn:s3:::codecommit-sdv-cross-account/*"
        }
    ]
}

该 Role 的信任关系如下:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": [
                    "arn:aws-cn:iam::<Account_A_ID>:root"
                ]
            },
            "Action": "sts:AssumeRole"
        }
    ]
}

二、创建 CodeCommit Repository

该 Repo 命名为:cros-account-b-repo,并在该 Repo 中创建文件 demo.txt。

image.png

流水线账号 A

三、创建 Codepipeline IAM Role

创建 IAM Role,名为:AWSCodePipelineServiceRole-cn-north-1-sdv-pipeline-cros,为 Codepipeline 的创建做准备。

该 role 关联 Codepipeline 默认 Role 的权限策略,具体如下:

{
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "iam:PassRole"
            ],
            "Resource": "*",
            "Condition": {
                "StringEqualsIfExists": {
                    "iam:PassedToService": [
                        "cloudformation.amazonaws.com",
                        "elasticbeanstalk.amazonaws.com",
                        "ec2.amazonaws.com",
                        "ecs-tasks.amazonaws.com"
                    ]
                }
            }
        },
        {
            "Effect": "Allow",
            "Action": [
                "codecommit:CancelUploadArchive",
                "codecommit:GetBranch",
                "codecommit:GetCommit",
                "codecommit:GetRepository",
                "codecommit:GetUploadArchiveStatus",
                "codecommit:UploadArchive"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "codedeploy:CreateDeployment",
                "codedeploy:GetApplication",
                "codedeploy:GetApplicationRevision",
                "codedeploy:GetDeployment",
                "codedeploy:GetDeploymentConfig",
                "codedeploy:RegisterApplicationRevision"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "elasticbeanstalk:*",
                "ec2:*",
                "elasticloadbalancing:*",
                "autoscaling:*",
                "cloudwatch:*",
                "s3:*",
                "sns:*",
                "cloudformation:*",
                "rds:*",
                "sqs:*",
                "ecs:*"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "lambda:InvokeFunction",
                "lambda:ListFunctions"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "cloudformation:CreateStack",
                "cloudformation:DeleteStack",
                "cloudformation:DescribeStacks",
                "cloudformation:UpdateStack",
                "cloudformation:CreateChangeSet",
                "cloudformation:DeleteChangeSet",
                "cloudformation:DescribeChangeSet",
                "cloudformation:ExecuteChangeSet",
                "cloudformation:SetStackPolicy",
                "cloudformation:ValidateTemplate"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "codebuild:BatchGetBuilds",
                "codebuild:StartBuild",
                "codebuild:BatchGetBuildBatches",
                "codebuild:StartBuildBatch"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "servicecatalog:ListProvisioningArtifacts",
                "servicecatalog:CreateProvisioningArtifact",
                "servicecatalog:DescribeProvisioningArtifact",
                "servicecatalog:DeleteProvisioningArtifact",
                "servicecatalog:UpdateProduct"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "cloudformation:ValidateTemplate"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "ecr:DescribeImages"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "states:DescribeExecution",
                "states:DescribeStateMachine",
                "states:StartExecution"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "appconfig:StartDeployment",
                "appconfig:StopDeployment",
                "appconfig:GetDeployment"
            ],
            "Resource": "*"
        }
    ],
    "Version": "2012-10-17"
}

除了默认权限策略,为了提供跨账号调用,该 Role 还需要加入如下权限策略:

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

四、创建 KMS 秘钥

创建名为:account_a_cros_kms 的 KMS 秘钥。

image.png

image.png

image.png

image.png

在定义秘钥使用权限时,需要加入 Codepipeline 所关联的 Role(上一步创建名为:AWSCodePipelineServiceRole-cn-north-1-sdv-pipeline-cros 的 IAM Role)和 Account B 的账号 ID。记录 KMS ARN 为:arn:aws-cn:kms:cn-north-1:<Account_A_ID>:key/XXX-XXX-XXX-XXX

五、创建 S3桶

这里创建名为:codecommit-sdv-cross-account 的 S3 桶。

image.png

这里 S3桶命名为 codecommit-sdv-cross-account。然后编辑存储桶权限,即权限->存储通权限,点击编辑按钮,添加如下 policy json:

{
"Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Statement1",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws-cn:iam::<Account_B_ID>:root"
            },
            "Action": [
                "s3:Get*",
                "s3:Put*"
            ],
            "Resource": "arn:aws-cn:s3:::codecommit-sdv-cross-account/*"
        },
        {
            "Sid": "Statement2",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws-cn:iam:: <Account_B_ID>:root"
            },
            "Action": "s3:ListBucket",
            "Resource": "arn:aws-cn:s3:::codecommit-sdv-cross-account"
        }
    ]
}

六、创建 CodeBuild

创建名为:sdv-build 的 codebuild 项目,供 codepipeline 调用。

image.png

在 Buildspec 中添加命令如下:

image.png

七、创建 Codepipeline

对于跨账号调用 Codecommit 的 Codepipeline 只能通过 Amazon CLI 创建,准备如下 pipeline.json 文件,

{
    "pipeline": {
        "roleArn": "arn:aws-cn:iam::<Account_A_ID>:role/service-role/AWSCodePipelineServiceRole-cn-north-1-sdv-pipeline-cros", 
        "stages": [
            {
                "name": "Source", 
                "actions": [
                    {
                        "inputArtifacts": [], 
                        "name": "Source", 
                        "region": "cn-north-1", 
                        "namespace": "SourceVariables", 
                        "actionTypeId": {
                            "category": "Source", 
                            "owner": "AWS", 
                            "version": "1", 
                            "provider": "CodeCommit"
                        }, 
                        "outputArtifacts": [
                            {
                                "name": "SourceArtifact"
                            }
                        ], 
                        "roleArn":"arn:aws-cn:iam::<Account_B_ID>:role/assume-admin-role",
                        "configuration": {
                            "BranchName": "master", 
                            "PollForSourceChanges": "false", 
                            "RepositoryName": "cros-account-b-repo"
                        }, 
                        "runOrder": 1
                    }
                ]
            }, 
            {
                "name": "Build", 
                "actions": [
                    {
                        "inputArtifacts": [
                            {
                                "name": "SourceArtifact"
                            }
                        ], 
                        "name": "Build", 
                        "region": "cn-north-1", 
                        "namespace": "BuildVariables", 
                        "actionTypeId": {
                            "category": "Build", 
                            "owner": "AWS", 
                            "version": "1", 
                            "provider": "CodeBuild"
                        }, 
                        "outputArtifacts": [
                            {
                                "name": "BuildArtifact"
                            }
                        ], 
                        "configuration": {
                            "ProjectName": "sdv-build"
                        }, 
                        "runOrder": 1
                    }
                ]
            }
        ], 
        "artifactStore": {
            "type": "S3", 
            "location": "codecommit-sdv-cross-account",
            "encryptionKey": {
               "id": " arn:aws-cn:kms:cn-north-1:<Account_A_ID>:key/XXX-XXX-XXX-XXX ",
               "type": "KMS"
            }
       },
        "name": "pipeline-cros", 
        "version": 1
    }
}

这里计划在 Account A 创建名为 pipeline-cros的codepipeline,该 pipeline 以 Account B 的 codecommit repo: cros-account-b-repo (master branch) 作为源,并利用预先准备好的位于 Account A 的 codebuild 进行流水线的执行。

使用如上 Json,并利用 Amazon cli 执行命令如下:

image.png

amazon codepipeline create-pipeline –cli-input-json file://pipeline.json # 创建 pipeline

同时 codebuild 会打印日志如下:

……
[Container] 2022/07/18 03:23:11 Entering phase BUILD
[Container] 2022/07/18 03:23:11 Running command ls
demo.txt
[Container] 2022/07/18 03:23:11 Phase complete: BUILD State: SUCCEEDED
……

本篇作者

image.png

王帅
Amazon 专业服务团队 Devops 顾问。提倡融合文化,实践和工具的 Devops 理念,致力于帮助客户使组织能够以更高的速度和可靠性交付产品并获得业务价值。擅长平台规划,迁移和工具链设计。对新鲜事物充满热情。

image.png

冯霄鹏
Amazon 专业服务团队高级 DevOps 顾问。主要负责 DevOps 咨询和技术实施。在 DevSecOps 加速企业数字化转型方面领域拥有多年经验,对公有云、DevOps、基于云原生的微服务架构、敏捷加速研发效能等有深入的研究和热情。

文章来源:https://dev.amazoncloud.cn/column/article/630a07ad86218f3ca3e...


亚马逊云开发者
2.9k 声望9.6k 粉丝

亚马逊云开发者社区是面向开发者交流与互动的平台。在这里,你可以分享和获取有关云计算、人工智能、IoT、区块链等相关技术和前沿知识,也可以与同行或爱好者们交流探讨,共同成长。


引用和评论

0 条评论