AWSTemplateFormatVersion: 2010-09-09 Description: LinuxBastion+VPC Jul,30,2020 (qs-1qup6ra99) (Please do not remove) Metadata: 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 - 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: 'VPC tenancy to launch the bastion in. Options: ''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 - 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: To include a banner to be displayed when connecting via SSH to the bastion, choose true. 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: Quick Start bucket name can include numbers, lowercase letters, uppercase letters, and hyphens (-). It cannot start or end with a hyphen (-). Default: aws-quickstart Description: S3 bucket name for the Quick Start assets. Quick Start bucket name can include numbers, lowercase letters, uppercase letters, and hyphens (-). It cannot start or end with a hyphen (-). Type: String QSS3BucketRegion: Default: 'us-east-1' Description: The AWS Region where the Quick Start S3 bucket (QSS3BucketName) is hosted. When using your own bucket, you must specify this value. Type: String QSS3KeyPrefix: AllowedPattern: '^([0-9a-zA-Z-.]+/)*$' ConstraintDescription: Quick Start key prefix can include numbers, lowercase letters, uppercase letters, hyphens (-), dots (.) and forward slash (/). The prefix should end with a forward slash (/). Default: quickstart-skillnet-xstoreoffice/ Description: S3 key prefix for the Quick Start assets. Quick Start key prefix can include numbers, lowercase letters, uppercase letters, hyphens (-), dots (.) and forward slash (/) and it should end with a forward slash (/). 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: ^http.*|^$ ConstraintDescription: URL must begin with http 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 Mappings: AWSAMIRegionMap: ap-northeast-1: AMZNLINUX2: ami-0cc75a8978fbbc969 US2004HVM: ami-0461b11e2fad8c14a CENTOS7HVM: ami-06a46da680048c8ae SLES15HVM: ami-056ac8ad44e6a7e1f ap-northeast-2: AMZNLINUX2: ami-0bd7691bf6470fe9c US2004HVM: ami-0dbad3c7f731477cb CENTOS7HVM: ami-06e83aceba2cb0907 SLES15HVM: ami-0f81fff879bafe6b8 ap-south-1: AMZNLINUX2: ami-0ebc1ac48dfd14136 US2004HVM: ami-0ebd654017556e025 CENTOS7HVM: ami-026f33d38b6410e30 SLES15HVM: ami-01be89269d32f2a16 ap-southeast-1: AMZNLINUX2: ami-0cd31be676780afa7 US2004HVM: ami-0ba1d1f3433cd4c68 CENTOS7HVM: ami-07f65177cb990d65b SLES15HVM: ami-070356c21596ddc67 ap-southeast-2: AMZNLINUX2: ami-0ded330691a314693 US2004HVM: ami-02be36619a83e9a16 CENTOS7HVM: ami-0b2045146eb00b617 SLES15HVM: ami-0c4245381c67efb39 ca-central-1: AMZNLINUX2: ami-013d1df4bcea6ba95 US2004HVM: ami-071c33c681c9d4a00 CENTOS7HVM: ami-04a25c39dc7a8aebb SLES15HVM: ami-0c97d9b588207dad6 eu-central-1: AMZNLINUX2: ami-0c115dbd34c69a004 US2004HVM: ami-0c2b1c303a2e4cb49 CENTOS7HVM: ami-0e8286b71b81c3cc1 SLES15HVM: ami-05dfd265ea534a3e9 me-south-1: AMZNLINUX2: ami-01f41d49c363da2ad US2004HVM: ami-07f9fe3f7a8c82448 CENTOS7HVM: ami-011c71a894b10f35b SLES15HVM: ami-0252c6d3a59c7473b ap-east-1: AMZNLINUX2: ami-47317236 US2004HVM: ami-545b1825 CENTOS7HVM: ami-0e5c29e6c87a9644f SLES15HVM: ami-0ad6e15bcbb2dbe38 eu-north-1: AMZNLINUX2: ami-039609244d2810a6b US2004HVM: ami-08baf9e3c347b7092 CENTOS7HVM: ami-05788af9005ef9a93 SLES15HVM: ami-0741fa1a008af40ad eu-west-1: AMZNLINUX2: ami-07d9160fa81ccffb5 US2004HVM: ami-0f1d11c92a9467c07 CENTOS7HVM: ami-0b850cf02cc00fdc8 SLES15HVM: ami-0a58a1b152ba55f1d eu-west-2: AMZNLINUX2: ami-0a13d44dccf1f5cf6 US2004HVM: ami-082335b69bcfdb15b CENTOS7HVM: ami-09e5afc68eed60ef4 SLES15HVM: ami-01497522185aaa4ee eu-west-3: AMZNLINUX2: ami-093fa4c538885becf US2004HVM: ami-00f6fb16625871821 CENTOS7HVM: ami-0cb72d2e599cffbf9 SLES15HVM: ami-0f238bd4c6fdbefb0 sa-east-1: AMZNLINUX2: ami-018ccfb6b4745882a US2004HVM: ami-083aa2af86ff2bd11 CENTOS7HVM: ami-0b30f38d939dd4b54 SLES15HVM: ami-0772af912976aa692 us-east-1: AMZNLINUX2: ami-02354e95b39ca8dec US2004HVM: ami-0758470213bdd23b1 CENTOS7HVM: ami-0affd4508a5d2481b SLES15HVM: ami-0b1764f3d7d2e2316 us-gov-west-1: AMZNLINUX2: ami-74c4f215 SLES15HVM: ami-57c0ba36 us-gov-east-1: AMZNLINUX2: ami-30e00c41 SLES15HVM: ami-05e4bedfad53425e9 us-east-2: AMZNLINUX2: ami-07c8bc5c1ce9598c3 US2004HVM: ami-07fb7bd53bacdfc16 CENTOS7HVM: ami-01e36b7901e884a10 SLES15HVM: ami-05ea824317ffc0c20 us-west-1: AMZNLINUX2: ami-05655c267c89566dd US2004HVM: ami-0cd230f950c3de5d8 CENTOS7HVM: ami-098f55b4287a885ba SLES15HVM: ami-00e34a7624e5a7107 us-west-2: AMZNLINUX2: ami-0873b46c45c11058d US2004HVM: ami-056cb9ae6e2df09e8 CENTOS7HVM: ami-0bc06212a56393ee1 SLES15HVM: ami-0f1e3b3fb0fec0361 cn-north-1: AMZNLINUX2: ami-010e92a33d9d1fc40 CENTOS7HVM: ami-0e02aaefeb74c3373 SLES15HVM: ami-021392849b6221a81 cn-northwest-1: AMZNLINUX2: ami-0959f8e18a2aac0fb CENTOS7HVM: ami-07183a7702633260b SLES15HVM: ami-00e1de3ee6d0d28ea LinuxAMINameMap: Amazon-Linux2-HVM: Code: AMZNLINUX2 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:AssociateAddress' - 'ec2:DescribeAddresses' Resource: '*' Effect: Allow 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 done export PATH=$PATH:/usr/local/bin yum install squid -y find /etc/squid -type f -name 'squid.conf' -exec sed -i'' -e 's/\http_access deny all/http_access allow all/g' {} + systemctl enable squid systemctl start squid #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 - IpProtocol: tcp FromPort: 3128 ToPort: 3128 CidrIp: 0.0.0.0/0 SecurityGroupEgress: - IpProtocol: TCP FromPort: 3128 ToPort: 3128 CidrIp: 0.0.0.0/0 Description: "Proxy Server" - IpProtocol: "-1" CidrIp: 0.0.0.0/0 Description: "Bastion" 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'