はじめに
エンドポイントは動作していますが、利用者はサーバーの身元を検証する暗号化接続で内容を読むべきです。用意された ACM 証明書を CloudFront の代替ドメイン名に関連付け、HTTPS を必須にし、実際のページと証明書の信頼・名前をテストします。
先に非公開 S3 配信ラボを完了してください。この独立 VM には新しい非公開オリジン接続、content.labex-n04.test 用のインポート済み証明書、公開の信頼アンカー practice-ca.pem が用意されています。証明書はまだディストリビューションに関連付けられていません。上部の AWS View で状態を確認し、下部の Terminal を使います。個人の AWS アカウントや購入したドメインは不要です。
練習証明書は用意されたプライベート認証局が署名しています。公開 CA ファイルを単一コマンドで信頼し、システムの信頼ストアは変更しません。公開 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 に証明書があっても、自動的にディストリビューションへ関連付けられるわけではありません。
用意されたリソースを特定します。$(...) は出力をシェル変数へ保存し、--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 を読みます。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 文字列として渡します。引用符内の | は、代替名、カスタム証明書、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 の失敗は削除の証拠になりません。

まとめ
ACM 証明書と代替名を CloudFront に関連付け、HTTPS を必須にし、検証済み TLS で実際の内容を読みました。発行者の信頼、ホスト名一致、ビューアー暗号化、非公開オリジンアクセスを区別しました。平文は拒否され、信頼されない発行者や誤った名前の検証は失敗しました。自分の配信リソースと単元証明書だけを削除し、無関係な参照を維持しました。



