介绍
内容端点已经能正常工作,但客户应通过加密连接读取内容,并验证服务器身份。为 CloudFront 备用域名关联预置 ACM 证书,要求 HTTPS,再测试实际页面、证书信任和名称匹配。
请先完成私有 S3 分发实验。本独立 VM 提供新的私有源站连接、为 content.labex-n04.test 导入的练习证书,以及公开信任锚文件 practice-ca.pem。证书尚未关联到分配。在上方 AWS View 观察证书和分配状态,在下方 Terminal 执行命令。无需个人 AWS 账户或购买域名。
练习证书由预置的私有证书颁发机构签名。只在单条命令中信任其公开 CA 文件,不修改 VM 的系统信任存储。公开 CloudFront 网站需要受公开信任的证书。本实验练习关联和真实 TLS 检查,不涉及公开域名注册或证书签发。
认证考点
| 认证 | 考试任务 | 实践内容 |
|---|---|---|
| Cloud Practitioner (CLF-C02) | 任务 2.2 | 通过 HTTPS 识别传输中加密,并将其与私有源站访问策略区分。 |
| Solutions Architect – Associate (SAA-C03) | 任务 1.3 | 关联 ACM 证书,验证 TLS 证书信任、主机名匹配及加密内容访问。 |
实验概览

关联证书并要求 HTTPS
本步骤将预置证书和备用名称连接到分配,要求用户端通过加密连接请求内容。
TLS 加密网络连接,让客户端验证服务器身份。服务器证书包含名称和公钥,由证书颁发机构 CA 签名。ACM(AWS Certificate Manager)管理 AWS 服务使用的证书。ACM 中存在证书并不意味着证书已自动关联到分配。
找到预置资源。$(...) 将命令输出存入 Shell 变量;--query 选择匹配资源,--output text 让 ID 可用作参数。保持 Terminal 打开:
cd /home/labex/project
HOST_NAME=content.labex-n04.test
DIST_ID=$(aws cloudfront list-distributions \
--query "DistributionList.Items[?Comment=='labex-n04:private-content'].Id | [0]" \
--output text)
CERT_ARN=$(aws acm list-certificates \
--query "CertificateSummaryList[?DomainName=='content.labex-n04.test'].CertificateArn | [0]" \
--output text)
aws acm describe-certificate \
--certificate-arn "$CERT_ARN" \
--query 'Certificate.{Name:DomainName,Names:SubjectAlternativeNames,Status:Status}'
预期状态为 ISSUED,Names 中包含练习名称。证书 ARN 标识其账户和区域。CloudFront 的 ACM 用户端证书必须位于 us-east-1;预置 ARN 使用该区域。证书必须覆盖关联的备用域名。
读取当前分配配置及其 ETag,这是更新所需的版本令牌。> 将输出保存到文件:
aws cloudfront get-distribution-config \
--id "$DIST_ID" \
--query DistributionConfig > current-config.json
ETAG=$(aws cloudfront get-distribution-config \
--id "$DIST_ID" \
--query ETag \
--output text)
备用域名(alias)让分配识别你的内容名称。SNI(Server Name Indication)在 TLS 建立时发送该名称,让服务器选择证书。用户端协议策略控制 HTTP 与 HTTPS 请求,与 S3 源站权限分开。
jq 编辑 JSON 并保留其他源站和分配设置。--arg 将捕获的值作为 JSON 字符串提供。引号内 jq 表达式中的 | 依次执行三个修改:备用名称、自定义证书设置和 https-only 用户端访问。所选安全策略要求 TLS 1.2 或更高版本:
jq --arg host "$HOST_NAME" --arg cert "$CERT_ARN" '.Aliases = {Quantity: 1, Items: [$host]} |
.ViewerCertificate = {CloudFrontDefaultCertificate: false,
ACMCertificateArn: $cert, SSLSupportMethod: "sni-only",
MinimumProtocolVersion: "TLSv1.2_2021"} |
.DefaultCacheBehavior.ViewerProtocolPolicy = "https-only"' current-config.json > https-config.json
aws cloudfront update-distribution \
--id "$DIST_ID" \
--if-match "$ETAG" \
--distribution-config file://https-config.json
aws cloudfront wait distribution-deployed \
--id "$DIST_ID"
测试连接前查看已保存的设置:
aws cloudfront get-distribution-config \
--id "$DIST_ID" \
--query 'DistributionConfig.{Names:Aliases.Items,Certificate:ViewerCertificate.ACMCertificateArn,Protocol:DefaultCacheBehavior.ViewerProtocolPolicy}'
预期显示精确练习名称、你的证书 ARN 和 https-only。AWS View 显示备用名称和关联的 ACM 证书。原生配置已经就绪;下一步证明实际加密请求。执行关联检查。

验证加密内容与证书检查
本步骤通过可信 HTTPS 读取页面,观察明文访问被拒绝,并区分证书信任与主机名匹配。
curl --cacert practice-ca.pem 只为当前命令信任预置公开 CA。--resolve 将精确练习名称和端口连接到本 VM,同时保留该名称用于 SNI 和证书验证。它不会注册公开域名或修改系统 DNS。预置 HTTPS 用户端使用端口 8443:
curl --fail --include --noproxy '*' --cacert practice-ca.pem --resolve "${HOST_NAME}:8443:127.0.0.1" "https://${HOST_NAME}:8443/index.html"
预期 HTTP 200 和 Release one。客户端建立了真实 TLS 连接,验证证书的受信任颁发者及名称,并收到实际 S3 页面。该成功证明的不只是已保存的证书 ARN。
测试明文用户端和匿名直接源站访问:
curl --noproxy '*' --output /dev/null --resolve "${HOST_NAME}:8082:127.0.0.1" --write-out 'Plaintext viewer: HTTP %{http_code}\n' "http://${HOST_NAME}:8082/index.html"
curl --noproxy '*' --output /dev/null --write-out 'Anonymous origin: HTTP %{http_code}\n' http://127.0.0.1:5000/labex-n04-content/index.html
两者必须都返回 HTTP 403。要求用户端 HTTPS 不会使 S3 桶公开;这是两项独立保护。
现在省略练习 CA 文件,测试信任。以下命令预期失败:
curl --fail --noproxy '*' --resolve "${HOST_NAME}:8443:127.0.0.1" "https://${HOST_NAME}:8443/index.html"
预期证书验证错误,通常为 curl 错误 60:默认信任存储不信任此私有练习 CA。遇到预期失败后继续。成功请求选择了正确的信任锚;关闭证书验证会移除正在练习的保护。
openssl s_client 可以分别指定用于 SNI 选择的名称和需要验证的名称。发送正确 SNI 名称、信任练习 CA,但故意要求验证错误主机名。-verify_return_error 在验证失败时停止,< /dev/null 避免交互输入:
openssl s_client -connect 127.0.0.1:8443 -servername "$HOST_NAME" -CAfile practice-ca.pem -verify_hostname wrong.labex-n04.test -verify_return_error < /dev/null
预期 hostname mismatch 和验证失败。信任颁发者还不够,证书也必须覆盖请求的身份。AWS View 保留真实加密请求结果和明文拒绝记录。执行 HTTPS 结果检查。


只删除自己的分发资源
本步骤先禁用并删除分配,再删除 OAC、S3 内容及预置单元证书。保持参照桶不变。
CloudFront 用 ETag 作为配置变更的版本令牌。获取当前配置及 ETag,不要猜测令牌。先捕获与源站连接的精确 OAC:
OAC_ID=$(aws cloudfront get-distribution-config \
--id "$DIST_ID" \
--query 'DistributionConfig.Origins.Items[0].OriginAccessControlId' \
--output text)
保存配置并获取 ETag:
aws cloudfront get-distribution-config \
--id "$DIST_ID" \
--query DistributionConfig \
--output json > distribution-current.json
DIST_ETAG=$(aws cloudfront get-distribution-config \
--id "$DIST_ID" \
--query ETag \
--output text)
在本实验当前配置中,分配的 Enabled 是唯一值为 true 的同名属性。以下标准 sed 替换生成禁用副本,同时保留源站设置:
sed 's/"Enabled": true/"Enabled": false/' distribution-current.json > distribution-disabled.json
aws cloudfront update-distribution \
--id "$DIST_ID" \
--if-match "$DIST_ETAG" \
--distribution-config file://distribution-disabled.json
等待禁用配置部署完成。AWS 配置传播可能需要时间,本实验不测量全球部署延迟:
aws cloudfront wait distribution-deployed \
--id "$DIST_ID"
更新会改变 ETag。删除已禁用分配前读取最新令牌:
DIST_ETAG=$(aws cloudfront get-distribution-config \
--id "$DIST_ID" \
--query ETag \
--output text)
aws cloudfront delete-distribution \
--id "$DIST_ID" \
--if-match "$DIST_ETAG"
用 OAC 自己的 ETag 删除它。分配 ID 和 OAC ID 指向不同资源:
OAC_ETAG=$(aws cloudfront get-origin-access-control \
--id "$OAC_ID" \
--query ETag \
--output text)
aws cloudfront delete-origin-access-control \
--id "$OAC_ID" \
--if-match "$OAC_ETAG"
只删除本实验的内容对象和桶:
aws s3api delete-object \
--bucket labex-n04-content \
--key index.html
aws s3api delete-bucket \
--bucket labex-n04-content
aws s3api list-buckets \
--query 'Buckets[].Name'
分配删除后,使用先前选择的 ARN 只删除预置单元证书。这会移除 ACM 资源;公开练习 CA 文件作为无关本地素材可以保留:
aws acm delete-certificate \
--certificate-arn "$CERT_ARN"
aws acm list-certificates \
--query 'CertificateSummaryList[].CertificateArn'
预期无单元证书,参照桶保留,内容桶不存在。AWS View 应显示无内容分配,且只有参照对象。执行清理检查。失败的 API 请求不能证明资源已删除。

总结
你为 CloudFront 关联 ACM 证书和备用域名,要求 HTTPS,并通过经过验证的 TLS 连接读取实际内容。你区分了受信任颁发者、匹配的主机名、用户端加密和私有源站访问。明文请求被拒绝,不受信任颁发者及错误名称检查失败。你只删除自己的分发资源和单元证书,保留无关参照。



