[アップデート] CloudFront VPC オリジンが CloudFormation で作成できるようになりました
いわさです。
昨年の AWS re:Invent 直前に CloudFront に VPC オリジンというオリジンタイプが追加され、CloudFront のオリジンにパブリック IP アドレスを持たない ALB や EC2 などが指定できるようになりました。
色々なところで使い所がありそうなこの機能ですが、これまで CloudFormation はまだサポートされておらず、AWS API 経由で例えば CLI などで作成したり、あるいはカスタムリソースなどで CloudFormation 対応させる必要がありました。
そんな VPC オリジンですが、先日のアップデートで CloudFormation に専用リソースタイプやプロパティが追加され、CloudFormation から構築できるようになりました。
今回は次のようにプライベートサブネット内の Internal ALB に対して VPC オリジンを構成して CloudFront 経由でアクセスできるようにしてみたのでテンプレートなど含めて紹介します。
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 内にデプロイしてアクセスしてみるとこのような感じです。
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 オリジンとなっています。
ディストリビューションに設定される VPC オリジンタイプ
このオリジンは次のように VPC オリジンとして指定されており、内部 ALB を指す形で構成されています。
作成された VPC オリジンリソース
今回は次のようにプレフィックスリストを指定しています。リージョンごとにリストの ID は異なるのでご注意ください。
CloudFront プレフィックスリストを使用
ということでこんな感じで無事アクセスすることができました。
% curl http://d1gdftjtm14ttx.cloudfront.net
Hello from ALB!
さいごに
本日は CloudFront VPC オリジンが CloudFormation で作成できるようになったのでテンプレートを作成してみました。
なお、今回はプレフィックスリストを使いましたが、前述のとおり VPC オリジンは VPC 内に ENI をプロビジョニングしてそこから内部リソースにアクセスする形となっており、Verified Access などと同じパターンです。次のように自動で ENI やセキュリティグループも生成されています。
自動作成される VPC Origin 用の ENI
ALB 側のセキュリティグループでより細かく制限を加えたい。あるいはマネージドプレフィックスリストが大きすぎて上限を超過してしまうような場合は手動でこのセキュリティグループをソースに追加しましょう。
ENI に自動で作成・アタッチされるセキュリティグループ
本日時点では CloudFormation 側のリソース参照ではセキュリティグループ情報を取得したり事前作成はできなさそうです。