如何使用 CodePipeline 将构件部署到不同账户中的 Amazon S3?

上次更新时间:2020 年 6 月 24 日

我想要使用 S3 部署操作提供商的 AWS CodePipeline 将构件部署到不同账户中的 Amazon Simple Storage Service (Amazon S3)。我还希望将构件的拥有者设置为目标账户。

简短描述

下面的解决方法基于假定以下内容的示例场景:

  • 您有两个账户:开发 (dev) 账户和生产 (prod) 账户。
  • 开发账户中的输入存储桶称为 codepipeline-input-bucket(启用了版本控制)。
  • 开发账户中的默认构件存储桶称为 codepipeline-us-east-1-0123456789
  • 生产账户中的输出存储桶称为 codepipeline-output-bucket
  • 您正在将开发账户中的构件部署到生产账户中的 S3 存储桶。
  • 您希望代入在开发账户中创建的跨账户角色,然后部署构件。该角色将构件的对象拥有者设置为目标生产账户而不是开发账户。

解决方法

创建一个能够在开发账户中与 CodePipeline 一起使用的 AWS Key Management Service (AWS KMS) 密钥

1.    打开开发账户中的 AWS KMS 控制台

2.    从导航窗格中选择客户管理的密钥

3.    选择创建密钥

4.    对于密钥类型,选择对称密钥

5.    展开高级选项

6.    对于密钥材料来源,请选择KMS,然后选择下一步

7.    对于别名,请选择 s3deploykey

注意:请使用密钥别名替换s3deploykey

8.    选择下一步

9.    在定义密钥管理权限页面的密钥管理员部分,选择 AWS Identity and Access Management (IAM) 用户或角色作为密钥管理员,然后选择下一步

10.    在定义密钥使用权限页面的其他 AWS 账户部门,选择添加其他 AWS 账户

11.    在出现的文本框中,添加生产账户的账户 ID,然后选择下一步

注意:您也可以在此账户部分中选择现有的服务角色,然后跳过更新开发账户中的 KMS 使用策略部分中的步骤。

12.    查看密钥策略,然后选择完成

重要提示:您必须使用 KMS 客户管理的密钥进行跨账户部署。如果未配置密钥,则 CodePipeline 将使用默认加密方式加密对象,这些对象无法使用目标账户中的角色进行解密。

在开发账户中创建 CodePipeline

1.    打开 CodePipeline 控制台,然后选择创建管道

2.    对于管道名称,输入 crossaccountdeploy

注意:请使用管道名称替换 crossaccountdeploy

角色名称文本框会自动填充服务角色名称 AWSCodePipelineServiceRole-us-east-1-crossaccountdeploy。您也可以选择有权访问 KMS 密钥的现有服务角色。

3.    展开高级设置部分。

4.    对于构件存储,请选择默认位置

注意:如果场景需要,则可以选择自定义位置

5.    对于加密密钥,请选择客户管理的密钥

6.    对于 KMS 客户主密钥,请从列表中选择 s3deploykey,然后选择下一步

重要提示:请使用密钥别名替换 s3deploykey

7.    对于添加源阶段页面上的源提供商,选择 Amazon S3

8.    对于存储桶,请输入 codepipeline-input-bucket

注意:请使用输入存储桶名称替换 codepipeline-input-bucket

重要提示:输入存储桶必须启用版本控制才能使用 CodePipeline。

9.    对于 S3 对象键,输入 sample-website.zip

重要提示:要使用示例 AWS 网站而不是您自己的网站,请参阅教程:创建一个使用 Amazon S3 作为部署提供商的管道。然后,在 1:将静态网站文件部署到 Amazon S3 部分的前提条件中搜索“示例静态网站”。

10.    对于更改检测选项,选择 Amazon CloudWatch Events(推荐),然后选择下一步

11.    在添加构建阶段页面上,选择跳过构建阶段,然后选择跳过

12.    对于添加部署阶段页面上的部署提供商,选择 Amazon S3

13.    对于区域,选择美国东部(弗吉尼亚北部)

重要提示:请使用输出存储桶所在的 AWS 区域替换美国东部(弗吉尼亚北部)

14.    对于存储桶,输入生产存储桶名称 codepipeline-output-bucket

注意:请使用生产账户中的输出存储桶名称替换 codepipeline-output-bucket

15.    选择在部署前提取文件复选框。

注意:如果需要,请为部署路径输入路径。

16.    选择下一步

17.    选择创建管道

现在,您的管道已触发,但源阶段出现故障。然后,您将收到以下错误信息:

The object with key 'sample-website.zip' does not exist.

上传示例网站至输入存储桶部分将向您展示稍后如何解决此错误。

更新开发账户中的 KMS 使用策略

重要提示:如果您使用的是现有 CodePipeline 服务角色并且已在创建一个能够在开发账户中与 CodePipeline 一起使用的 AWS Key Management Service (AWS KMS) 密钥部分中将该角色添加为关键用户,则可以跳过本部分。

1.    打开开发账户中的 AWS KMS 控制台,然后选择 s3deploykey

重要提示:请使用密钥别名替换 s3deploykey

2.    在关键用户部分中,选择添加

3.    在搜索框中,输入服务角色 AWSCodePipelineServiceRole-us-east-1-crossaccountdeploy,然后选择添加

在生产账户中配置跨账户角色

要创建策略:

1.    打开生产账户中的 IAM 控制台

2.    在导航窗格中,选择策略,然后选择创建策略

3.    选择 JSON 选项卡,然后在 JSON 编辑器中输入以下策略:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:*"
            ],
            "Resource": [
                "arn:aws:s3:::codepipeline-output-bucket/*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::codepipeline-output-bucket"
            ]
        }
    ]
}

注意:请使用生产账户中的输出存储桶名称替换 codepipeline-output-bucket

4.    选择查看策略

5.    对于名称,输入 outputbucketfullaccess

6.    选择创建策略

7.    要创建其他策略,请选择创建策略

8.    选择 JSON 选项卡,然后在 JSON 编辑器中输入以下策略:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "kms:DescribeKey",
                "kms:GenerateDataKey*",
                "kms:Encrypt",
                "kms:ReEncrypt*",
                "kms:Decrypt"
            ],
            "Resource": [
                "arn:aws:kms:us-east-1:<dev-account-id>:key/<key id>"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:Get*"
            ],
            "Resource": [
                "arn:aws:s3:::codepipeline-us-east-1-0123456789/*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::codepipeline-us-east-1-0123456789"
            ]
        }
    ]
}

注意:请替换您创建的 KMS 密钥的 ARN。请使用开发账户中的构件存储桶名称替换 codepipeline-us-east-1-0123456789

9.    选择查看策略

10.    对于名称,输入 devkmss3access

11.    选择创建策略

要创建角色:

1.    打开生产账户中的 IAM 控制台

2.    在导航窗格中,选择角色,然后选择创建角色

3.    选择其他 AWS 账户

4.    对于账户 ID,输入开发账户 ID。

5.    选择下一步: 权限

6.    在策略列表中,选择 outputbucketfullaccessdevkmss3access

7.    选择下一步: 标签

8.    (可选)添加标签,然后选择下一步:查看

9.    对于角色名称,输入 prods3role

10.    选择创建角色

11.    在角色列表中,选择 prods3role

12.    选择信任关系选项卡,然后选择编辑信任关系

13.    在策略文档编辑器中,输入以下策略:

{
    "Version": "2012-10-17",
    "Statement": [
        {
        "Effect": "Allow",
        "Principal": {
            "AWS": [
            "arn:aws:iam::<dev-account-id>:role/service-role/AWSCodePipelineServiceRole-us-east-1-crossaccountdeploy"
            ]
        },
        "Action": "sts:AssumeRole",
        "Condition": {}
        }
    ]
}

注意:请使用开发环境的账户 ID 和管道的服务角色替换 dev-account-id

14.    选择更新信任策略

在开发账户中配置 CodePipeline 构件存储桶和服务角色

1.    打开开发账户中的 Amazon S3 控制台

2.    在存储桶名称列表中,选择 codepipeline-us-east-1-0123456789

注意:请使用构件存储桶的名称替换 codepipeline-us-east-1-0123456789

3.    选择权限,然后选择存储桶策略

4.    在文本编辑器中,使用以下语句更新现有策略:

{
    "Sid": "",
    "Effect": "Allow",
    "Principal": {
        "AWS": "arn:aws:iam::<prod-account-id>:root"
    },
    "Action": [
        "s3:Get*",
        "s3:Put*"
    ],
    "Resource": "arn:aws:s3:::codepipeline-us-east-1-0123456789/*"
},
{
    "Sid": "",
    "Effect": "Allow",
    "Principal": {
        "AWS": "arn:aws:iam::<prod-account-id>:root"
    },
    "Action": "s3:ListBucket",
    "Resource": "arn:aws:s3:::codepipeline-us-east-1-0123456789"
}

重要提示:为了符合正确的 JSON 格式,请在现有语句之后添加一个逗号。

注意:请使用生产环境的账户 ID 替换 prod-account-id。请使用构件存储桶名称替换 codepipeline-us-east-1-0123456789

5.    选择保存

6.    打开开发账户中的 IAM 控制台

7.    在导航窗格中,选择策略,然后选择创建策略

8.    选择 JSON 选项卡,然后在 JSON 编辑器中输入以下策略:

{
    "Version": "2012-10-17",
    "Statement": {
        "Effect": "Allow",
        "Action": "sts:AssumeRole",
        "Resource": [
            "arn:aws:iam::<prod-account-id>:role/prods3role" 
        ]
    }   
}

注意:请使用生产环境的账户 ID 替换 prod-account-id

9.    选择查看策略

10.    对于名称,输入 assumeprods3role

11.    选择创建策略

12.    在导航窗格中,选择角色,然后选择 AWSCodePipelineServiceRole-us-east-1-crossaccountdeploy

注意:如果适用,请使用服务角色替换 AWSCodePipelineServiceRole-us-east-1-crossaccountdeploy

13.    选择附加策略,然后选择 assumeprods3role

14.    选择附加策略

更新 CodePipeline,以便在开发账户中使用跨账户角色

1.    要将管道定义放入名为 codepipeline.json 的文件中,请运行以下命令:

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

注意:请使用管道名称替换 crossaccountdeploy

2.    更新 codepipeline.json 中的部署部分,以便包含 roleArn。请参阅以下示例:

"roleArn": "arn:aws:iam::your-prod-account id:role/prods3role",

要添加 roleArn,请进行以下更新:

{
    "name": "Deploy",
    "actions": [
        {
            "name": "Deploy",
            "actionTypeId": {
                "category": "Deploy",
                "owner": "AWS",
                "provider": "S3",
                "version": "1"
            },
            "runOrder": 1,
            "configuration": {
                "BucketName": "codepipeline-output-bucket",
                "Extract": "true"
            },
            "outputArtifacts": [],
            "inputArtifacts": [
                {
                    "name": "SourceArtifact"
                }
            ],
            "roleArn": "arn:aws:iam::<prod-account-id>:role/prods3role",
            "region": "us-east-1",
            "namespace": "DeployVariables"
        }
    ]
}

注意:请使用生产环境的账户 ID 替换 prod-account-id

3.    删除 codepipeline.json 文件末尾的元数据部分。例如:

"metadata": {
    "pipelineArn": "arn:aws:codepipeline:us-east-1:<dev-account-id>:crossaccountdeploy",
    "created": 1587527378.629,
    "updated": 1587534327.983
}

重要提示:为了符合正确的 JSON 格式,请删除元数据部分之前的逗号。

4.    要更新管道,请运行以下命令:

aws codepipeline update-pipeline --cli-input-json file://codepipeline.json

向输入存储桶上传示例网站

1.    打开开发账户中的 Amazon S3 控制台

2.    在存储桶名称列表中,选择 codepipeline-input-bucket

注意:请使用输入存储桶名称替换 codepipeline-input-bucket

3.    选择上传,然后选择添加文件

4.    选择之前下载的 sample-website.zip 文件。

5.    选择上传

现在,CodePipeline 已触发,并发生以下情况:

1.    源操作选择 codepipeline-input-bucket 中的 sample-website.zip,然后将网站作为源构件置于 codepipeline-us-east-1-0123456789 构件存储桶中。

2.    在部署操作中,CodePipeline 服务角色 AWSCodePipelineServiceRole-us-east-1-crossaccountdeploy 代入生产账户的 prods3role

3.    CodePipeline 使用 prods3role 访问开发账户中的 KMS 密钥和构件存储桶来获取构件,然后将提取到的文件部署到开发账户中的 codepipeline-output-bucket

现在,codepipeline-output-bucket 中的提取对象拥有者为开发账户。


这篇文章对您有帮助吗?

我们可以改进什么?


需要更多帮助?