11
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

VPCオリジンを使ってCloudFrontとプライベートなALB接続を試すのをTerraformで設定してみた

Last updated at Posted at 2024-12-24

というものが2024年11月に来ました。

で、TerraformのAWS Providerでも、つい最近実装されてこの機能が設定できるようになったので、試してみたいと思います。

※ v5.82.0で追加されました。

細かい仕組みなどはドキュメントをご覧ください。

AWS Providerのドキュメントはこちら。

今回、試してみる構成は

Cloudfront - vpc origin - alb(private subnet)

のような感じになります。

お試しなので最低限の設定しかしていません。ご了承ください。

まず、ロードバランサーを作る

resource "aws_lb" "this" {
  name               = "vpc-origin-test"
  internal           = true
  load_balancer_type = "application"
  security_groups    = [aws_security_group.this.id]
  subnets            = var.subnet_ids
}


resource "aws_security_group" "this" {
  name   = "vpc_origin_test"
  vpc_id = var.vpc_id
}

resource "aws_vpc_security_group_egress_rule" "main" {
  security_group_id = aws_security_group.this.id
  cidr_ipv4         = "10.0.0.0/8"
  from_port         = 1
  ip_protocol       = "tcp"
  to_port           = 65535
}
resource "aws_vpc_security_group_ingress_rule" "main" {
  security_group_id = aws_security_group.this.id
  cidr_ipv4         = "10.0.0.0/8"
  from_port         = 80
  ip_protocol       = "tcp"
  to_port           = 80
}

# セキュリティグループの詳細は後で追記します。

resource "aws_lb_listener" "http" {
  load_balancer_arn = aws_lb.this.arn
  port              = "80"
  protocol          = "HTTP"

  default_action {
    type = "fixed-response"

    fixed_response {
      content_type = "text/plain"
      message_body = "Nekodaisuki!!!"
      status_code  = "200"
    }
  }
}

はい、できました。

image.png

VPCオリジンを作ってみる

CloudFrontディストリビューションのオリジンに紐づけると変更できなくなるんで、3つ作ります。テストのために入れ替えたいんです(と言いつつ2つしか使わなかったけど)。

resource "aws_cloudfront_vpc_origin" "https_only" {
  vpc_origin_endpoint_config {
    name                   = "https_only"
    arn                    = aws_lb.this.arn
    http_port              = 80
    https_port             = 443
    origin_protocol_policy = "https-only"

    origin_ssl_protocols {
      items    = ["TLSv1.2"]
      quantity = 1
    }
  }
}
resource "aws_cloudfront_vpc_origin" "http_and_https" {
  vpc_origin_endpoint_config {
    name                   = "http_and_https"
    arn                    = aws_lb.this.arn
    http_port              = 80
    https_port             = 443
    origin_protocol_policy = "match-viewer"

    origin_ssl_protocols {
      items    = ["TLSv1.2"]
      quantity = 1
    }
  }
}
resource "aws_cloudfront_vpc_origin" "http_only" {
  vpc_origin_endpoint_config {
    name                   = "http_only"
    arn                    = aws_lb.this.arn
    http_port              = 80
    https_port             = 443
    origin_protocol_policy = "http-only"

    origin_ssl_protocols {
      items    = ["TLSv1.2"]
      quantity = 1
    }
  }
}
aws_cloudfront_vpc_origin.https_only: Creation complete after 2m55s [id=vo_DZJH4ZRTpFpCy07MrMXXX3]
aws_cloudfront_vpc_origin.http_only: Creation complete after 2m55s [id=vo_5MYtzqRGd6CGEx9tXXXOIQ]
aws_cloudfront_vpc_origin.http_and_https: Creation complete after 3m15s [id=vo_1sRlzayRVWnEXXXRpbPngX]

完了までそこそこ時間かかります。

CloudFrontを作ってみる

locals {
  origin_id = "example"
}
resource "aws_cloudfront_distribution" "main" {
  #provider = aws.global
  origin {
    domain_name = aws_lb.this.dns_name
    origin_id   = local.origin_id
    vpc_origin_config {
      vpc_origin_id = aws_cloudfront_vpc_origin.http_only.id
    }
  }
  enabled = true
  restrictions {
    geo_restriction {
      restriction_type = "none"
      locations        = []
    }
  }

  default_cache_behavior {
    allowed_methods        = ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"]
    cached_methods         = ["GET", "HEAD"]
    target_origin_id       = local.origin_id
    viewer_protocol_policy = "allow-all"
    forwarded_values {
      query_string = false
      cookies {
        forward = "none"
      }
    }
  }

  viewer_certificate {
    cloudfront_default_certificate = true
  }
}

この時点ではアクセスしてもちゃんとつながりません。

(`-´) < Tue Dec 24 23:47:48 $ curl -I https://d1XXXvzzbg9XXX.cloudfront.net
HTTP/2 504
(snip)

セキュリティグループの設定

多分 VPCオリジンを作った時に自動で作られたSGをごにょっとしてあげる必要があります。

image.png

image.png

data "aws_security_group" "vpc_origin_sg" {
  name = "CloudFront-VPCOrigins-Service-SG"
}
resource "aws_vpc_security_group_ingress_rule" "vpc_origin" {
  security_group_id            = aws_security_group.this.id
  from_port                    = 80
  ip_protocol                  = "tcp"
  to_port                      = 80
  referenced_security_group_id = data.aws_security_group.vpc_origin_sg.id
}

image.png

わーい、表示できたぁぁぁ~~~~!

※ てか、なぜここだけChromeでアクセスした……?!

試すだけならばここまでで終了。

けど、ちょっと疑問があるので試してみる。

CloudFrontからALBへのアクセスをhttpsに出来るのか

以下、ざっと試したてみた結果を貼っておきます。

ALBを別のドメインでアクセスできるようにする。ACMも設定する。

resource "aws_acm_certificate" "cert" {
  domain_name       = var.record_name
  validation_method = "DNS"
  lifecycle {
    create_before_destroy = true
  }
}

data "aws_route53_zone" "cert" {
  name = var.zone_name
}
resource "aws_route53_record" "cert" {
  for_each = {
    for dvo in aws_acm_certificate.cert.domain_validation_options : dvo.domain_name => {
      name   = dvo.resource_record_name
      record = dvo.resource_record_value
      type   = dvo.resource_record_type
    }
  }

  allow_overwrite = true
  name            = each.value.name
  records         = [each.value.record]
  ttl             = 60
  type            = each.value.type
  zone_id         = data.aws_route53_zone.cert.zone_id
}

resource "aws_route53_record" "alb" {
  name = var.record_name
  alias {
    name                   = aws_lb.this.dns_name
    zone_id                = aws_lb.this.zone_id
    evaluate_target_health = false
  }
  type    = "A"
  zone_id = data.aws_route53_zone.cert.zone_id
}

VPCオリジンを、https-onlyのに変更

resource "aws_cloudfront_distribution" "main" {
  origin {
    domain_name = var.record_name
    origin_id   = local.origin_id
    vpc_origin_config {
      vpc_origin_id = aws_cloudfront_vpc_origin.https_only.id
    }
  }
(snip)  

セキュリティグループも443のみ通すように変更

resource "aws_vpc_security_group_ingress_rule" "main" {
  security_group_id = aws_security_group.this.id
  cidr_ipv4         = "10.0.0.0/8"
  from_port         = 443
  ip_protocol       = "tcp"
  to_port           = 443
}
resource "aws_vpc_security_group_ingress_rule" "vpc_origin" {
  security_group_id            = aws_security_group.this.id
  from_port                    = 443
  ip_protocol                  = "tcp"
  to_port                      = 443
  referenced_security_group_id = data.aws_security_group.vpc_origin_sg.id
}

ALBのリスナーも変更

resource "aws_lb_listener" "http" {
  load_balancer_arn = aws_lb.this.arn
  port              = "443"
  protocol          = "HTTPS"
  ssl_policy        = "ELBSecurityPolicy-TLS13-1-2-2021-06"
  certificate_arn   = aws_acm_certificate.cert.arn

  default_action {
    type = "fixed-response"

    fixed_response {
      content_type = "text/plain"
      message_body = "Nekodaisuki!!!"
      status_code  = "200"
    }
  }
}
(`-´) < Thu Dec 26 12:50:45 $ curl https://d3gsoddhvrfXXX.cloudfront.net
Nekodaisuki!!!

よっしゃ……!

image.png

リスナーはHTTPSしかないので、HTTPSで通信できてることがわかるかなと思います。

最後に

作ったリソースは削除しましょう

(`-´) < Wed Dec 25 01:48:43 $ terraform destroy

なお、VPCオリジンの設定全部消しましたが CloudFront-VPCOrigins-Service-SG は残ってました。けど、翌日見たらいなくなっていました。

ENIはすぐ消えてくれてました。

それでは。

後で書き足すかも

エラー集

Terraform 構成コード全部

11
2
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
11
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?