---
# Creates a VPC with a Managed NAT for demo to communicate with grapfana through internet
Parameters:
  PrivateLinkDemoVpcCidrBlock:
    Default: 10.0.0.0/24
    Type: String
  PrivateSubnet01Block:
    Default: 10.0.0.0/26
    Description: CidrBlock for private subnet 1
    Type: String
  PrivateSubnet02Block:
    Default: 10.0.0.64/26
    Description: CidrBlock for private subnet 2
    Type: String
  PublicSubnet01Block:
    Default: 10.0.0.128/26
    Description: CidrBlock for public subnet 1
    Type: String
  PublicSubnet02Block:
    Default: 10.0.0.192/26
    Description: CidrBlock for public subnet 2
    Type: String

Resources:
  PrivateLinkDemoVpc:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: !Ref PrivateLinkDemoVpcCidrBlock
      EnableDnsHostnames: 'true'
      EnableDnsSupport: 'true'
      Tags:
        - Key: Name
          Value: PrivateLinkDemoVpc
        - Key: Network
          Value: Public

  PrivateSubnet01:
    Type: AWS::EC2::Subnet
    Properties:
      CidrBlock: !Ref PrivateSubnet01Block
      Tags:
        - Key: Name
          Value: PrivateSubnet01
      VpcId: !Ref PrivateLinkDemoVpc
      AvailabilityZone: !Select
        - 0
        - Fn::GetAZs: !Ref 'AWS::Region'

  PrivateSubnet02:
    Type: AWS::EC2::Subnet
    Properties:
      CidrBlock: !Ref PrivateSubnet02Block
      Tags:
        - Key: Name
          Value: PrivateSubnet02
      VpcId: !Ref PrivateLinkDemoVpc
      AvailabilityZone: !Select
        - 1
        - Fn::GetAZs: !Ref 'AWS::Region'

  PublicSubnet01:
    Type: "AWS::EC2::Subnet"
    Properties:
      VpcId: !Ref PrivateLinkDemoVpc
      AvailabilityZone: !Select
        - 0
        - Fn::GetAZs: !Ref 'AWS::Region'
      CidrBlock: !Ref PublicSubnet01Block
      MapPublicIpOnLaunch: "true"
      Tags:
        - Key: Network
          Value: Public
        - Key: Name
          Value: PublicSubnet01

  PublicSubnet02:
    Type: "AWS::EC2::Subnet"
    Properties:
      VpcId: !Ref PrivateLinkDemoVpc
      AvailabilityZone: !Select
        - 1
        - Fn::GetAZs: !Ref 'AWS::Region'
      CidrBlock: !Ref PublicSubnet02Block
      MapPublicIpOnLaunch: "true"
      Tags:
        - Key: Network
          Value: Public
        - Key: Name
          Value: PublicSubnet02

  LambdaSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: "Security group for Lambda"
      VpcId:
        Ref: PrivateLinkDemoVpc
      SecurityGroupEgress:
        - IpProtocol: tcp
          FromPort: 443
          ToPort: 443
          CidrIp: 0.0.0.0/0

  PrivateLinkDemoVpcInternetGateway:
    Type: "AWS::EC2::InternetGateway"
    Properties:
      Tags:
        - Key: "Name"
          Value: "PrivateLinkDemoVpc-IGW"

  PrivateLinkDemoVpcGatewayToInternet:
    Type: "AWS::EC2::VPCGatewayAttachment"
    Properties:
      VpcId: !Ref PrivateLinkDemoVpc
      InternetGatewayId: !Ref PrivateLinkDemoVpcInternetGateway

  PublicRouteTable:
    Type: "AWS::EC2::RouteTable"
    Properties:
      VpcId: !Ref PrivateLinkDemoVpc

  PublicRoute:
    DependsOn: PrivateLinkDemoVpcGatewayToInternet
    Type: "AWS::EC2::Route"
    Properties:
      RouteTableId: !Ref PublicRouteTable
      DestinationCidrBlock: "0.0.0.0/0"
      GatewayId: !Ref PrivateLinkDemoVpcInternetGateway

  PublicSubnetRouteTableAssociation01:
    Type: "AWS::EC2::SubnetRouteTableAssociation"
    Properties:
      SubnetId: !Ref PublicSubnet01
      RouteTableId: !Ref PublicRouteTable

  PublicSubnetRouteTableAssociation02:
    Type: "AWS::EC2::SubnetRouteTableAssociation"
    Properties:
      SubnetId: !Ref PublicSubnet02
      RouteTableId: !Ref PublicRouteTable

  PublicNetworkAcl:
    Type: "AWS::EC2::NetworkAcl"
    Properties:
      VpcId: !Ref PrivateLinkDemoVpc
      Tags:
        - Key: "Application"
          Value:
            Ref: "AWS::StackName"
        - Key: "Network"
          Value: "Public"

  InboundHTTPPublicNetworkAclEntry:
    Type: "AWS::EC2::NetworkAclEntry"
    Properties:
      NetworkAclId: !Ref PublicNetworkAcl
      RuleNumber: "100"
      Protocol: "-1"
      RuleAction: "allow"
      Egress: "false"
      CidrBlock: "0.0.0.0/0"
      PortRange:
        From: "0"
        To: "65535"

  OutboundPublicNetworkAclEntry:
    Type: "AWS::EC2::NetworkAclEntry"
    Properties:
      NetworkAclId: !Ref PublicNetworkAcl
      RuleNumber: "100"
      Protocol: "-1"
      RuleAction: "allow"
      Egress: "true"
      CidrBlock: "0.0.0.0/0"
      PortRange:
        From: "0"
        To: "65535"

  PublicSubnetNetworkAclAssociation01:
    Type: "AWS::EC2::SubnetNetworkAclAssociation"
    Properties:
      SubnetId: !Ref PublicSubnet01
      NetworkAclId: !Ref PublicNetworkAcl

  PublicSubnetNetworkAclAssociation02:
    Type: "AWS::EC2::SubnetNetworkAclAssociation"
    Properties:
      SubnetId: !Ref PublicSubnet02
      NetworkAclId: !Ref PublicNetworkAcl


  ElasticIP01:
    Type: "AWS::EC2::EIP"
    Properties:
      Domain: "vpc"

  ElasticIP02:
    Type: "AWS::EC2::EIP"
    Properties:
      Domain: "vpc"

  NATGateway01:
    Type: "AWS::EC2::NatGateway"
    Properties:
      AllocationId: !GetAtt ElasticIP01.AllocationId
      SubnetId: !Ref PublicSubnet01
  NATGateway02:
    Type: "AWS::EC2::NatGateway"
    Properties:
      AllocationId: !GetAtt ElasticIP02.AllocationId
      SubnetId: !Ref PublicSubnet02

  PrivateRouteTable01:
    Type: "AWS::EC2::RouteTable"
    Properties:
      VpcId: !Ref PrivateLinkDemoVpc
  PrivateRouteTable02:
    Type: "AWS::EC2::RouteTable"
    Properties:
      VpcId: !Ref PrivateLinkDemoVpc

  PrivateRouteToInternet01:
    Type: "AWS::EC2::Route"
    Properties:
      RouteTableId: !Ref PrivateRouteTable01
      DestinationCidrBlock: "0.0.0.0/0"
      NatGatewayId: !Ref NATGateway01

  PrivateRouteToInternet02:
    Type: "AWS::EC2::Route"
    Properties:
      RouteTableId: !Ref PrivateRouteTable02
      DestinationCidrBlock: "0.0.0.0/0"
      NatGatewayId: !Ref NATGateway02

  PrivateSubnetRouteTableAssociation01:
    Type: "AWS::EC2::SubnetRouteTableAssociation"
    Properties:
      SubnetId: !Ref PrivateSubnet01
      RouteTableId: !Ref PrivateRouteTable01

  PrivateSubnetRouteTableAssociation02:
    Type: "AWS::EC2::SubnetRouteTableAssociation"
    Properties:
      SubnetId: !Ref PrivateSubnet02
      RouteTableId: !Ref PrivateRouteTable02

  VpcEndpointSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: "Security group for the Ingest/Query VPC Endpoint"
      VpcId:
        Ref: PrivateLinkDemoVpc
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 443
          ToPort: 443
          CidrIp: !Ref PrivateLinkDemoVpcCidrBlock
      SecurityGroupEgress:
        - IpProtocol: tcp
          FromPort: 443
          ToPort: 443
          CidrIp: 0.0.0.0/0

  IngestVpcEndpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      VpcId:
        Ref: PrivateLinkDemoVpc
      ServiceName: !Sub "com.amazonaws.${AWS::Region}.timestream.ingest-cell1"
      SubnetIds:
        - !Ref PrivateSubnet01
        - !Ref PrivateSubnet02
      SecurityGroupIds:
        - !Ref  VpcEndpointSecurityGroup


  QueryVpcEndpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      VpcId:
        Ref: PrivateLinkDemoVpc
      ServiceName: !Sub "com.amazonaws.${AWS::Region}.timestream.query-cell1"
      SubnetIds:
        - !Ref PrivateSubnet01
        - !Ref PrivateSubnet02
      SecurityGroupIds:
        - !Ref  VpcEndpointSecurityGroup

Outputs:
  IngestVpcEndpointId:
    Description: "Ingest VPC Endpoint Id"
    Value: !Ref IngestVpcEndpoint
  QueryVpcEndpointId:
    Description: "Query VPC Endpoint Id"
    Value: !Ref QueryVpcEndpoint