AWSTemplateFormatVersion: 2010-09-09
Description: >-
  AWS CloudFormation template for deploying Linux bastion hosts in an
  auto-scaling group in an existing VPC. (qs-1qup6ra99)
Metadata:
  QuickStartDocumentation:
    EntrypointName: Launch into an existing VPC
    Order: 2
  LICENSE: Apache License, Version 2.0
  LintSpellExclude:
    - onlyssmaccess
  AWS::CloudFormation::Interface:
    ParameterGroups:
      - Label:
          default: Network configuration
        Parameters:
          - VPCID
          - PublicSubnet1ID
          - PublicSubnet2ID
          - RemoteAccessCIDR
      - Label:
          default: IAM configuration
        Parameters:
          - RolePath
          - PermissionsBoundaryArn
      - Label:
          default: Amazon EC2 configuration
        Parameters:
          - KeyPairName
          - BastionAMIOS
          - BastionInstanceType
          - RootVolumeSize
      - Label:
          default: Linux bastion configuration
        Parameters:
          - NumBastionHosts
          - OndemandPercentage
          - BastionHostName
          - BastionTenancy
          - EnableBanner
          - BastionBanner
          - EnableTCPForwarding
          - EnableX11Forwarding
          - EC2MetadataPutResponseHopLimit
          - EC2MetadataHttpTokens
      - Label:
          default: Alternative configurations
        Parameters:
          - AlternativeInitializationScript
          - OSImageOverride
          - AlternativeIAMRole
          - EnvironmentVariables
      - Label:
          default: AWS Quick Start configuration
        Parameters:
          - QSS3BucketName
          - QSS3KeyPrefix
          - QSS3BucketRegion
    ParameterLabels:
      AlternativeIAMRole:
        default: Alternative IAM role
      AlternativeInitializationScript:
        default: Alternative initialization script URL
      BastionAMIOS:
        default: Bastion AMI operating system
      BastionHostName:
        default: Bastion host Name
      BastionTenancy:
        default: Bastion tenancy
      BastionBanner:
        default: SSH banner content file URL
      BastionInstanceType:
        default: Bastion instance type
      EnableBanner:
        default: Bastion banner
      EnableTCPForwarding:
        default: TCP forwarding
      EnableX11Forwarding:
        default: X11 forwarding
      EnvironmentVariables:
        default: Environment variables
      KeyPairName:
        default: Key pair name
      NumBastionHosts:
        default: Number of bastion hosts
      OndemandPercentage:
        default: On-demand percentage
      OSImageOverride:
        default: Operating system override
      PublicSubnet1ID:
        default: Public subnet 1 ID
      PublicSubnet2ID:
        default: Public subnet 2 ID
      QSS3BucketName:
        default: Quick Start S3 bucket name
      QSS3BucketRegion:
        default: Quick Start S3 bucket Region
      QSS3KeyPrefix:
        default: Quick Start S3 key prefix
      RemoteAccessCIDR:
        default: Allowed bastion external access CIDR
      VPCID:
        default: VPC ID
      RootVolumeSize:
        default: Root volume size
      PermissionsBoundaryArn:
        default: Permissions boundary ARN
      RolePath:
        default: Role path
      EC2MetadataPutResponseHopLimit:
        default: Amazon EC2 metadata put response hop limit
      EC2MetadataHttpTokens:
        default: Amazon EC2 metadata HTTP tokens
Parameters:
  BastionAMIOS:
    Type: String
    Description: The Linux distribution for the AMI to be used for the bastion host instances.
    AllowedValues:
      - Amazon-Linux2-HVM
      - Amazon-Linux2-HVM-ARM
      - Amazon-Linux2022
      - Amazon-Linux2022-ARM
      - Ubuntu-Server-20.04-LTS-HVM
      - Ubuntu-Server-22.04-LTS-HVM
      - Ubuntu-Server-22.04-LTS-HVM-ARM
    Default: Amazon-Linux2-HVM
  BastionHostName:
    Type: String
    Description: The value used for the name tag of the bastion host.
    Default: LinuxBastion
  BastionBanner:
    Type: String
    Description: >-
      Amazon S3 object URL for the text file with the content to display upon
      SSH login. The bastion host must have permission to download the file
      from the S3 bucket.
    AllowedPattern: ^(s3:\/\/[0-9a-z]+([0-9a-z-]*[0-9a-z])*/.+)?$
    ConstraintDescription: >-
      Must be either a valid Amazon S3 object URL
      (example: s3://bucket/key/file.txt) or empty.
    Default: ''
  BastionTenancy:
    Type: String
    Description: Bastion VPC tenancy (dedicated or default).
    AllowedValues: [dedicated, default]
    Default: default
  BastionInstanceType:
    Type: String
    Description: Amazon EC2 instance type for the bastion instances.
    Default: t3.micro
  EnableBanner:
    Type: String
    Description: Choose "true" to display a banner when connecting to the bastion using SSH.
    AllowedValues: ['true', 'false']
    Default: 'false'
  EnableTCPForwarding:
    Type: String
    Description: Choose "true" to enable TCP forwarding.
    AllowedValues: ['true', 'false']
    Default: 'false'
  EnableX11Forwarding:
    Type: String
    Description: Choose "true" to enable X11 forwarding.
    AllowedValues: ['true', 'false']
    Default: 'false'
  KeyPairName:
    Type: String
    Description:
      Name of an existing public/private key pair. If you do not have one in this AWS Region,
      please create it before continuing. If left empty, AWS Systems Manager Session Manager can still be used to connect to the instance.
    Default: ''
  NumBastionHosts:
    Type: String
    Description: The number of bastion hosts to create. The maximum number is four.
    AllowedValues: [1, 2, 3, 4]
    Default: 1
  OndemandPercentage:
    Type: Number
    Description: >-
      Percentage of on-demand instances versus spot instances. With the
      default of 100, the ratio will be 100% on-demand instances and 0% spot
      instances.
    Default: 100
  PublicSubnet1ID:
    Type: AWS::EC2::Subnet::Id
    Description: >-
      ID of the public subnet 1 that you want to provision the first bastion
      into (for example, subnet-a0246dcd). If RemoteAccessCIDR is set to
      'disabled-onlyssmaccess', enter the ID of a private subnet instead.
  PublicSubnet2ID:
    Type: AWS::EC2::Subnet::Id
    Description: >-
      ID of the public subnet 2 that you want to provision the second bastion
      into (for example, subnet-e3246d8e). If RemoteAccessCIDR is set to
      'disabled-onlyssmaccess', enter the ID of a private subnet instead.
  EC2MetadataPutResponseHopLimit:
    Type: String
    Description: >-
      The desired HTTP PUT response hop limit for instance metadata requests.
      The larger the number, the further instance metadata requests can travel.
    Default: 2
  EC2MetadataHttpTokens:
    Type: String
    Description: >-
      If set to "optional" instances will be able to use their IAM instance
      profile. If set to "required" amd "EC2MetadataPutResponseHopLimit" is set
      to 1, instances will not be able to access the IAM role. If set to
      "required" amd "EC2MetadataPutResponseHopLimit" is set greater than 1
      instances must send a signed token header with any instance metadata
      retrieval requests.
    AllowedValues: [optional, required]
    Default: required
  QSS3BucketName:
    Type: String
    Description: Name of the S3 bucket for your copy of the Quick Start assets.
      Keep the default name unless you are customizing the template.
      Changing the name updates code references to point to a new Quick
      Start location. This name can include numbers, lowercase letters,
      and hyphens, but do not start or end with a hyphen (-).
      See https://aws-quickstart.github.io/option1.html.
    MinLength: 3
    MaxLength: 63
    AllowedPattern: ^[0-9a-z]+([0-9a-z-]*[0-9a-z])*$
    ConstraintDescription:
      The Quick Start bucket name can include numbers, lowercase
      letters, uppercase letters, and hyphens (-). It cannot start or end with a
      hyphen (-).
    Default: aws-quickstart
  QSS3BucketRegion:
    Type: String
    Description: The AWS Region where the Quick Start S3 bucket (QSS3BucketName) is hosted. When using your own bucket, you must specify this value.
    Default: us-east-1
  QSS3KeyPrefix:
    Type: String
    Description:
      S3 key prefix that is used to simulate a directory for your copy of the
      Quick Start assets. Keep the default prefix unless you are customizing
      the template. Changing this prefix updates code references to point to
      a new Quick Start location. This prefix can include numbers, lowercase
      letters, uppercase letters, hyphens (-), and forward slashes (/). End
      with a forward slash.
      See https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingMetadata.html
      and https://aws-quickstart.github.io/option1.html.
    AllowedPattern: ^([0-9a-zA-Z-.]+/)*$
    ConstraintDescription:
      The Quick Start S3 key prefix can include numbers, lowercase letters,
      uppercase letters, hyphens (-), and forward slashes (/).
    Default: quickstart-linux-bastion/
  RemoteAccessCIDR:
    Type: String
    Description: >-
      Allowed CIDR block or prefix list for external SSH access to the
      bastions.
    AllowedPattern: ^disabled-onlyssmaccess$|^pl-([0-9a-f]{8}|[0-9a-f]{17})$|^(([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]))$
    ConstraintDescription: CIDR block parameter must be disabled-onlyssmaccess or in the format "x.x.x.x/x".
    Default: disabled-onlyssmaccess
  VPCID:
    Type: AWS::EC2::VPC::Id
    Description: ID of the VPC (for example, vpc-0343606e).
  AlternativeInitializationScript:
    Type: String
    Description: >-
      HTTPS format Amazon S3 object URL for your custom initialization script
      to run during setup. The bastion host must have permission to download
      the file from the S3 bucket.
    AllowedPattern: ^https.*|^$
    ConstraintDescription: >-
      Must be either a valid Amazon S3 object URL
      (example: https://bucket/key/file.txt) or empty.
    Default: ''
  OSImageOverride:
    Type: String
    Description: The Region-specific image to use for the instance.
    Default: ''
  AlternativeIAMRole:
    Type: String
    Description:
      An existing IAM role name to attach to the bastion. If left blank,
      a new role will be created.
    Default: ''
  EnvironmentVariables:
    Type: String
    Description: A comma-separated list of environment variables for use in
      bootstrapping. Variables must be in the format "key=value". "Value" cannot
      contain commas.
    Default: ''
  RootVolumeSize:
    Type: Number
    Description: The size in GB for the root EBS volume.
    Default: 10
  PermissionsBoundaryArn:
    Type: String
    Description: Will be attached to all created IAM roles to satisfy security requirements.
    Default: ''
  RolePath:
    Type: String
    Description: Will be attached to all created IAM roles to satisfy security requirements.
    Default: ''
Rules:
  SubnetsInVPC:
    Assertions:
      - Assert: !EachMemberIn
          - !ValueOfAll [AWS::EC2::Subnet::Id, VpcId]
          - !RefAll AWS::EC2::VPC::Id
        AssertDescription: All subnets must exist in the VPC.
  ArmInstance:
    RuleCondition: !Contains
      - - Amazon-Linux2-HVM-ARM
        - Amazon-Linux2022-ARM
        - Ubuntu-Server-22.04-LTS-HVM-ARM
      - !Ref BastionAMIOS
    Assertions:
      - Assert: !Contains
          - - t4g.nano
            - t4g.micro
            - t4g.small
            - t4g.medium
            - t4g.large
            - t4g.xlarge
            - t4g.2xlarge
            - m6g.medium
            - m6g.large
            - m6g.xlarge
            - m6g.2xlarge
          - !Ref BastionInstanceType
        AssertDescription: >-
          You selected an ARM AMI operating system, so you must also enter an
          ARM instance type, such as t4g.micro. For additional details, see
          https://aws.amazon.com/ec2/instance-types/.
  X86_64Instance:
    RuleCondition: !Not
      - !Contains
          - - Amazon-Linux2-HVM-ARM
            - Amazon-Linux2022-ARM
            - Ubuntu-Server-22.04-LTS-HVM-ARM
          - !Ref BastionAMIOS
    Assertions:
      - Assert: !Not
          - !Contains
              - - t4g.nano
                - t4g.micro
                - t4g.small
                - t4g.medium
                - t4g.large
                - t4g.xlarge
                - t4g.2xlarge
                - m6g.medium
                - m6g.large
                - m6g.xlarge
                - m6g.2xlarge
              - !Ref BastionInstanceType
        AssertDescription: >-
          You selected a x86_64 AMI operating system, so you must also enter a
          x86_64 instance type, such as t3.micro. For additional details, see
          https://aws.amazon.com/ec2/instance-types/.
Mappings:
  AWSAMIRegionMap:
    af-south-1:
      AMZNLINUX2: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}'
      AMZNLINUX2ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2}}'
      AMZNLINUX2022: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-x86_64}}'
      AMZNLINUX2022ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-arm64}}'
      US2004HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}'
      US2204HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}'
      US2204HVMARM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/arm64/hvm/ebs-gp2/ami-id}}'
    ap-east-1:
      AMZNLINUX2: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}'
      AMZNLINUX2ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2}}'
      AMZNLINUX2022: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-x86_64}}'
      AMZNLINUX2022ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-arm64}}'
      US2004HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}'
      US2204HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}'
      US2204HVMARM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/arm64/hvm/ebs-gp2/ami-id}}'
    ap-northeast-1:
      AMZNLINUX2: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}'
      AMZNLINUX2ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2}}'
      AMZNLINUX2022: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-x86_64}}'
      AMZNLINUX2022ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-arm64}}'
      US2004HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}'
      US2204HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}'
      US2204HVMARM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/arm64/hvm/ebs-gp2/ami-id}}'
    ap-northeast-2:
      AMZNLINUX2: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}'
      AMZNLINUX2ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2}}'
      AMZNLINUX2022: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-x86_64}}'
      AMZNLINUX2022ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-arm64}}'
      US2004HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}'
      US2204HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}'
      US2204HVMARM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/arm64/hvm/ebs-gp2/ami-id}}'
    ap-northeast-3:
      AMZNLINUX2: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}'
      AMZNLINUX2ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2}}'
      AMZNLINUX2022: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-x86_64}}'
      AMZNLINUX2022ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-arm64}}'
      US2004HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}'
      US2204HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}'
      US2204HVMARM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/arm64/hvm/ebs-gp2/ami-id}}'
    ap-south-1:
      AMZNLINUX2: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}'
      AMZNLINUX2ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2}}'
      AMZNLINUX2022: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-x86_64}}'
      AMZNLINUX2022ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-arm64}}'
      US2004HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}'
      US2204HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}'
      US2204HVMARM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/arm64/hvm/ebs-gp2/ami-id}}'
    ap-south-2:
      AMZNLINUX2: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}'
      AMZNLINUX2ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2}}'
      AMZNLINUX2022: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-x86_64}}'
      AMZNLINUX2022ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-arm64}}'
      US2004HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}'
      US2204HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}'
      US2204HVMARM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/arm64/hvm/ebs-gp2/ami-id}}'
    ap-southeast-1:
      AMZNLINUX2: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}'
      AMZNLINUX2ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2}}'
      AMZNLINUX2022: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-x86_64}}'
      AMZNLINUX2022ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-arm64}}'
      US2004HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}'
      US2204HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}'
      US2204HVMARM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/arm64/hvm/ebs-gp2/ami-id}}'
    ap-southeast-2:
      AMZNLINUX2: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}'
      AMZNLINUX2ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2}}'
      AMZNLINUX2022: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-x86_64}}'
      AMZNLINUX2022ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-arm64}}'
      US2004HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}'
      US2204HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}'
      US2204HVMARM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/arm64/hvm/ebs-gp2/ami-id}}'
    ap-southeast-3:
      AMZNLINUX2: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}'
      AMZNLINUX2ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2}}'
      AMZNLINUX2022: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-x86_64}}'
      AMZNLINUX2022ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-arm64}}'
      US2004HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}'
      US2204HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}'
      US2204HVMARM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/arm64/hvm/ebs-gp2/ami-id}}'
    ap-southeast-4:
      AMZNLINUX2: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}'
      AMZNLINUX2ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2}}'
      AMZNLINUX2022: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-x86_64}}'
      AMZNLINUX2022ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-arm64}}'
      US2004HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}'
      US2204HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}'
      US2204HVMARM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/arm64/hvm/ebs-gp2/ami-id}}'
    ca-central-1:
      AMZNLINUX2: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}'
      AMZNLINUX2ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2}}'
      AMZNLINUX2022: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-x86_64}}'
      AMZNLINUX2022ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-arm64}}'
      US2004HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}'
      US2204HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}'
      US2204HVMARM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/arm64/hvm/ebs-gp2/ami-id}}'
    eu-central-1:
      AMZNLINUX2: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}'
      AMZNLINUX2ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2}}'
      AMZNLINUX2022: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-x86_64}}'
      AMZNLINUX2022ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-arm64}}'
      US2004HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}'
      US2204HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}'
      US2204HVMARM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/arm64/hvm/ebs-gp2/ami-id}}'
    eu-central-2:
      AMZNLINUX2: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}'
      AMZNLINUX2ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2}}'
      AMZNLINUX2022: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-x86_64}}'
      AMZNLINUX2022ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-arm64}}'
      US2004HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}'
      US2204HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}'
      US2204HVMARM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/arm64/hvm/ebs-gp2/ami-id}}'
    eu-north-1:
      AMZNLINUX2: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}'
      AMZNLINUX2ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2}}'
      AMZNLINUX2022: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-x86_64}}'
      AMZNLINUX2022ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-arm64}}'
      US2004HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}'
      US2204HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}'
      US2204HVMARM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/arm64/hvm/ebs-gp2/ami-id}}'
    eu-south-1:
      AMZNLINUX2: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}'
      AMZNLINUX2ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2}}'
      AMZNLINUX2022: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-x86_64}}'
      AMZNLINUX2022ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-arm64}}'
      US2004HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}'
      US2204HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}'
      US2204HVMARM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/arm64/hvm/ebs-gp2/ami-id}}'
    eu-south-2:
      AMZNLINUX2: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}'
      AMZNLINUX2ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2}}'
      AMZNLINUX2022: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-x86_64}}'
      AMZNLINUX2022ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-arm64}}'
      US2004HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}'
      US2204HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}'
      US2204HVMARM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/arm64/hvm/ebs-gp2/ami-id}}'
    eu-west-1:
      AMZNLINUX2: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}'
      AMZNLINUX2ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2}}'
      AMZNLINUX2022: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-x86_64}}'
      AMZNLINUX2022ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-arm64}}'
      US2004HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}'
      US2204HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}'
      US2204HVMARM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/arm64/hvm/ebs-gp2/ami-id}}'
    eu-west-2:
      AMZNLINUX2: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}'
      AMZNLINUX2ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2}}'
      AMZNLINUX2022: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-x86_64}}'
      AMZNLINUX2022ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-arm64}}'
      US2004HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}'
      US2204HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}'
      US2204HVMARM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/arm64/hvm/ebs-gp2/ami-id}}'
    eu-west-3:
      AMZNLINUX2: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}'
      AMZNLINUX2ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2}}'
      AMZNLINUX2022: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-x86_64}}'
      AMZNLINUX2022ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-arm64}}'
      US2004HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}'
      US2204HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}'
      US2204HVMARM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/arm64/hvm/ebs-gp2/ami-id}}'
    me-central-1:
      AMZNLINUX2: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}'
      AMZNLINUX2ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2}}'
      AMZNLINUX2022: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-x86_64}}'
      AMZNLINUX2022ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-arm64}}'
      US2004HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}'
      US2204HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}'
      US2204HVMARM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/arm64/hvm/ebs-gp2/ami-id}}'
    me-south-1:
      AMZNLINUX2: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}'
      AMZNLINUX2ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2}}'
      AMZNLINUX2022: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-x86_64}}'
      AMZNLINUX2022ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-arm64}}'
      US2004HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}'
      US2204HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}'
      US2204HVMARM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/arm64/hvm/ebs-gp2/ami-id}}'
    sa-east-1:
      AMZNLINUX2: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}'
      AMZNLINUX2ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2}}'
      AMZNLINUX2022: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-x86_64}}'
      AMZNLINUX2022ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-arm64}}'
      US2004HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}'
      US2204HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}'
      US2204HVMARM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/arm64/hvm/ebs-gp2/ami-id}}'
    us-east-1:
      AMZNLINUX2: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}'
      AMZNLINUX2ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2}}'
      AMZNLINUX2022: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-x86_64}}'
      AMZNLINUX2022ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-arm64}}'
      US2004HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}'
      US2204HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}'
      US2204HVMARM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/arm64/hvm/ebs-gp2/ami-id}}'
    us-east-2:
      AMZNLINUX2: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}'
      AMZNLINUX2ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2}}'
      AMZNLINUX2022: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-x86_64}}'
      AMZNLINUX2022ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-arm64}}'
      US2004HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}'
      US2204HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}'
      US2204HVMARM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/arm64/hvm/ebs-gp2/ami-id}}'
    us-west-1:
      AMZNLINUX2: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}'
      AMZNLINUX2ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2}}'
      AMZNLINUX2022: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-x86_64}}'
      AMZNLINUX2022ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-arm64}}'
      US2004HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}'
      US2204HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}'
      US2204HVMARM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/arm64/hvm/ebs-gp2/ami-id}}'
    us-west-2:
      AMZNLINUX2: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}'
      AMZNLINUX2ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2}}'
      AMZNLINUX2022: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-x86_64}}'
      AMZNLINUX2022ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-arm64}}'
      US2004HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}'
      US2204HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}'
      US2204HVMARM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/arm64/hvm/ebs-gp2/ami-id}}'
    us-gov-east-1:
      AMZNLINUX2: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}'
      AMZNLINUX2ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2}}'
      AMZNLINUX2022: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-x86_64}}'
      AMZNLINUX2022ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-arm64}}'
      US2004HVM: ami-0cfbbbb41dd6a9cad
      US2204HVM: ami-0c4bea13c0e0c588f
      US2204HVMARM: ami-0dbcf7fc866b67aed
    us-gov-west-1:
      AMZNLINUX2: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}'
      AMZNLINUX2ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2}}'
      AMZNLINUX2022: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-x86_64}}'
      AMZNLINUX2022ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-arm64}}'
      US2004HVM: ami-0b152eed9cb83f2bd
      US2204HVM: ami-0585fd40760ad42a3
      US2204HVMARM: ami-0f0aac22ded9e2425
    cn-north-1:
      AMZNLINUX2: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}'
      AMZNLINUX2ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2}}'
      AMZNLINUX2022: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-x86_64}}'
      AMZNLINUX2022ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-arm64}}'
      US2004HVM: ami-0ee5d3b4bc88442f4
      US2204HVM: ami-05739266c542f05d5
      US2204HVMARM: ami-0d41564e295b1064e
    cn-northwest-1:
      AMZNLINUX2: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}'
      AMZNLINUX2ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2}}'
      AMZNLINUX2022: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-x86_64}}'
      AMZNLINUX2022ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-arm64}}'
      US2004HVM: ami-05de738393a8dcebf
      US2204HVM: ami-0528ba5522b075ac5
      US2204HVMARM: ami-076f450c832df8f9b
  LinuxAMINameMap:
    Amazon-Linux2-HVM:
      Code: AMZNLINUX2
      OS: Amazon
    Amazon-Linux2-HVM-ARM:
      Code: AMZNLINUX2ARM
      OS: Amazon
    Amazon-Linux2022:
      Code: AMZNLINUX2022
      OS: Amazon
    Amazon-Linux2022-ARM:
      Code: AMZNLINUX2022ARM
      OS: Amazon
    Ubuntu-Server-20.04-LTS-HVM:
      Code: US2004HVM
      OS: Ubuntu
    Ubuntu-Server-22.04-LTS-HVM:
      Code: US2204HVM
      OS: Ubuntu
    Ubuntu-Server-22.04-LTS-HVM-ARM:
      Code: US2204HVMARM
      OS: Ubuntu
Conditions:
  RolePathProvided: !Not [!Equals ['', !Ref RolePath]]
  PermissionsBoundaryProvided: !Not [!Equals ['', !Ref PermissionsBoundaryArn]]
  2BastionConditionHost: !Or [!Equals [!Ref NumBastionHosts, 2], !Condition 3BastionCondition, !Condition 4BastionCondition]
  3BastionConditionHost: !Or [!Equals [!Ref NumBastionHosts, 3], !Condition 4BastionCondition]
  4BastionConditionHost: !Equals [!Ref NumBastionHosts, 4]
  2BastionCondition: !And [!Condition NeedsEip, !Condition 2BastionConditionHost]
  3BastionCondition: !And [!Condition NeedsEip, !Condition 3BastionConditionHost]
  4BastionCondition: !And [!Condition NeedsEip, !Condition 4BastionConditionHost]
  HasRemoteCIDR: !And
    - !Not [!Equals [!Ref RemoteAccessCIDR, disabled-onlyssmaccess]]
    - !Not [!Condition HasPrefixList]
  HasPrefixList: !Equals [!Select [0, !Split ['-', !Ref RemoteAccessCIDR]], pl]
  NeedsEip: !Or [!Condition HasRemoteCIDR, !Condition HasPrefixList]
  UseAlternativeInitialization: !Not [!Equals [!Ref AlternativeInitializationScript, '']]
  CreateIAMRole: !Equals [!Ref AlternativeIAMRole, '']
  UseOSImageOverride: !Not [!Equals [!Ref OSImageOverride, '']]
  UsingDefaultBucket: !Equals [!Ref QSS3BucketName, aws-quickstart]
  DefaultBanner: !Equals [!Ref BastionBanner, '']
  UseKeyPair: !Not [!Equals [!Ref KeyPairName, '']]
Resources:
  BastionMainLogGroup:
    Type: AWS::Logs::LogGroup
  SSHMetricFilter:
    Type: AWS::Logs::MetricFilter
    Properties:
      LogGroupName: !Ref BastionMainLogGroup
      FilterPattern: ON FROM USER PWD
      MetricTransformations:
        - MetricName: SSHCommandCount
          MetricValue: 1
          MetricNamespace: !Sub AWSQuickStart/${AWS::StackName}
  BastionHostRole:
    Condition: CreateIAMRole
    Type: AWS::IAM::Role
    Properties:
      Path: !If [RolePathProvided, !Ref RolePath, !Ref AWS::NoValue]
      PermissionsBoundary:
        !If [PermissionsBoundaryProvided, !Ref PermissionsBoundaryArn, !Ref AWS::NoValue]
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Action: sts:AssumeRole
            Principal:
              Service:
                - !Sub ec2.${AWS::URLSuffix}
      ManagedPolicyArns:
        - !Sub arn:${AWS::Partition}:iam::aws:policy/AmazonSSMManagedInstanceCore
        - !Sub arn:${AWS::Partition}:iam::aws:policy/CloudWatchAgentServerPolicy
  BastionHostPolicy:
    Type: AWS::IAM::Policy
    Condition: CreateIAMRole
    Properties:
      PolicyName: BastionPolicy
      PolicyDocument:
        Version: 2012-10-17
        Statement:
          - Sid: ListQSS3BucketObjects
            Effect: Allow
            Action: s3:ListBucket
            Resource: !Sub
              - arn:${AWS::Partition}:s3:::${S3Bucket}
              - S3Bucket: !If [UsingDefaultBucket, !Sub '${QSS3BucketName}-${AWS::Region}', !Ref QSS3BucketName]
          - Sid: GetQSS3Objects
            Effect: Allow
            Action:
              - s3:GetObject
              - s3:GetObjectVersion
            Resource: !Sub
              - arn:${AWS::Partition}:s3:::${S3Bucket}/${QSS3KeyPrefix}*
              - S3Bucket: !If [UsingDefaultBucket, !Sub '${QSS3BucketName}-${AWS::Region}', !Ref QSS3BucketName]
          - Sid: WriteToCloudWatchLogs
            Effect: Allow
            Action:
              - logs:CreateLogStream
              - logs:GetLogEvents
              - logs:PutLogEvents
              - logs:DescribeLogGroups
              - logs:DescribeLogStreams
              - logs:PutRetentionPolicy
              - logs:PutMetricFilter
              - logs:CreateLogGroup
            Resource: !Sub arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:${BastionMainLogGroup}:*
          - Sid: Global
            Effect: Allow
            Action:
              - ec2:DescribeAddresses
            Resource: '*'
          - !If
              - NeedsEip
              - Sid: AssociateStackEips
                Effect: Allow
                Action: ec2:AssociateAddress
                Resource: '*'
                Condition:
                  StringEquals:
                    ec2:ResourceTag/aws:cloudformation:stack-id: !Ref AWS::StackId
              - !Ref AWS::NoValue
      Roles:
        - !If [CreateIAMRole, !Ref BastionHostRole, !Ref AlternativeIAMRole]
  BastionHostProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      Roles:
        - !If [CreateIAMRole, !Ref BastionHostRole, !Ref AlternativeIAMRole]
      Path: !If [CreateIAMRole, /, /account-managed/]
  EIP1:
    Type: AWS::EC2::EIP
    Condition: NeedsEip
    Properties:
      Domain: vpc
  EIP2:
    Type: AWS::EC2::EIP
    Condition: 2BastionCondition
    Properties:
      Domain: vpc
  EIP3:
    Type: AWS::EC2::EIP
    Condition: 3BastionCondition
    Properties:
      Domain: vpc
  EIP4:
    Type: AWS::EC2::EIP
    Condition: 4BastionCondition
    Properties:
      Domain: vpc
  BastionAutoScalingGroup:
    Type: AWS::AutoScaling::AutoScalingGroup
    Properties:
      VPCZoneIdentifier: [!Ref PublicSubnet1ID, !Ref PublicSubnet2ID]
      MinSize: !Ref NumBastionHosts
      MaxSize: !Ref NumBastionHosts
      Cooldown: 900
      DesiredCapacity: !Ref NumBastionHosts
      MixedInstancesPolicy:
        LaunchTemplate:
          LaunchTemplateSpecification:
            LaunchTemplateId: !Ref BastionLaunchTemplate
            Version: !GetAtt BastionLaunchTemplate.LatestVersionNumber
        InstancesDistribution:
          OnDemandPercentageAboveBaseCapacity: !Ref OndemandPercentage
          SpotInstancePools: 1
      Tags:
        - Key: Name
          Value: !Ref BastionHostName
          PropagateAtLaunch: true
    CreationPolicy:
      ResourceSignal:
        Count: !Ref NumBastionHosts
        Timeout: PT60M
      AutoScalingCreationPolicy:
        MinSuccessfulInstancesPercent: 100
    UpdatePolicy:
      AutoScalingReplacingUpdate:
        WillReplace: true
  BastionLaunchTemplate:
    Type: AWS::EC2::LaunchTemplate
    Metadata:
      AWS::CloudFormation::Authentication:
        S3AccessCreds:
          type: S3
          roleName: !If [CreateIAMRole, !Ref BastionHostRole, !Ref AlternativeIAMRole]
          buckets:
            - !If [UsingDefaultBucket, !Sub '${QSS3BucketName}-${AWS::Region}', !Ref QSS3BucketName]
      AWS::CloudFormation::Init:
        config:
          files:
            /tmp/auditd.rules:
              mode: 000550
              owner: root
              group: root
              content: |
                -a exit,always -F arch=b64 -S execve
                -a exit,always -F arch=b32 -S execve
            /tmp/auditing_configure.sh:
              source: !Sub
                - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/auditing_configure.sh
                - S3Bucket: !If [UsingDefaultBucket, !Sub 'aws-quickstart-${AWS::Region}', !Ref QSS3BucketName]
                  S3Region: !If [UsingDefaultBucket, !Ref AWS::Region, !Ref QSS3BucketRegion]
              mode: 000550
              owner: root
              group: root
              authentication: S3AccessCreds
            /tmp/bastion_bootstrap.sh:
              source: !If
                - UseAlternativeInitialization
                - !Ref AlternativeInitializationScript
                - !Sub
                    - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/bastion_bootstrap.sh
                    - S3Bucket: !If [UsingDefaultBucket, !Sub 'aws-quickstart-${AWS::Region}', !Ref QSS3BucketName]
                      S3Region: !If [UsingDefaultBucket, !Ref AWS::Region, !Ref QSS3BucketRegion]
              mode: 000550
              owner: root
              group: root
              authentication: S3AccessCreds
          commands:
            a-add_auditd_rules:
              cwd: /tmp/
              env:
                BASTION_OS: !FindInMap [LinuxAMINameMap, !Ref BastionAMIOS, OS]
              command: ./auditing_configure.sh
            b-bootstrap:
              cwd: /tmp/
              env:
                REGION: !Sub ${AWS::Region}
                URL_SUFFIX: !Sub ${AWS::URLSuffix}
                BANNER_REGION: !If [UsingDefaultBucket, !Ref AWS::Region, !Ref QSS3BucketRegion]
              command: !Sub
                - ./bastion_bootstrap.sh --banner ${BannerUrl} --enable ${EnableBanner} --tcp-forwarding ${EnableTCPForwarding} --x11-forwarding ${EnableX11Forwarding}
                - BannerUrl: !If
                    - DefaultBanner
                    - !Sub
                        - s3://${S3Bucket}/${QSS3KeyPrefix}scripts/banner_message.txt
                        - S3Bucket: !If [UsingDefaultBucket, !Sub 'aws-quickstart-${AWS::Region}', !Ref QSS3BucketName]
                    - !Ref BastionBanner
    Properties:
      LaunchTemplateData:
        Placement:
          Tenancy: !Ref BastionTenancy
        KeyName: !If [UseKeyPair, !Ref KeyPairName, !Ref AWS::NoValue]
        ImageId: !If
          - UseOSImageOverride
          - !Ref OSImageOverride
          - !FindInMap [AWSAMIRegionMap, !Ref AWS::Region, !FindInMap [LinuxAMINameMap, !Ref BastionAMIOS, Code]]
        InstanceType: !Ref BastionInstanceType
        IamInstanceProfile:
          Arn: !GetAtt BastionHostProfile.Arn
        NetworkInterfaces:
          - DeviceIndex: 0
            AssociatePublicIpAddress: !If [NeedsEip, true, false]
            Groups:
              - !Ref BastionSecurityGroup
        BlockDeviceMappings:
          - DeviceName: /dev/xvda
            Ebs:
              VolumeSize: !Ref RootVolumeSize
              VolumeType: gp2
              Encrypted: true
              DeleteOnTermination: true
        UserData:
          Fn::Base64: !Sub
            - |
              #!/usr/bin/env bash
              set -x
              for e in $(echo "${EnvironmentVariables}" | tr ',' ' '); do
                export $e
                echo "$e" >> /root/.bashrc
              done
              export PATH=$PATH:/usr/local/bin
              yum install -y git unzip wget curl || apt-get install -y git unzip wget curl || zypper -n install git unzip wget curl

              #cfn signaling functions
              cfn_fail() {
                cfn-signal -e 1 --stack ${AWS::StackName} --region ${AWS::Region} --resource BastionAutoScalingGroup
                exit 1
              }

              cfn_success() {
                cfn-signal -e 0 --stack ${AWS::StackName} --region ${AWS::Region} --resource BastionAutoScalingGroup
                exit 0
              }

              pushd /tmp

              if [[ "a$(which aws)" == "a" ]]
              then
                echo "Installing AWS CLI..."
                uname=$(uname -m)
                wget -nv -O "./awscliv2.zip" "https://awscli.amazonaws.com/awscli-exe-linux-$uname.zip"
                unzip -q ./awscliv2.zip
                ./aws/install
              fi

              for (( i=0; i<=5; i++ ))
              do
                aws s3 cp --no-progress --region ${AWS::Region} "s3://${S3Bucket}/${QSS3KeyPrefix}scripts/cfn-tools.sh" .
                if [ $? -ne 0 ]
                then
                  echo "Retrying..."
                fi
              done
              source ./cfn-tools.sh

              popd /tmp

              qs_update-os || qs_err;
              qs_bootstrap_pip || qs_err " pip bootstrap failed ";
              qs_aws-cfn-bootstrap || qs_err " cfn bootstrap failed ";

              EIP_LIST="${EIP1},${EIP2},${EIP3},${EIP4}"
              CLOUDWATCHGROUP=${BastionMainLogGroup}
              cfn-init -v --stack '${AWS::StackName}' --resource BastionLaunchTemplate --region ${AWS::Region} || cfn_fail
              [ $(qs_status) == 0 ] && cfn_success || cfn_fail
            - EIP1: !If [NeedsEip, !Ref EIP1, 'Null']
              EIP2: !If [2BastionCondition, !Ref EIP2, 'Null']
              EIP3: !If [3BastionCondition, !Ref EIP3, 'Null']
              EIP4: !If [4BastionCondition, !Ref EIP4, 'Null']
              S3Bucket: !If [UsingDefaultBucket, !Sub 'aws-quickstart-${AWS::Region}', !Ref QSS3BucketName]
        MetadataOptions:
          HttpEndpoint: enabled
          HttpPutResponseHopLimit: !Ref EC2MetadataPutResponseHopLimit
          HttpTokens: !Ref EC2MetadataHttpTokens
  BastionSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Enables access to bastion hosts
      VpcId: !Ref VPCID
  BastionSecurityGroupCidrSshIngress:
    Type: AWS::EC2::SecurityGroupIngress
    Condition: HasRemoteCIDR
    Properties:
      GroupId: !Ref BastionSecurityGroup
      CidrIp: !Ref RemoteAccessCIDR
      IpProtocol: tcp
      FromPort: 22
      ToPort: 22
  BastionSecurityGroupCidrIcmpIngress:
    Type: AWS::EC2::SecurityGroupIngress
    Condition: HasRemoteCIDR
    Properties:
      GroupId: !Ref BastionSecurityGroup
      CidrIp: !Ref RemoteAccessCIDR
      IpProtocol: icmp
      FromPort: -1
      ToPort: -1
  BastionSecurityGroupPrefixListSshIngress:
    Type: AWS::EC2::SecurityGroupIngress
    Condition: HasPrefixList
    Properties:
      GroupId: !Ref BastionSecurityGroup
      SourcePrefixListId: !Ref RemoteAccessCIDR
      IpProtocol: tcp
      FromPort: 22
      ToPort: 22
  BastionSecurityGroupPrefixListIcmpIngress:
    Type: AWS::EC2::SecurityGroupIngress
    Condition: HasPrefixList
    Properties:
      GroupId: !Ref BastionSecurityGroup
      SourcePrefixListId: !Ref RemoteAccessCIDR
      IpProtocol: icmp
      FromPort: -1
      ToPort: -1
Outputs:
  BastionAutoScalingGroup:
    Description: Auto Scaling group reference ID.
    Value: !Ref BastionAutoScalingGroup
    Export:
      Name: !Sub ${AWS::StackName}-BastionAutoScalingGroup
  EIP1:
    Condition: NeedsEip
    Description: Elastic IP 1 for bastion.
    Value: !Ref EIP1
    Export:
      Name: !Sub ${AWS::StackName}-EIP1
  EIP2:
    Condition: 2BastionCondition
    Description: Elastic IP 2 for bastion.
    Value: !Ref EIP2
    Export:
      Name: !Sub ${AWS::StackName}-EIP2
  EIP3:
    Condition: 3BastionCondition
    Description: Elastic IP 3 for bastion.
    Value: !Ref EIP3
    Export:
      Name: !Sub ${AWS::StackName}-EIP3
  EIP4:
    Condition: 4BastionCondition
    Description: Elastic IP 4 for bastion.
    Value: !Ref EIP4
    Export:
      Name: !Sub ${AWS::StackName}-EIP4
  CloudWatchLogs:
    Description: CloudWatch Logs GroupName. Your SSH logs will be stored here.
    Value: !Ref BastionMainLogGroup
    Export:
      Name: !Sub ${AWS::StackName}-CloudWatchLogs
  BastionSecurityGroupID:
    Description: Bastion security group ID.
    Value: !Ref BastionSecurityGroup
    Export:
      Name: !Sub ${AWS::StackName}-BastionSecurityGroupID
  BastionHostRole:
    Description: Bastion IAM role name.
    Value: !If [CreateIAMRole, !Ref BastionHostRole, !Ref AlternativeIAMRole]
    Export:
      Name: !Sub ${AWS::StackName}-BastionHostRole
  Postdeployment:
    Description: See the deployment guide for post-deployment steps.
    Value: https://fwd.aws/YqpXk?