AWSTemplateFormatVersion: 2010-09-09
Description: LinuxBastion+VPC Jul,30,2020 (qs-1qup6ra99) (Please do not remove)
Metadata:
  QuickStartDocumentation:
    EntrypointName: Launch into an existing VPC
    Order: 2
  LICENSE: Apache License, Version 2.0
  'AWS::CloudFormation::Interface':
    ParameterGroups:
      - Label:
          default: Network configuration
        Parameters:
          - VPCID
          - PublicSubnet1ID
          - PublicSubnet2ID
          - RemoteAccessCIDR
      - Label:
          default: Amazon EC2 configuration
        Parameters:
          - KeyPairName
          - BastionAMIOS
          - BastionInstanceType
          - RootVolumeSize
      - Label:
          default: Linux bastion configuration
        Parameters:
          - NumBastionHosts
          - BastionHostName
          - BastionTenancy
          - EnableBanner
          - BastionBanner
          - EnableTCPForwarding
          - EnableX11Forwarding
      - 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
      BastionAMIOS:
        default: Bastion AMI operating system
      BastionHostName:
        default: Bastion host Name
      BastionTenancy:
        default: Bastion tenancy
      BastionBanner:
        default: Banner text
      QSS3BucketRegion:
        default: Quick Start S3 bucket region
      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
      OSImageOverride:
        default: Operating system override
      PublicSubnet1ID:
        default: Public subnet 1 ID
      PublicSubnet2ID:
        default: Public subnet 2 ID
      QSS3BucketName:
        default: Quick Start S3 bucket name
      QSS3KeyPrefix:
        default: Quick Start S3 key prefix
      RemoteAccessCIDR:
        default: Allowed bastion external access CIDR
      VPCID:
        default: VPC ID
      RootVolumeSize:
        default: Root volume size
  cfn-lint: { config: { ignore_checks: [E9007] } }
Parameters:
  BastionAMIOS:
    AllowedValues:
      - Amazon-Linux2-HVM
      - Amazon-Linux2-HVM-ARM
      - CentOS-7-HVM
      - Ubuntu-Server-20.04-LTS-HVM
      - SUSE-SLES-15-HVM
    Default: Amazon-Linux2-HVM
    Description: The Linux distribution for the AMI to be used for the bastion instances.
    Type: String
  BastionHostName:
    Default: 'LinuxBastion'
    Description: The value used for the name tag of the bastion host.
    Type: String
  BastionBanner:
    Default: ""
    Description: Banner text to display upon login.
    Type: String
  BastionTenancy:
    Description: Bastion VPC tenancy (dedicated or default).
    Type: String
    Default: default
    AllowedValues:
      - dedicated
      - default
  BastionInstanceType:
    AllowedValues:
      - t2.nano
      - t2.micro
      - t2.small
      - t2.medium
      - t2.large
      - t3.micro
      - t3.small
      - t3.medium
      - t3.large
      - t3.xlarge
      - t3.2xlarge
      - t4g.nano
      - t4g.micro
      - t4g.small
      - t4g.medium
      - t4g.large
      - t4g.xlarge
      - t4g.2xlarge
      - m4.large
      - m4.xlarge
      - m4.2xlarge
      - m4.4xlarge
    Default: t2.micro
    Description: Amazon EC2 instance type for the bastion instances.
    Type: String
  EnableBanner:
    AllowedValues:
      - 'true'
      - 'false'
    Default: 'false'
    Description: Choose *true* to display a banner when connecting via SSH to the bastion.
    Type: String
  EnableTCPForwarding:
    Type: String
    Description: To enable TCP forwarding, choose *true*.
    Default: 'false'
    AllowedValues:
      - 'true'
      - 'false'
  EnableX11Forwarding:
    Type: String
    Description: To enable X11 forwarding, choose *true*.
    Default: 'false'
    AllowedValues:
      - 'true'
      - 'false'
  KeyPairName:
    Description: Name of an existing public/private key pair. If you do not have one in this AWS Region,
      please create it before continuing.
    Type: 'AWS::EC2::KeyPair::KeyName'
  NumBastionHosts:
    AllowedValues:
      - '1'
      - '2'
      - '3'
      - '4'
    Default: '1'
    Description: The number of bastion hosts to create. The maximum number is four.
    Type: String
  PublicSubnet1ID:
    Description: ID of the public subnet 1 that you want to provision the first bastion into (e.g., subnet-a0246dcd).
    Type: 'AWS::EC2::Subnet::Id'
  PublicSubnet2ID:
    Description: ID of the public subnet 2 that you want to provision the second bastion into (e.g., subnet-e3246d8e).
    Type: 'AWS::EC2::Subnet::Id'
  QSS3BucketName:
    AllowedPattern: ^[0-9a-zA-Z]+([0-9a-zA-Z-]*[0-9a-zA-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
    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, 
      uppercase letters, and hyphens, but do not start or end with a hyphen (-). 
      See https://aws-quickstart.github.io/option1.html.
    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: The Quick Start S3 key prefix can include numbers, lowercase letters,
      uppercase letters, hyphens (-), and forward slashes (/).
    Default: quickstart-linux-bastion/
    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.
    Type: String
  RemoteAccessCIDR:
    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]))$
    ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/x
    Description: Allowed CIDR block for external SSH access to the bastions.
    Type: String
  VPCID:
    Description: ID of the VPC (e.g., vpc-0343606e).
    Type: 'AWS::EC2::VPC::Id'
  AlternativeInitializationScript:
    AllowedPattern: ^https.*|^$
    ConstraintDescription: URL must begin with https.
    Description: An alternative initialization script to run during setup.
    Default: ''
    Type: String
  OSImageOverride:
    Description: The Region-specific image to use for the instance.
    Type: String
    Default: ''
  AlternativeIAMRole:
    Description: An existing IAM role name to attach to the bastion. If left blank,
      a new role will be created.
    Default: ''
    Type: String
  EnvironmentVariables:
    Description: A comma-separated list of environment variables for use in
      bootstrapping. Variables must be in the format `key=value`. `Value` cannot
      contain commas.
    Type: String
    Default: ''
  RootVolumeSize:
    Description: The size in GB for the root EBS volume.
    Type: Number
    Default: '10'
Rules:
  SubnetsInVPC:
    Assertions:
      - Assert:
          'Fn::EachMemberIn':
            - 'Fn::ValueOfAll':
                - 'AWS::EC2::Subnet::Id'
                - VpcId
            - 'Fn::RefAll': 'AWS::EC2::VPC::Id'
        AssertDescription: All subnets must exist in the VPC.
  ArmInstance:
    Assertions:
      - Assert: !Contains
          - - t4g.nano
            - t4g.medium
            - t4g.large
            - t4g.micro
            - t4g.small
            - t4g.2xlarge
            - t4g.xlarge
          - !Ref 'BastionInstanceType'
        AssertDescription: This instance type must use BastionAMIOS type of Amazon-Linux2-HVM-ARM.
    RuleCondition: !Equals
      - !Ref BastionAMIOS
      - Amazon-Linux2-HVM-ARM
Mappings:
  AWSAMIRegionMap:
    af-south-1:
      AMZNLINUX2: ami-0936d2754993c364e
      AMZNLINUX2ARM: ami-01d326fa7db123542
      US2004HVM: ami-022666956ad401a16
      CENTOS7HVM: ami-0a2be7731769e6cc1
#      SLES15HVM: ami-EXAMPLE
    ap-northeast-1:
      AMZNLINUX2: ami-0ca38c7440de1749a
      AMZNLINUX2ARM: ami-005322a6d5cecfe58
      US2004HVM: ami-015f1a68ce825a8d2
      CENTOS7HVM: ami-06a46da680048c8ae
      SLES15HVM: ami-056ac8ad44e6a7e1f
    ap-northeast-2:
      AMZNLINUX2: ami-0f2c95e9fe3f8f80e
      AMZNLINUX2ARM: ami-01b0796a552129792
      US2004HVM: ami-0be9734c9e68b99f4
      CENTOS7HVM: ami-06e83aceba2cb0907
      SLES15HVM: ami-0f81fff879bafe6b8
    ap-northeast-3:
      AMZNLINUX2: ami-06e9ad0943b200859
      AMZNLINUX2ARM: ami-02415340f44a47b93
      US2004HVM: ami-01cb3e73f8ef13fdc
      CENTOS7HVM: ami-02d6b455335e3af14
      SLES15HVM: ami-0d8518dd12d11dfc2
    ap-south-1:
      AMZNLINUX2: ami-010aff33ed5991201
      AMZNLINUX2ARM: ami-01ad94fdf8150776c
      US2004HVM: ami-00aaac1f2ef4ce965
      CENTOS7HVM: ami-026f33d38b6410e30
      SLES15HVM: ami-01be89269d32f2a16
    ap-southeast-1:
      AMZNLINUX2: ami-02f26adf094f51167
      AMZNLINUX2ARM: ami-006eccfc9e6f597af
      US2004HVM: ami-0012ffabeb7413479
      CENTOS7HVM: ami-07f65177cb990d65b
      SLES15HVM: ami-070356c21596ddc67
    ap-southeast-2:
      AMZNLINUX2: ami-0186908e2fdeea8f3
      AMZNLINUX2ARM: ami-00719b70b31680d14
      US2004HVM: ami-03ec1fe05b3849c74
      CENTOS7HVM: ami-0b2045146eb00b617
      SLES15HVM: ami-0c4245381c67efb39
    ca-central-1:
      AMZNLINUX2: ami-0101734ab73bd9e15
      AMZNLINUX2ARM: ami-039750f0a88733fff
      US2004HVM: ami-04c56d394d31cdeac
      CENTOS7HVM: ami-04a25c39dc7a8aebb
      SLES15HVM: ami-0c97d9b588207dad6
    eu-central-1:
      AMZNLINUX2: ami-043097594a7df80ec
      AMZNLINUX2ARM: ami-000cbb96a79217336
      US2004HVM: ami-0980c5102b5ef10cc
      CENTOS7HVM: ami-0e8286b71b81c3cc1
      SLES15HVM: ami-05dfd265ea534a3e9
    me-south-1:
      AMZNLINUX2: ami-0880769bc15eeec4f
      AMZNLINUX2ARM: ami-001dc219c441b922d
      US2004HVM: ami-03cc0b5db8321f2e5
      CENTOS7HVM: ami-011c71a894b10f35b
      SLES15HVM: ami-0252c6d3a59c7473b
    ap-east-1:
      AMZNLINUX2: ami-0aca22cb23f122f27
      AMZNLINUX2ARM: ami-01f5cec80321bd86e
      US2004HVM: ami-0c7e5903bee96ef81
      CENTOS7HVM: ami-0e5c29e6c87a9644f
      SLES15HVM: ami-0ad6e15bcbb2dbe38
    eu-north-1:
      AMZNLINUX2: ami-050fdc53cf6ba8f7f
      AMZNLINUX2ARM: ami-00a8ac2b5311cd613
      US2004HVM: ami-0663a4867a210287a
      CENTOS7HVM: ami-05788af9005ef9a93
      SLES15HVM: ami-0741fa1a008af40ad
    eu-south-1:
      AMZNLINUX2: ami-0f447354763f0eaac
      AMZNLINUX2ARM: ami-011d4067dedd119f5
      US2004HVM: ami-035e213233577516f
      CENTOS7HVM: ami-03014b98e9665115a
      SLES15HVM: ami-051cbea0e7660063d
    eu-west-1:
      AMZNLINUX2: ami-063d4ab14480ac177
      AMZNLINUX2ARM: ami-00552336fb4b81164
      US2004HVM: ami-0213344887e47003a
      CENTOS7HVM: ami-0b850cf02cc00fdc8
      SLES15HVM: ami-0a58a1b152ba55f1d
    eu-west-2:
      AMZNLINUX2: ami-06dc09bb8854cbde3
      AMZNLINUX2ARM: ami-03144ab666315a8a3
      US2004HVM: ami-0add0a5a0cf9afc6c
      CENTOS7HVM: ami-09e5afc68eed60ef4
      SLES15HVM: ami-01497522185aaa4ee
    eu-west-3:
      AMZNLINUX2: ami-0b3e57ee3b63dd76b
      AMZNLINUX2ARM: ami-009b1ed4d1f59029a
      US2004HVM: ami-01019e7343a5f361d
      CENTOS7HVM: ami-0cb72d2e599cffbf9
      SLES15HVM: ami-0f238bd4c6fdbefb0
    sa-east-1:
      AMZNLINUX2: ami-05373777d08895384
      AMZNLINUX2ARM: ami-0092271c8131fcde7
      US2004HVM: ami-0312c74c38dc7bae6
      CENTOS7HVM: ami-0b30f38d939dd4b54
      SLES15HVM: ami-0772af912976aa692
    us-east-1:
      AMZNLINUX2: ami-0d5eff06f840b45e9
      AMZNLINUX2ARM: ami-002cc39e7bf021a77
      US2004HVM: ami-0db6c6238a40c0681
      CENTOS7HVM: ami-0affd4508a5d2481b
      SLES15HVM: ami-0b1764f3d7d2e2316
    us-gov-west-1:
      AMZNLINUX2: ami-0bbf3595bb2fb39ec
      AMZNLINUX2ARM: ami-6bd0e80a
      SLES15HVM: ami-57c0ba36
    us-gov-east-1:
      AMZNLINUX2: ami-0cc17d57bec8c6017
      AMZNLINUX2ARM: ami-4a31d93b
      SLES15HVM: ami-05e4bedfad53425e9
    us-east-2:
      AMZNLINUX2: ami-077e31c4939f6a2f3
      AMZNLINUX2ARM: ami-0029d4ab5707ce922
      US2004HVM: ami-03b6c8bd55e00d5ed
      CENTOS7HVM: ami-01e36b7901e884a10
      SLES15HVM: ami-05ea824317ffc0c20
    us-west-1:
      AMZNLINUX2: ami-04468e03c37242e1e
      AMZNLINUX2ARM: ami-00872c48515f06ba0
      US2004HVM: ami-0f5868930cb63c89c
      CENTOS7HVM: ami-098f55b4287a885ba
      SLES15HVM: ami-00e34a7624e5a7107
    us-west-2:
      AMZNLINUX2: ami-0cf6f5c8a62fa5da6
      AMZNLINUX2ARM: ami-0043879194eb2ad40
      US2004HVM: ami-038a0ccaaedae6406
      CENTOS7HVM: ami-0bc06212a56393ee1
      SLES15HVM: ami-0f1e3b3fb0fec0361
    cn-north-1:
      AMZNLINUX2: ami-0c52e2685c7218558
      AMZNLINUX2ARM: ami-088cc0c104292da9c
      CENTOS7HVM: ami-08c16f7e830c0e393
      SLES15HVM: ami-021392849b6221a81
    cn-northwest-1:
      AMZNLINUX2: ami-05b9b6d6acf8ae9b6
      AMZNLINUX2ARM: ami-0b5c6ceb80eb57861
      CENTOS7HVM: ami-0f21aa96a61df8c44
      SLES15HVM: ami-00e1de3ee6d0d28ea
  LinuxAMINameMap:
    Amazon-Linux2-HVM:
      Code: AMZNLINUX2
      OS: Amazon
    Amazon-Linux2-HVM-ARM:
      Code: AMZNLINUX2ARM
      OS: Amazon
    CentOS-7-HVM:
      Code: CENTOS7HVM
      OS: CentOS
    Ubuntu-Server-18.04-LTS-HVM:
      Code: US1804HVM
      OS: Ubuntu
    Ubuntu-Server-20.04-LTS-HVM:
      Code: US2004HVM
      OS: Ubuntu
    SUSE-SLES-15-HVM:
      Code: SLES15HVM
      OS: SLES
Conditions:
  2BastionCondition: !Or
    - !Equals
      - !Ref NumBastionHosts
      - '2'
    - !Condition 3BastionCondition
    - !Condition 4BastionCondition
  3BastionCondition: !Or
    - !Equals
      - !Ref NumBastionHosts
      - '3'
    - !Condition 4BastionCondition
  4BastionCondition: !Equals
    - !Ref NumBastionHosts
    - '4'
  UseAlternativeInitialization: !Not
    - !Equals
      - !Ref AlternativeInitializationScript
      - ''
  CreateIAMRole: !Equals
    - !Ref AlternativeIAMRole
    - ''
  UseOSImageOverride: !Not
    - !Equals
      - !Ref OSImageOverride
      - ''
  UsingDefaultBucket: !Equals
    - !Ref QSS3BucketName
    - 'aws-quickstart'
  DefaultBanner: !Equals [!Ref BastionBanner, ""]
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: /
      AssumeRolePolicyDocument:
        Statement:
          - Action:
              - 'sts:AssumeRole'
            Principal:
              Service:
                - !Sub 'ec2.${AWS::URLSuffix}'
            Effect: Allow
        Version: 2012-10-17
      ManagedPolicyArns:
        - !Sub 'arn:${AWS::Partition}:iam::aws:policy/AmazonSSMManagedInstanceCore'
        - !Sub 'arn:${AWS::Partition}:iam::aws:policy/CloudWatchAgentServerPolicy'
  BastionHostPolicy:
    Type: 'AWS::IAM::Policy'
    Properties:
      PolicyName: BastionPolicy
      PolicyDocument:
        Version: 2012-10-17
        Statement:
          - Action:
              - 's3:GetObject'
            Resource: !Sub
              - arn:${AWS::Partition}:s3:::${S3Bucket}/${QSS3KeyPrefix}*
              - S3Bucket: !If [UsingDefaultBucket, !Sub '${QSS3BucketName}-${AWS::Region}', !Ref QSS3BucketName]
            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}:*"
            Effect: Allow
          - Action:
              - 'ec2:DescribeAddresses'
            Resource: '*'
            Effect: Allow
          - Effect: Allow
            Action:
              - 'ec2:AssociateAddress'
            Resource: '*'
            Condition:
              StringEquals:
                ec2:ResourceTag/aws:cloudformation:stack-id: !Ref AWS::StackId
      Roles:
        - !If
          - CreateIAMRole
          - !Ref BastionHostRole
          - !Ref AlternativeIAMRole
  BastionHostProfile:
    DependsOn: BastionHostPolicy
    Type: 'AWS::IAM::InstanceProfile'
    Properties:
      Roles:
        - !If
          - CreateIAMRole
          - !Ref BastionHostRole
          - !Ref AlternativeIAMRole
      Path: /
  EIP1:
    Type: 'AWS::EC2::EIP'
    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:
      LaunchConfigurationName: !Ref BastionLaunchConfiguration
      VPCZoneIdentifier:
        - !Ref PublicSubnet1ID
        - !Ref PublicSubnet2ID
      MinSize: !Ref NumBastionHosts
      MaxSize: !Ref NumBastionHosts
      Cooldown: '900'
      DesiredCapacity: !Ref NumBastionHosts
      Tags:
        - Key: Name
          Value: !Ref BastionHostName
          PropagateAtLaunch: true
    CreationPolicy:
      ResourceSignal:
        Count: !Ref NumBastionHosts
        Timeout: PT60M
      AutoScalingCreationPolicy:
        MinSuccessfulInstancesPercent: 100
    UpdatePolicy:
      AutoScalingReplacingUpdate:
        WillReplace: true
  BastionLaunchConfiguration:
    Type: 'AWS::AutoScaling::LaunchConfiguration'
    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"
              # command:
              #   - !If [ ]
              #   - "cat /tmp/auditd.rules >> /etc/audit/rules.d/audit.rules && service auditd restart"
            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:
      AssociatePublicIpAddress: true
      PlacementTenancy: !Ref BastionTenancy
      KeyName: !Ref KeyPairName
      IamInstanceProfile: !Ref BastionHostProfile
      ImageId: !If
        - UseOSImageOverride
        - !Ref OSImageOverride
        - !FindInMap
          - AWSAMIRegionMap
          - !Ref 'AWS::Region'
          - !FindInMap
            - LinuxAMINameMap
            - !Ref BastionAMIOS
            - Code
      SecurityGroups:
        - !Ref BastionSecurityGroup
      InstanceType: !Ref BastionInstanceType
      BlockDeviceMappings:
        - DeviceName: /dev/xvda
          Ebs:
            VolumeSize: !Ref RootVolumeSize
            VolumeType: gp2
            Encrypted: true
            DeleteOnTermination: true
      UserData:
        Fn::Base64: !Sub
          - |
            #!/bin/bash
            set -x
            for e in $(echo "${EnvironmentVariables}" | tr ',' ' '); do
              export $e
              echo "$e" >> /root/.bashrc
            done
            export PATH=$PATH:/usr/local/bin
            #cfn signaling functions
            yum install git -y || apt-get install -y git || zypper -n install git

            function cfn_fail
            {
              cfn-signal -e 1 --stack ${AWS::StackName} --region ${AWS::Region} --resource BastionAutoScalingGroup
              exit 1
            }

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

            until git clone https://github.com/aws-quickstart/quickstart-linux-utilities.git ; do echo "Retrying"; done
            cd /quickstart-linux-utilities;
            source quickstart-cfn-tools.source;
            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 BastionLaunchConfiguration --region ${AWS::Region} || cfn_fail
            [ $(qs_status) == 0 ] && cfn_success || cfn_fail
          - EIP2:
              !If
              - 2BastionCondition
              - !Ref EIP2
              - 'Null'
            EIP3:
              !If
              - 3BastionCondition
              - !Ref EIP3
              - 'Null'
            EIP4:
              !If
              - 4BastionCondition
              - !Ref EIP4
              - 'Null'
  BastionSecurityGroup:
    Type: 'AWS::EC2::SecurityGroup'
    Properties:
      GroupDescription: Enables SSH Access to Bastion Hosts
      VpcId: !Ref VPCID
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 22
          ToPort: 22
          CidrIp: !Ref RemoteAccessCIDR
        - IpProtocol: icmp
          FromPort: -1
          ToPort: -1
          CidrIp: !Ref RemoteAccessCIDR
Outputs:
  BastionAutoScalingGroup:
    Description: Auto Scaling group reference ID.
    Value: !Ref BastionAutoScalingGroup
    Export:
      Name: !Sub '${AWS::StackName}-BastionAutoScalingGroup'
  EIP1:
    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://aws.amazon.com/quickstart/?quickstart-all.sort-by=item.additionalFields.sortDate&quickstart-all.sort-order=desc&awsm.page-quickstart-all=5