0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

TerraformでALBをオリジンとするCloudFront構築

Last updated at Posted at 2025-03-23

はじめに

Terraformを使用して、ALBをオリジンにCloudFrontで配信するWebサーバを構築してみました。
前回ALBまで作成したので今回はALBの変更、CloudFrontディストリビューション、Route53ホストゾーンの作成となります。

※今回の構成では、CloudFrontのIPは不確定でALBのSGではCloudFrontに限定したインバウンドアクセス制御ができないため、ALBへのアクセス制限はない状態です。
※ALBに直接アクセスさせないためにはHostヘッダーの制限をCloudFrontのWhitelistとALBリスナールールで行う必要があります。

構成

ネットワーク構成図.png

ALBリスナーとSGの修正

  • HTTPリスナーのデフォルトアクションの変更(forward→redirect)
  • HTTPSリスナーの追加
    ※リスナーで競合エラーが出たら、HTTPリスナーを一度削除してからもう再度追加したらいけます
  • SGインバウンドルール追加(HTTPS)
resource "aws_lb" "alb" {
  name               = "MyLoadBalancer"
  internal           = false
  load_balancer_type = "application"
  security_groups    = [aws_security_group.alb_sg.id]
  subnets            = [
    aws_subnet.public1.id,
    aws_subnet.public2.id
  ]
  enable_deletion_protection = false
} 

# HTTPSリスナーでターゲットグループに転送
resource "aws_lb_listener" "https_listner" {
  load_balancer_arn = aws_lb.alb.arn
  port              = "443"
  protocol          = "HTTPS"
  ssl_policy = "ELBSecurityPolicy-TLS-1-2-2017-01"
  certificate_arn = "arn:aws:acm:ap-northeast-1:xxxxxxxxxxxx:certificate/b7f2c39b-71e8-4bb3-8595-8a0cfe3738da" # ALBリージョンの証明書

  default_action {
    type = "forward"
    target_group_arn = aws_lb_target_group.lb_tg.arn
  }
}

# HTTPリスナーでHTTPSにリダイレクト
resource "aws_lb_listener" "http_listner" {
  load_balancer_arn = aws_lb.alb.arn
  port              = "80"
  protocol          = "HTTP"

  default_action {
    type             = "redirect"
    redirect {
      protocol = "HTTPS"
      port     = "443"
      status_code = "HTTP_301"
    }
  }
}

resource "aws_lb_target_group" "lb_tg" {
  name = "test-lb-tg"
  port = 80
  protocol = "HTTP"
  vpc_id = aws_vpc.main.id

  health_check {
    path = "/health"
  }
}

resource "aws_lb_target_group_attachment" "instance1" {
  target_group_arn = aws_lb_target_group.lb_tg.arn
  target_id = aws_instance.instance1.id
  port = 80
}

resource "aws_lb_target_group_attachment" "instance2" {
  target_group_arn = aws_lb_target_group.lb_tg.arn
  target_id = aws_instance.instance2.id
  port = 80
}

resource "aws_security_group" "alb_sg" {
  name = "alb-sg"
  description = "Allow HTTP and SSH"
  vpc_id = aws_vpc.main.id
  
  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"] 
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

CloudFrontディストリビューション

  • オリジン:ALB
  • プロトコルポリシー:HTTPS ONLY
  • キャッシュ:テスト目的のため無効化
  • プロトコルポリシー:Redirect HTTP to HTTPS
  • 代替ドメイン:example.com
  • 証明書:us-east-1で発行した証明書
  • 地理的制限:なし
resource "aws_cloudfront_distribution" "test_cf" {
  origin {
    domain_name = aws_lb.alb.dns_name
    origin_id   = aws_lb.alb.dns_name
    custom_origin_config {
      origin_protocol_policy    = "https-only"
      https_port                = 443
      http_port                 = 80 
      origin_ssl_protocols      = ["TLSv1.2"]
    }
  }

  default_cache_behavior {
    allowed_methods  = ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"]
    cached_methods   = ["GET", "HEAD"]
    cache_policy_id  = "4135ea2d-6df8-44a3-9df3-4b5a84be39ad" # Caching Disabled
    origin_request_policy_id = "216adef6-5c7f-47e4-b989-5492eafa07d3" # All Viewer
    target_origin_id = aws_lb.alb.dns_name
    viewer_protocol_policy = "redirect-to-https"
  }

  enabled = true # ディストリビューションがリクエストを受け付ける

  price_class = "PriceClass_200" # 北米、ヨーロッパ、アジアのエッジロケーションのみ使用

  aliases = ["example.com"]
  viewer_certificate {
    acm_certificate_arn = "arn:aws:acm:us-east-1:xxxxxxxxxxxx:certificate/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" # us-east-1の証明書
    ssl_support_method = "sni-only"
    minimum_protocol_version = "TLSv1.2_2021"
  }

  restrictions {
    geo_restriction {
      restriction_type = "none"
    }
  }
}

Route53

  • シンプルルーティング
  • ホストゾーンを作成してAレコードを追加
  • エイリアス:CloudFrontのDNS名
resource "aws_route53_zone" "test_zone" {
  name = "example.com"
}

resource "aws_route53_record" "test_record" {
  zone_id = aws_route53_zone.test_zone.id
  name    = "example.com"
  type    = "A"
  alias {
    name                   = aws_cloudfront_distribution.test_cf.domain_name
    zone_id                = aws_cloudfront_distribution.test_cf.hosted_zone_id
    evaluate_target_health = false
  }
}

確認

ALB

202503023_000001.JPG

リクエスト処理

$ curl -I  https://example.com
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 615
Connection: keep-alive
Date: Sun, 23 Mar 2025 07:49:39 GMT
Accept-Ranges: bytes
Server: nginx/1.22.1 
Last-Modified: Tue, 27 Aug 2024 13:55:08 GMT
ETag: "66cddabc-267"
X-Cache: Miss from cloudfront # リクエストがオリジンに送信されている
Via: 1.1 ccec8f7c8547a994f6578dd30ad7acce.cloudfront.net (CloudFront) # CloudFrontを経由して処理
X-Amz-Cf-Pop: NRT57-P6
X-Amz-Cf-Id: jBOQzTgmJg-WR5HPrRle_fXzuhwa0rRsrU0og1Su6zsB3D8cIY23Bw==

202503023_000000.JPG

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?