Codepipeline 跨賬號訪問 Codecommit

亞馬遜雲開發者發表於2023-04-17

背景

大型企業中程式碼倉庫通常存放在各部門開發賬戶中,而流水線則位於獨立 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...

相關文章