使用 awscli 更新云端配置
Update cloudfront configuration using awscli
我想 edit/update 我的 CloudFront 分配与 awscli。
我正在使用最新的 cli 版本:
aws-cli/1.11.56 Python/2.7.10 Darwin/16.4.0 botocore/1.5.19
要在 awscli 中使用云端功能,您需要将其添加到您的 aws 配置文件中:
[preview]
cloudfront = true
我正在获取要修改的分发配置:
aws cloudfront get-distribution-config --id FOO_BAR_ID > cf_config.json
看起来像预期的那样有效。配置对我来说没问题。现在我正在尝试使用相同的配置重新配置我的 CF 发行版。
aws cloudfront update-distribution --distribution-config file://cf_config.json --id FOO_BAR_ID
我得到:
Parameter validation failed:
Missing required parameter in DistributionConfig: "CallerReference"
Missing required parameter in DistributionConfig: "Origins"
Missing required parameter in DistributionConfig: "DefaultCacheBehavior"
Missing required parameter in DistributionConfig: "Comment"
Missing required parameter in DistributionConfig: "Enabled"
Unknown parameter in DistributionConfig: "ETag", must be one of: CallerReference, Aliases, DefaultRootObject, Origins, DefaultCacheBehavior, CacheBehaviors, CustomErrorResponses, Comment, Logging, PriceClass, Enabled, ViewerCertificate, Restrictions, WebACLId, HttpVersion, IsIPV6Enabled
Unknown parameter in DistributionConfig: "DistributionConfig", must be one of: CallerReference, Aliases, DefaultRootObject, Origins, DefaultCacheBehavior, CacheBehaviors, CustomErrorResponses, Comment, Logging, PriceClass, Enabled, ViewerCertificate, Restrictions, WebACLId, HttpVersion, IsIPV6Enabled
使用 awscli 重新配置 CF 的正确方法是什么?
在与 update-distribution
一起使用之前,您必须编辑 cf_config.json 并删除
{
"ETag": "ETag_Value",
"DistributionConfig":
从文件开头到最后
}
从文件末尾开始。
然后将此命令与从 cf_config.json
中删除的正确 id
和 ETag
值一起使用
aws cloudfront update-distribution --distribution-config file://cf_config.json --id FOO_BAR_ID --if-match ETag_Value
@usterk 的回答是正确的,但我又花了 3 个小时才找到我需要的脚本。在此,分享给大家。
我的案例:CI/CD 使用 S3/CloudFront 和手动工件版本控制
我在 S3 中托管一个静态网站 (SSG),我希望它由 CloudFront 提供服务。该网站在其代码(不仅仅是内容)方面得到频繁更新,我想将网站的所有版本存储在 S3 中(就像所有工件或 docker 图像一样)并更新 CloudFront 以指向一个新版本,在新版本被推送到 S3 之后。
我知道 S3 中有“文件版本控制”,但这种保留资产所有版本的老式格式有助于分析资产以及轻松回滚。
我的配置
- 构建资产(JS、CSS 等)后,新文件将上传到 S3 中的文件夹,如
s3://<mybucket-name>/artifacts/<version-id>
- 在 CloudFront 中,我有一个 Distribution
www
网站。 www.domain.com
的 Route53 指向它。
- 在那个 Distribution 我有几个 Origins (例如,一个发送
/api
到 ELB 的路径。)
- 这里重要的 Origin 是
www
,它的 OriginPath
指向 /artifacts/<version-id>
。
工作流程
- 在通过 AWS CLI 完成 S3 同步后,我需要更新 CloudFront 的配置,使 www Origin 的 OriginPath 值指向 S3 中的新路径。
- 我还需要在分发上启动失效,以便 CloudFront 在内部(S3 和它之间)获取新文件
任务
正如@usterk 和@BrianLeishman 所指出的,此作业的唯一 CLI 命令是 update-distribution
,其中 per the documentation,需要 ENTIRE CONFIGURATION分配给REPLACE吧。因此,没有命令仅部分更新配置中的一个字段。
要实现这一点,必须首先获取当前的分发配置,然后提取“DistributionConfig”组件,然后更新它所使用的字段,最后,用正确的验证令牌将其放回正确的格式。
请注意,“更新”命令需要的是“获取”返回的内容的“子集”。所以通过jq
解析JSON是不可避免的。
Bash 脚本
我想出的以下脚本适合我:
# 0) You need to set the followings for your case
CLOUDFRONT_DISTRIBUTION_ID="EABCDEF12345ABCD"
NEW_ORIGIN_PATH="/art/0.0.9"
CLOUDFRONT_ORIGIN_ID="E1A2B3C4D5E6F"
DIST_CONFIG_OLD_FILENAME="dist-config.json" # a temp file, which will be removed later
DIST_CONFIG_NEW_FILENAME="dist-config2.json" # a temp file, which will be removed later
# 1) Get the current config, entirely, and put it in a file
aws cloudfront get-distribution --id $CLOUDFRONT_DISTRIBUTION_ID > $DIST_CONFIG_OLD_FILENAME
# 2) Extract the Etag which we need this later for update
Etag=`cat $DIST_CONFIG_OLD_FILENAME | jq '.ETag' | tr -d \"`
# 3) Modify the config as wished, for me I used `jq` extensively to update the "OriginPath" of the desired "originId"
cat $DIST_CONFIG_OLD_FILENAME | jq \
--arg targetOriginId $CLOUDFRONT_ORIGIN_ID \
--arg newOriginPath $NEW_ORIGIN_PATH \
'.Distribution.DistributionConfig | .Origins.Items = (.Origins.Items | map(if (.Id == $targetOriginId) then (.OriginPath = $newOriginPath) else . end))' \
> $DIST_CONFIG_NEW_FILENAME
# 4) Update the distribution with the new file
aws cloudfront update-distribution --id $CLOUDFRONT_DISTRIBUTION_ID \
--distribution-config "file://${DIST_CONFIG_NEW_FILENAME}" \
--if-match $Etag \
> /dev/null
# 5) Invalidate the distribution to pick up the changes
aws cloudfront create-invalidation --distribution-id $CLOUDFRONT_DISTRIBUTION_ID --paths "/*"
# 6) Clean up
rm -f $DIST_CONFIG_OLD_FILENAME $DIST_CONFIG_NEW_FILENAME
最后说明:IAM 访问
执行这些操作的用户需要 IAM 访问 CloudFront 中分配的获取、无效和更新操作。这是规定的政策:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"cloudfront:GetDistribution",
"cloudfront:UpdateDistribution",
"cloudfront:CreateInvalidation"
],
"Resource": "arn:aws:cloudfront::<ACCOUNT_ID>:distribution/<DISTRIBUTION_ID>
}
]
}
aws cloudfront get-distribution-config
生成您无法在 update-distribution
中使用的额外信息
所以你只需要从生成的 json 中获取 DistributionConfig
并修改它。
使用 jq
aws cloudfront get-distribution --id <CLOUDFRONT_DISTRIBUTION_ID> | jq .Distribution.DistributionConfig > config.json
您还需要单独的 Etag,您可以通过以下方式获取:
ETAG=`aws cloudfront get-distribution --id <CLOUDFRONT_DISTRIBUTION_ID> | jq -r .ETag`
然后在update-distribution
中使用它。例如
如果您将配置保存在 config.json
:
aws cloudfront update-distribution --id <CLOUDFRONT_DISTRIBUTION_ID> --distribution-config "file://config.json" --if-match $ETAG > /dev/null
示例 bash 更改来源的脚本:
https://gist.github.com/ahmed-abdelazim/d5aa4dea6ecb5dbbff94ce1f5c1f32ff?fbclid=IwAR1QL1CujiCEyd5cDLoEuocOuXNfstxV9Ev6ndO9IorHVsx0EMroBVnimNg
#!/bin/bash
CLOUDFRONT_DISTRIBUTION_ID=E2C3RNL2F4MRMQ
NEW_ORIGIN="origin2-zaid.s3.us-west-2.amazonaws.com"
ETAG=`aws cloudfront get-distribution --id $CLOUDFRONT_DISTRIBUTION_ID | jq -r .ETag`
aws cloudfront get-distribution --id $CLOUDFRONT_DISTRIBUTION_ID | \
jq --arg NEW_ORIGIN "$NEW_ORIGIN" '.Distribution.DistributionConfig.Origins.Items[0].Id=$NEW_ORIGIN' | \
jq --arg NEW_ORIGIN "$NEW_ORIGIN" '.Distribution.DistributionConfig.Origins.Items[0].DomainName=$NEW_ORIGIN' | \
jq --arg NEW_ORIGIN "$NEW_ORIGIN" '.Distribution.DistributionConfig.DefaultCacheBehavior.TargetOriginId=$NEW_ORIGIN' | \
jq .Distribution.DistributionConfig > config.json
aws cloudfront update-distribution --id $CLOUDFRONT_DISTRIBUTION_ID --distribution-config "file://config.json" --if-match $ETAG > /dev/null
aws cloudfront create-invalidation --distribution-id $CLOUDFRONT_DISTRIBUTION_ID --paths "/*"
rm config.json
我想 edit/update 我的 CloudFront 分配与 awscli。
我正在使用最新的 cli 版本:
aws-cli/1.11.56 Python/2.7.10 Darwin/16.4.0 botocore/1.5.19
要在 awscli 中使用云端功能,您需要将其添加到您的 aws 配置文件中:
[preview]
cloudfront = true
我正在获取要修改的分发配置:
aws cloudfront get-distribution-config --id FOO_BAR_ID > cf_config.json
看起来像预期的那样有效。配置对我来说没问题。现在我正在尝试使用相同的配置重新配置我的 CF 发行版。
aws cloudfront update-distribution --distribution-config file://cf_config.json --id FOO_BAR_ID
我得到:
Parameter validation failed:
Missing required parameter in DistributionConfig: "CallerReference"
Missing required parameter in DistributionConfig: "Origins"
Missing required parameter in DistributionConfig: "DefaultCacheBehavior"
Missing required parameter in DistributionConfig: "Comment"
Missing required parameter in DistributionConfig: "Enabled"
Unknown parameter in DistributionConfig: "ETag", must be one of: CallerReference, Aliases, DefaultRootObject, Origins, DefaultCacheBehavior, CacheBehaviors, CustomErrorResponses, Comment, Logging, PriceClass, Enabled, ViewerCertificate, Restrictions, WebACLId, HttpVersion, IsIPV6Enabled
Unknown parameter in DistributionConfig: "DistributionConfig", must be one of: CallerReference, Aliases, DefaultRootObject, Origins, DefaultCacheBehavior, CacheBehaviors, CustomErrorResponses, Comment, Logging, PriceClass, Enabled, ViewerCertificate, Restrictions, WebACLId, HttpVersion, IsIPV6Enabled
使用 awscli 重新配置 CF 的正确方法是什么?
在与 update-distribution
一起使用之前,您必须编辑 cf_config.json 并删除
{
"ETag": "ETag_Value",
"DistributionConfig":
从文件开头到最后
}
从文件末尾开始。
然后将此命令与从 cf_config.json
id
和 ETag
值一起使用
aws cloudfront update-distribution --distribution-config file://cf_config.json --id FOO_BAR_ID --if-match ETag_Value
@usterk 的回答是正确的,但我又花了 3 个小时才找到我需要的脚本。在此,分享给大家。
我的案例:CI/CD 使用 S3/CloudFront 和手动工件版本控制
我在 S3 中托管一个静态网站 (SSG),我希望它由 CloudFront 提供服务。该网站在其代码(不仅仅是内容)方面得到频繁更新,我想将网站的所有版本存储在 S3 中(就像所有工件或 docker 图像一样)并更新 CloudFront 以指向一个新版本,在新版本被推送到 S3 之后。
我知道 S3 中有“文件版本控制”,但这种保留资产所有版本的老式格式有助于分析资产以及轻松回滚。
我的配置
- 构建资产(JS、CSS 等)后,新文件将上传到 S3 中的文件夹,如
s3://<mybucket-name>/artifacts/<version-id>
- 在 CloudFront 中,我有一个 Distribution
www
网站。www.domain.com
的 Route53 指向它。 - 在那个 Distribution 我有几个 Origins (例如,一个发送
/api
到 ELB 的路径。) - 这里重要的 Origin 是
www
,它的OriginPath
指向/artifacts/<version-id>
。
工作流程
- 在通过 AWS CLI 完成 S3 同步后,我需要更新 CloudFront 的配置,使 www Origin 的 OriginPath 值指向 S3 中的新路径。
- 我还需要在分发上启动失效,以便 CloudFront 在内部(S3 和它之间)获取新文件
任务
正如@usterk 和@BrianLeishman 所指出的,此作业的唯一 CLI 命令是 update-distribution
,其中 per the documentation,需要 ENTIRE CONFIGURATION分配给REPLACE吧。因此,没有命令仅部分更新配置中的一个字段。
要实现这一点,必须首先获取当前的分发配置,然后提取“DistributionConfig”组件,然后更新它所使用的字段,最后,用正确的验证令牌将其放回正确的格式。
请注意,“更新”命令需要的是“获取”返回的内容的“子集”。所以通过jq
解析JSON是不可避免的。
Bash 脚本
我想出的以下脚本适合我:
# 0) You need to set the followings for your case
CLOUDFRONT_DISTRIBUTION_ID="EABCDEF12345ABCD"
NEW_ORIGIN_PATH="/art/0.0.9"
CLOUDFRONT_ORIGIN_ID="E1A2B3C4D5E6F"
DIST_CONFIG_OLD_FILENAME="dist-config.json" # a temp file, which will be removed later
DIST_CONFIG_NEW_FILENAME="dist-config2.json" # a temp file, which will be removed later
# 1) Get the current config, entirely, and put it in a file
aws cloudfront get-distribution --id $CLOUDFRONT_DISTRIBUTION_ID > $DIST_CONFIG_OLD_FILENAME
# 2) Extract the Etag which we need this later for update
Etag=`cat $DIST_CONFIG_OLD_FILENAME | jq '.ETag' | tr -d \"`
# 3) Modify the config as wished, for me I used `jq` extensively to update the "OriginPath" of the desired "originId"
cat $DIST_CONFIG_OLD_FILENAME | jq \
--arg targetOriginId $CLOUDFRONT_ORIGIN_ID \
--arg newOriginPath $NEW_ORIGIN_PATH \
'.Distribution.DistributionConfig | .Origins.Items = (.Origins.Items | map(if (.Id == $targetOriginId) then (.OriginPath = $newOriginPath) else . end))' \
> $DIST_CONFIG_NEW_FILENAME
# 4) Update the distribution with the new file
aws cloudfront update-distribution --id $CLOUDFRONT_DISTRIBUTION_ID \
--distribution-config "file://${DIST_CONFIG_NEW_FILENAME}" \
--if-match $Etag \
> /dev/null
# 5) Invalidate the distribution to pick up the changes
aws cloudfront create-invalidation --distribution-id $CLOUDFRONT_DISTRIBUTION_ID --paths "/*"
# 6) Clean up
rm -f $DIST_CONFIG_OLD_FILENAME $DIST_CONFIG_NEW_FILENAME
最后说明:IAM 访问
执行这些操作的用户需要 IAM 访问 CloudFront 中分配的获取、无效和更新操作。这是规定的政策:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"cloudfront:GetDistribution",
"cloudfront:UpdateDistribution",
"cloudfront:CreateInvalidation"
],
"Resource": "arn:aws:cloudfront::<ACCOUNT_ID>:distribution/<DISTRIBUTION_ID>
}
]
}
aws cloudfront get-distribution-config
生成您无法在 update-distribution
中使用的额外信息
所以你只需要从生成的 json 中获取 DistributionConfig
并修改它。
使用 jq
aws cloudfront get-distribution --id <CLOUDFRONT_DISTRIBUTION_ID> | jq .Distribution.DistributionConfig > config.json
您还需要单独的 Etag,您可以通过以下方式获取:
ETAG=`aws cloudfront get-distribution --id <CLOUDFRONT_DISTRIBUTION_ID> | jq -r .ETag`
然后在update-distribution
中使用它。例如
如果您将配置保存在 config.json
:
aws cloudfront update-distribution --id <CLOUDFRONT_DISTRIBUTION_ID> --distribution-config "file://config.json" --if-match $ETAG > /dev/null
示例 bash 更改来源的脚本: https://gist.github.com/ahmed-abdelazim/d5aa4dea6ecb5dbbff94ce1f5c1f32ff?fbclid=IwAR1QL1CujiCEyd5cDLoEuocOuXNfstxV9Ev6ndO9IorHVsx0EMroBVnimNg
#!/bin/bash
CLOUDFRONT_DISTRIBUTION_ID=E2C3RNL2F4MRMQ
NEW_ORIGIN="origin2-zaid.s3.us-west-2.amazonaws.com"
ETAG=`aws cloudfront get-distribution --id $CLOUDFRONT_DISTRIBUTION_ID | jq -r .ETag`
aws cloudfront get-distribution --id $CLOUDFRONT_DISTRIBUTION_ID | \
jq --arg NEW_ORIGIN "$NEW_ORIGIN" '.Distribution.DistributionConfig.Origins.Items[0].Id=$NEW_ORIGIN' | \
jq --arg NEW_ORIGIN "$NEW_ORIGIN" '.Distribution.DistributionConfig.Origins.Items[0].DomainName=$NEW_ORIGIN' | \
jq --arg NEW_ORIGIN "$NEW_ORIGIN" '.Distribution.DistributionConfig.DefaultCacheBehavior.TargetOriginId=$NEW_ORIGIN' | \
jq .Distribution.DistributionConfig > config.json
aws cloudfront update-distribution --id $CLOUDFRONT_DISTRIBUTION_ID --distribution-config "file://config.json" --if-match $ETAG > /dev/null
aws cloudfront create-invalidation --distribution-id $CLOUDFRONT_DISTRIBUTION_ID --paths "/*"
rm config.json