---
AWSTemplateFormatVersion: 2010-09-09
Description: Biotech Blueprint is an AWS Quick Start that helps Biotech companies deploy core AWS Infrastructure as well as CloudFormation templates for common ISV solutions. (qs-1of009lua)
Metadata:
  QuickStartDocumentation:
    EntrypointName: "Parameter for existing VPC"
  AWS::CloudFormation::Interface:
    ParameterGroups:
      - Label:
          default: DNS information
        Parameters:
          - pInternalDnsSecondLevelDomain
          - pInternalDnsTLDDomain
      - Label:
          default: Networking information
        Parameters:
          - pAvailabilityZones
          - pPreclinicalVPCCidrAandBBlock
          - pManagementVPCCidrAandBBlock
      - Label:
          default: Misc Options
        Parameters:
          - pNotifyEmail
          - pSupportConfig
          - pKeyPairName
      - Label:
          default: Managed VPN
        Parameters:
          - pCreateClientVPNEndpoint
          - pClientCidr
          - pTargetNetworkCidr
      - Label:
          default: Biotech Blueprint Informatics Catalog
        Parameters:
          - pLaunchServiceCatalogPortfolio
      - Label:
          default: AWS Quick Start Configuration
        Parameters:
          - QSS3BucketName
          - QSS3BucketRegion
          - QSS3KeyPrefix
    ParameterLabels:
      pPreclinicalVPCCidrAandBBlock:
        default: A and B CIDR Blocks for Preclinical VPC
      pManagementVPCCidrAandBBlock:
        default: A and B CIDR Blocks for Management VPC
      pAvailabilityZones:
        default: Availability Zones
      pNotifyEmail:
        default: Notification Email Address
      QSS3BucketName:
        default: Quick Start S3 Bucket Name
      QSS3BucketRegion:
        default: Quick Start S3 bucket region
      QSS3KeyPrefix:
        default: Quick Start S3 Key Prefix
      pInternalDnsSecondLevelDomain:
        default: Preferred internal 2nd level domain name
      pInternalDnsTLDDomain:
        default: Preferred internal top level domain name
      pSupportConfig:
        default: Support AWS Config
      pCreateClientVPNEndpoint:
        default: Create an Client VPN Endpoint
      pClientCidr:
        default: VPN Client CIDR Range (when connected)
      pTargetNetworkCidr:
        default: Inbound VPN Client CIDR Range (for ingress)
      pLaunchServiceCatalogPortfolio:
        default: Create Informatics Catalog?
      pKeyPairName:
        default: Key Pair
Parameters:
  pPreclinicalVPCCidrAandBBlock:
    Description: Preferred A and B CIDR block for Preclinical VPC. For example, this would be 10.82 in 10.82.0.0/20. Default is 10.82.
    Type: String
    Default: 10.82
  pManagementVPCCidrAandBBlock:
    Description: Preferred A and B CIDR block for Management VPC. For example, this would be 10.81 in 10.81.0.0/20. Default is 10.81.
    Type: String
    Default: 10.81
  pAvailabilityZones:
    Description:
      List of Availability Zones to use for the subnets in the VPC. Only
      two Availability Zones are used for this deployment, and the logical order of
      your selections is preserved.
    Type: List<AWS::EC2::AvailabilityZone::Name>
  pNotifyEmail:
    Description: Notification email address for security events (you will receive a confirmation email)
    Type: String
  QSS3BucketName:
    AllowedPattern: ^[0-9a-zA-Z]+([0-9a-zA-Z-]*[0-9a-zA-Z])*$
    ConstraintDescription:
      Quick Start bucket name can include numbers, lowercase
      letters, uppercase letters, and hyphens (-). It cannot start or end with a hyphen
      (-).
    Default: aws-quickstart
    Description:
      S3 bucket name for the Quick Start assets. Quick Start bucket name
      can include numbers, lowercase letters, uppercase letters, and hyphens (-).
      It cannot start or end with a hyphen (-).
    Type: String
  QSS3BucketRegion:
    Default: "us-east-1"
    Description: "The AWS Region where the Quick Start S3 bucket (QSS3BucketName) is hosted. When using your own bucket, you must specify this value."
    Type: String
  QSS3KeyPrefix:
    AllowedPattern: ^[0-9a-zA-Z-/]*$
    ConstraintDescription:
      Quick Start key prefix can include numbers, lowercase letters,
      uppercase letters, hyphens (-), and a forward slash (/) at the end of the prefix.
    Default: quickstart-biotech-blueprint/
    Description:
      S3 key prefix for the Quick Start assets. Quick Start key prefix
      can include numbers, lowercase letters, uppercase letters, hyphens (-), and
      forward slash (/).
    Type: String
  pInternalDnsSecondLevelDomain:
    Description: What second level domain should future biotech blueprint resources use? This would be the 'mycompany' portion of mycompany.com. Default is 'corp'
    Default: corp
    Type: String
  pInternalDnsTLDDomain:
    Description: What TLD domain should future biotech blueprint resources use? This would be the 'com' portion of mycompany.com.
    Default: com
    Type: String
  pSupportConfig:
    Description: Adds Config Rules to your deployment provided that the region supports Config Rules and you have previously deployed a Config Recorder. Default is No
    Type: String
    AllowedValues:
      - "Yes"
      - "No"
    Default: "No"
  pCreateClientVPNEndpoint:
    Description: Do want to deploy the AWS Client VPN Endpoint solution? This is a managed VPN solution to securely access the VPCs created by the quickstart.
    Type: String
    AllowedValues:
      - "Yes"
      - "No"
    Default: "Yes"
  pClientCidr:
    Description: What CIDR range should you give your VPN clients? Leave the default if you are unsure what this is.
    Type: String
    Default: "11.0.0.0/16"
  pTargetNetworkCidr:
    Description: "What CIDR range will your VPN clients be coming from? This could be your corporate network or 0.0.0.0/0 to make it public."
    Type: String
  pLaunchServiceCatalogPortfolio:
    Description: Do you want to make additional informatics tools available after deployment via service catalog?
    Type: String
    AllowedValues:
      - "Yes"
      - "No"
    Default: "Yes"
  pKeyPairName:
    Description: Public/private key pairs allow you to securely connect to your NAT instance after it launches. This is used only if the region does not support NAT gateways, but still required.
    Type: AWS::EC2::KeyPair::KeyName
Mappings:
  RegionServiceSupport:
    us-east-1:
      ConfigRules: true
      Glacier: true
    us-west-2:
      ConfigRules: true
      Glacier: true
    eu-west-1:
      ConfigRules: true
      Glacier: true
  AWSAMIRegionMap:
    us-east-1:
      AMI: ami-c481fad3
      InstanceType: m4.large
    us-west-2:
      AMI: ami-b04e92d0
      InstanceType: m4.large
    eu-west-1:
      AMI: ami-d41d58a7
      InstanceType: m4.large

Conditions:
  UsingDefaultBucket: !Equals [!Ref QSS3BucketName, "aws-quickstart"]
  cLoadConfigRulesTemplate:
    !And [
      !Equals [
        !FindInMap [RegionServiceSupport, !Ref "AWS::Region", ConfigRules],
        true,
      ],
      !Equals [pSupportConfig, "Yes"],
    ]
  cCreateClientVPNEndpoint: !Equals [!Ref pCreateClientVPNEndpoint, "Yes"]
  cLaunchServiceCatalogPortfolio:
    !Equals [!Ref pLaunchServiceCatalogPortfolio, "Yes"]

Resources:
  # Create standard IAM users
  rIam:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: !Sub
        - "https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}submodules/quickstart-compliance-common/templates/iam.template"
        - S3Region:
            !If [UsingDefaultBucket, !Ref "AWS::Region", !Ref QSS3BucketRegion]
          S3Bucket:
            !If [
              UsingDefaultBucket,
              !Sub "${QSS3BucketName}-${AWS::Region}",
              !Ref QSS3BucketName,
            ]

  # Create logging config
  rLogging:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: !Sub
        - "https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}submodules/quickstart-compliance-common/templates/logging.template"
        - S3Region:
            !If [UsingDefaultBucket, !Ref "AWS::Region", !Ref QSS3BucketRegion]
          S3Bucket:
            !If [
              UsingDefaultBucket,
              !Sub "${QSS3BucketName}-${AWS::Region}",
              !Ref QSS3BucketName,
            ]
      Parameters:
        pNotifyEmail: !Ref pNotifyEmail
        pSupportsGlacier:
          !FindInMap [RegionServiceSupport, !Ref "AWS::Region", Glacier]
  # Create PreclinicalVPC
  rPreclinicalVpc:
    Type: AWS::CloudFormation::Stack
    DependsOn:
      - rLogging
    Properties:
      TemplateURL: !Sub
        - "https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}submodules/quickstart-aws-vpc/templates/aws-vpc.template"
        - S3Region:
            !If [UsingDefaultBucket, !Ref "AWS::Region", !Ref QSS3BucketRegion]
          S3Bucket:
            !If [
              UsingDefaultBucket,
              !Sub "${QSS3BucketName}-${AWS::Region}",
              !Ref QSS3BucketName,
            ]
      Parameters:
        AvailabilityZones: !Join [",", !Ref pAvailabilityZones]
        CreateAdditionalPrivateSubnets: true
        CreatePrivateSubnets: true
        KeyPairName: !Ref pKeyPairName
        NATInstanceType:
          !FindInMap [AWSAMIRegionMap, !Ref "AWS::Region", InstanceType]
        NumberOfAZs: 2
        PrivateSubnet1ACIDR: !Sub ${pPreclinicalVPCCidrAandBBlock}.96.0/21
        PrivateSubnet1BCIDR: !Sub ${pPreclinicalVPCCidrAandBBlock}.119.0/21
        PrivateSubnet2ACIDR: !Sub ${pPreclinicalVPCCidrAandBBlock}.194.0/21
        PrivateSubnet2BCIDR: !Sub ${pPreclinicalVPCCidrAandBBlock}.212.0/21
        PublicSubnet1CIDR: !Sub ${pPreclinicalVPCCidrAandBBlock}.10.0/24
        PublicSubnet2CIDR: !Sub ${pPreclinicalVPCCidrAandBBlock}.20.0/24
        VPCCIDR: !Sub ${pPreclinicalVPCCidrAandBBlock}.0.0/16
        PublicSubnetTag1: "Name=DMZ Subnet"
        PrivateSubnetATag1: "Name=App Subnet"
        PrivateSubnetBTag1: "Name=DB Subnet"
  # Create management VPC
  rManagementVpc:
    Type: AWS::CloudFormation::Stack
    DependsOn:
      - rLogging
    Properties:
      TemplateURL: !Sub
        - "https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}submodules/quickstart-aws-vpc/templates/aws-vpc.template"
        - S3Region:
            !If [UsingDefaultBucket, !Ref "AWS::Region", !Ref QSS3BucketRegion]
          S3Bucket:
            !If [
              UsingDefaultBucket,
              !Sub "${QSS3BucketName}-${AWS::Region}",
              !Ref QSS3BucketName,
            ]
      Parameters:
        AvailabilityZones: !Join [",", !Ref pAvailabilityZones]
        CreateAdditionalPrivateSubnets: false
        CreatePrivateSubnets: true
        KeyPairName: !Ref pKeyPairName
        NATInstanceType:
          !FindInMap [AWSAMIRegionMap, !Ref "AWS::Region", InstanceType]
        NumberOfAZs: 2
        PrivateSubnet1ACIDR: !Sub ${pManagementVPCCidrAandBBlock}.20.0/24
        PrivateSubnet2ACIDR: !Sub ${pManagementVPCCidrAandBBlock}.30.0/24
        PublicSubnet1CIDR: !Sub ${pManagementVPCCidrAandBBlock}.1.0/24
        PublicSubnet2CIDR: !Sub ${pManagementVPCCidrAandBBlock}.2.0/24
        VPCCIDR: !Sub ${pManagementVPCCidrAandBBlock}.0.0/16
        PublicSubnetTag1: "Name=DMZ Subnet"
        PrivateSubnetATag1: "Name=Private Subnet"
  # Create additional VPC networking - peering and Internal DNS
  rVpcNetworking:
    Type: AWS::CloudFormation::Stack
    DependsOn:
      - rLogging
    Properties:
      TemplateURL: !Sub
        - "https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}templates/vpc-networking.template.yaml"
        - S3Region:
            !If [UsingDefaultBucket, !Ref "AWS::Region", !Ref QSS3BucketRegion]
          S3Bucket:
            !If [
              UsingDefaultBucket,
              !Sub "${QSS3BucketName}-${AWS::Region}",
              !Ref QSS3BucketName,
            ]
      Parameters:
        pPreclinicalVpcId: !GetAtt rPreclinicalVpc.Outputs.VPCID
        pPreclinicalVpcCidr: !GetAtt rPreclinicalVpc.Outputs.VPCCIDR
        pPreclinicalRouteTablePrivateA: !GetAtt rPreclinicalVpc.Outputs.PrivateSubnet1ARouteTable
        pPreclinicalRouteTablePrivateB: !GetAtt rPreclinicalVpc.Outputs.PrivateSubnet2ARouteTable
        pPreclinicalRouteTablePublic: !GetAtt rPreclinicalVpc.Outputs.PublicSubnetRouteTable
        pManagementVpcId: !GetAtt rManagementVpc.Outputs.VPCID
        pManagementVpcCidr: !GetAtt rManagementVpc.Outputs.VPCCIDR
        pManagementRouteTablePrivateA: !GetAtt rManagementVpc.Outputs.PrivateSubnet1ARouteTable
        pManagementRouteTablePrivateB: !GetAtt rManagementVpc.Outputs.PrivateSubnet2ARouteTable
        pManagementRouteTablePublic: !GetAtt rManagementVpc.Outputs.PublicSubnetRouteTable
        pInternal2ndLevelDomainName: !Ref pInternalDnsSecondLevelDomain
        pInternalDnsTopLevelDomain: !Ref pInternalDnsTLDDomain

  # Create Config Rules
  rConfigRules:
    Type: AWS::CloudFormation::Stack
    Condition: cLoadConfigRulesTemplate
    DependsOn:
      - rIam
      - rPreclinicalVpc
      - rManagementVpc
      - rLogging
    Properties:
      TemplateURL: !Sub
        - "https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}submodules/quickstart-compliance-common/templates/config-rules.template"
        - S3Region:
            !If [UsingDefaultBucket, !Ref "AWS::Region", !Ref QSS3BucketRegion]
          S3Bucket:
            !If [
              UsingDefaultBucket,
              !Sub "${QSS3BucketName}-${AWS::Region}",
              !Ref QSS3BucketName,
            ]
      Parameters:
        pRequiredTagKey: ""
  rClientVpnEndpoint:
    Type: AWS::CloudFormation::Stack
    Condition: cCreateClientVPNEndpoint
    DependsOn:
      - rSystemsManager
      - rPreclinicalVpc
      - rLogging
      - rVpcNetworking
    Properties:
      TemplateURL: !Sub
        - "https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}templates/clientvpnendpoint.template.yaml"
        - S3Region:
            !If [UsingDefaultBucket, !Ref "AWS::Region", !Ref QSS3BucketRegion]
          S3Bucket:
            !If [
              UsingDefaultBucket,
              !Sub "${QSS3BucketName}-${AWS::Region}",
              !Ref QSS3BucketName,
            ]
      Parameters:
        pClientCidr: !Ref pClientCidr
        pTargetNetworkCidr: !Ref pTargetNetworkCidr
        QSS3BucketName: !Ref QSS3BucketName
        QSS3BucketRegion: !Ref QSS3BucketRegion
        QSS3KeyPrefix: !Ref QSS3KeyPrefix
  rServiceCatalog:
    Type: AWS::CloudFormation::Stack
    DependsOn:
      - rSystemsManager
    Condition: cLaunchServiceCatalogPortfolio
    Properties:
      TemplateURL: !Sub
        - "https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}templates/servicecatalog.template.yaml"
        - S3Region:
            !If [UsingDefaultBucket, !Ref "AWS::Region", !Ref QSS3BucketRegion]
          S3Bucket:
            !If [
              UsingDefaultBucket,
              !Sub "${QSS3BucketName}-${AWS::Region}",
              !Ref QSS3BucketName,
            ]
      Parameters:
        QSS3BucketName: !Ref QSS3BucketName
        QSS3BucketRegion: !Ref QSS3BucketRegion
        QSS3KeyPrefix: !Ref QSS3KeyPrefix

  rSystemsManager:
    Type: AWS::CloudFormation::Stack
    DependsOn:
      - rIam
      - rManagementVpc
      - rLogging
    Properties:
      TemplateURL: !Sub
        - "https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}templates/systemsmanager.template.yaml"
        - S3Region:
            !If [UsingDefaultBucket, !Ref "AWS::Region", !Ref QSS3BucketRegion]
          S3Bucket:
            !If [
              UsingDefaultBucket,
              !Sub "${QSS3BucketName}-${AWS::Region}",
              !Ref QSS3BucketName,
            ]
      Parameters:
        pVpcResearch: !GetAtt rPreclinicalVpc.Outputs.VPCID
        pVpcResearchSubnetDmzA: !GetAtt rPreclinicalVpc.Outputs.PublicSubnet1ID
        pVpcResearchSubnetDmzB: !GetAtt rPreclinicalVpc.Outputs.PublicSubnet2ID
        pVpcResearchSubnetAppA: !GetAtt rPreclinicalVpc.Outputs.PrivateSubnet1AID
        pVpcResearchSubnetAppB: !GetAtt rPreclinicalVpc.Outputs.PrivateSubnet2AID
        pVpcResearchSubnetDbA: !GetAtt rPreclinicalVpc.Outputs.PrivateSubnet1BID
        pVpcResearchSubnetDbB: !GetAtt rPreclinicalVpc.Outputs.PrivateSubnet2BID
        pQSS3BucketName: !Ref QSS3BucketName
        pQSS3KeyPrefix: !Ref QSS3KeyPrefix
        pDnsHostedZoneID: !GetAtt rVpcNetworking.Outputs.InternalHostedZoneIDParam
        pDnsHostedZoneApexDomain: !GetAtt rVpcNetworking.Outputs.InternalHostedZoneApexDomainName
        pInformaticsAccessSG: !GetAtt rVpcNetworking.Outputs.InformaticsAccessSecurityGroup
        pInternalHostedZoneTLDDomainName: !GetAtt rVpcNetworking.Outputs.InternalHostedZoneTLDDomainName
        pInternalHostedZoneSecondLevelDomainName: !GetAtt rVpcNetworking.Outputs.InternalHostedZoneSecondLevelDomainName
        pPreclinicalVPCCidrAandBBlock: !Ref pPreclinicalVPCCidrAandBBlock
        pManagementVPCCidrAandBBlock: !Ref pManagementVPCCidrAandBBlock

Outputs:
  TemplateVersion:
    Value: 1.0