[アップデート] CloudFront VPC オリジンが CloudFormation で作成できるようになりました

[アップデート] CloudFront VPC オリジンが CloudFormation で作成できるようになりました

Clock Icon2025.02.05

いわさです。

昨年の AWS re:Invent 直前に CloudFront に VPC オリジンというオリジンタイプが追加され、CloudFront のオリジンにパブリック IP アドレスを持たない ALB や EC2 などが指定できるようになりました。

https://dev.classmethod.jp/articles/cloudfront-vpc-origins-internal-alb/

色々なところで使い所がありそうなこの機能ですが、これまで CloudFormation はまだサポートされておらず、AWS API 経由で例えば CLI などで作成したり、あるいはカスタムリソースなどで CloudFormation 対応させる必要がありました。

そんな VPC オリジンですが、先日のアップデートで CloudFormation に専用リソースタイプやプロパティが追加され、CloudFormation から構築できるようになりました。

今回は次のようにプライベートサブネット内の Internal ALB に対して VPC オリジンを構成して CloudFront 経由でアクセスできるようにしてみたのでテンプレートなど含めて紹介します。

9FAB4B2B-466A-452A-A273-4621E6BBE14B.png
CloudFront VPC Origin + Internal ALB の構成例

CloudFront + VPC オリジン以外のリソース

まず、VPC + ALB だけになりますがこのようなテンプレートです。
ALB はリスナーから固定レスポンスを返すようにしています。

AWSTemplateFormatVersion: '2010-09-09'
Description: ---

Parameters:
  VpcCidr:
    Type: String
    Default: '10.0.0.0/16'
  PrivateSubnet1Cidr:
    Type: String
    Default: '10.0.1.0/24'
  PrivateSubnet2Cidr:
    Type: String
    Default: '10.0.2.0/24'

Resources:
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: !Ref VpcCidr
      EnableDnsHostnames: true
      EnableDnsSupport: true
      Tags:
        - Key: Name
          Value: Private VPC

  PrivateSubnet1:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: !Ref PrivateSubnet1Cidr
      AvailabilityZone: !Select [0, !GetAZs '']
      Tags:
        - Key: Name
          Value: Private Subnet 1

  PrivateSubnet2:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: !Ref PrivateSubnet2Cidr
      AvailabilityZone: !Select [1, !GetAZs '']
      Tags:
        - Key: Name
          Value: Private Subnet 2

  PrivateRouteTable1:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: Private Route Table 1

  PrivateRouteTable2:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: Private Route Table 2

  PrivateSubnet1RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PrivateSubnet1
      RouteTableId: !Ref PrivateRouteTable1

  PrivateSubnet2RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PrivateSubnet2
      RouteTableId: !Ref PrivateRouteTable2

  AlbSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Security group for internal ALB
      VpcId: !Ref VPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: !Ref VpcCidr

  InternalALB:
    Type: AWS::ElasticLoadBalancingV2::LoadBalancer
    Properties:
      Scheme: internal
      SecurityGroups:
        - !Ref AlbSecurityGroup
      Subnets:
        - !Ref PrivateSubnet1
        - !Ref PrivateSubnet2
      Type: application

  AlbListener:
    Type: AWS::ElasticLoadBalancingV2::Listener
    Properties:
      DefaultActions:
        - Type: fixed-response
          FixedResponseConfig:
            ContentType: text/plain
            MessageBody: "Hello from ALB!"
            StatusCode: "200"
      LoadBalancerArn: !Ref InternalALB
      Port: 80
      Protocol: HTTP

パブリック IP アドレスが割り当てられていないので当然外部からアクセスは出来ません。
CloudShell を VPC 内にデプロイしてアクセスしてみるとこのような感じです。

BD19FFF5-2A2F-4B11-9304-7F0C86968DA3_4_5005_c.jpeg
VPC CloudShell からのアクセス

VPC オリジン関係のリソースを追加

ではここに CloudFront ディストリビューションと VPC オリジンを追加していきます。

まず、今回のアップデートで、AWS::CloudFront::VpcOriginが新しく追加されています。

さらにAWS::CloudFront::Distribution Origin にてVpcOriginConfigを指定できるようになっています。

そのあたりを踏まえて次のようにテンプレートにリソースを追加します。

Resources:

:

  HogeVpcOrigin:
    Type: AWS::CloudFront::VpcOrigin
    Properties:
      VpcOriginEndpointConfig: 
          Name: HogeVpcOrigin
          Arn: !Ref InternalALB

  CloudFrontDistribution:
    Type: AWS::CloudFront::Distribution
    Properties:
      DistributionConfig:
        Enabled: true
        HttpVersion: http2
        DefaultCacheBehavior:
          ViewerProtocolPolicy: allow-all
          TargetOriginId: VPCOrigin
          ForwardedValues:
            QueryString: false
            Cookies:
              Forward: none
        Origins:
          - Id: VPCOrigin
            DomainName: !GetAtt InternalALB.DNSName
            VpcOriginConfig: 
              VpcOriginId: !GetAtt HogeVpcOrigin.Id

  InternetGateway:
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags:
        - Key: Name
          Value: Main Internet Gateway

  AttachGateway:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref VPC
      InternetGatewayId: !Ref InternetGateway

  ALBSGIngress:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      FromPort: 80
      ToPort: 80
      IpProtocol: tcp
      SourcePrefixListId: pl-58a04531
      GroupId: !Ref AlbSecurityGroup

ポイントとして、VPC オリジンの利用にあたっていくつか前提条件[1]がありまして、それらを満たす必要があります。

具体的にはここでは VPC にインターネットゲートウェイを追加し、ALB のセキュリティグループは CloudFtont のマネージドプレフィックスリストを許可するようにしています。
後述しますが、もう少し制限をしたければ、プレフィックスリストではなく VPC オリジンの ENI が使うセキュリティグループを指定する必要があるのですが、自動作成されるセキュリティグループになるので CloudFormation 上では指定・取得が出来ません。

上記テンプレートをデプロイすると次のように CloudFront ディストリビューションが作成され、オリジンタイプは VPC オリジンとなっています。

08CACA4F-5522-4C63-97AC-D019838EBD74.png
ディストリビューションに設定される VPC オリジンタイプ

このオリジンは次のように VPC オリジンとして指定されており、内部 ALB を指す形で構成されています。

86BB85D3-F952-446B-960E-3F50A4904488_4_5005_c.jpeg
作成された VPC オリジンリソース

今回は次のようにプレフィックスリストを指定しています。リージョンごとにリストの ID は異なるのでご注意ください。

4263EA9C-9537-439A-878F-4FA4B54E9C73.png
CloudFront プレフィックスリストを使用

ということでこんな感じで無事アクセスすることができました。

% curl http://d1gdftjtm14ttx.cloudfront.net
Hello from ALB!

さいごに

本日は CloudFront VPC オリジンが CloudFormation で作成できるようになったのでテンプレートを作成してみました。

なお、今回はプレフィックスリストを使いましたが、前述のとおり VPC オリジンは VPC 内に ENI をプロビジョニングしてそこから内部リソースにアクセスする形となっており、Verified Access などと同じパターンです。次のように自動で ENI やセキュリティグループも生成されています。

06452DF1-1224-4BF5-97C7-986454EE14F5_4_5005_c.jpeg
自動作成される VPC Origin 用の ENI

ALB 側のセキュリティグループでより細かく制限を加えたい。あるいはマネージドプレフィックスリストが大きすぎて上限を超過してしまうような場合は手動でこのセキュリティグループをソースに追加しましょう。

CC8DE4DC-96B4-4D73-ABD9-5B03173F0D10.png
ENI に自動で作成・アタッチされるセキュリティグループ

本日時点では CloudFormation 側のリソース参照ではセキュリティグループ情報を取得したり事前作成はできなさそうです。

脚注
  1. Restrict access with VPC origins - Amazon CloudFront ↩︎

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.