使用 HTTPS 保护内容端点

AWSBeginner
立即练习

介绍

内容端点已经能正常工作,但客户应通过加密连接读取内容,并验证服务器身份。为 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 证书信任、主机名匹配及加密内容访问。

实验概览

概念图:用户端在 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 证书。原生配置已经就绪;下一步证明实际加密请求。执行关联检查。

AWS View 示例检查点:分配具有练习备用名称、ACM 用户端证书及 https-only 策略;预置证书状态为 ISSUED。

验证加密内容与证书检查

本步骤通过可信 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 结果检查。

Terminal 示例检查点:故意指定错误验证主机名导致 hostname mismatch,而预置 SNI 名称选择了练习证书。

AWS View 示例检查点:最近实际 HTTPS 页面请求返回 HTTP 200;先前明文访问已被拒绝。

只删除自己的分发资源

本步骤先禁用并删除分配,再删除 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 请求不能证明资源已删除。

AWS View 示例检查点:单元分配及证书已经删除,仅参照对象保留;历史请求事件仍可见。

总结

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