AWSTemplateFormatVersion: '2010-09-09'
Description: Deploy an Auto Scaling Group of CloudGuard Security Gateways for Transit Gateway with an optional Management Server into an existing VPC (20230801)
Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
      - Label:
          default: Network Configuration
        Parameters:
          - VPC
          - GatewaysSubnets
      - Label:
          default: General Settings
        Parameters:
          - KeyName
          - EnableVolumeEncryption
          - VolumeSize
          - VolumeType
          - EnableInstanceConnect
          - TerminationProtection
          - AllowUploadDownload
      - Label:
          default: Check Point CloudGuard IaaS Security Gateways Auto Scaling Group Configuration
        Parameters:
          - GatewayName
          - GatewayInstanceType
          - GatewaysMinSize
          - GatewaysMaxSize
          - GatewayVersion
          - GatewayPasswordHash
          - GatewaySICKey
          - CloudWatch
          - ASN
          - AdminEmail
      - Label:
          default: Check Point CloudGuard IaaS Security Management Server Configuration
        Parameters:
          - ManagementDeploy
          - ManagementInstanceType
          - ManagementVersion
          - ManagementPasswordHash
          - ManagementPermissions
          - ManagementPredefinedRole
          - GatewaysBlades
          - AdminCIDR
          - GatewayManagement
          - GatewaysAddresses
      - Label:
          default: Automatic Provisioning with Security Management Server Settings
        Parameters:
          - ControlGatewayOverPrivateOrPublicAddress
          - ManagementServer
          - ConfigurationTemplate
    ParameterLabels:
      VPC:
        default: VPC
      GatewaysSubnets:
        default: Subnets
      KeyName:
        default: Key name
      EnableVolumeEncryption:
        default: Enable environment volume encryption
      VolumeSize:
        default: Root volume size (GB)
      VolumeType:
        default: Volume Type
      EnableInstanceConnect:
        default: Enable AWS Instance Connect
      TerminationProtection:
        default: Termination Protection
      AllowUploadDownload:
        default: Allow upload & download
      GatewayName:
        default: Name
      GatewayInstanceType:
        default: Instance type
      GatewaysMinSize:
        default: Minimum group size
      GatewaysMaxSize:
        default: Maximum group size
      GatewayVersion:
        default: Version & license
      GatewayPasswordHash:
        default: Password hash
      GatewaySICKey:
        default: SIC key
      CloudWatch:
        default: CloudWatch metrics
      ASN:
        default: BGP ASN
      AdminEmail:
        default: Email address
      ManagementDeploy:
        default: Deploy Management Server
      ManagementInstanceType:
        default: Instance type
      ManagementVersion:
        default: Version & license
      ManagementPasswordHash:
        default: Password hash
      ManagementPermissions:
        default: IAM role
      ManagementPredefinedRole:
        default: Existing IAM role name
      GatewaysBlades:
        default: Default Blades
      AdminCIDR:
        default: Administrator addresses
      GatewaysAddresses:
        default: Gateways addresses
      GatewayManagement:
        default: Manage Gateways
      ControlGatewayOverPrivateOrPublicAddress:
        default: Gateways addresses
      ManagementServer:
        default: Management Server
      ConfigurationTemplate:
        default: Configuration template
Parameters:
  VPC:
    Description: Select an existing VPC.
    Type: AWS::EC2::VPC::Id
    MinLength: 1
    ConstraintDescription: You must select a VPC.
  GatewaysSubnets:
    Description: Select at least 2 external subnets in the VPC. If you choose to deploy a Security Management Server it will be deployed in the first subnet.
    Type: List<AWS::EC2::Subnet::Id>
    MinLength: 2
  KeyName:
    Description: The EC2 Key Pair to allow SSH access to the instances created by this stack.
    Type: AWS::EC2::KeyPair::KeyName
    MinLength: 1
    ConstraintDescription: Must be the name of an existing EC2 KeyPair.
  EnableVolumeEncryption:
    Description: Encrypt Environment instances volume with default AWS KMS key.
    Type: String
    Default: true
    AllowedValues:
      - true
      - false
  VolumeSize:
    Type: Number
    MinValue: 100
    Default: 100
  VolumeType:
    Description: General Purpose SSD Volume Type
    Type: String
    Default: gp3
    AllowedValues:
      - gp3
      - gp2
  EnableInstanceConnect:
    Description: Enable SSH connection over AWS web console.
    Type: String
    Default: false
    AllowedValues:
      - true
      - false
  TerminationProtection:
    Description: Prevents an instance from accidental termination.
    Type: String
    Default: false
    AllowedValues:
      - true
      - false
  AllowUploadDownload:
    Description: Automatically download updates and share statistical data for product improvement purpose.
    Type: String
    Default: true
    AllowedValues:
      - true
      - false
  GatewayName:
    Description: The name tag of the Security Gateway instances. (optional)
    Type: String
    Default: Check-Point-Gateway
  GatewayInstanceType:
    Description: The EC2 instance type for the Security Gateways.
    Type: String
    Default: c5.xlarge
    AllowedValues:
      - c5.large
      - c5.xlarge
      - c5.2xlarge
      - c5.4xlarge
      - c5.9xlarge
      - c5.12xlarge
      - c5.18xlarge
      - c5.24xlarge
      - c5n.large
      - c5n.xlarge
      - c5n.2xlarge
      - c5n.4xlarge
      - c5n.9xlarge
      - c5n.18xlarge
      - m5.large
      - m5.xlarge
      - m5.2xlarge
      - m5.4xlarge
      - m5.8xlarge
      - m5.12xlarge
      - m5.16xlarge
      - m5.24xlarge
      - m6i.large
      - m6i.xlarge
      - m6i.2xlarge
      - m6i.4xlarge
      - m6i.8xlarge
      - m6i.12xlarge
      - m6i.16xlarge
      - m6i.24xlarge
      - m6i.32xlarge
      - c6i.large
      - c6i.xlarge
      - c6i.2xlarge
      - c6i.4xlarge
      - c6i.8xlarge
      - c6i.12xlarge
      - c6i.16xlarge
      - c6i.24xlarge
      - c6i.32xlarge
      - c6in.large
      - c6in.xlarge
      - c6in.2xlarge
      - c6in.4xlarge
      - c6in.8xlarge
      - c6in.12xlarge
      - c6in.16xlarge
      - c6in.24xlarge
      - c6in.32xlarge
      - r5.large
      - r5.xlarge
      - r5.2xlarge
      - r5.4xlarge
      - r5.8xlarge
      - r5.12xlarge
      - r5.16xlarge
      - r5.24xlarge
      - r5a.large
      - r5a.xlarge
      - r5a.2xlarge
      - r5a.4xlarge
      - r5a.8xlarge
      - r5a.12xlarge
      - r5a.16xlarge
      - r5a.24xlarge
      - r5b.large
      - r5b.xlarge
      - r5b.2xlarge
      - r5b.4xlarge
      - r5b.8xlarge
      - r5b.12xlarge
      - r5b.16xlarge
      - r5b.24xlarge
      - r5n.large
      - r5n.xlarge
      - r5n.2xlarge
      - r5n.4xlarge
      - r5n.8xlarge
      - r5n.12xlarge
      - r5n.16xlarge
      - r5n.24xlarge
      - r6i.large
      - r6i.xlarge
      - r6i.2xlarge
      - r6i.4xlarge
      - r6i.8xlarge
      - r6i.12xlarge
      - r6i.16xlarge
      - r6i.24xlarge
      - r6i.32xlarge
      - m6a.large
      - m6a.xlarge
      - m6a.2xlarge
      - m6a.4xlarge
      - m6a.8xlarge
      - m6a.12xlarge
      - m6a.16xlarge
      - m6a.24xlarge
      - m6a.32xlarge
      - m6a.48xlarge
    ConstraintDescription: Must be a valid EC2 instance type
  GatewaysMinSize:
    Description: The minimal number of Security Gateways.
    Type: Number
    Default: 2
    MinValue: 1
  GatewaysMaxSize:
    Description: The maximal number of Security Gateways.
    Type: Number
    Default: 10
    MinValue: 1
  GatewayVersion:
    Description: The version and license to install on the Security Gateways.
    Type: String
    Default: R81.20-BYOL
    AllowedValues:
      - R81.10-BYOL
      - R81.20-BYOL
      - R82-BYOL
  GatewayPasswordHash:
    Description: Admin user's password hash (use command "openssl passwd -6 PASSWORD" to get the PASSWORD's hash). (optional)
    Type: String
    Default: ''
    AllowedPattern: '^[\$\./a-zA-Z0-9]*$'
    NoEcho: true
  GatewaySICKey:
    Description: The Secure Internal Communication key creates trusted connections between Check Point components. Choose a random string consisting of at least 8 alphanumeric characters.
    Type: String
    AllowedPattern: '[a-zA-Z0-9]{8,}'
    ConstraintDescription: Secure Internal Communication activation key should contain only alpha numeric characters and be at least 8 characters long.
    NoEcho: true
  CloudWatch:
    Description: Report Check Point specific CloudWatch metrics.
    Type: String
    Default: false
    AllowedValues:
      - true
      - false
  ASN:
    Description: The organization Autonomous System Number (ASN) that identifies the routing domain for the Security Gateways.
    Type: String
    Default: 65000
    AllowedPattern: '^[0-9]+$'
  AdminEmail:
    Description: Notifications about scaling events will be sent to this email address. (optional)
    Type: String
    Default: ''
    AllowedPattern: '^(([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?))?$'
    ConstraintDescription: Must be a valid email address.
  ManagementDeploy:
    Description: Select 'false' to use an existing Security Management Server or to deploy one later and to ignore the other parameters of this section.
    Type: String
    Default: true
    AllowedValues:
      - true
      - false
  ManagementInstanceType:
    Description: The EC2 instance type of the Security Management Server.
    Type: String
    Default: m5.xlarge
    AllowedValues:
      - c5.large
      - c5.xlarge
      - c5.2xlarge
      - c5.4xlarge
      - c5.9xlarge
      - c5.12xlarge
      - c5.18xlarge
      - c5.24xlarge
      - c5n.large
      - c5n.xlarge
      - c5n.2xlarge
      - c5n.4xlarge
      - c5n.9xlarge
      - c5n.18xlarge
      - m5.large
      - m5.xlarge
      - m5.2xlarge
      - m5.4xlarge
      - m5.8xlarge
      - m5.12xlarge
      - m5.16xlarge
      - m5.24xlarge
      - m6i.large
      - m6i.xlarge
      - m6i.2xlarge
      - m6i.4xlarge
      - m6i.8xlarge
      - m6i.12xlarge
      - m6i.16xlarge
      - m6i.24xlarge
      - m6i.32xlarge
      - c6i.large
      - c6i.xlarge
      - c6i.2xlarge
      - c6i.4xlarge
      - c6i.8xlarge
      - c6i.12xlarge
      - c6i.16xlarge
      - c6i.24xlarge
      - c6i.32xlarge
      - c6in.large
      - c6in.xlarge
      - c6in.2xlarge
      - c6in.4xlarge
      - c6in.8xlarge
      - c6in.12xlarge
      - c6in.16xlarge
      - c6in.24xlarge
      - c6in.32xlarge
      - r5.large
      - r5.xlarge
      - r5.2xlarge
      - r5.4xlarge
      - r5.8xlarge
      - r5.12xlarge
      - r5.16xlarge
      - r5.24xlarge
      - r5a.large
      - r5a.xlarge
      - r5a.2xlarge
      - r5a.4xlarge
      - r5a.8xlarge
      - r5a.12xlarge
      - r5a.16xlarge
      - r5a.24xlarge
      - r5b.large
      - r5b.xlarge
      - r5b.2xlarge
      - r5b.4xlarge
      - r5b.8xlarge
      - r5b.12xlarge
      - r5b.16xlarge
      - r5b.24xlarge
      - r5n.large
      - r5n.xlarge
      - r5n.2xlarge
      - r5n.4xlarge
      - r5n.8xlarge
      - r5n.12xlarge
      - r5n.16xlarge
      - r5n.24xlarge
      - r6i.large
      - r6i.xlarge
      - r6i.2xlarge
      - r6i.4xlarge
      - r6i.8xlarge
      - r6i.12xlarge
      - r6i.16xlarge
      - r6i.24xlarge
      - r6i.32xlarge
      - m6a.large
      - m6a.xlarge
      - m6a.2xlarge
      - m6a.4xlarge
      - m6a.8xlarge
      - m6a.12xlarge
      - m6a.16xlarge
      - m6a.24xlarge
      - m6a.32xlarge
      - m6a.48xlarge
    ConstraintDescription: Must be a valid EC2 instance type
  ManagementVersion:
    Description: The version and license to install on the Security Management Server.
    Type: String
    Default: R81.20-BYOL
    AllowedValues:
      - R80.40-BYOL
      - R81-BYOL
      - R81.10-BYOL
      - R81.20-BYOL
  ManagementPasswordHash:
    Description: Admin user's password hash (use command "openssl passwd -6 PASSWORD" to get the PASSWORD's hash). (optional)
    Type: String
    Default: ''
    AllowedPattern: '[\$\./a-zA-Z0-9]*'
    NoEcho: true
  ManagementPermissions:
    Description: IAM role to attach to the instance profile.
    Type: String
    Default: Create with read-write permissions
    AllowedValues:
      - None (configure later)
      - Use existing (specify an existing IAM role name)
      - Create with assume role permissions (specify an STS role ARN)
      - Create with read permissions
      - Create with read-write permissions
  ManagementPredefinedRole:
    Description: A predefined IAM role to attach to the instance profile. Ignored if IAM role is not set to 'Use existing'.
    Type: String
    Default: ''
  GatewaysBlades:
    Description: Turn on the Intrusion Prevention System, Application Control, Anti-Virus and Anti-Bot Blades (these and additional Blades can be manually turned on or off later).
    Type: String
    Default: true
    AllowedValues:
      - true
      - false
  AdminCIDR:
    Description: Allow web, SSH, and graphical clients only from this network to communicate with the Security Management Server.
    Type: String
    AllowedPattern: '^((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2])))?$'
  GatewayManagement:
    Description: Select 'Over the internet' if any of the gateways you wish to manage are not directly accessed via their private IP address.
    Type: String
    Default: Locally managed
    AllowedValues:
      - Locally managed
      - Over the internet
  GatewaysAddresses:
    Description: Allow gateways only from this network to communicate with the Security Management Server.
    Type: String
    AllowedPattern: '^$|^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2]))$'
  ControlGatewayOverPrivateOrPublicAddress:
    Description: Determines if the gateways are provisioned using their private or public address.
    Type: String
    Default: private
    AllowedValues:
      - private
      - public
  ManagementServer:
    Description: The name that represents the Security Management Server in the automatic provisioning configuration.
    Type: String
    Default: management-server
    MinLength: 1
  ConfigurationTemplate:
    Description: A name of a gateway configuration template in the automatic provisioning configuration.
    Type: String
    Default: TGW-ASG-configuration
    MinLength: 1
Conditions:
  VolumeEncryption: !Equals [!Ref EnableVolumeEncryption, true]
  DeployManagement: !Equals [!Ref ManagementDeploy, true]
Resources:
  ManagementStack:
    Type: AWS::CloudFormation::Stack
    Condition: DeployManagement
    Properties:
      TemplateURL: https://cgi-cfts.s3.cn-northwest-1.amazonaws.com.cn/management/management.yaml
      Parameters:
        VPC: !Ref VPC
        ManagementSubnet: !Select [0, !Ref GatewaysSubnets]
        ManagementName: !Ref ManagementServer
        ManagementInstanceType: !Ref ManagementInstanceType
        KeyName: !Ref KeyName
        AllocatePublicAddress: true
        VolumeEncryption: !If [VolumeEncryption, alias/aws/ebs, '']
        VolumeType: !Ref VolumeType
        VolumeSize: !Ref VolumeSize
        EnableInstanceConnect: !Ref EnableInstanceConnect
        TerminationProtection: !Ref TerminationProtection
        ManagementPermissions: !Ref ManagementPermissions
        ManagementPredefinedRole: !Ref ManagementPredefinedRole
        ManagementVersion: !Ref ManagementVersion
        ManagementPasswordHash: !Ref ManagementPasswordHash
        AllowUploadDownload: !Ref AllowUploadDownload
        AdminCIDR: !Ref AdminCIDR
        GatewayManagement: !Ref GatewayManagement
        GatewaysAddresses: !Ref GatewaysAddresses
        ManagementBootstrapScript: !Join
          - ';'
          - - 'echo -e "\nStarting Bootstrap script\n"'
            - 'echo "Setting up bootstrap parameters"'
            - !Sub 'conf_template=${ConfigurationTemplate} ; mgmt=${ManagementServer} ; region=${AWS::Region} ; blades=${GatewaysBlades}'
            - !Sub ['version=${Version}', {Version: !Select [0, !Split ['-', !Ref GatewayVersion]]}]
            - !Join ['', ['sic="$(echo ', 'Fn::Base64': !Ref GatewaySICKey, ' | base64 -d)"']]
            - 'community="tgw-community" ; controller="tgw-controller"'
            - 'echo "Adding tgw identifier to cloud-version"'
            - 'template="management_tgw_asg"'
            - 'cv_path="/etc/cloud-version"'
            - 'if test -f ${cv_path}; then sed -i ''/template_name/c\template_name: ''"${template}"'''' /etc/cloud-version; fi'
            - 'cv_json_path="/etc/cloud-version.json"'
            - 'cv_json_path_tmp="/etc/cloud-version-tmp.json"'
            - 'if test -f ${cv_json_path}; then cat ${cv_json_path} | jq ''.template_name = "''"${template}"''"'' > ${cv_json_path_tmp}; mv ${cv_json_path_tmp} ${cv_json_path}; fi'
            - 'echo "Configuring VPN community: ${community}"'
            - '[[ -d /opt/CPcme/menu/additions ]] && /opt/CPcme/menu/additions/config-community.sh "${community}" || /etc/fw/scripts/autoprovision/config-community.sh "${community}"'
            - 'echo "Setting VPN rules"'
            - 'mgmt_cli -r true add access-layer name "Inline"'
            - 'mgmt_cli -r true add access-rule layer Network position 1 name "${community} VPN Traffic Rule" vpn.directional.1.from "${community}" vpn.directional.1.to "${community}" vpn.directional.2.from "${community}" vpn.directional.2.to External_clear action "Apply Layer" source "Any" destination "Any" service "Any" inline-layer "Inline"'
            - 'mgmt_cli -r true add dynamic-object name "LocalGateway"'
            - 'mgmt_cli -r true add nat-rule package standard position bottom install-on "Policy Targets" original-source All_Internet translated-source "LocalGateway" method hide'
            - 'echo "Setting CME configurations"'
            - 'autoprov_cfg -f init AWS -mn "${mgmt}" -tn "${conf_template}" -cn "${controller}" -po Standard -otp "${sic}" -r "${region}" -ver "${version}" -iam -dt TGW'
            - 'autoprov_cfg -f set controller AWS -cn "${controller}" -sv -com "${community}"'
            - 'autoprov_cfg -f set template -tn "${conf_template}" -vpn -vd "" -con "${community}"'
            - '${blades} && autoprov_cfg -f set template -tn "${conf_template}" -ia -ips -appi -av -ab'
            - 'echo -e "\nFinished Bootstrap script\n"'
  SecurityGatewaysStack:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: https://cgi-cfts.s3.cn-northwest-1.amazonaws.com.cn/autoscale/autoscale.yaml
      Parameters:
        VPC: !Ref VPC
        GatewaysSubnets: !Join [',', !Ref GatewaysSubnets]
        GatewayName: !Ref GatewayName
        GatewayInstanceType: !Ref GatewayInstanceType
        KeyName: !Ref KeyName
        EnableVolumeEncryption: !Ref EnableVolumeEncryption
        VolumeType: !Ref VolumeType
        VolumeSize: !Ref VolumeSize
        EnableInstanceConnect: !Ref EnableInstanceConnect
        GatewaysMinSize: !Ref GatewaysMinSize
        GatewaysMaxSize: !Ref GatewaysMaxSize
        AdminEmail: !Ref AdminEmail
        GatewayVersion: !Ref GatewayVersion
        GatewayPasswordHash: !Ref GatewayPasswordHash
        GatewaySICKey: !Ref GatewaySICKey
        AllowUploadDownload: !Ref AllowUploadDownload
        CloudWatch: !Ref CloudWatch
        GatewayBootstrapScript: !Join
          - ';'
          - - 'echo -e "\nStarting Bootstrap script\n"'
            - 'echo "Setting up bootstrap parameters"'
            - !Sub 'asn=${ASN}'
            - 'echo "Adding tgw identifier to cloud-version"'
            - 'template="autoscale_tgw"'
            - 'cv_path="/etc/cloud-version"'
            - 'if test -f ${cv_path}; then sed -i ''/template_name/c\template_name: ''"${template}"'''' /etc/cloud-version; fi'
            - 'cv_json_path="/etc/cloud-version.json"'
            - 'cv_json_path_tmp="/etc/cloud-version-tmp.json"'
            - 'if test -f ${cv_json_path}; then cat ${cv_json_path} | jq ''.template_name = "''"${template}"''"'' > ${cv_json_path_tmp}; mv ${cv_json_path_tmp} ${cv_json_path}; fi'
            - 'echo "Setting ASN to: ${asn}"'
            - 'clish -c "set as ${asn}" -s'
            - 'echo -e "\nFinished Bootstrap script\n"'
        ControlGatewayOverPrivateOrPublicAddress: !Ref ControlGatewayOverPrivateOrPublicAddress
        ManagementServer: !Ref ManagementServer
        ConfigurationTemplate: !Ref ConfigurationTemplate
Outputs:
  ManagementName:
    Description: The name that represents the Security Management Server.
    Value: !Ref ManagementServer
  ConfigurationTemplateName:
    Description: The name that represents the configuration template. Configurations required to automatically provision the Gateways in the Auto Scaling Group, such as what Security Policy to install and which Blades to enable, will be placed under this template name.
    Value: !Ref ConfigurationTemplate
  ControllerName:
    Description: The name that represents the controller. Configurations required to connect to your AWS environment, such as credentials and regions, will be placed under this controller name.
    Value: tgw-controller
  ManagementPublicAddress:
    Description: The public address of the management servers.
    Value: !GetAtt ManagementStack.Outputs.PublicAddress
    Condition: DeployManagement
Rules:
  GatewayAddressRule:
    RuleCondition: !Equals [!Ref ManagementDeploy, 'true'] 
    Assertions:  
      - AssertDescription: "Gateway's netowrk to communicate with the Security Management Server must be provided"
        Assert: !Not [ !Equals [!Ref GatewaysAddresses, '']]