AWSTemplateFormatVersion: '2010-09-09'
Description:  This template deploys the infrastructure for the EMR on Outposts blog post

Parameters:
# -----------------------------------------------------------------------------------
# VPC and subnet CIDRs
#
  VpcCIDR:
    Type: "String"
    Description: "VPC CIDR. Corresponds to circle 5 in the architecture diagram"
    Default: "10.11.0.0/16"

Resources:
# -----------------------------------------------------------------------------------
#  VPC used to allow the private connectivity with S3
#
  VPCS3PrivateAccess:
    Type: 'AWS::EC2::VPC'
    Metadata:
      cfn_nag:
        rules_to_suppress:
          - id: W60
            reason: "VPC flow log will not be enable in this sample code. If you need to enable it, follow the instructions in https://docs.aws.amazon.com/vpc/latest/userguide/working-with-flow-logs.html"
    Properties:
      CidrBlock: !Ref VpcCIDR
      EnableDnsHostnames: true
      EnableDnsSupport: true
      Tags:
        - Key: "Name"
          Value: "vpc-s3-private-access"

# -----------------------------------------------------------------------------------
# Subnets
#
  # Private subnet to allow private connectivity with S3
  PrivateSubnet:
    Type: AWS::EC2::Subnet
    Metadata:
      cfn-lint:
        config:
          ignore_checks:
            - W3010
    Properties:
      VpcId: !Ref VPCS3PrivateAccess
      CidrBlock: !ImportValue AmazonS3SubnetCIDR
      MapPublicIpOnLaunch: false

# -----------------------------------------------------------------------------------
#  Route tables
#
  # Private Route Table to associate to the Private subnet
  PrivateRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPCS3PrivateAccess

# -----------------------------------------------------------------------------------
#  Route table subnet association
#
  # Public Subnet Route Table Association
  PrivateSubnetRouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref PrivateRouteTable
      SubnetId: !Ref PrivateSubnet

# -----------------------------------------------------------------------------------
#  Amazon S3 endpoint
#
  # Security group for the S3 endpoint
  AmazonS3EndpointSecurityGroup:
    Type: 'AWS::EC2::SecurityGroup'
    Properties:
      GroupDescription: Allow HTTPS traffic from the VPC
      VpcId: !Ref VPCS3PrivateAccess
      SecurityGroupIngress:
        - Description: Allow inboud traffic inside the VPC on port 443
          IpProtocol: tcp
          FromPort: 443
          ToPort: 443
          CidrIp: !GetAtt VPCS3PrivateAccess.CidrBlock
        - Description: Allow inboud traffic inside the VPC from the Outpost subnet
          IpProtocol: tcp
          FromPort: 443
          ToPort: 443
          CidrIp: !ImportValue OutpostSubnetCIDR
      SecurityGroupEgress:
        - Description: Allow outbound traffic inside the VPC
          IpProtocol: tcp
          FromPort: 443
          ToPort: 443
          CidrIp: !GetAtt VPCS3PrivateAccess.CidrBlock
        - Description: Allow outbound traffic to the Outpost subnet
          IpProtocol: tcp
          FromPort: 443
          ToPort: 443
          CidrIp: !ImportValue OutpostSubnetCIDR

  AmazonS3InterfaceEndpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      SecurityGroupIds:
        - !Ref AmazonS3EndpointSecurityGroup
      ServiceName: !Sub "com.amazonaws.${AWS::Region}.s3"
      VpcEndpointType: Interface
      SubnetIds:
           - !Ref PrivateSubnet
      VpcId: !Ref VPCS3PrivateAccess

  VirtualPrivateGateway: 
    Type: AWS::EC2::VPNGateway
    Properties: 
        Type: ipsec.1

  VirtualPrivateGatewayAttachment:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId:
        Ref: VPCS3PrivateAccess
      VpnGatewayId:
        Ref: VirtualPrivateGateway

  OutpostPrivateSubnetNatRoute:
    DependsOn:
         - VirtualPrivateGatewayAttachment
    Type: AWS::EC2::Route
    Properties:
      RouteTableId: 
        Ref: PrivateRouteTable
      DestinationCidrBlock: !ImportValue OutpostSubnetCIDR
      GatewayId: 
        Ref: VirtualPrivateGateway

# -----------------------------------------------------------------------------------
# Route 53 private zone
#
  # Create a route 53 private hosted zone
  PrivateHostedZone:
    Type: AWS::Route53::HostedZone
    Properties:
      Name: !Sub "s3.${AWS::Region}.amazonaws.com"
      VPCs:
        - VPCId: !Ref VPCS3PrivateAccess
          VPCRegion: !Ref "AWS::Region"
        - VPCId: !ImportValue 'VPCID'
          VPCRegion: !Ref "AWS::Region"

  # Create a record for the route 53 private zone for the S3 alias
  PrivateHostedZoneAliasRootRecord:
    Type: AWS::Route53::RecordSet
    Properties:
      HostedZoneId: !Ref PrivateHostedZone
      Name: !Sub "s3.${AWS::Region}.amazonaws.com"
      Type: A
      AliasTarget:
        DNSName: !Select ['1', !Split [':', !Select ['0', !GetAtt AmazonS3InterfaceEndpoint.DnsEntries]]]
        HostedZoneId: !Select ['0', !Split [':', !Select ['0', !GetAtt AmazonS3InterfaceEndpoint.DnsEntries]]]

  PrivateHostedZoneAliasSubdomainRecord:
    Type: AWS::Route53::RecordSet
    Properties:
      HostedZoneId: !Ref PrivateHostedZone
      Name: !Sub "*.s3.${AWS::Region}.amazonaws.com"
      Type: A
      AliasTarget:
        DNSName: !Select ['1', !Split [':', !Select ['0', !GetAtt AmazonS3InterfaceEndpoint.DnsEntries]]]
        HostedZoneId: !Select ['0', !Split [':', !Select ['0', !GetAtt AmazonS3InterfaceEndpoint.DnsEntries]]]
