如何使用 CodePipeline 将构件部署到不同账户中的 Amazon S3?
上次更新日期:2020 年 10 月 20 日
我想要使用 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. 选择 Next (下一步)。
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,然后选择添加。
在生产账户中配置跨账户角色
{
"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. 在策略列表中,选择 outputbucketfullaccess 和 devkmss3access。
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. 选择 Save。
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 将提取到的文件部署到开发账户中的 codepipeline-output-bucket。
现在,codepipeline-output-bucket 中的提取对象拥有者为开发账户。</p