3重の鍵付きリレー配送で理解する
エンドツーエンド暗号化は、大切な荷物を3つの異なる鍵付き車両でリレー配送するようなものです
たとえ話:機密書類のリレー配送
あなたが「機密書類」を遠くの金庫室に届けたいとします。
途中で3つの配送区間があり、各区間で別々の鍵付き配送車に乗り換えます。
どの区間でも鍵がかかっているから、途中で誰かが覗き見することはできません。
これがエンドツーエンド暗号化の考え方です!
途中で3つの配送区間があり、各区間で別々の鍵付き配送車に乗り換えます。
どの区間でも鍵がかかっているから、途中で誰かが覗き見することはできません。
これがエンドツーエンド暗号化の考え方です!
| リレー配送のたとえ | AWSでの対応 | ポイント |
|---|---|---|
| 機密書類(荷物) | ユーザーのリクエスト・レスポンスデータ | 守りたい対象 |
| 第1配送車(公道を走る) | ユーザー → CloudFront 間の通信 | インターネット上で最も危険な区間 |
| 第2配送車(専用道路を走る) | CloudFront → ALB 間の通信 | AWS内部だが油断禁物 |
| 第3配送車(施設内を走る) | ALB → EC2 間の通信 | VPC内部でも暗号化が必要 |
| 各車の鍵 | 各区間のSSL/TLS証明書 | 区間ごとに異なる鍵(証明書)が必要 |
| 配送会社の身分証明 | ACM(AWS Certificate Manager) | CloudFrontとALBの鍵は ACMで無料発行できる |
| 自前で作る特殊な鍵 | サードパーティ証明書(EC2用) | EC2にはACMが使えないため 自分で証明書を用意する |
アーキテクチャ全体図
3つの区間すべてがHTTPSで暗号化された通信経路
各区間の詳細
ユーザー ↔ CloudFront
インターネット上の公開区間 ― 最も攻撃リスクが高い
必要な証明書
カスタムドメイン(例:service.example.com)用のパブリック証明書が必要です。
- ACMで発行(推奨)― 無料で自動更新
- 外部CAから取得してACMにインポートも可能
設定のポイント
- CloudFrontディストリビューションに証明書を関連付け
- ビューワープロトコルポリシーを「Redirect HTTP to HTTPS」に設定
- TLS 1.2以上を推奨(セキュリティポリシーで指定)
たとえ話でいうと:公道を走る第1配送車の鍵です。公道は誰でも通れるため、最も厳重な鍵(パブリック証明書)が必要です。ACMを使えば鍵の自動更新もしてくれます。
CloudFront ↔ ALB
AWSバックボーンネットワーク ― AWS内部でも暗号化が必須
必要な証明書
ALBのドメイン(例:service-alb.example.com)用の証明書が必要です。
- ACMで発行(推奨)
- ALBのHTTPSリスナー(443)にアタッチ
設定のポイント
- CloudFrontのオリジンプロトコルを「HTTPS Only」に設定
- ALBのHTTPリスナー(80番ポート)を削除
- オリジンのSSLプロトコルにTLS 1.2を指定
よくあるミス:ALBにHTTPリスナー(80番ポート)を残したまま運用すると、CloudFront経由以外のHTTP通信が可能になり、暗号化が不完全になります。必ず削除しましょう。
ALB ↔ EC2
VPC内部 ― 見落とされがちだが暗号化が必要
必要な証明書
EC2インスタンスにサードパーティの証明書をインストールする必要があります。
- ACM証明書はEC2に直接使用不可
- Let's Encryptや有料CAから取得
- Nginx/Apache等のWebサーバーに設定
設定のポイント
- ターゲットグループのプロトコルをHTTPSに設定
- ターゲットグループのポートを443に設定
- Auto Scaling Groupをこのターゲットグループにアタッチ
たとえ話でいうと:施設内を走る第3配送車の鍵です。施設内(VPC)は関係者しかいませんが、万が一に備えて専用の鍵(サードパーティ証明書)を用意します。配送会社の共通鍵(ACM)は使えないため、自前で用意する必要があります。
証明書の比較表
3つの区間で使用する証明書の違いを一覧で確認
| 項目 | 区間① User↔CF | 区間② CF↔ALB | 区間③ ALB↔EC2 |
|---|---|---|---|
| 対象ドメイン | service.example.com | service-alb.example.com | EC2内部ドメイン |
| ACM利用 | 利用可能 | 利用可能 | 利用不可 |
| 証明書の種類 | ACMパブリック証明書 or 外部CA証明書 |
ACM証明書 | サードパーティ証明書 (Let's Encrypt等) |
| 設定場所 | CloudFront ディストリビューション |
ALB HTTPSリスナー |
EC2インスタンス (Nginx/Apache等) |
| 自動更新 | ACMで自動 | ACMで自動 | 手動管理 |
| リスクレベル | 高(インターネット) | 中(AWSバックボーン) | 低(VPC内部) |
実装コード例
CloudFormation / AWS CLI / Terraform での設定例
# エンドツーエンド暗号化のCloudFormation設定 Resources: # ① ACM証明書(CloudFront用 - us-east-1必須) CloudFrontCertificate: Type: AWS::CertificateManager::Certificate Properties: DomainName: service.example.com ValidationMethod: DNS # ② ACM証明書(ALB用) ALBCertificate: Type: AWS::CertificateManager::Certificate Properties: DomainName: service-alb.example.com ValidationMethod: DNS # ALB - HTTPSリスナーのみ(HTTPリスナーなし) ALBHTTPSListener: Type: AWS::ElasticLoadBalancingV2::Listener Properties: LoadBalancerArn: !Ref ALB Port: 443 Protocol: HTTPS SslPolicy: ELBSecurityPolicy-TLS13-1-2-2021-06 Certificates: - CertificateArn: !Ref ALBCertificate DefaultActions: - Type: forward TargetGroupArn: !Ref HTTPSTargetGroup # ③ ターゲットグループ(HTTPS - EC2への暗号化通信) HTTPSTargetGroup: Type: AWS::ElasticLoadBalancingV2::TargetGroup Properties: Protocol: HTTPS Port: 443 VpcId: !Ref VPC HealthCheckProtocol: HTTPS HealthCheckPath: /health # CloudFrontディストリビューション Distribution: Type: AWS::CloudFront::Distribution Properties: DistributionConfig: ViewerCertificate: AcmCertificateArn: !Ref CloudFrontCertificate SslSupportMethod: sni-only MinimumProtocolVersion: TLSv1.2_2021 Origins: - DomainName: service-alb.example.com CustomOriginConfig: OriginProtocolPolicy: https-only OriginSSLProtocols: - TLSv1.2 DefaultCacheBehavior: ViewerProtocolPolicy: redirect-to-https
# ① ACM証明書の発行(CloudFront用 - us-east-1) aws acm request-certificate \ --domain-name "service.example.com" \ --validation-method DNS \ --region us-east-1 # ② ACM証明書の発行(ALB用 - ALBのリージョン) aws acm request-certificate \ --domain-name "service-alb.example.com" \ --validation-method DNS \ --region ap-northeast-1 # ALBのHTTPSリスナーを作成 aws elbv2 create-listener \ --load-balancer-arn "arn:aws:elasticloadbalancing:..." \ --protocol HTTPS \ --port 443 \ --ssl-policy "ELBSecurityPolicy-TLS13-1-2-2021-06" \ --certificates "CertificateArn=arn:aws:acm:..." \ --default-actions "Type=forward,TargetGroupArn=arn:..." # ⚠️ HTTPリスナー(80)があれば削除 aws elbv2 delete-listener \ --listener-arn "arn:aws:elasticloadbalancing:...:listener/..." # ③ ターゲットグループをHTTPSに設定 aws elbv2 create-target-group \ --name "e2e-https-tg" \ --protocol HTTPS \ --port 443 \ --vpc-id "vpc-xxxxxxxx" \ --health-check-protocol HTTPS
# ① ACM証明書(CloudFront用 - us-east-1) resource "aws_acm_certificate" "cloudfront" { provider = aws.us_east_1 domain_name = "service.example.com" validation_method = "DNS" } # ② ACM証明書(ALB用) resource "aws_acm_certificate" "alb" { domain_name = "service-alb.example.com" validation_method = "DNS" } # ALB HTTPSリスナー(HTTPリスナーは作成しない) resource "aws_lb_listener" "https" { load_balancer_arn = aws_lb.main.arn port = 443 protocol = "HTTPS" ssl_policy = "ELBSecurityPolicy-TLS13-1-2-2021-06" certificate_arn = aws_acm_certificate.alb.arn default_action { type = "forward" target_group_arn = aws_lb_target_group.https.arn } } # ③ ターゲットグループ(HTTPS - EC2への暗号化) resource "aws_lb_target_group" "https" { name = "e2e-https-tg" port = 443 protocol = "HTTPS" vpc_id = aws_vpc.main.id health_check { protocol = "HTTPS" path = "/health" } } # CloudFrontディストリビューション resource "aws_cloudfront_distribution" "main" { origin { domain_name = "service-alb.example.com" custom_origin_config { origin_protocol_policy = "https-only" origin_ssl_protocols = ["TLSv1.2"] } } viewer_certificate { acm_certificate_arn = aws_acm_certificate.cloudfront.arn ssl_support_method = "sni-only" minimum_protocol_version = "TLSv1.2_2021" } default_cache_behavior { viewer_protocol_policy = "redirect-to-https" } }
ベストプラクティス
TLS 1.2以上を強制
CloudFront・ALBともにTLS 1.2以上のセキュリティポリシーを設定し、古いプロトコルを無効化しましょう。
HTTPリスナーの完全排除
ALBのHTTPリスナー(80番ポート)を削除して、暗号化されていない通信経路を完全に塞ぎましょう。
証明書の自動更新
ACM証明書は自動更新されますが、EC2のサードパーティ証明書は手動管理です。certbot等で自動化を検討しましょう。
CloudFront用ACMはus-east-1
CloudFrontに関連付けるACM証明書は、必ずus-east-1(バージニア北部)で発行する必要があります。
よくある質問(FAQ)
ACMはAWSのマネージドサービス(CloudFront、ALB、API Gateway等)に証明書を提供するための仕組みです。ACMの秘密鍵はAWSが管理しており、外部にエクスポートできません。EC2インスタンスは自分でWebサーバー(Nginx、Apache等)を管理するため、秘密鍵にアクセスできるサードパーティの証明書が必要になります。
はい、必要です。AWSバックボーンネットワークは安全性が高いですが、コンプライアンス要件(PCI DSS、HIPAA等)やゼロトラストセキュリティの観点から、すべての通信を暗号化することが推奨されています。「信頼できる内部ネットワーク」という考え方自体がセキュリティリスクになりえます。
エンドツーエンド暗号化の観点からは推奨されません。CloudFrontのオリジンとしてALBを使う場合、CloudFront側でHTTPS Onlyを設定すれば、ALB側のHTTPリスナーは不要です。HTTPリスナーを残すと、CloudFrontを迂回した直接アクセスが暗号化されないリスクがあります。
いくつかのアプローチがあります。Let's Encryptとcertbotを使えば無料で自動更新が可能です。また、AWS Systems Manager(SSM)を使って証明書の配布・更新を自動化する方法もあります。さらに、EC2の代わりにECS/Fargateを使えば、ALBとの間はAWS内部通信となり、証明書管理が簡素化されます。
NLBにはTLSリスナーを設定できますが、NLBはL4(トランスポート層)で動作するため、TLSターミネーションを行わずにパススルーすることも可能です。パススルーの場合、EC2で直接TLS終端を行うため、EC2にサードパーティ証明書が必要です。ALBと同じくACM証明書をNLBのTLSリスナーにアタッチすることもできます。
まとめ
区間①
User ↔ CloudFront
User ↔ CloudFront
ACMパブリック証明書で
インターネット通信を暗号化
インターネット通信を暗号化
区間②
CloudFront ↔ ALB
CloudFront ↔ ALB
ACM証明書+HTTPS Only設定
HTTPリスナーは削除
HTTPリスナーは削除
区間③
ALB ↔ EC2
ALB ↔ EC2
サードパーティ証明書を
EC2にインストール
EC2にインストール
試験対策ポイント(ANS-C01 / SAP)
試験では「エンドツーエンド暗号化を実現する構成」を問う問題が頻出します。特に以下の点を押さえましょう:
ACM証明書がEC2に直接使えないこと、CloudFront用のACM証明書はus-east-1で発行が必要なこと、ALBのHTTPリスナーを削除してHTTPS Onlyにする必要があること、ターゲットグループのプロトコルをHTTPSに設定する必要があること。これらが選択肢の引っかけポイントになります。