Create a REST API which acts as a proxy for a NGINX server hosted on a Amazon Elastic Compute Cloud (Amazon EC2)
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
(uksb-1tthgi812) (tag:apigw-ec2)
This CloudFormation deploys public REST API along with private network load balancer which will route the request to an EC2 website via vpc link
Parameters:
InstanceType:
Type: String
Description: Select an instance type
Default: t2.micro
AllowedValues: [c4.2xlarge, c4.4xlarge, c4.8xlarge, c4.large, c4.xlarge, c5.12xlarge, c5.18xlarge, c5.24xlarge, c5.2xlarge, c5.4xlarge, c5.9xlarge, c5.large, c5.metal, c5.xlarge, c5a.12xlarge, c5a.16xlarge, c5a.24xlarge, c5a.2xlarge, c5a.4xlarge, c5a.8xlarge, c5a.large, c5a.xlarge, c5d.12xlarge, c5d.18xlarge, c5d.24xlarge, c5d.2xlarge, c5d.4xlarge, c5d.9xlarge, c5d.large, c5d.metal, c5d.xlarge, c5n.18xlarge, c5n.2xlarge, c5n.4xlarge, c5n.9xlarge, c5n.large, c5n.metal, c5n.xlarge, c6g.12xlarge, c6g.16xlarge, c6g.2xlarge, c6g.4xlarge, c6g.8xlarge, c6g.large, c6g.medium, c6g.metal, c6g.xlarge, c6gd.12xlarge, c6gd.16xlarge, c6gd.2xlarge, c6gd.4xlarge, c6gd.8xlarge, c6gd.large, c6gd.medium, c6gd.metal, c6gd.xlarge, c6gn.12xlarge, c6gn.16xlarge, c6gn.2xlarge, c6gn.4xlarge, c6gn.8xlarge, c6gn.large, c6gn.medium, c6gn.xlarge, c6i.12xlarge, c6i.16xlarge, c6i.24xlarge, c6i.2xlarge, c6i.32xlarge, c6i.4xlarge, c6i.8xlarge, c6i.large, c6i.metal, c6i.xlarge, d2.2xlarge, d2.4xlarge, d2.8xlarge, d2.xlarge, d3.2xlarge, d3.4xlarge, d3.8xlarge, d3.xlarge, g3.16xlarge, g3.4xlarge, g3.8xlarge, g4ad.16xlarge, g4ad.2xlarge, g4ad.4xlarge, g4ad.8xlarge, g4ad.xlarge, g4dn.12xlarge, g4dn.16xlarge, g4dn.2xlarge, g4dn.4xlarge, g4dn.8xlarge, g4dn.metal, g4dn.xlarge, g5.12xlarge, g5.16xlarge, g5.24xlarge, g5.2xlarge, g5.48xlarge, g5.4xlarge, g5.8xlarge, g5.xlarge, i3.16xlarge, i3.2xlarge, i3.4xlarge, i3.8xlarge, i3.large, i3.metal, i3.xlarge, i3en.12xlarge, i3en.24xlarge, i3en.2xlarge, i3en.3xlarge, i3en.6xlarge, i3en.large, i3en.metal, i3en.xlarge, i4i.16xlarge, i4i.2xlarge, i4i.32xlarge, i4i.4xlarge, i4i.8xlarge, i4i.large, i4i.metal, i4i.xlarge, im4gn.16xlarge, im4gn.2xlarge, im4gn.4xlarge, im4gn.8xlarge, im4gn.large, im4gn.xlarge, inf1.24xlarge, inf1.2xlarge, inf1.6xlarge, inf1.xlarge, is4gen.2xlarge, is4gen.4xlarge, is4gen.8xlarge, is4gen.large, is4gen.medium, is4gen.xlarge, m4.10xlarge, m4.16xlarge, m4.2xlarge, m4.4xlarge, m4.large, m4.xlarge, m5.12xlarge, m5.16xlarge, m5.24xlarge, m5.2xlarge, m5.4xlarge, m5.8xlarge, m5.large, m5.metal, m5.xlarge, m5a.12xlarge, m5a.16xlarge, m5a.24xlarge, m5a.2xlarge, m5a.4xlarge, m5a.8xlarge, m5a.large, m5a.xlarge, m5ad.12xlarge, m5ad.16xlarge, m5ad.24xlarge, m5ad.2xlarge, m5ad.4xlarge, m5ad.8xlarge, m5ad.large, m5ad.xlarge, m5d.12xlarge, m5d.16xlarge, m5d.24xlarge, m5d.2xlarge, m5d.4xlarge, m5d.8xlarge, m5d.large, m5d.metal, m5d.xlarge, m6g.12xlarge, m6g.16xlarge, m6g.2xlarge, m6g.4xlarge, m6g.8xlarge, m6g.large, m6g.medium, m6g.metal, m6g.xlarge, m6i.12xlarge, m6i.16xlarge, m6i.24xlarge, m6i.2xlarge, m6i.32xlarge, m6i.4xlarge, m6i.8xlarge, m6i.large, m6i.metal, m6i.xlarge, p3.16xlarge, p3.2xlarge, p3.8xlarge, r4.16xlarge, r4.2xlarge, r4.4xlarge, r4.8xlarge, r4.large, r4.xlarge, r5.12xlarge, r5.16xlarge, r5.24xlarge, r5.2xlarge, r5.4xlarge, r5.8xlarge, r5.large, r5.metal, r5.xlarge, r5a.12xlarge, r5a.16xlarge, r5a.24xlarge, r5a.2xlarge, r5a.4xlarge, r5a.8xlarge, r5a.large, r5a.xlarge, r5ad.12xlarge, r5ad.16xlarge, r5ad.24xlarge, r5ad.2xlarge, r5ad.4xlarge, r5ad.8xlarge, r5ad.large, r5ad.xlarge, r5b.12xlarge, r5b.16xlarge, r5b.24xlarge, r5b.2xlarge, r5b.4xlarge, r5b.8xlarge, r5b.large, r5b.metal, r5b.xlarge, r5d.12xlarge, r5d.16xlarge, r5d.24xlarge, r5d.2xlarge, r5d.4xlarge, r5d.8xlarge, r5d.large, r5d.metal, r5d.xlarge, r5n.12xlarge, r5n.16xlarge, r5n.24xlarge, r5n.2xlarge, r5n.4xlarge, r5n.8xlarge, r5n.large, r5n.metal, r5n.xlarge, r6g.12xlarge, r6g.16xlarge, r6g.2xlarge, r6g.4xlarge, r6g.8xlarge, r6g.large, r6g.medium, r6g.metal, r6g.xlarge, r6gd.12xlarge, r6gd.16xlarge, r6gd.2xlarge, r6gd.4xlarge, r6gd.8xlarge, r6gd.large, r6gd.medium, r6gd.metal, r6gd.xlarge, r6i.12xlarge, r6i.16xlarge, r6i.24xlarge, r6i.2xlarge, r6i.32xlarge, r6i.4xlarge, r6i.8xlarge, r6i.large, r6i.metal, r6i.xlarge, t2.2xlarge, t2.large, t2.medium, t2.micro, t2.nano, t2.small, t2.xlarge, t3.2xlarge, t3.large, t3.medium, t3.micro, t3.nano, t3.small, t3.xlarge, t3a.2xlarge, t3a.large, t3a.medium, t3a.micro, t3a.nano, t3a.small, t3a.xlarge, t4g.2xlarge, t4g.large, t4g.medium, t4g.micro, t4g.nano, t4g.small, t4g.xlarge, u-3tb1.56xlarge, u-6tb1.112xlarge, u-6tb1.56xlarge, x1.16xlarge, x1.32xlarge, x1e.16xlarge, x1e.2xlarge, x1e.32xlarge, x1e.4xlarge, x1e.8xlarge, x1e.xlarge, x2idn.16xlarge, x2idn.24xlarge, x2idn.32xlarge, x2idn.metal, x2iedn.16xlarge, x2iedn.24xlarge, x2iedn.2xlarge, x2iedn.32xlarge, x2iedn.4xlarge, x2iedn.8xlarge, x2iedn.metal, x2iedn.xlarge, c5ad.12xlarge, c5ad.16xlarge, c5ad.24xlarge, c5ad.2xlarge, c5ad.4xlarge, c5ad.8xlarge, c5ad.large, c5ad.xlarge, c6a.12xlarge, c6a.16xlarge, c6a.24xlarge, c6a.2xlarge, c6a.32xlarge, c6a.48xlarge, c6a.4xlarge, c6a.8xlarge, c6a.large, c6a.metal, c6a.xlarge, c6id.12xlarge, c6id.16xlarge, c6id.24xlarge, c6id.2xlarge, c6id.32xlarge, c6id.4xlarge, c6id.8xlarge, c6id.large, c6id.metal, c6id.xlarge, c6in.12xlarge, c6in.16xlarge, c6in.24xlarge, c6in.2xlarge, c6in.32xlarge, c6in.4xlarge, c6in.8xlarge, c6in.large, c6in.xlarge, c7g.12xlarge, c7g.16xlarge, c7g.2xlarge, c7g.4xlarge, c7g.8xlarge, c7g.large, c7g.medium, c7g.metal, c7g.xlarge, d3en.12xlarge, d3en.2xlarge, d3en.4xlarge, d3en.6xlarge, d3en.8xlarge, d3en.xlarge, dl1.24xlarge, f1.16xlarge, f1.2xlarge, f1.4xlarge, g3s.xlarge, g5g.16xlarge, g5g.2xlarge, g5g.4xlarge, g5g.8xlarge, g5g.metal, g5g.xlarge, h1.16xlarge, h1.2xlarge, h1.4xlarge, h1.8xlarge, m5dn.12xlarge, m5dn.16xlarge, m5dn.24xlarge, m5dn.2xlarge, m5dn.4xlarge, m5dn.8xlarge, m5dn.large, m5dn.metal, m5dn.xlarge, m5n.12xlarge, m5n.16xlarge, m5n.24xlarge, m5n.2xlarge, m5n.4xlarge, m5n.8xlarge, m5n.large, m5n.metal, m5n.xlarge, m5zn.12xlarge, m5zn.2xlarge, m5zn.3xlarge, m5zn.6xlarge, m5zn.large, m5zn.metal, m5zn.xlarge, m6a.12xlarge, m6a.16xlarge, m6a.24xlarge, m6a.2xlarge, m6a.32xlarge, m6a.48xlarge, m6a.4xlarge, m6a.8xlarge, m6a.large, m6a.metal, m6a.xlarge, m6gd.12xlarge, m6gd.16xlarge, m6gd.2xlarge, m6gd.4xlarge, m6gd.8xlarge, m6gd.large, m6gd.medium, m6gd.metal, m6gd.xlarge, m6id.12xlarge, m6id.16xlarge, m6id.24xlarge, m6id.2xlarge, m6id.32xlarge, m6id.4xlarge, m6id.8xlarge, m6id.large, m6id.metal, m6id.xlarge, m6idn.12xlarge, m6idn.16xlarge, m6idn.24xlarge, m6idn.2xlarge, m6idn.32xlarge, m6idn.4xlarge, m6idn.8xlarge, m6idn.large, m6idn.xlarge, m6in.12xlarge, m6in.16xlarge, m6in.24xlarge, m6in.2xlarge, m6in.32xlarge, m6in.4xlarge, m6in.8xlarge, m6in.large, m6in.xlarge, m7g.12xlarge, m7g.16xlarge, m7g.2xlarge, m7g.4xlarge, m7g.8xlarge, m7g.large, m7g.medium, m7g.metal, m7g.xlarge, mac1.metal, mac2.metal, p2.16xlarge, p2.8xlarge, p2.xlarge, p3dn.24xlarge, p4d.24xlarge, r5dn.12xlarge, r5dn.16xlarge, r5dn.24xlarge, r5dn.2xlarge, r5dn.4xlarge, r5dn.8xlarge, r5dn.large, r5dn.metal, r5dn.xlarge, r6a.12xlarge, r6a.16xlarge, r6a.24xlarge, r6a.2xlarge, r6a.32xlarge, r6a.48xlarge, r6a.4xlarge, r6a.8xlarge, r6a.large, r6a.metal, r6a.xlarge, r6id.12xlarge, r6id.16xlarge, r6id.24xlarge, r6id.2xlarge, r6id.32xlarge, r6id.4xlarge, r6id.8xlarge, r6id.large, r6id.metal, r6id.xlarge, r6idn.12xlarge, r6idn.16xlarge, r6idn.24xlarge, r6idn.2xlarge, r6idn.32xlarge, r6idn.4xlarge, r6idn.8xlarge, r6idn.large, r6idn.xlarge, r6in.12xlarge, r6in.16xlarge, r6in.24xlarge, r6in.2xlarge, r6in.32xlarge, r6in.4xlarge, r6in.8xlarge, r6in.large, r6in.xlarge, r7g.12xlarge, r7g.16xlarge, r7g.2xlarge, r7g.4xlarge, r7g.8xlarge, r7g.large, r7g.medium, r7g.metal, r7g.xlarge, trn1.2xlarge, trn1.32xlarge, u-12tb1.112xlarge, u-18tb1.112xlarge, u-24tb1.112xlarge, u-9tb1.112xlarge, vt1.24xlarge, vt1.3xlarge, vt1.6xlarge, x2gd.12xlarge, x2gd.16xlarge, x2gd.2xlarge, x2gd.4xlarge, x2gd.8xlarge, x2gd.large, x2gd.medium, x2gd.metal, x2gd.xlarge, x2iezn.12xlarge, x2iezn.2xlarge, x2iezn.4xlarge, x2iezn.6xlarge, x2iezn.8xlarge, x2iezn.metal, z1d.12xlarge, z1d.2xlarge, z1d.3xlarge, z1d.6xlarge, z1d.large, z1d.metal, z1d.xlarge, hpc6a.48xlarge, hpc6id.32xlarge]
KeyPair:
Description: Select the key pair
Type: AWS::EC2::KeyPair::KeyName
VPC:
Description: Please select if you want to use existing VPC
Type: AWS::EC2::VPC::Id
PrivateSubnetIDs:
Description: Private Subnet IDs for VPCE
Type: "List<AWS::EC2::Subnet::Id>"
SecurityGroupIDsForNLBAndEC2:
Description: Security group IDs for NLB and EC2. Note - please make sure that the security group allows traffic on port 80 from VPC Cidr or 0.0.0.0
Type: "List<AWS::EC2::SecurityGroup::Id>"
RouteTableId:
Description: PrivateSubnets route table Id
Type: String
Mappings:
RegionMap:
us-east-1:
AMI: ami-0dfcb1ef8550277af
us-east-2:
AMI: ami-0cc87e5027adcdca8
us-west-1:
AMI: ami-00569e54da628d17c
us-west-2:
AMI: ami-0f1a5f5ada0e7da53
ap-southeast-4:
AMI: ami-0272ee0cbe63bb8e8
ap-east-1:
AMI: ami-0e679816c1d0be6df
ap-south-2:
AMI: ami-0155ae3341da656ae
ap-south-1:
AMI: ami-0e742cca61fb65051
ap-northeast-3:
AMI: ami-090ae0a4750988734
ap-northeast-2:
AMI: ami-0f6e451b865011317
ca-central-1:
AMI: ami-099effcf516c942b7
eu-north-1:
AMI: ami-0bb935e4614c12d86
eu-west-1:
AMI: ami-06e0ce9d3339cb039
eu-west-2:
AMI: ami-09ee0944866c73f62
eu-west-3:
AMI: ami-00575c0cbc20caf50
eu-central-1:
AMI: ami-0c0d3776ef525d5dd
ap-southeast-1:
AMI: ami-0f2eac25772cd4e36
ap-southeast-2:
AMI: ami-0692dea0a2f8a1b35
ap-northeast-1:
AMI: ami-0ffac3e16de16665e
sa-east-1:
AMI: ami-01fc9174dd9330556
af-south-1:
AMI: ami-0d4fd6ba7ffe8260e
ap-southeast-3:
AMI: ami-0ebaeda1c62cceddb
eu-west-3:
AMI: ami-00575c0cbc20caf50
eu-south-2:
AMI: ami-089ea1de61e0c9c18
me-south-1:
AMI: ami-06131a860e2930b5c
me-central-1:
AMI: ami-0c30c5d64bef7fade
Resources:
VPCE:
Type: AWS::EC2::VPCEndpoint
Properties:
RouteTableIds:
- !Ref RouteTableId
ServiceName: !Sub com.amazonaws.${AWS::Region}.s3
VpcEndpointType: Gateway
VpcId: !Ref VPC
EC2:
Type: AWS::EC2::Instance
DependsOn: ApiGatewayModel
Properties:
InstanceType: !Ref InstanceType
KeyName: !Ref KeyPair
ImageId: !FindInMap [RegionMap, !Ref 'AWS::Region', AMI]
SecurityGroupIds: !Ref SecurityGroupIDsForNLBAndEC2
SubnetId: !Select [0, !Ref PrivateSubnetIDs]
UserData:
Fn::Base64:
!Sub |
#!/bin/bash
yum update -y
sudo amazon-linux-extras install nginx1 -y
sudo systemctl enable --now nginx
Tags:
- Key: Name
Value: priv
NetworkLoadBalancer:
DependsOn: EC2
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
Name: NLB
Scheme: internal
Subnets:
- !Select [0, !Ref PrivateSubnetIDs]
- !Select [1, !Ref PrivateSubnetIDs]
Type: network
NetworkLoadBalancerTargetGroup:
DependsOn: EC2
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
Port: 80
Name: NLBTargetGroup
HealthCheckEnabled: true
Protocol: TCP
VpcId: !Ref VPC
Targets:
- Id: !GetAtt EC2.PrivateIp
Port: 80
TargetType: ip
NetworkLoadBalancerListener:
DependsOn: NetworkLoadBalancerTargetGroup
Type: AWS::ElasticLoadBalancingV2::Listener
Properties:
DefaultActions:
- Type: forward
TargetGroupArn: !Ref NetworkLoadBalancerTargetGroup
LoadBalancerArn: !Ref NetworkLoadBalancer
Port: '80'
Protocol: TCP
ApiGatewayRestApi:
Type: 'AWS::ApiGateway::RestApi'
DependsOn: VPCE
Properties:
ApiKeySourceType: HEADER
Description: An API Gateway to connect to ec2 server
Name: PublicApiViaCFN
EndpointConfiguration:
Types:
- REGIONAL
ApiGatewayGetMethod:
DependsOn: VPCLink
Type: AWS::ApiGateway::Method
Properties:
HttpMethod: GET
AuthorizationType: NONE
Integration:
ConnectionType: VPC_LINK
ConnectionId: "${stageVariables.vpclink}"
IntegrationHttpMethod: GET
PassthroughBehavior: WHEN_NO_MATCH
TimeoutInMillis: 10000
Type: HTTP_PROXY
Uri: !Sub
- "http://${privateIP}"
- privateIP: !GetAtt EC2.PrivateIp
ResourceId: !GetAtt ApiGatewayRestApi.RootResourceId
RestApiId: !Ref ApiGatewayRestApi
ApiGatewayModel:
DependsOn: ApiGatewayRestApi
Type: AWS::ApiGateway::Model
Properties:
ContentType: 'application/json'
RestApiId: !Ref ApiGatewayRestApi
Schema: {}
ApiGatewayStage:
Type: AWS::ApiGateway::Stage
DependsOn: ApiGatewayDeployment
Properties:
DeploymentId: !Ref ApiGatewayDeployment
Description: API Stage v0
RestApiId: !Ref ApiGatewayRestApi
StageName: 'v0'
Variables:
vpclink: !Ref VPCLink
ApiGatewayDeployment:
Type: 'AWS::ApiGateway::Deployment'
DependsOn: ApiGatewayGetMethod
Properties:
RestApiId: !Ref ApiGatewayRestApi
VPCLink:
Type: AWS::ApiGateway::VpcLink
DependsOn: NetworkLoadBalancer
Properties:
Name: NLB
TargetArns:
- !Join
- ''
- - 'arn:aws:elasticloadbalancing:'
- !Ref AWS::Region
- ':'
- !Ref AWS::AccountId
- ':loadbalancer/'
- !GetAtt NetworkLoadBalancer.LoadBalancerFullName
Outputs:
WebsiteURL:
Value: !Sub
- "curl https://${ApiId}.execute-api.${AWS::Region}.amazonaws.com/v0"
- ApiId: !Ref ApiGatewayRestApi
Description: ApiGateway URL
git clone https://github.com/aws-samples/serverless-patterns
cd serverless-patterns/apigw-ec2