AWSTemplateFormatVersion: '2010-09-09' Description: HPC-Networking Parameters: CidrBlock: AllowedPattern: '((\d{1,3})\.){3}\d{1,3}/\d{1,2}' Default: 10.3.0.0/16 Description: VPC CIDR Block (eg 10.3.0.0/16) Type: String CidrPublicSubnetA: AllowedPattern: '((\d{1,3})\.){3}\d{1,3}/\d{1,2}' Default: 10.3.128.0/20 Description: VPC CIDR Block for the Public Subnet A (eg 10.3.128.0/20) Type: String CidrPublicSubnetB: AllowedPattern: '((\d{1,3})\.){3}\d{1,3}/\d{1,2}' Default: 10.3.144.0/20 Description: VPC CIDR Block for the Public Subnet B (eg 10.3.144.0/20) Type: String CidrPrivateSubnetA: AllowedPattern: '((\d{1,3})\.){3}\d{1,3}/\d{1,2}' Default: 10.3.0.0/18 Description: VPC CIDR Block for the Private Subnet A (eg 10.3.1.0/18) Type: String CidrPrivateSubnetB: AllowedPattern: '((\d{1,3})\.){3}\d{1,3}/\d{1,2}' Default: 10.3.64.0/18 Description: VPC CIDR Block for the Private Subnet B (eg 10.3.64.0/18) Type: String Mappings: RegionMap: us-east-1: ZoneId1: use1-az6 ZoneId2: use1-az4 us-east-2: ZoneId1: use2-az2 ZoneId2: use2-az3 us-west-1: ZoneId1: usw1-az1 ZoneId2: usw1-az3 us-west-2: ZoneId1: usw2-az1 ZoneId2: usw2-az2 eu-central-1: ZoneId1: euc1-az3 ZoneId2: euc1-az2 eu-west-1: ZoneId1: euw1-az1 ZoneId2: euw1-az2 eu-north-1: ZoneId1: eun1-az2 ZoneId2: eun1-az1 ca-central-1: ZoneId1: cac1-az2 ZoneId2: cac1-az1 eu-south-1: ZoneId1: eus1-az2 ZoneId2: eus1-az1 ap-east-1: ZoneId1: ape1-az3 ZoneId2: ape1-az2 ap-northeast-1: ZoneId1: apne1-az4 ZoneId2: apne1-az1 ap-northeast-2: ZoneId1: apne2-az1 ZoneId2: apne2-az3 ap-south-1: ZoneId1: aps1-az2 ZoneId2: aps1-az3 Resources: VPC: Type: AWS::EC2::VPC Properties: CidrBlock: !Ref CidrBlock EnableDnsHostnames: true EnableDnsSupport: true Tags: - Key: "Name" Value: !Sub '${AWS::StackName}-HPC-VPC' PublicSubnetA: Type: AWS::EC2::Subnet Properties: VpcId: !Ref VPC CidrBlock: !Ref CidrPublicSubnetA AvailabilityZone: !GetAtt AvailabiltyZone1.ZoneName MapPublicIpOnLaunch: true Tags: - Key: Name Value: !Sub '${AWS::StackName}-Public-SubnetA' PublicSubnetB: Type: AWS::EC2::Subnet Properties: VpcId: !Ref VPC CidrBlock: !Ref CidrPublicSubnetB AvailabilityZone: !GetAtt AvailabiltyZone2.ZoneName MapPublicIpOnLaunch: true Tags: - Key: Name Value: !Sub '${AWS::StackName}-Public-SubnetB' InternetGateway: Type: AWS::EC2::InternetGateway AttachGateway: Type: AWS::EC2::VPCGatewayAttachment Properties: VpcId: !Ref VPC InternetGatewayId: !Ref InternetGateway PublicRouteTable: Type: AWS::EC2::RouteTable Properties: VpcId: !Ref VPC Tags: - Key: Name Value: !Sub '${AWS::StackName}-Public-Route' PublicRoute1: Type: AWS::EC2::Route Properties: RouteTableId: !Ref PublicRouteTable DestinationCidrBlock: 0.0.0.0/0 GatewayId: !Ref InternetGateway PublicSubnetARouteTableAssociation: Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: !Ref PublicSubnetA RouteTableId: !Ref PublicRouteTable PublicSubnetBRouteTableAssociation: Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: !Ref PublicSubnetB RouteTableId: !Ref PublicRouteTable PrivateSubnetA: Type: AWS::EC2::Subnet Properties: VpcId: !Ref VPC AvailabilityZone: !GetAtt AvailabiltyZone1.ZoneName CidrBlock: !Ref CidrPrivateSubnetA MapPublicIpOnLaunch: false Tags: - Key: Name Value: !Sub '${AWS::StackName}-Private-SubnetA' PrivateSubnetB: Type: AWS::EC2::Subnet Properties: VpcId: !Ref VPC AvailabilityZone: !GetAtt AvailabiltyZone2.ZoneName CidrBlock: !Ref CidrPrivateSubnetB MapPublicIpOnLaunch: false Tags: - Key: Name Value: !Sub '${AWS::StackName}-Private-SubnetB' NatGatewayAEIP: Type: AWS::EC2::EIP DependsOn: AttachGateway Properties: Domain: vpc NatGatewayBEIP: Type: AWS::EC2::EIP DependsOn: AttachGateway Properties: Domain: vpc NatGatewayA: Type: AWS::EC2::NatGateway Properties: AllocationId: !GetAtt NatGatewayAEIP.AllocationId SubnetId: !Ref PublicSubnetA NatGatewayB: Type: AWS::EC2::NatGateway Properties: AllocationId: !GetAtt NatGatewayBEIP.AllocationId SubnetId: !Ref PublicSubnetB PrivateRouteTableA: Type: AWS::EC2::RouteTable Properties: VpcId: !Ref VPC Tags: - Key: Name Value: !Sub '${AWS::StackName}-Private-Route-A' PrivateRouteTableB: Type: AWS::EC2::RouteTable Properties: VpcId: !Ref VPC Tags: - Key: Name Value: !Sub '${AWS::StackName}-Private-Route-B' DefaultPrivateRouteA: Type: AWS::EC2::Route Properties: RouteTableId: !Ref PrivateRouteTableA DestinationCidrBlock: 0.0.0.0/0 NatGatewayId: !Ref NatGatewayA DefaultPrivateRouteB: Type: AWS::EC2::Route Properties: RouteTableId: !Ref PrivateRouteTableB DestinationCidrBlock: 0.0.0.0/0 NatGatewayId: !Ref NatGatewayB PrivateSubnetARouteTableAssociation: Type: AWS::EC2::SubnetRouteTableAssociation Properties: RouteTableId: !Ref PrivateRouteTableA SubnetId: !Ref PrivateSubnetA PrivateSubnetBRouteTableAssociation: Type: AWS::EC2::SubnetRouteTableAssociation Properties: RouteTableId: !Ref PrivateRouteTableB SubnetId: !Ref PrivateSubnetB AvailabiltyZone1: Type: Custom::AvailabiltyZone DependsOn: LogGroupGetAZLambdaFunction Properties: ServiceToken: !GetAtt GetAZLambdaFunction.Arn ZoneId: !FindInMap [RegionMap, !Ref "AWS::Region", ZoneId1] AvailabiltyZone2: Type: Custom::AvailabiltyZone DependsOn: LogGroupGetAZLambdaFunction Properties: ServiceToken: !GetAtt GetAZLambdaFunction.Arn ZoneId: !FindInMap [RegionMap, !Ref "AWS::Region", ZoneId2] LogGroupGetAZLambdaFunction: Type: AWS::Logs::LogGroup DeletionPolicy: Delete Properties: LogGroupName: !Sub /aws/lambda/${GetAZLambdaFunction} RetentionInDays: 7 GetAZLambdaFunction: Type: AWS::Lambda::Function Properties: Description: GetAZLambdaFunction Timeout: 60 Runtime: python3.7 Handler: index.handler Role: !GetAtt GetAZLambdaRole.Arn Code: ZipFile: | import cfnresponse from json import dumps from boto3 import client EC2 = client('ec2') def handler(event, context): if event['RequestType'] in ('Create', 'Update'): print(dumps(event, default=str)) data = {} try: response = EC2.describe_availability_zones( Filters=[{'Name': 'zone-id', 'Values': [event['ResourceProperties']['ZoneId']]}] ) print(dumps(response, default=str)) data['ZoneName'] = response['AvailabilityZones'][0]['ZoneName'] except Exception as error: cfnresponse.send(event, context, cfnresponse.FAILED, {}, reason=error) finally: cfnresponse.send(event, context, cfnresponse.SUCCESS, data) else: cfnresponse.send(event, context, cfnresponse.SUCCESS, {}) Tags: - Key: Name Value: !Sub ${AWS::StackName}-GetAZLambdaFunction GetAZLambdaRole: Type: AWS::IAM::Role Properties: Path: / Description: GetAZLambdaFunction AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: - sts:AssumeRole Principal: Service: - !Sub 'lambda.${AWS::URLSuffix}' ManagedPolicyArns: - !Sub 'arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole' Policies: - PolicyName: GetAZLambdaFunction PolicyDocument: Version: '2012-10-17' Statement: - Sid: ec2 Effect: Allow Action: - ec2:DescribeAvailabilityZones Resource: - '*' Tags: - Key: Name Value: !Sub ${AWS::StackName}-GetAZLambdaFunction S3Endpoint: Type: 'AWS::EC2::VPCEndpoint' Properties: VpcEndpointType: 'Gateway' ServiceName: !Sub 'com.amazonaws.${AWS::Region}.s3' RouteTableIds: - !Ref PublicRouteTable - !Ref PrivateRouteTableA - !Ref PrivateRouteTableB VpcId: !Ref VPC localSG: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: Allow all traffic from resources in VPC VpcId: Ref: VPC SecurityGroupIngress: - IpProtocol: -1 CidrIp: !Ref CidrBlock SecurityGroupEgress: - IpProtocol: -1 CidrIp: !Ref CidrBlock Outputs: VPC: Description: The ID of the VPC Value: !Ref VPC Export: Name: !Sub "${AWS::StackName}-VPC" PrivateSubnetA: Description: The ID of the PrivateSubnetA Value: !Ref PrivateSubnetA Export: Name: !Sub "${AWS::StackName}-PrivateSubnetA" PrivateSubnetB: Description: The ID of the PrivateSubnetB Value: !Ref PrivateSubnetB Export: Name: !Sub "${AWS::StackName}-PrivateSubnetB" PublicSubnetA: Description: The ID of the PublicSubnetA Value: !Ref PublicSubnetA Export: Name: !Sub "${AWS::StackName}-PublicSubnetA" PublicSubnetB: Description: The ID of the PublicSubnetB Value: !Ref PublicSubnetB Export: Name: !Sub "${AWS::StackName}-PublicSubnetB" localSG: Description: The ID of the localSG Value: !Ref localSG Export: Name: !Sub "${AWS::StackName}-localSG"