--- AWSTemplateFormatVersion: "2010-09-09" Description: Set up a demonstration topology for using gwlbtun in two-arm mode Parameters: LinuxAmiId: Type: AWS::SSM::Parameter::Value Description: AMI ID to use for GWLB appliances Default: '/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2' GWLBInstanceType: Type: String Description: Instance type code to use for the GWLB appliances. The default is fine for light testing, for heavier workloads you should consider a c5n instance. Default: t2.micro Resources: EC2Role: Type: AWS::IAM::Role Properties: RoleName: !Join [ "-", [ !Ref AWS::StackName, "EC2Role" ] ] Description: Role for all EC2 instances to run under to allow SSM and S3 AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: Service: - ec2.amazonaws.com Action: - 'sts:AssumeRole' ManagedPolicyArns: - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore - arn:aws:iam::aws:policy/AmazonSSMPatchAssociation - arn:aws:iam::aws:policy/AmazonEC2ReadOnlyAccess - arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess EC2RoleInstanceProfile: Type: AWS::IAM::InstanceProfile Properties: InstanceProfileName: !Join [ "-", [ !Ref AWS::StackName, "EC2Role" ] ] Path: / Roles: - !Ref EC2Role GWLBTunVPC: Type: AWS::EC2::VPC Properties: CidrBlock: 10.10.0.0/16 EnableDnsHostnames: true EnableDnsSupport: true Tags: - Key: Name Value: !Join [ "-", [ !Ref AWS::StackName, "GWLBTun" ] ] GWLBTunPublicSubnet: Type: AWS::EC2::Subnet Properties: AvailabilityZone: !Select [0, !GetAZs '' ] CidrBlock: 10.10.2.0/24 VpcId: !Ref GWLBTunVPC Tags: - Key: Name Value: !Join [ "-", [ !Ref AWS::StackName, "GWLBTun public" ] ] GWLBTunPublicRT: Type: AWS::EC2::RouteTable Properties: VpcId: !Ref GWLBTunVPC Tags: - Key: Name Value: !Join [ "-", [ !Ref AWS::StackName, "GWLBTun public" ] ] GWLBTunPublicRTA: Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: !Ref GWLBTunPublicSubnet RouteTableId: !Ref GWLBTunPublicRT # Set up the GWLB GWLB: Type: AWS::ElasticLoadBalancingV2::LoadBalancer Properties: Name: !Join [ "-", [ !Ref AWS::StackName, "GWLB" ] ] Type: gateway Subnets: - !Ref GWLBTunPublicSubnet GWLBTargetGroup: Type: AWS::ElasticLoadBalancingV2::TargetGroup Properties: Name: !Join [ "-", [ !Ref AWS::StackName, "Instances" ] ] VpcId: !Ref GWLBTunVPC Protocol: GENEVE Port: 6081 HealthCheckProtocol: HTTP HealthCheckPort: 80 HealthCheckPath: / HealthCheckEnabled: true TargetType: ip # TargetType IP allows specifying the specific NIC on the GWLBTun instance to target Targets: - Id: !GetAtt GWLBTunInstanceTwoArm.PrivateIp GWLBListener: Type: AWS::ElasticLoadBalancingV2::Listener Properties: LoadBalancerArn: !Ref GWLB DefaultActions: - Type: forward TargetGroupArn: !Ref GWLBTargetGroup GWLBEndpointService: Type: AWS::EC2::VPCEndpointService Properties: GatewayLoadBalancerArns: - !Ref GWLB AcceptanceRequired: false GWLBe: Type: AWS::EC2::VPCEndpoint DependsOn: GWLBEndpointService Properties: VpcId: !Ref ApplicationVPC ServiceName: !Sub "com.amazonaws.vpce.${AWS::Region}.${GWLBEndpointService}" VpcEndpointType: GatewayLoadBalancer SubnetIds: - !Ref ApplicationPrivateSubnet # Build a GWLBTun instance GWLBTunInstanceTwoArm: Type: AWS::EC2::Instance Properties: ImageId: !Ref LinuxAmiId InstanceType: !Ref GWLBInstanceType IamInstanceProfile: !Join [ "-", [ !Ref AWS::StackName, "EC2Role" ] ] SourceDestCheck: false BlockDeviceMappings: - DeviceName: /dev/xvda Ebs: VolumeSize: 8 NetworkInterfaces: - DeviceIndex: 0 AssociatePublicIpAddress: True SubnetId: !Ref GWLBTunPublicSubnet GroupSet: - Ref: GWLBTunSG UserData: Fn::Base64: | #!/bin/bash -ex yum -y groupinstall "Development Tools" yum -y install cmake3 cd /root git clone https://github.com/aws-samples/aws-gateway-load-balancer-tunnel-handler.git cd aws-gateway-load-balancer-tunnel-handler cmake3 . make echo "[Unit]" > /usr/lib/systemd/system/gwlbtun.service echo "Description=AWS GWLB Tunnel Handler" >> /usr/lib/systemd/system/gwlbtun.service echo "" >> /usr/lib/systemd/system/gwlbtun.service echo "[Service]" >> /usr/lib/systemd/system/gwlbtun.service echo "ExecStart=/root/aws-gateway-load-balancer-tunnel-handler/gwlbtun -c /root/aws-gateway-load-balancer-tunnel-handler/example-scripts/create-nat.sh -p 80" >> /usr/lib/systemd/system/gwlbtun.service echo "Restart=always" >> /usr/lib/systemd/system/gwlbtun.service echo "RestartSec=5s" >> /usr/lib/systemd/system/gwlbtun.service systemctl daemon-reload systemctl enable --now --no-block gwlbtun.service systemctl start gwlbtun.service echo Tags: - Key: Name Value: !Join [ "-", [ !Ref AWS::StackName, "GWLBTun" ] ] GWLBTunSG: Type: AWS::EC2::SecurityGroup Properties: VpcId: !Ref GWLBTunVPC GroupName: !Join [ "-", [ !Ref AWS::StackName, "GWLBTun Security" ] ] GroupDescription: GWLBTun Security SecurityGroupIngress: - CidrIp: !GetAtt GWLBTunVPC.CidrBlock IpProtocol: -1 # Make an Internet Gateway in our GWLB VPC and route to it from the public subnet. GWLBTunIG: Type: AWS::EC2::InternetGateway Properties: Tags: - Key: Name Value: !Join [ "-", [ !Ref AWS::StackName, "GWLBTun" ] ] GWLBTunIGA: Type: AWS::EC2::VPCGatewayAttachment Properties: InternetGatewayId: !Ref GWLBTunIG VpcId: !Ref GWLBTunVPC GWLBTunIGRoute: Type: AWS::EC2::Route DependsOn: GWLBTunIGA Properties: RouteTableId: !Ref GWLBTunPublicRT DestinationCidrBlock: 0.0.0.0/0 GatewayId: !Ref GWLBTunIG # Set up the Application VPC ApplicationVPC: Type: AWS::EC2::VPC Properties: CidrBlock: 10.20.0.0/16 EnableDnsHostnames: true EnableDnsSupport: true Tags: - Key: Name Value: !Join [ "-", [ !Ref AWS::StackName, "Application" ] ] ApplicationPrivateSubnet: Type: AWS::EC2::Subnet Properties: AvailabilityZone: !Select [0, !GetAZs '' ] CidrBlock: 10.20.0.0/24 VpcId: !Ref ApplicationVPC Tags: - Key: Name Value: !Join [ "-", [ !Ref AWS::StackName, "Application private" ] ] ApplicationPrivateRT: Type: AWS::EC2::RouteTable Properties: VpcId: !Ref ApplicationVPC Tags: - Key: Name Value: !Join [ "-", [ !Ref AWS::StackName, "Application private" ] ] ApplicationPrivateRTA: Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: !Ref ApplicationPrivateSubnet RouteTableId: !Ref ApplicationPrivateRT # Route traffic from our applications to the GWLB endpoint ApplicationPrivateGWLBRoute: Type: AWS::EC2::Route Properties: RouteTableId: !Ref ApplicationPrivateRT VpcEndpointId: !Ref GWLBe DestinationCidrBlock: 0.0.0.0/0 # Create a test application instance ApplicationInstance: Type: AWS::EC2::Instance Properties: ImageId: !Ref LinuxAmiId InstanceType: t2.micro IamInstanceProfile: !Join [ "-", [ !Ref AWS::StackName, "EC2Role" ] ] BlockDeviceMappings: - DeviceName: /dev/xvda Ebs: VolumeSize: 8 NetworkInterfaces: - DeviceIndex: 0 SubnetId: !Ref ApplicationPrivateSubnet Tags: - Key: Name Value: !Join [ "-", [ !Ref AWS::StackName, "Application" ] ] # For the two-arm traffic return, create a Transit Gateway, attachments to both VPCs, and set routing. TGW: Type: AWS::EC2::TransitGateway Properties: AmazonSideAsn: 64512 DefaultRouteTableAssociation: enable DefaultRouteTablePropagation: enable Tags: - Key: Name Value: !Sub ${AWS::StackName} TGW Description: !Sub ${AWS::StackName} TGW TGWtoGWLBTun: Type: AWS::EC2::TransitGatewayAttachment Properties: SubnetIds: - !Ref GWLBTunPublicSubnet TransitGatewayId: !Ref TGW VpcId: !Ref GWLBTunVPC Tags: - Key: Name Value: !Sub "${AWS::StackName}-GWLBTun" TGWtoApplication: Type: AWS::EC2::TransitGatewayAttachment Properties: SubnetIds: - !Ref ApplicationPrivateSubnet TransitGatewayId: !Ref TGW VpcId: !Ref ApplicationVPC Tags: - Key: Name Value: !Sub "${AWS::StackName}-Application" TGWRouteGWLBTunToApplication: Type: AWS::EC2::Route Properties: DestinationCidrBlock: 10.20.0.0/16 RouteTableId: !Ref GWLBTunPublicRT TransitGatewayId: !Ref TGW DependsOn: - TGWtoGWLBTun