5
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

S3 静的WebサイトホスティングのHTTPS化/プライベート化 + PrivateLinkのResorceGW対応をTerraformでやってみた

Last updated at Posted at 2025-06-27

こんにちは!
記事をご覧頂きありがとうございます。

突然ですが、S3の静的Webサイトホスティング機能ありますよね。
この機能自体は使われている方も多いと思いますが、HTTPSに対応しておらず困ったというネットの記事をよく見ます。
image.png

この解決策としては、AWSの公式でも紹介されているのが、前段にCloudFrontを立てる方法です。
image.png

ですが、CloudFrontたてずに実現したいというケースもあると思います。
例えば、以下のような理由です。

  • 前段にAkamaiがいてCDNを2つも立てたくない
  • リソースの種類を増やして運用の手間を増やしたくない
  • CloudFrontをあまり使ったことがないから、よく分からない

また、プライベート環境で静的Webサイトホスティングを利用したいけど対応していなくて困ったという記事もよく見ます。
image.png

私もここ1-2年で、CloudFrontをたてずに静的Webサイトホスティング機能をHTTPSで使いたい、プライベート環境で静的Webサイトホスティング機能を使いたいといったプロジェクトに複数回遭遇しました。

そんな中、ちょうどこれらの要件を合わせた、プライベート環境で静的WebサイトホスティングをHTTPS化するという案件に携わりましたので、ご紹介していきたいと思います。

はじめに

今回ご紹介する構成ですが、直近で構築した構成がプライベート化+HTTPS化だけでなく、静的WebサイトをPrivateLinkで提供したパターンだったので、PrivateLinkでの提供も含めてご紹介します。

実際にとった構成は下図の通りです。
image.png

今回は必要最低限の構成でかつ、動作確認がしやすい下図の構成で作成していきます。
image.png

「もっとシンプルな構成で手っ取り早く画面での構築方法が知りたい!」という方は、AWSのブログに構築方法が記載されておりますので、以下のリンクからご確認下さい。

環境構築

今回はコードで環境を構築したのですが、それにあたり以下のどのコードを使うか迷いました。

  1. CloudFormation
  2. CDK
  3. Terraform

実際のプロジェクトでは、CDKもしくはTerraformを使っており、直近に作ったのがTerraformだったので、今回はTerraformを採用しました。

また、今さらですが生成AIにコードを作ってもらおうと思い、上記で載せた図をChatGPTに渡して、Terraformのコードを作ってもらいました。
image.png

当然、一次出力では思うように作ってもらえなかったので、何度かChatGPTに修正をしてもらいました。また、どうしてもうまくいかない部分は手で修正しております。

上記候補に挙げたTerraform以外のコードも載せて!などありましたら、是非コメントして下さい。同じようにChatGPTを使いながら、作って載せようと思います。

前提

証明書について

HTTPS用の証明書に関しましては本コード内で触れておりません。
そのため、この記事を参考に環境構築をお試しされる際は事前に準備しておいて頂ければと思います。
因みに、今回は事前に証明書を作成し、ACMにインポートしておきました。

HTMLファイルについて

表示させるHTMLファイルについても本コード内では触れません。
こちらも事前のご準備をお願い致します。
今回は、簡単な文字を返すHTMLファイルを配置しております。

接続先環境の構築

接続先環境ということで、まずはこちらのリソースを作って行きます。
image.png

VPC

VPC1つと、Subnetを3つ作ります。

resource "aws_vpc" "provider_vpc" {
    cidr_block           = "10.1.0.0/16"
    enable_dns_support   = true
    enable_dns_hostnames = true

    tags = {
        Name = "provider-vpc"
    }
}

resource "aws_subnet" "provider_lb_subnet01" {
    vpc_id                  = aws_vpc.provider_vpc.id
    cidr_block              = "10.1.1.0/24"
    availability_zone       = "ap-northeast-1a"
    map_public_ip_on_launch = false

    tags = {
        Name = "provider-lb-subnet01"
    }
}

resource "aws_subnet" "provider_lb_subnet02" {
    vpc_id                  = aws_vpc.provider_vpc.id
    cidr_block              = "10.1.2.0/24"
    availability_zone       = "ap-northeast-1c"
    map_public_ip_on_launch = false

    tags = {
        Name = "provider-lb-subnet02"
    }
}

resource "aws_subnet" "provider_endpoint_subnet01" {
    vpc_id                  = aws_vpc.provider_vpc.id
    cidr_block              = "10.1.3.0/24"
    availability_zone       = "ap-northeast-1a"
    map_public_ip_on_launch = false

    tags = {
        Name = "provider-endpoint-subnet01"
    }
}

Security Group

Security Groupを作ります、今回はNLBにもSecurity Groupを設定するパターンで作成しております。

resource "aws_security_group" "provider_endpoint_sg" {
  name        = "provider-endpoint-sg"
  description = "Allow internal traffic from EC2SG"
  vpc_id      = aws_vpc.provider_vpc.id

  tags = {
    Name = "provider-endpoint-sg"
  }
}

resource "aws_vpc_security_group_ingress_rule" "provider_endpoint_sg_ingress" {
    security_group_id            = aws_security_group.provider_endpoint_sg.id
    referenced_security_group_id = aws_security_group.provider_alb_sg.id
    from_port                    = 443
    to_port                      = 443
    ip_protocol                  = "tcp"
}

resource "aws_vpc_security_group_egress_rule" "provider_endpoint_sg_egress" {
    security_group_id = aws_security_group.provider_endpoint_sg.id
    cidr_ipv4         = "0.0.0.0/0"
    ip_protocol       = "-1"
}

resource "aws_security_group" "provider_nlb_sg" {
  name        = "nlb-sg"
  description = "Allow traffic from ConsumerVPC"
  vpc_id      = aws_vpc.provider_vpc.id

  tags = {
    Name = "alb-sg"
  }
}

resource "aws_vpc_security_group_ingress_rule" "provider_nlb_sg_ingress" {
    security_group_id            = aws_security_group.provider_nlb_sg.id
    cidr_ipv4                    = "${aws_instance.ec2_instance.private_ip}/32"
    from_port                    = 443
    to_port                      = 443
    ip_protocol                  = "tcp"
}

resource "aws_vpc_security_group_egress_rule" "provider_nlb_sg_egress" {
    security_group_id = aws_security_group.provider_nlb_sg.id
    cidr_ipv4         = "0.0.0.0/0"
    ip_protocol       = "-1"
}


resource "aws_security_group" "provider_alb_sg" {
  name        = "alb-sg"
  description = "Allow traffic from NLB"
  vpc_id      = aws_vpc.provider_vpc.id

  tags = {
    Name = "alb-sg"
  }
}

resource "aws_vpc_security_group_ingress_rule" "provider_alb_sg_ingress" {
    security_group_id            = aws_security_group.provider_alb_sg.id
    referenced_security_group_id = aws_security_group.provider_nlb_sg.id
    from_port                    = 443
    to_port                      = 443
    ip_protocol                  = "tcp"
}

resource "aws_vpc_security_group_egress_rule" "provider_alb_sg_egress" {
    security_group_id = aws_security_group.provider_alb_sg.id
    cidr_ipv4         = "0.0.0.0/0"
    ip_protocol       = "-1"
}

VPC Endpoint

続いてS3のVPC Endpointを作ります、通常S3のVPC Endpointは理由がない限りは料金等の関係からGateway型で作成することが多いと思いますが、今回の構成ではTarget Groupに登録するためにInterface型で作成します。

resource "aws_vpc_endpoint" "s3_interface_endpoint" {
    vpc_id              = aws_vpc.provider_vpc.id
    vpc_endpoint_type   = "Interface"
    service_name        = "com.amazonaws.ap-northeast-1.s3"
    subnet_ids          = [aws_subnet.provider_endpoint_subnet01.id]
    security_group_ids  = [aws_security_group.provider_endpoint_sg.id]
    subnet_configuration {
      ipv4      = "10.1.3.5"
      subnet_id = aws_subnet.provider_endpoint_subnet01.id
    }

    tags = {
        Name = "s3-interface-endpoint"
    }
}

S3

次はS3です、S3のバケットポリシーはVPC Endpointからのみアクセス可能なようにしています。また、この構成ですとS3の名前は接続するドメイン名と同じにする必要があります、そのためドメイン名と同じ名前で作成してください。

resource "aws_s3_bucket" "static_site" {
  bucket = "provider-s3.com"

  tags = {
    Name = "provider-s3-static-site"
  }
}

data "aws_iam_policy_document" "allow_access_from_vpcendpoint" {
  statement {
    principals {
      type        = "*"
      identifiers = ["*"]
    }

    actions = [
      "s3:GetObject",
      "s3:ListBucket",
    ]

    resources = [
      aws_s3_bucket.static_site.arn,
      "${aws_s3_bucket.static_site.arn}/*",
    ]

    condition {
      test     = "StringEquals"
      variable = "aws:SourceVpce"

      values = [
        aws_vpc_endpoint.s3_interface_endpoint.id
      ]
    }
  }
}

resource "aws_s3_bucket_policy" "allow_access_from_vpcendpoint" {
  bucket = aws_s3_bucket.static_site.id
  policy = data.aws_iam_policy_document.allow_access_from_vpcendpoint.json
}

LB

NLBとALBを作成しますが、この構成のポイントとなるのがALBです。
リスナールールで静的Webサイトホスティングっぽく動くように工夫していたり、ターゲットグループでVPC EndpointのIPを指定しているので、ヘルスチェックの成功コードがデフォルトと異なっていたりするので、この辺はご注意下さい。

resource "aws_lb" "provider_nlb" {
    name               = "provider-nlb"
    internal           = true
    load_balancer_type = "network"
    security_groups    = [aws_security_group.provider_nlb_sg.id]
    subnets            = [aws_subnet.provider_lb_subnet01.id, aws_subnet.provider_lb_subnet02.id]

    tags = {
        Name = "provider-nlb"
    }
}

resource "aws_lb_target_group" "nlb_tg" {
    name        = "nlb-target-group"
    port        = 443
    protocol    = "TCP"
    vpc_id      = aws_vpc.provider_vpc.id
    target_type = "alb"

    health_check {
        protocol = "HTTPS"
    }
}

resource "aws_lb_target_group_attachment" "nlb_tg_attachment" {
  target_group_arn  = aws_lb_target_group.nlb_tg.arn
  target_id         = aws_lb.provider_alb.arn
  port              = 443
}

resource "aws_lb_listener" "nlb_listener" {
  load_balancer_arn = aws_lb.provider_nlb.arn
  port              = 443
  protocol          = "TCP"
  default_action {
    type             = "forward"
    target_group_arn = aws_lb_target_group.nlb_tg.arn
  }
}

resource "aws_lb" "provider_alb" {
    name               = "provider-alb"
    internal           = true
    load_balancer_type = "application"
    security_groups    = [aws_security_group.provider_alb_sg.id]
    subnets            = [aws_subnet.provider_lb_subnet01.id, aws_subnet.provider_lb_subnet02.id]

    tags = {
      Name = "provider-alb"
    }
}

resource "aws_lb_target_group" "alb_tg" {
    name        = "alb-target-group"
    port        = 443
    protocol    = "HTTPS"
    vpc_id      = aws_vpc.provider_vpc.id
    target_type = "ip"

    health_check {
        protocol = "HTTPS"
        matcher  = "307,405"
    }

    tags = {
      Name = "alb-tg"
    }
}

resource "aws_lb_target_group_attachment" "alb_tg_attachment" {
  target_group_arn  = aws_lb_target_group.alb_tg.arn
  availability_zone = "ap-northeast-1a"
  target_id         = "10.1.3.5"
  port              = 443
}

resource "aws_lb_listener" "alb_listener" {
  load_balancer_arn = aws_lb.provider_alb.arn
  port              = 443
  protocol          = "HTTPS"
  ssl_policy        = "ELBSecurityPolicy-TLS13-1-2-2021-06"
  certificate_arn   = var.certificate

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

resource "aws_lb_listener_rule" "aws_lb_listener_rule" {
  listener_arn = aws_lb_listener.alb_listener.arn
  priority     = 10

  action {
    type = "redirect"

    redirect {
      protocol    = "HTTPS"
      port        = "#{port}"
      host        = "#{host}"
      path        = "/#{path}index.html"
      query       = "#{query}"
      status_code = "HTTP_301"
    }
  }

  condition {
    path_pattern {
      values = ["*/"]
    }
  }
}

VPC Endpoint Service

接続先最後はVPC Endpoint Serviceです、今回はTerraformでの構築なので、承認不要としています。

resource "aws_vpc_endpoint_service" "private_service" {
    acceptance_required        = false
    network_load_balancer_arns = [aws_lb.provider_nlb.arn]

    tags = {
        Name = "private-link-service"
    }
}

接続元環境の構築

続いて接続元環境に入ります、作成するリソースはこちらです。
image.png

VPC

接続元もまずはVPCから作成していきます、接続元はLBがないのでサブネットはシングル構成にしています。

resource "aws_vpc" "consumer_vpc" {
    cidr_block           = "10.0.0.0/16"
    enable_dns_support   = true
    enable_dns_hostnames = true

    tags = {
        Name = "consumer-vpc"
    }
}

resource "aws_subnet" "consumer_ec2_subnet01" {
    vpc_id                  = aws_vpc.consumer_vpc.id
    cidr_block              = "10.0.1.0/24"
    availability_zone       = "ap-northeast-1a"
    map_public_ip_on_launch = false

    tags = {
        Name = "consumer-ec2-subnet01"
    }
}

resource "aws_subnet" "consumer_endpoint_subnet01" {
    vpc_id                  = aws_vpc.consumer_vpc.id
    cidr_block              = "10.0.2.0/24"
    availability_zone       = "ap-northeast-1a"
    map_public_ip_on_launch = false

    tags = {
        Name = "consumer-endpoint-subnet01"
    }
}

Security Group

Security Groupを作成します、Fleet Managerでの接続ですのでEC2のインバウンドは何も許可をしておりません。

resource "aws_security_group" "consumer_ec2_sg" {
    name        = "ec2-sg"
    description = "Allo external traffic"
    vpc_id      = aws_vpc.consumer_vpc.id

    tags = {
        Name = "ec2-sg"
    }
}

resource "aws_vpc_security_group_egress_rule" "consumer_ec2_sg_egress" {
    security_group_id = aws_security_group.consumer_ec2_sg.id
    cidr_ipv4         = "0.0.0.0/0"
    ip_protocol       = "-1"
}

resource "aws_security_group" "consumer_endpoint_sg" {
    name        = "consumer-endpoint-sg"
    description = "Allow internal traffic from EC2SG"
    vpc_id      = aws_vpc.consumer_vpc.id

    tags = {
        Name = "consumer-endpoint-sg"
    }
}

resource "aws_vpc_security_group_ingress_rule" "consumer_endpoint_sg_ingress" {
    security_group_id            = aws_security_group.consumer_endpoint_sg.id
    referenced_security_group_id = aws_security_group.consumer_ec2_sg.id
    from_port                    = 443
    to_port                      = 443
    ip_protocol                  = "tcp"
}

resource "aws_vpc_security_group_egress_rule" "consumer_endpoint_sg_egress" {
    security_group_id = aws_security_group.consumer_endpoint_sg.id
    cidr_ipv4         = "0.0.0.0/0"
    ip_protocol       = "-1"
}

IAM

Fleet Managerで接続するための権限を付与するためにEC2用のIAM Roleを作成します。

data "aws_iam_policy_document" "instance_assume_role_policy" {
    statement {
        actions = ["sts:AssumeRole"]
        principals {
            type        = "Service"
            identifiers = ["ec2.amazonaws.com"]
        }
    }
}

resource "aws_iam_role" "consumer_instance_role" {
    name                = "consumer_instance_role"
    assume_role_policy  = data.aws_iam_policy_document.instance_assume_role_policy.json
}

resource "aws_iam_role_policy_attachments_exclusive" "example" {
    role_name   = aws_iam_role.consumer_instance_role.name
    policy_arns = ["arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"]
}

resource "aws_iam_instance_profile" "instance_role" {
    name = "instance_profile"
    role = aws_iam_role.consumer_instance_role.name
}

EC2

続いてEC2です、今回はWebサイトということで視覚的にも分かりやすいようにWindows Serverで作成していきます。

resource "aws_instance" "ec2_instance" {
    ami                         = "ami-0acdf322a60c9db6e"
    instance_type               = "t3.micro"
    subnet_id                   = aws_subnet.consumer_ec2_subnet01.id
    vpc_security_group_ids      = [aws_security_group.consumer_ec2_sg.id]
    associate_public_ip_address = false
    iam_instance_profile        = aws_iam_instance_profile.instance_role.name
    key_name                    = var.keypair

    root_block_device {
        volume_size = 30
        volume_type = "gp3"
        encrypted   = true
    }

    tags = {
        Name = "consumer-ec2"
    }
}

VPC Endpoint

次はVPC Endpointです、接続元はFleet Manager用にSSMSSMMessages、VPC Endpoint Service用の計3つを作成します。

resource "aws_vpc_endpoint" "consumer_interface_endpoint" {
  vpc_id              = aws_vpc.consumer_vpc.id
  vpc_endpoint_type   = "Interface"
  service_name        = aws_vpc_endpoint_service.private_service.service_name
  subnet_ids          = [aws_subnet.consumer_endpoint_subnet01.id]
  security_group_ids  = [aws_security_group.consumer_endpoint_sg.id]

  tags = {
    Name = "consumer-interface-endpoint"
  }
}

resource "aws_vpc_endpoint" "ssm_interface_endpoint" {
  vpc_id              = aws_vpc.consumer_vpc.id
  vpc_endpoint_type   = "Interface"
  service_name        = "com.amazonaws.ap-northeast-1.ssm"
  subnet_ids          = [aws_subnet.consumer_endpoint_subnet01.id]
  security_group_ids  = [aws_security_group.consumer_endpoint_sg.id]
  private_dns_enabled = true

  tags = {
    Name = "ssm-interface-endpoint"
  }
}

resource "aws_vpc_endpoint" "ssmmessage_interface_endpoint" {
  vpc_id              = aws_vpc.consumer_vpc.id
  vpc_endpoint_type   = "Interface"
  service_name        = "com.amazonaws.ap-northeast-1.ssmmessages"
  subnet_ids          = [aws_subnet.consumer_endpoint_subnet01.id]
  security_group_ids  = [aws_security_group.consumer_endpoint_sg.id]
  private_dns_enabled = true

  tags = {
    Name = "ssmmessage-interface-endpoint"
  }
}

Route53

最後にRoute53です、S3のところで記載したように接続用のドメイン名とS3の名前が同じである必要があります。今回は動作確認用の構成ですが、VPC EndpointのデフォルトのDNS名だと長すぎてS3に設定出来ないため、カスタムDNS名を設定します。

resource "aws_route53_zone" "main" {
  name = "provider-s3.com"

  vpc {
    vpc_id = aws_vpc.consumer_vpc.id
  }

}

resource "aws_route53_record" "s3_alias" {
  zone_id = aws_route53_zone.main.zone_id
  name    = "provider-s3.com"
  type    = "A"

  alias {
    name                   = aws_vpc_endpoint.consumer_interface_endpoint.dns_entry[0].dns_name
    zone_id                = aws_vpc_endpoint.consumer_interface_endpoint.dns_entry[0].hosted_zone_id
    evaluate_target_health = false
  }
}

動作確認

動作確認ということで、早速サーバにアクセスします。
本記事の本質ではないのでFleet Managerでの接続手順については省略します。

Windows ServerのEdgeでRoute53に設定したドメインにアクセスします。
screenshot.2373.jpg

結果、S3に配置したindex.htmlに無事リダイレクトされました。
image.png

HTMLの表示方法等についてはリスナールールを追加/変更して、要件に沿った形にして頂ければと思います。

番外編

2024年のre:InventでResource Gatewayを使えば、VPC Endpoint Service無しでPrivateLinkが組めるようになりました。そのため、上記でご紹介したような従来の構成とは別に以下のような構成でも実現可能となっています。
image.png

VPC Endpoint Serviceがなくなるので必然的にNLBも不要となり、条件次第ではありますが、こちらの構成にした方が安価になる可能性が高いと言われています。そのため、今後はこの構成を取られることもあると思いますので、この構成も試してみたいと思います。

構築

ほとんどのリソースは同じ設定となるため、上で記載したTerraformコードと異なる部分のみ記載していきます。

前提

こちらではNLBやVPC Endpoint Service、これらに付随したSGやVPC Endpointの削除については触れません。上記を試した後にこちらを実施される場合は、削除、もしくはコメントアウトのご対応をお願い致します。

接続先環境の構築

まずは接続先環境です。
image.png

元々の構成と変わった部分は、NLBがResourceGatewayになったのと、S3の名前を変えるために新しく作成しています。
image.png

S3

S3の名前を変えた理由ですが、ResourceGatewayにアクセスするためのResourceタイプのVPC EndpointがAレコードにまだ対応しておらず、CNAMEレコードで作成する方法を採用しました。一方で、CNAMEレコードだと同じ名前を持つ他のレコードと同じ名前のレコードを作成出来ないため、異なる名前で新しくS3を作成しています。

resource "aws_s3_bucket" "static_site" {
  bucket = "rg.provider-s3.com"

  tags = {
    Name = "rg.provider-s3-static-site"
  }
}

data "aws_iam_policy_document" "allow_access_from_vpcendpoint" {
  statement {
    principals {
      type        = "*"
      identifiers = ["*"]
    }

    actions = [
      "s3:GetObject",
      "s3:ListBucket",
    ]

    resources = [
      aws_s3_bucket.static_site.arn,
      "${aws_s3_bucket.static_site.arn}/*",
    ]

    condition {
      test     = "StringEquals"
      variable = "aws:SourceVpce"

      values = [
        aws_vpc_endpoint.s3_interface_endpoint.id
      ]
    }
  }
}

resource "aws_s3_bucket_policy" "allow_access_from_another_account" {
  bucket = aws_s3_bucket.static_site.id
  policy = data.aws_iam_policy_document.allow_access_from_vpcendpoint.json
}

Security Group

ResourceGatewayに紐づけるSecurity Groupを作成します。インバウンドの設定は不要なので、アウトバウンドのみの指定となります。また、これに伴いALBのSecurity Groupも変更しておりますが、ResourceGatewayの場合送信IPは紐づくENIとは別のIPが使われるようで、ResourceGatewayが配置されたサブネットのCIDRを許可するようにしております。

resource "aws_security_group" "provider_resourcegateway_sg" {
  name        = "resourcegateway-sg"
  description = "Allow traffic from ConsumerVPC"
  vpc_id      = aws_vpc.provider_vpc.id

  tags = {
    Name = "resourcegateway-sg"
  }
}

resource "aws_vpc_security_group_egress_rule" "provider_resourcegateway_sg_egress" {
    security_group_id = aws_security_group.provider_resourcegateway_sg.id
    cidr_ipv4         = "0.0.0.0/0"
    ip_protocol       = "-1"
}

resource "aws_vpc_security_group_ingress_rule" "provider_alb_sg_ingress" {
    security_group_id            = aws_security_group.provider_alb_sg.id

/** ResourceGateway対応で削除
    referenced_security_group_id = aws_security_group.provider_nlb_sg.id
**/

# 以下ResourceGateway対応で追加
    cidr_ipv4                   = aws_subnet.provider_lb_subnet01.cidr_block
# 追加ここまで

    from_port                   = 443
    to_port                     = 443
    ip_protocol                 = "tcp"
}

resource "aws_vpc_security_group_egress_rule" "provider_alb_sg_egress" {
    security_group_id = aws_security_group.provider_alb_sg.id
    cidr_ipv4         = "0.0.0.0/0"
    ip_protocol       = "-1"
}

ResourceGateway

今回の変更のメインになる部分です。実際にはResourceGatewayだけでなく、ResourceGatewayに紐づけるResourceConfigurationも作成しており、ResourceConfigurationにALBを紐づけております。

resource "aws_vpclattice_resource_gateway" "provider_resource_gateway" {
    name               = "provider-resource-gateway"
    vpc_id             = aws_vpc.provider_vpc.id
    subnet_ids         = [aws_subnet.provider_lb_subnet01.id]
    security_group_ids = [aws_security_group.provider_resourcegateway_sg.id]

    tags = {
        Environment = "provider-resource-gateway"
    }
}

resource "aws_vpclattice_resource_configuration" "provider_resource_configuration" {
    name                        = "provider-resource-configuration"
    resource_gateway_identifier = aws_vpclattice_resource_gateway.provider_resource_gateway.id
    port_ranges                 = ["443"]
    protocol                    = "TCP"

    resource_configuration_definition {
        dns_resource {
            domain_name     = aws_lb.provider_alb.dns_name
            ip_address_type = "IPV4"
        }
    }

    tags = {
        Environment = "provider-resource-configuration"
    }
}

接続元環境の構築

続いて接続元環境です。
image.png

元々の構成と変わった部分は、VPC Endpoint Service向けに作成していたVPC EndpointがResourceConfiguration向けのVPC Endpointになったのと、Route53のAレコードをS3の所で述べた理由から、CNAMEレコードに変更しています。
image.png

VPC Endpoit

VPC Endpointは、新しくリリースされたリソース型で作成します。

resource "aws_vpc_endpoint" "consumer_resource_endpoint" {
  vpc_id                     = aws_vpc.consumer_vpc.id
  vpc_endpoint_type          = "Resource"
  resource_configuration_arn = aws_vpclattice_resource_configuration.provider_resource_configuration.arn
  subnet_ids                 = [aws_subnet.consumer_endpoint_subnet01.id]
  security_group_ids         = [aws_security_group.consumer_endpoint_sg.id]
  private_dns_enabled        = true

  tags = {
    Name = "consumer-resource-endpoint"
  }
}

Route53

VPC Endpointへの名前解決の為のCNAMEレコードを作成します。
レコードの指定部分ですが、Resource型のVPC Endpointが出たばかりでTerraformのDNS名の出力がまだ対応しておりませんでした。そのため、1度Route53以外をapplyした上で、VPC EndpointのDNS名を変数に入れて再度applyしております。

resource "aws_route53_record" "s3_cname" {
  zone_id = aws_route53_zone.main.zone_id
  name    = "rg"
  type    = "CNAME"
  ttl     = 300
  records = [var.dnsname]
}

動作確認

上記動作確認と同じようにサーバにアクセスし、Windows ServerのEdgeで新たにRoute53に設定したドメインにアクセスします。
screenshot.2380.jpg

結果、S3に配置したindex.htmlに無事リダイレクトされました。
image.png

まとめ

今回はS3の静的WebサイトホスティングのHTTPS化、並びにプライベート化について記載しました。

CloudFrontを使わずにHTTPS化したいであったり、プライベート化したいといった要件はあると思いますので、是非そういった場合に今回の記事がお役に立てることを願います。

また、昨年末のアップデートによりResourceGatewayを使ったPrivateLink構成での静的Webサイトホスティングも試してみましたが、こちらはTerraformの対応が追い付いておらず、完璧な形にはなりませんでした。

一方で、今後はこちらの構成が増えていくと思いますのでTerraformもアップデートされると思いますし、Resource型のVPC EndpointもAレコードに対応してくれると思います。

そのため、この記事がS3の静的Webサイトホスティングだけでなく、ResourceGatewayを使ったPrivateLink構成を検討されている方の参考にもなれば幸いです。

ご覧頂きありがとうございました!

We Are Hiring!

5
4
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
5
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?