
# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: MIT-0
---
AWSTemplateFormatVersion: 2010-09-09
Parameters:
  MyKeyPair:
    Description: Amazon EC2 Key Pair for bastion instance and the OWCA server
    Type: "AWS::EC2::KeyPair::KeyName"
  CreateBastionParameter:
    Description: Create a Bastion Instance for access to the OWCA server?
    Default: Yes
    Type: String
    AllowedValues:
      - Yes
      - No
    ConstraintDescription: Must specify Yes or No.
  CreateCustomResource:
    Description: Create an OpsWorks for Chef Automateserver as part of this new VPC on this same stack?
    Default: Yes
    Type: String
    AllowedValues:
      - Yes
      - No
    ConstraintDescription: Must specify Yes or No.
Conditions:
  CreateBastionCondition: !Equals [ !Ref CreateBastionParameter, Yes ]
  CreateCustomResourceCondition: !Equals [ !Ref CreateCustomResource, Yes ]
Resources:
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 172.31.0.0/16
      EnableDnsSupport: true
      EnableDnsHostnames: true
      InstanceTenancy: default
  InternetGateway:
    Type: AWS::EC2::InternetGateway
  VPCGatewayAttachment:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref VPC
      InternetGatewayId: !Ref InternetGateway
  ServerSubnet:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: !Select
        - 0
        - !GetAZs
          Ref: 'AWS::Region'
      CidrBlock: 172.31.0.0/20
  NodeSubnet:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: !Select
        - 1
        - !GetAZs
          Ref: 'AWS::Region'
      CidrBlock: 172.31.16.0/20
  BastionSubnet:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: !Select
        - 2
        - !GetAZs
          Ref: 'AWS::Region'
      CidrBlock: 172.31.32.0/20
      MapPublicIpOnLaunch: true
  PrivateRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
  PublicRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
  InternetRoute:
    Type: AWS::EC2::Route
    DependsOn: InternetGateway
    Properties:
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway
      RouteTableId: !Ref PublicRouteTable
  BastionSubnetRouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref PublicRouteTable
      SubnetId: !Ref BastionSubnet
  ServerSubnetRouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref PrivateRouteTable
      SubnetId: !Ref ServerSubnet
  NodeSubnetRouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref PrivateRouteTable
      SubnetId: !Ref NodeSubnet
  PublicSubnetSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: "Internet Group"
      GroupDescription: "SSH traffic in, all traffic out."
      VpcId: !Ref VPC
      SecurityGroupIngress:
        -
          IpProtocol: tcp
          FromPort: '3128'
          ToPort: '3128'
          CidrIp: 0.0.0.0/0
        -
          IpProtocol: tcp
          FromPort: '22'
          ToPort: '22'
          CidrIp: 0.0.0.0/0
        -
          IpProtocol: tcp
          FromPort: '443'
          ToPort: '443'
          CidrIp: 0.0.0.0/0
      SecurityGroupEgress:
        - IpProtocol: -1
          CidrIp: 0.0.0.0/0
  PrivateSubnetSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: "Interface Security Group for the Private Subnets"
      GroupDescription: "Security Group for the Private Resoruces"
      VpcId: !Ref VPC
      SecurityGroupIngress:
        -
          IpProtocol: tcp
          FromPort: '22'
          ToPort: '22'
          SourceSecurityGroupId: !Ref PublicSubnetSecurityGroup
        -
          IpProtocol: tcp
          FromPort: '443'
          ToPort: '443'
          CidrIp: 0.0.0.0/0
      SecurityGroupEgress:
        - IpProtocol: -1
          CidrIp: 0.0.0.0/0
  InterfaceToBastion:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !Ref PublicSubnetSecurityGroup
      IpProtocol: -1
      SourceSecurityGroupId: !Ref PrivateSubnetSecurityGroup

  S3Endpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      RouteTableIds:
        - !Ref PrivateRouteTable
        - !Ref PublicRouteTable
      ServiceName: !Join
        - ''
        - - com.amazonaws.
          - !Ref 'AWS::Region'
          - .s3
      VpcId: !Ref VPC
  SSMEndpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      PrivateDnsEnabled: true
      ServiceName: !Join
        - ''
        - - com.amazonaws.
          - !Ref 'AWS::Region'
          - .ssm
      VpcId: !Ref VPC
      SubnetIds:
        - !Ref ServerSubnet
        - !Ref NodeSubnet
        - !Ref BastionSubnet
      SecurityGroupIds:
        - !Ref PrivateSubnetSecurityGroup
      VpcEndpointType: Interface
  EC2Endpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      PrivateDnsEnabled: true
      ServiceName: !Join
        - ''
        - - com.amazonaws.
          - !Ref 'AWS::Region'
          - .ec2
      VpcEndpointType: Interface
      SubnetIds:
        - !Ref ServerSubnet
        - !Ref NodeSubnet
        - !Ref BastionSubnet
      SecurityGroupIds:
        - !Ref PrivateSubnetSecurityGroup
      VpcId: !Ref VPC
  EC2MessagesEndpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      PrivateDnsEnabled: true
      ServiceName: !Join
        - ''
        - - com.amazonaws.
          - !Ref 'AWS::Region'
          - .ec2messages
      VpcEndpointType: Interface
      SubnetIds:
        - !Ref ServerSubnet
        - !Ref NodeSubnet
        - !Ref BastionSubnet
      SecurityGroupIds:
        - !Ref PrivateSubnetSecurityGroup
      VpcId: !Ref VPC
  CFNEndpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      PrivateDnsEnabled: true
      ServiceName: !Join
        - ''
        - - com.amazonaws.
          - !Ref 'AWS::Region'
          - .cloudformation
      VpcEndpointType: Interface
      SubnetIds:
        - !Ref ServerSubnet
        - !Ref NodeSubnet
        - !Ref BastionSubnet
      SecurityGroupIds:
        - !Ref PrivateSubnetSecurityGroup
      VpcId: !Ref VPC
  BastionHostInstanceStack:
    Type: AWS::CloudFormation::Stack
    Condition: CreateBastionCondition
    Properties:
      TemplateURL: https://s3.amazonaws.com/opsworkscm/BastionHost.yaml
      Parameters:
        SecurityGroup: !Ref PublicSubnetSecurityGroup
        KeyPair: !Ref MyKeyPair
        SubnetId: !Ref BastionSubnet
  CustomResourceStack:
    Type: AWS::CloudFormation::Stack
    Condition: CreateCustomResourceCondition
    Properties:
      TemplateURL: https://s3.amazonaws.com/opsworkscm/CustomResource.yaml
      Parameters:
        SecurityGroup: !Ref PrivateSubnetSecurityGroup
        KeyPair: !Ref MyKeyPair
        SubnetId: !Ref ServerSubnet
Outputs:
  ChefVPC:
    Description: The VPC created
    Value: !Ref VPC
  NodeSubnet:
    Description: The Private Subnet for Nodes
    Value: !Ref NodeSubnet
  ServerSubnet:
    Description: The Private Subnet for the Server
    Value: !Ref ServerSubnet
  PublicSubnet:
    Description: The Public subnet for the Bastion Host
    Value: !Ref BastionSubnet
