├── .gitignore ├── .gitmodules ├── .metadata ├── .taskcat.yml ├── CODEOWNERS ├── LICENSE.txt ├── NOTICE.txt ├── README.md ├── cfn-module └── .rpdk-config ├── manifests └── app-manager │ └── app-manager-manifest.yaml ├── scripts ├── auditing_configure.sh ├── banner_message.txt ├── bastion_bootstrap.sh └── cfn-tools.sh └── templates ├── linux-bastion-entrypoint-existing-vpc.template.yaml └── linux-bastion-entrypoint-new-vpc.template.yaml /.gitignore: -------------------------------------------------------------------------------- 1 | # TaskCat 2 | taskcat_outputs/ 3 | .taskcat/ 4 | .taskcat_overrides.yml 5 | functions/packages/ 6 | packages/ 7 | 8 | # cfn module build 9 | cfn-module/*.zip 10 | cfn-module/*.json 11 | cfn-module/fragments/ 12 | cfn-module/rpdk.log 13 | 14 | # Docs 15 | docs/ 16 | index.html 17 | prod_example.html 18 | 19 | # macOS 20 | .DS_Store 21 | 22 | # IDE workspace settings 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "submodules/quickstart-aws-vpc"] 2 | path = submodules/quickstart-aws-vpc 3 | url = https://github.com/aws-quickstart/quickstart-aws-vpc.git 4 | branch = main 5 | -------------------------------------------------------------------------------- /.metadata: -------------------------------------------------------------------------------- 1 | language_type: cloudformation 2 | -------------------------------------------------------------------------------- /.taskcat.yml: -------------------------------------------------------------------------------- 1 | project: 2 | name: quickstart-linux-bastion 3 | owner: quickstart-eng@amazon.com 4 | s3_regional_buckets: true 5 | regions: 6 | - af-south-1 7 | - ap-east-1 8 | - ap-northeast-1 9 | - ap-northeast-2 10 | - ap-northeast-3 11 | - ap-south-1 12 | - ap-south-2 13 | - ap-southeast-1 14 | - ap-southeast-2 15 | - ap-southeast-3 16 | - ap-southeast-4 17 | - ca-central-1 18 | - eu-central-1 19 | - eu-central-2 20 | - eu-north-1 21 | - eu-south-1 22 | - eu-south-2 23 | - eu-west-1 24 | - eu-west-2 25 | - eu-west-3 26 | - me-central-1 27 | - me-south-1 28 | - sa-east-1 29 | - us-east-1 30 | - us-east-2 31 | - us-west-1 32 | - us-west-2 33 | - us-gov-east-1 34 | - us-gov-west-1 35 | - cn-north-1 36 | - cn-northwest-1 37 | template: templates/linux-bastion-entrypoint-new-vpc.template.yaml 38 | parameters: 39 | AvailabilityZones: $[taskcat_getaz_2] 40 | KeyPairName: --override-- 41 | QSS3BucketName: $[taskcat_autobucket] 42 | QSS3BucketRegion: $[taskcat_current_region] 43 | tests: 44 | amznlinux2hvm: 45 | parameters: 46 | BastionAMIOS: Amazon-Linux2-HVM 47 | RemoteAccessCIDR: 10.0.0.0/16 48 | regions: 49 | - me-south-1 50 | - us-west-2 51 | - us-gov-east-1 52 | - cn-north-1 53 | amznlinux2022: 54 | parameters: 55 | BastionAMIOS: Amazon-Linux2022 56 | RemoteAccessCIDR: 10.0.0.0/16 57 | regions: 58 | - eu-west-2 59 | - ap-southeast-2 60 | - us-gov-east-1 61 | - cn-north-1 62 | us2004hvm: 63 | parameters: 64 | BastionAMIOS: Ubuntu-Server-20.04-LTS-HVM 65 | BastionInstanceType: t3.small 66 | RemoteAccessCIDR: 10.0.0.0/16 67 | regions: 68 | - eu-west-3 69 | us2204hvm: 70 | parameters: 71 | BastionAMIOS: Ubuntu-Server-22.04-LTS-HVM 72 | BastionInstanceType: t3.small 73 | RemoteAccessCIDR: 10.0.0.0/16 74 | regions: 75 | - eu-north-1 76 | amznlinux2hvmarm: 77 | parameters: 78 | BastionAMIOS: Amazon-Linux2-HVM-ARM 79 | BastionInstanceType: t4g.nano 80 | RemoteAccessCIDR: 10.0.0.0/16 81 | regions: 82 | - ap-south-1 83 | - us-west-1 84 | - us-gov-west-1 85 | amznlinux2022arm: 86 | parameters: 87 | BastionAMIOS: Amazon-Linux2022-ARM 88 | BastionInstanceType: t4g.nano 89 | RemoteAccessCIDR: 10.0.0.0/16 90 | regions: 91 | - ap-southeast-1 92 | - us-west-1 93 | - us-gov-west-1 94 | us2204hvmarm: 95 | parameters: 96 | BastionAMIOS: Ubuntu-Server-22.04-LTS-HVM-ARM 97 | BastionInstanceType: t4g.nano 98 | RemoteAccessCIDR: 10.0.0.0/16 99 | regions: 100 | - ap-northeast-2 101 | onlyssmaccess: 102 | parameters: 103 | BastionAMIOS: Amazon-Linux2-HVM-ARM 104 | BastionInstanceType: t4g.nano 105 | RemoteAccessCIDR: disabled-onlyssmaccess 106 | NumBastionHosts: 1 107 | regions: 108 | - us-east-2 109 | multiplehosts: 110 | parameters: 111 | BastionAMIOS: Amazon-Linux2-HVM-ARM 112 | BastionInstanceType: t4g.nano 113 | RemoteAccessCIDR: 10.0.0.0/16 114 | NumBastionHosts: 2 115 | regions: 116 | - eu-west-1 117 | spot: 118 | parameters: 119 | BastionAMIOS: Amazon-Linux2-HVM-ARM 120 | BastionInstanceType: t4g.nano 121 | RemoteAccessCIDR: disabled-onlyssmaccess 122 | OndemandPercentage: 0 123 | NumBastionHosts: 1 124 | regions: 125 | - us-east-1 126 | prefix-list-access: 127 | parameters: 128 | RemoteAccessCIDR: pl-a6a742cf 129 | regions: 130 | - sa-east-1 131 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | # @aws-quickstart/aws_quickstart_team 2 | * @tlindsay42 @andrew-glenn @tonynv @aws-quickstart/aws_quickstart_team 3 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | -------------------------------------------------------------------------------- /NOTICE.txt: -------------------------------------------------------------------------------- 1 | Copyright 2016-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with the License. A copy of the License is located at 4 | 5 | http://aws.amazon.com/apache2.0/ 6 | 7 | or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # quickstart-linux-bastion 2 | ## Deprecation Notice 3 | 4 | :x: This repository is subject to deprecation in Q4 2024. For more details, [please review this announcement](https://github.com/aws-ia/.announcements/issues/1). 5 | 6 | ## This repository has been deprecated in favor of https://github.com/aws-ia/cfn-ps-linux-bastion. 7 | ***We will archive this repository and keep it publicly available until May 1, 2024.*** 8 | -------------------------------------------------------------------------------- /cfn-module/.rpdk-config: -------------------------------------------------------------------------------- 1 | { 2 | "artifact_type": "MODULE", 3 | "typeName": "AWSQS::EC2::LinuxBastionQS::MODULE", 4 | "settings": {} 5 | } 6 | -------------------------------------------------------------------------------- /manifests/app-manager/app-manager-manifest.yaml: -------------------------------------------------------------------------------- 1 | ssm_app_manager: 2 | should_upload: true 3 | documents_list: 4 | - document_name: AWSQuickStarts-LinuxBastion 5 | template_name: linux-bastion.template -------------------------------------------------------------------------------- /scripts/auditing_configure.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -xe 4 | 5 | install_stuff_ubuntu() { 6 | apt-get -y install auditd 7 | } 8 | 9 | add_the_rules() { 10 | cat /tmp/auditd.rules >> /etc/audit/rules.d/audit.rules 11 | rm /tmp/auditd.rules 12 | } 13 | 14 | restart_services() { 15 | case "${BASTION_OS}" in 16 | Amazon) 17 | /usr/sbin/service auditd restart 18 | ;; 19 | CentOS|SUSE) 20 | /sbin/service auditd restart 21 | ;; 22 | Ubuntu) 23 | service auditd restart 24 | ;; 25 | esac 26 | } 27 | 28 | case "${BASTION_OS}" in 29 | Ubuntu) 30 | install_stuff_ubuntu 31 | ;; 32 | esac 33 | 34 | add_the_rules 35 | restart_services 36 | -------------------------------------------------------------------------------- /scripts/banner_message.txt: -------------------------------------------------------------------------------- 1 | 2 | ########################################################################## 3 | # __ _______ _____ _ _ _ # 4 | # /\ \ / / ____| / ____| | | | | (_) # 5 | # / \ \ /\ / / (___ | (___ ___ | |_ _| |_ _ ___ _ __ ___ # 6 | # / /\ \ \/ \/ / \___ \ \___ \ / _ \| | | | | __| |/ _ \| '_ \/ __| # 7 | # / ____ \ /\ / ____) | ____) | (_) | | |_| | |_| | (_) | | | \__ \ # 8 | # /_/ \_\/ \/ |_____/ |_____/ \___/|_|\__,_|\__|_|\___/|_| |_|___/ # 9 | #------------------------------------------------------------------------# 10 | # Authorized access only! # 11 | # Disconnect IMMEDIATELY if you are not an authorized user!!! # 12 | # All actions will be monitored and recorded. # 13 | # https://aws-quickstart.github.io/quickstart-linux-bastion/ # 14 | ########################################################################## 15 | -------------------------------------------------------------------------------- /scripts/bastion_bootstrap.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Bastion Bootstrapping 3 | # authors: tonynv@amazon.com, sancard@amazon.com, ianhill@amazon.com 4 | # NOTE: This requires GNU getopt. On Mac OS X and FreeBSD you must install GNU getopt and mod the checkos function so that it's supported 5 | 6 | set -xe 7 | 8 | # Configuration 9 | PROGRAM='Linux Bastion' 10 | IMDS_BASE_URL='http://169.254.169.254/latest' 11 | HARDWARE=$(uname -m) 12 | if [[ "${HARDWARE}" == 'x86_64' ]]; then 13 | ARCHITECTURE='amd64' 14 | ARCHITECTURE2='64bit' 15 | elif [[ "${HARDWARE}" == 'aarch64' ]]; then 16 | ARCHITECTURE='arm64' 17 | ARCHITECTURE2='arm64' 18 | else 19 | echo "[FAILED] Unsupported architecture: '${HARDWARE}'." 20 | exit 1 21 | fi 22 | 23 | ##################################### Functions Definitions 24 | checkos() { 25 | platform='unknown' 26 | unamestr=`uname` 27 | if [[ "${unamestr}" == 'Linux' ]]; then 28 | platform='linux' 29 | else 30 | echo "[WARNING] This script is not supported on MacOS or FreeBSD" 31 | exit 1 32 | fi 33 | echo "${FUNCNAME[0]} ended" 34 | } 35 | 36 | imdsv2_token() { 37 | curl -sSX PUT "${IMDS_BASE_URL}/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 600" 38 | } 39 | 40 | imds_request() { 41 | REQUEST_PATH=$1 42 | if [[ -z $TOKEN ]]; then 43 | TOKEN=$(imdsv2_token) 44 | fi 45 | curl -sSH "X-aws-ec2-metadata-token: $TOKEN" "${IMDS_BASE_URL}/${REQUEST_PATH}" 46 | } 47 | 48 | setup_environment_variables() { 49 | REGION=$(imds_request meta-data/placement/availability-zone/) 50 | #ex: us-east-1a => us-east-1 51 | REGION=${REGION: :-1} 52 | 53 | ETH0_MAC=$(/sbin/ip link show dev eth0 | /bin/egrep -o -i 'link/ether\ ([0-9a-z]{2}:){5}[0-9a-z]{2}' | /bin/sed -e 's,link/ether\ ,,g') 54 | 55 | _userdata_file="/var/lib/cloud/instance/user-data.txt" 56 | 57 | INSTANCE_ID=$(imds_request meta-data/instance-id) 58 | EIP_LIST=$(grep EIP_LIST ${_userdata_file} | sed -e 's/EIP_LIST=//g' -e 's/\"//g') 59 | 60 | LOCAL_IP_ADDRESS=$(imds_request meta-data/network/interfaces/macs/${ETH0_MAC}/local-ipv4s/) 61 | 62 | CWG=$(grep CLOUDWATCHGROUP ${_userdata_file} | sed -e 's/CLOUDWATCHGROUP=//g' -e 's/\"//g') 63 | 64 | export REGION ETH0_MAC EIP_LIST CWG LOCAL_IP_ADDRESS INSTANCE_ID 65 | } 66 | 67 | usage() { 68 | echo "$0 " 69 | echo " " 70 | echo "options:" 71 | echo -e "--help \t Show options for this script" 72 | echo -e "--banner \t Enable or disable bastion message" 73 | echo -e "--enable \t SSH banner" 74 | echo -e "--tcp-forwarding \t Enable or disable TCP forwarding" 75 | echo -e "--x11-forwarding \t Enable or disable X11 forwarding" 76 | } 77 | 78 | chkstatus() { 79 | if [[ $? -eq 0 ]] 80 | then 81 | echo "Script [PASS]" 82 | else 83 | echo "Script [FAILED]" >&2 84 | exit 1 85 | fi 86 | } 87 | 88 | osrelease() { 89 | OS=`cat /etc/os-release | grep '^NAME=' | tr -d \" | sed 's/\n//g' | sed 's/NAME=//g'` 90 | if [[ "${OS}" == "Ubuntu" ]]; then 91 | echo "Ubuntu" 92 | elif [[ "${OS}" == "Amazon Linux AMI" ]] || [[ "${OS}" == "Amazon Linux" ]]; then 93 | echo "AMZN" 94 | elif [[ "${OS}" == "CentOS Linux" ]]; then 95 | echo "CentOS" 96 | elif [[ "${OS}" == "SLES" ]]; then 97 | echo "SLES" 98 | else 99 | echo "Operating system not found" 100 | fi 101 | echo "${FUNCNAME[0]} ended" >> /var/log/cfn-init.log 102 | } 103 | 104 | # Setup Amazon EC2 Instance Connect agent 105 | # https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-connect-set-up.html#ec2-instance-connect-install 106 | setup_ec2_instance_connect() { 107 | echo "${FUNCNAME[0]} started" 108 | 109 | if [[ "${release}" == "AMZN" ]]; then 110 | yum install -y ec2-instance-connect 111 | elif [[ "${release}" == "Ubuntu" ]]; then 112 | apt-get install -y ec2-instance-connect 113 | fi 114 | } 115 | 116 | setup_logs() { 117 | echo "${FUNCNAME[0]} started" 118 | URL_SUFFIX="${URL_SUFFIX:-amazonaws.com}" 119 | if [[ "${release}" == 'SLES' ]]; then 120 | zypper install --allow-unsigned-rpm -y "https://amazoncloudwatch-agent-${REGION}.s3.${REGION}.${URL_SUFFIX}/suse/${ARCHITECTURE}/latest/amazon-cloudwatch-agent.rpm" 121 | elif [[ "${release}" == 'CentOS' ]]; then 122 | yum install -y "https://amazoncloudwatch-agent-${REGION}.s3.${REGION}.${URL_SUFFIX}/centos/${ARCHITECTURE}/latest/amazon-cloudwatch-agent.rpm" 123 | elif [[ "${release}" == 'Ubuntu' ]]; then 124 | export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin 125 | curl "https://amazoncloudwatch-agent-${REGION}.s3.${REGION}.${URL_SUFFIX}/ubuntu/${ARCHITECTURE}/latest/amazon-cloudwatch-agent.deb" -O 126 | dpkg -i -E ./amazon-cloudwatch-agent.deb 127 | rm ./amazon-cloudwatch-agent.deb 128 | elif [[ "${release}" == 'AMZN' ]]; then 129 | yum install -y "https://amazoncloudwatch-agent-${REGION}.s3.${REGION}.${URL_SUFFIX}/amazon_linux/${ARCHITECTURE}/latest/amazon-cloudwatch-agent.rpm" 130 | fi 131 | 132 | cat <> /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json 133 | { 134 | "logs": { 135 | "force_flush_interval": 5, 136 | "logs_collected": { 137 | "files": { 138 | "collect_list": [ 139 | { 140 | "file_path": "/var/log/audit/audit.log", 141 | "log_group_name": "${CWG}", 142 | "log_stream_name": "{instance_id}", 143 | "timestamp_format": "%Y-%m-%d %H:%M:%S", 144 | "timezone": "UTC" 145 | } 146 | ] 147 | } 148 | } 149 | } 150 | } 151 | EOF 152 | 153 | if [ -x /bin/systemctl ] || [ -x /usr/bin/systemctl ]; then 154 | systemctl enable amazon-cloudwatch-agent.service 155 | systemctl restart amazon-cloudwatch-agent.service 156 | else 157 | start amazon-cloudwatch-agent 158 | fi 159 | } 160 | 161 | setup_os() { 162 | echo "${FUNCNAME[0]} started" 163 | 164 | echo "Defaults env_keep += \"SSH_CLIENT\"" >> /etc/sudoers 165 | 166 | if [[ "${release}" == "Ubuntu" ]]; then 167 | user_group="ubuntu" 168 | elif [[ "${release}" == "CentOS" ]]; then 169 | user_group="centos" 170 | elif [[ "${release}" == "SLES" ]]; then 171 | user_group="users" 172 | else 173 | user_group="ec2-user" 174 | fi 175 | 176 | if [[ "${release}" == "CentOS" ]]; then 177 | /sbin/restorecon -v /etc/ssh/sshd_config 178 | fi 179 | 180 | if [[ "${release}" == "SLES" ]]; then 181 | echo "0 0 * * * zypper patch --non-interactive" > /etc/cron.d/yum-security-updates 182 | elif [[ "${release}" == "Ubuntu" ]]; then 183 | apt-get install -y unattended-upgrades 184 | echo "0 0 * * * unattended-upgrades -d" > /etc/cron.d/yum-security-updates 185 | else 186 | echo "0 0 * * * yum -y update --security" > /etc/cron.d/yum-security-updates 187 | fi 188 | 189 | systemctl restart sshd 190 | echo "${FUNCNAME[0]} ended" 191 | } 192 | 193 | # Setup AWS Systems Manager (SSM) agent 194 | setup_ssm() { 195 | echo "${FUNCNAME[0]} started" 196 | URL_SUFFIX="${URL_SUFFIX:-amazonaws.com}" 197 | 198 | echo "ssm-user ALL=(ALL:ALL) NOPASSWD: ALL" > /etc/sudoers.d/ssm-user 199 | 200 | if [[ "${release}" == 'CentOS' ]]; then 201 | echo 'Installing the AWS Systems Manager (SSM) agent...' 202 | yum install -y "https://amazon-ssm-${REGION}.s3.${REGION}.${URL_SUFFIX}/latest/linux_${ARCHITECTURE}/amazon-ssm-agent.rpm" 203 | fi 204 | 205 | if [[ "${release}" == "Ubuntu" ]]; then 206 | systemctl enable snap.amazon-ssm-agent.amazon-ssm-agent.service 207 | systemctl restart snap.amazon-ssm-agent.amazon-ssm-agent.service 208 | elif [ -x /bin/systemctl ] || [ -x /usr/bin/systemctl ]; then 209 | systemctl enable amazon-ssm-agent.service 210 | systemctl restart amazon-ssm-agent.service 211 | else 212 | start amazon-ssm-agent 213 | fi 214 | 215 | # As of 2022-10-03, the AWS Systems Manager plugin for the AWS CLI is only 216 | # officially hosted from the `session-manager-downloads` bucket in us-east-1 217 | # (ie: regional buckets are not yet supported). 218 | # https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager-working-with-install-plugin.html 219 | echo 'Installing the AWS Systems Manager (SSM) plugin for the AWS CLI...' 220 | if [[ "${release}" == 'AMZN' ]] || [[ "${release}" == 'CentOS' ]]; then 221 | yum install -y "https://session-manager-downloads.s3.us-east-1.amazonaws.com/plugin/latest/linux_${ARCHITECTURE2}/session-manager-plugin.rpm" 222 | elif [[ "${release}" == 'SLES' ]]; then 223 | zypper install --allow-unsigned-rpm -y "https://session-manager-downloads.s3.us-east-1.amazonaws.com/plugin/latest/linux_${ARCHITECTURE2}/session-manager-plugin.rpm" 224 | elif [[ "${release}" == 'Ubuntu' ]]; then 225 | wget "https://session-manager-downloads.s3.us-east-1.amazonaws.com/plugin/latest/ubuntu_${ARCHITECTURE2}/session-manager-plugin.deb" 226 | dpkg -i -E ./session-manager-plugin.deb 227 | rm ./session-manager-plugin.deb 228 | fi 229 | } 230 | 231 | request_eip() { 232 | # Is the already-assigned Public IP an elastic IP? 233 | _query_assigned_public_ip 234 | 235 | set +e 236 | _determine_eip_assc_status ${PUBLIC_IP_ADDRESS} 237 | set -e 238 | 239 | if [[ ${_eip_associated} -eq 0 ]]; then 240 | echo "The Public IP address associated with eth0 (${PUBLIC_IP_ADDRESS}) is already an Elastic IP. Not proceeding further." 241 | exit 1 242 | fi 243 | 244 | EIP_ARRAY=(${EIP_LIST//,/ }) 245 | _eip_assigned_count=0 246 | 247 | for eip in "${EIP_ARRAY[@]}"; do 248 | if [[ "${eip}" == "Null" ]]; then 249 | echo "Detected a NULL Value, moving on." 250 | continue 251 | fi 252 | 253 | # Determine if the EIP has already been assigned. 254 | set +e 255 | _determine_eip_assc_status ${eip} 256 | set -e 257 | _determine_eip_allocation ${eip} 258 | 259 | # Attempt to assign EIP to the ENI. 260 | set +e 261 | aws ec2 associate-address --instance-id ${INSTANCE_ID} --allocation-id ${eip_allocation} --region ${REGION} 262 | 263 | rc=$? 264 | set -e 265 | 266 | if [[ ${rc} -ne 0 ]]; then 267 | echo "Unable to associate EIP ${eip}. Failure. Exiting" 268 | exit 1 269 | fi 270 | done 271 | 272 | echo "${FUNCNAME[0]} ended" 273 | } 274 | 275 | _query_assigned_public_ip() { 276 | # Note: ETH0 Only. 277 | # - Does not distinguish between EIP and Standard IP. Need to cross-ref later. 278 | echo "Querying the assigned public IP" 279 | PUBLIC_IP_ADDRESS=$(imds_request meta-data/public-ipv4/${ETH0_MAC}/public-ipv4s/) 280 | } 281 | 282 | _determine_eip_assc_status() { 283 | # Is the provided EIP associated? 284 | # Also determines if an IP is an EIP. 285 | # 0 => true 286 | # 1 => false 287 | echo "Determining EIP Association Status for [${1}]" 288 | set +e 289 | aws ec2 describe-addresses --public-ips ${1} --output text --region ${REGION} 2>/dev/null | grep -o -i eipassoc -q 290 | rc=$? 291 | set -e 292 | if [[ ${rc} -eq 1 ]]; then 293 | _eip_associated=1 294 | else 295 | _eip_associated=0 296 | fi 297 | } 298 | 299 | _determine_eip_allocation() { 300 | echo "Determining EIP Allocation for [${1}]" 301 | resource_id_length=$(aws ec2 describe-addresses --public-ips ${1} --output text --region ${REGION} | head -n 1 | awk {'print $2'} | sed 's/.*eipalloc-//') 302 | if [[ "${#resource_id_length}" -eq 17 ]]; then 303 | eip_allocation=$(aws ec2 describe-addresses --public-ips ${1} --output text --region ${REGION}| egrep 'eipalloc-([a-z0-9]{17})' -o) 304 | else 305 | eip_allocation=$(aws ec2 describe-addresses --public-ips ${1} --output text --region ${REGION}| egrep 'eipalloc-([a-z0-9]{8})' -o) 306 | fi 307 | } 308 | 309 | prevent_process_snooping() { 310 | # Prevent bastion host users from viewing processes owned by other users. 311 | mount -o remount,rw,hidepid=2 /proc 312 | awk '!/proc/' /etc/fstab > temp && mv temp /etc/fstab 313 | echo "proc /proc proc defaults,hidepid=2 0 0" >> /etc/fstab 314 | echo "${FUNCNAME[0]} ended" 315 | } 316 | 317 | ##################################### End Function Definitions 318 | 319 | # Call checkos to ensure platform is Linux 320 | checkos 321 | 322 | # Assuming it is, setup environment variables. 323 | setup_environment_variables 324 | 325 | ## set an initial value 326 | SSH_BANNER="LINUX BASTION" 327 | 328 | # Read the options from cli input 329 | TEMP=`getopt -o h --longoptions help,banner:,enable:,tcp-forwarding:,x11-forwarding: -n $0 -- "$@"` 330 | eval set -- "${TEMP}" 331 | 332 | 333 | if [[ $# == 1 ]]; then 334 | echo "No input provided! type ($0 --help) to see usage help" >&2 335 | exit 1 336 | fi 337 | 338 | # extract options and their arguments into variables. 339 | while true; do 340 | case "$1" in 341 | -h | --help) 342 | usage 343 | exit 1 344 | ;; 345 | --banner) 346 | BANNER_PATH="$2"; 347 | shift 2 348 | ;; 349 | --enable) 350 | ENABLE="$2"; 351 | shift 2 352 | ;; 353 | --tcp-forwarding) 354 | TCP_FORWARDING="$2"; 355 | shift 2 356 | ;; 357 | --x11-forwarding) 358 | X11_FORWARDING="$2"; 359 | shift 2 360 | ;; 361 | --) 362 | break 363 | ;; 364 | *) 365 | break 366 | ;; 367 | esac 368 | done 369 | 370 | # BANNER CONFIGURATION 371 | BANNER_FILE="/etc/ssh_banner" 372 | if [[ ${ENABLE} == "true" ]]; then 373 | if [[ -z ${BANNER_PATH} ]]; then 374 | echo "BANNER_PATH is null skipping..." 375 | else 376 | echo "BANNER_PATH = ${BANNER_PATH}" 377 | echo "Creating Banner in ${BANNER_FILE}" 378 | aws s3 cp "${BANNER_PATH}" "${BANNER_FILE}" --region ${BANNER_REGION} 379 | if [[ -e ${BANNER_FILE} ]]; then 380 | echo "[INFO] Installing banner..." 381 | echo -e "\n Banner ${BANNER_FILE}" >>/etc/ssh/sshd_config 382 | else 383 | echo "[INFO] banner file is not accessible skipping..." 384 | exit 1; 385 | fi 386 | fi 387 | else 388 | echo "Banner message is not enabled!" 389 | fi 390 | 391 | #Enable/Disable TCP forwarding 392 | TCP_FORWARDING=`echo "${TCP_FORWARDING}" | sed 's/\\n//g'` 393 | 394 | #Enable/Disable X11 forwarding 395 | X11_FORWARDING=`echo "${X11_FORWARDING}" | sed 's/\\n//g'` 396 | 397 | echo "Value of TCP_FORWARDING - ${TCP_FORWARDING}" 398 | echo "Value of X11_FORWARDING - ${X11_FORWARDING}" 399 | if [[ ${TCP_FORWARDING} == "false" ]]; then 400 | awk '!/AllowTcpForwarding/' /etc/ssh/sshd_config > temp && mv temp /etc/ssh/sshd_config 401 | echo "AllowTcpForwarding no" >> /etc/ssh/sshd_config 402 | fi 403 | 404 | if [[ ${X11_FORWARDING} == "false" ]]; then 405 | awk '!/X11Forwarding/' /etc/ssh/sshd_config > temp && mv temp /etc/ssh/sshd_config 406 | echo "X11Forwarding no" >> /etc/ssh/sshd_config 407 | fi 408 | 409 | release=$(osrelease) 410 | if [[ "${release}" == "Operating System Not Found" ]]; then 411 | echo "[ERROR] Unsupported Linux Bastion OS" 412 | exit 1 413 | else 414 | setup_os 415 | setup_logs 416 | setup_ssm 417 | setup_ec2_instance_connect 418 | fi 419 | 420 | prevent_process_snooping 421 | request_eip 422 | 423 | echo "Bootstrap complete." 424 | -------------------------------------------------------------------------------- /scripts/cfn-tools.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # AWS Reference Common Linux Tools 3 | # authors: tonynv@amazon.com, andglenn@amazon.com 4 | # 5 | 6 | # Supported only while bootstrapping Amazon EC2: 7 | # 8 | # -Amazon Linux 2 9 | # -Amazon Linux 2022 10 | # -CentOS 7 11 | # -SUSE Linux Enterprise Server 15 12 | # -Ubuntu 20.04 & 22.04 13 | # 14 | # 15 | 16 | # Configuration 17 | # 18 | PROGRAM='AWS Reference Linux Common Tools' 19 | 20 | # Usage 21 | # 22 | # To use the functions defined here (source this file): 23 | # Example: 24 | # load script into scripts 25 | # source quickstart-cfn-tools.source 26 | # # To print os type to std out 27 | # get_os-type 28 | # # to assign the os type to a variable OS 29 | # get_os-type OS 30 | # 31 | 32 | 33 | # Detects operating system type and return value 34 | # If no variable is passed in function will print to std-out 35 | # 36 | qs_int_set_svc_executable() { 37 | if [[ $(which systemctl) ]]; then 38 | export qs_svc_executable="systemd" 39 | else 40 | export qs_svc_executable="sysvinit" 41 | fi 42 | } 43 | 44 | qs_int_is_svc_active() { 45 | case ${qs_svc_executable} in 46 | systemd) 47 | systemctl is-active --quiet ${1}.service 48 | ;; 49 | sysvinit) 50 | service ${1} status 51 | ;; 52 | esac 53 | } 54 | 55 | qs_int_service_restart() { 56 | case ${qs_svc_executable} in 57 | systemd) 58 | systemctl restart ${1}.service 59 | ;; 60 | sysvinit) 61 | service ${1} restart 62 | ;; 63 | esac 64 | } 65 | 66 | qs_get-ostype() { 67 | local __return=$1 68 | DETECTION_STRING="/etc/*-release" 69 | if [[ $(ls ${DETECTION_STRING}) ]]; then 70 | OS=$( cat /etc/*-release | 71 | grep ^ID= |awk -F= '{print $2}' | 72 | tr -cd [:alpha:]) 73 | 74 | if [ "${OS}" == "ol" ]; then 75 | OS="rhel" 76 | fi 77 | if [ $? -eq 0 ] && [ "$__return" ]; then 78 | eval $__return="${OS}" 79 | return 0 80 | elif [ $OS ]; then 81 | echo $OS 82 | return 0; 83 | else 84 | echo "Unknown" 85 | fi 86 | else 87 | if [ "$__return" ]; then 88 | __return="Unknown" 89 | return 1 90 | else 91 | echo "Unknown" 92 | return 1; 93 | fi 94 | fi 95 | } 96 | 97 | # Returns operating system version or return 1 98 | # If no variable is passed in function will print to std-out 99 | # 100 | qs_get-osversion () { 101 | local __return=$1 102 | DETECTION_STRING="/etc/*-release" 103 | if [[ $(ls ${DETECTION_STRING}) ]]; then 104 | OSLEVEL=$(cat ${DETECTION_STRING} | 105 | grep VERSION_ID | 106 | tr -d \" | 107 | awk -F= '{print $2}') 108 | 109 | if [ $? -eq 0 ] && [ "$__return" ]; then 110 | eval $__return="${OSLEVEL}" 111 | return 0 112 | elif [ $OS ]; then 113 | echo $OSLEVEL 114 | return 0; 115 | else 116 | echo "Unknown" 117 | fi 118 | else 119 | if [ "$__return" ]; then 120 | __return="Unknown" 121 | return 1 122 | else 123 | echo "Unknown" 124 | return 1; 125 | fi 126 | fi 127 | } 128 | 129 | # If python is install returns default python path 130 | # If no variable is passed in function will print to std-out 131 | # 132 | qs_get-python-path() { 133 | local __return=$1 134 | # Set PYTHON_EXECUTEABLE to default python version 135 | if command -v python > /dev/null 2>&1; then 136 | PYTHON_EXECUTEABLE=$(which python) 137 | else 138 | PYTHON_EXECUTEABLE=$(which python3) 139 | fi 140 | 141 | #Return python path or return code (1) 142 | if [ $PYTHON_EXECUTEABLE ] && [ "$__return" ]; then 143 | eval $__return="${PYTHON_EXECUTEABLE}" 144 | return 0 145 | elif [ $PYTHON_EXECUTEABLE ]; then 146 | echo $PYTHON_EXECUTEABLE 147 | return 0; 148 | else 149 | echo "Python Not installed" 150 | return 1 151 | fi 152 | } 153 | 154 | # Relax require tty 155 | # 156 | qs_notty() { 157 | qs_get-ostype INSTANCE_OSTYPE 158 | qs_get-osversion INSTANCE_OSVERSION 159 | echo "[INFO] Relax tty requirement" 160 | if [ "$INSTANCE_OSTYPE" == "centos" ]; then 161 | sed -i -e "s/Defaults requiretty/Defaults \!requiretty/" /etc/sudoers 162 | fi 163 | } 164 | 165 | # Installs pip from bootstrap.pypa 166 | # 167 | qs_bootstrap_pip() { 168 | qs_notty 169 | echo "[INFO] Check for python/pip" 170 | qs_get-python-path PYTHON_EXECUTEABLE 171 | if [ $? -eq 0 ] ;then 172 | command -v pip > /dev/null 2&>1 173 | if [ $? -eq 1 ]; then 174 | curl -sS --retry 5 https://bootstrap.pypa.io/pip/2.7/get-pip.py | 175 | $PYTHON_EXECUTEABLE 176 | fi 177 | else 178 | echo $PYTHON_EXECUTEABLE 179 | exit 1 180 | fi 181 | } 182 | 183 | # Installs and configures cloudwatch 184 | # Then adds /var/log/syslog to log collection 185 | # 186 | qs_cloudwatch_tracklog() { 187 | local -r __log="$@" 188 | cat cloudwatch_logs.stub | sed s,__LOG__,$__log,g >> /var/awslogs/etc/awslogs.conf 189 | qs_int_service_restart awslogs 190 | } 191 | 192 | # Added EPEL enabler 193 | # 194 | qs_enable_epel() { 195 | qs_get-ostype INSTANCE_OSTYPE 196 | qs_get-osversion INSTANCE_OSVERSION 197 | echo "[INFO] Enable epel-release-latest-7" 198 | if [ "$INSTANCE_OSTYPE" == "centos" ]; then 199 | yum install -y epel-release 200 | else 201 | exit 1 202 | fi 203 | } 204 | 205 | # Updates supported operating systems to latest 206 | # or 207 | # exit with code (1) 208 | # 209 | # If no variable is passed in function will print to std-out 210 | # 211 | qs_update-os() { 212 | # Assigns values to INSTANCE_OSTYPE 213 | qs_get-ostype INSTANCE_OSTYPE 214 | qs_get-osversion INSTANCE_OSVERSION 215 | 216 | echo "[INFO] Start OS Updates" 217 | if [ "$INSTANCE_OSTYPE" == "amzn" ]; then 218 | yum update -y 219 | elif [ "$INSTANCE_OSTYPE" == "ubuntu" ]; then 220 | apt-get update -y 221 | elif [ "$INSTANCE_OSTYPE" == "centos" ]; then 222 | yum update -y 223 | elif [ "$INSTANCE_OSTYPE" == "sles" ]; then 224 | zypper -n refresh && zypper -n update 225 | else 226 | exit 1 227 | fi 228 | echo "[INFO] Finished OS Updates" 229 | } 230 | 231 | # Install aws-cfn-bootstrap tools 232 | # 233 | qs_aws-cfn-bootstrap() { 234 | # Assigns values to INSTANCE_OSTYPE 235 | qs_get-ostype INSTANCE_OSTYPE 236 | qs_get-osversion INSTANCE_OSVERSION 237 | 238 | echo "[INSTALL aws-cfn-bootstrap tools]" 239 | if [[ "$INSTANCE_OSTYPE" == "amzn" && ( "$INSTANCE_OSVERSION" == "2" || "$INSTANCE_OSVERSION" == "2022" ) ]]; then 240 | cp scripts/opt-aws.sh /etc/profile.d/ 241 | ln -s /opt/aws/bin/cfn-* /usr/bin/ 242 | export PATH=$PATH:/opt/aws/bin 243 | yum install -y python3-pip 244 | if [ "$INSTANCE_OSVERSION" == "2" ]; then 245 | alternatives --set python /usr/bin/python3 246 | fi 247 | elif [ "$INSTANCE_OSTYPE" == "ubuntu" ]; then 248 | apt-get -y update 249 | pip3 install https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-py3-latest.tar.gz 250 | elif [ "$INSTANCE_OSTYPE" == "centos" ]; then 251 | yum update -y 252 | qs_bootstrap_pip 253 | pip install https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-latest.tar.gz 254 | elif [ "$INSTANCE_OSTYPE" == "sles" ]; then 255 | zypper -n refresh && zypper -n update 256 | pip install https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-py3-latest.tar.gz 257 | else 258 | exit 1 259 | fi 260 | 261 | if [ $(which cfn-signal) ];then 262 | echo "[FOUND] (cfn-signal)" 263 | else 264 | echo "[ERROR] (cfn-signal) not installed!!" 265 | exit 1 266 | fi 267 | } 268 | 269 | qs_err() { 270 | touch /var/tmp/stack_failed 271 | echo "[FAILED] @ $1" >>/var/tmp/stack_failed 272 | echo "[FAILED] @ $1" 273 | } 274 | 275 | qs_status() { 276 | if [ -f /var/tmp/stack_failed ]; then 277 | printf 1; 278 | return 1 279 | else 280 | printf 0 281 | return 0; 282 | fi 283 | } 284 | 285 | qs_status.clean() { 286 | if [ -f /var/tmp/stack_failed ]; then 287 | echo "clean failed state" 288 | rm /var/tmp/stack_failed 289 | else 290 | echo "failed state not active" 291 | fi 292 | } 293 | 294 | available_functions() { 295 | echo "--------------------------------" 296 | echo "Available quickstart_functions: 297 | #qs_err 298 | #qs_status 299 | #qs_get-ostype 300 | #qs_get-osversion 301 | #qs_get-python-path 302 | #qs_bootstrap_pip 303 | #qs_update-os 304 | #qs_enable_epel 305 | #qs_notty 306 | #qs_aws-cfn-bootstrap 307 | #qs_cloudwatch_tracklog 308 | #qs_retry_command" 309 | echo "--------------------------------" 310 | } 311 | 312 | # Install dependencies 313 | # Assigns values to INSTANCE_ 314 | # 315 | install_dependancies() { 316 | qs_get-ostype INSTANCE_OSTYPE 317 | qs_get-osversion INSTANCE_OSVERSION 318 | 319 | 320 | check_cmd() { 321 | if hash $1 &>/dev/null; then 322 | echo "[INFO] Dependencies met!" 323 | return 0 324 | else 325 | echo "[INFO] Installing dependencies" 326 | return 1 327 | fi 328 | } 329 | 330 | if [ "$INSTANCE_OSTYPE" == "amzn" ]; then 331 | check_cmd curl 332 | [[ $? -eq 1 ]] && yum clean all && yum install -y curl || return 0 333 | 334 | elif [ "$INSTANCE_OSTYPE" == "ubuntu" ]; then 335 | check_cmd curl 336 | [[ $? -eq 1 ]] && apt update && apt install -y curl || return 0 337 | 338 | elif [ "$INSTANCE_OSTYPE" == "centos" ]; then 339 | check_cmd curl 340 | [[ $? -eq 1 ]] && yum clean && yum install -y curl || return 0 341 | 342 | elif [ "$INSTANCE_OSTYPE" == "sles" ]; then 343 | check_cmd curl 344 | [[ $? -eq 1 ]] && zypper -n refresh && zypper -n install curl || return 0 345 | else 346 | echo "[FAIL] : Dependencies not satisfied!" 347 | exit 1 348 | fi 349 | } 350 | 351 | # $1 = NumberOfRetries $2 = Command 352 | # qs_retry_command 10 some_command.sh 353 | # Command will retry with linear back-off 354 | # 355 | qs_retry_command() { 356 | local -r __tries="$1"; shift 357 | local -r __run="$@" 358 | local -i __backoff_delay=2 359 | 360 | until $__run 361 | do 362 | if (( __current_try == __tries )) 363 | then 364 | echo "Tried $__current_try times and failed!" 365 | return 1 366 | else 367 | echo "Retrying ...." 368 | sleep $((((__backoff_delay++)) + ((__current_try++)))) 369 | fi 370 | done 371 | } 372 | 373 | # start exec 374 | available_functions 375 | install_dependancies 376 | # end exec 377 | -------------------------------------------------------------------------------- /templates/linux-bastion-entrypoint-existing-vpc.template.yaml: -------------------------------------------------------------------------------- 1 | AWSTemplateFormatVersion: 2010-09-09 2 | Description: >- 3 | AWS CloudFormation template for deploying Linux bastion hosts in an 4 | auto-scaling group in an existing VPC. (qs-1qup6ra99) 5 | Metadata: 6 | QuickStartDocumentation: 7 | EntrypointName: Launch into an existing VPC 8 | Order: 2 9 | LICENSE: Apache License, Version 2.0 10 | LintSpellExclude: 11 | - onlyssmaccess 12 | AWS::CloudFormation::Interface: 13 | ParameterGroups: 14 | - Label: 15 | default: Network configuration 16 | Parameters: 17 | - VPCID 18 | - PublicSubnet1ID 19 | - PublicSubnet2ID 20 | - RemoteAccessCIDR 21 | - Label: 22 | default: IAM configuration 23 | Parameters: 24 | - RolePath 25 | - PermissionsBoundaryArn 26 | - Label: 27 | default: Amazon EC2 configuration 28 | Parameters: 29 | - KeyPairName 30 | - BastionAMIOS 31 | - BastionInstanceType 32 | - RootVolumeSize 33 | - Label: 34 | default: Linux bastion configuration 35 | Parameters: 36 | - NumBastionHosts 37 | - OndemandPercentage 38 | - BastionHostName 39 | - BastionTenancy 40 | - EnableBanner 41 | - BastionBanner 42 | - EnableTCPForwarding 43 | - EnableX11Forwarding 44 | - EC2MetadataPutResponseHopLimit 45 | - EC2MetadataHttpTokens 46 | - Label: 47 | default: Alternative configurations 48 | Parameters: 49 | - AlternativeInitializationScript 50 | - OSImageOverride 51 | - AlternativeIAMRole 52 | - EnvironmentVariables 53 | - Label: 54 | default: AWS Quick Start configuration 55 | Parameters: 56 | - QSS3BucketName 57 | - QSS3KeyPrefix 58 | - QSS3BucketRegion 59 | ParameterLabels: 60 | AlternativeIAMRole: 61 | default: Alternative IAM role 62 | AlternativeInitializationScript: 63 | default: Alternative initialization script URL 64 | BastionAMIOS: 65 | default: Bastion AMI operating system 66 | BastionHostName: 67 | default: Bastion host Name 68 | BastionTenancy: 69 | default: Bastion tenancy 70 | BastionBanner: 71 | default: SSH banner content file URL 72 | BastionInstanceType: 73 | default: Bastion instance type 74 | EnableBanner: 75 | default: Bastion banner 76 | EnableTCPForwarding: 77 | default: TCP forwarding 78 | EnableX11Forwarding: 79 | default: X11 forwarding 80 | EnvironmentVariables: 81 | default: Environment variables 82 | KeyPairName: 83 | default: Key pair name 84 | NumBastionHosts: 85 | default: Number of bastion hosts 86 | OndemandPercentage: 87 | default: On-demand percentage 88 | OSImageOverride: 89 | default: Operating system override 90 | PublicSubnet1ID: 91 | default: Public subnet 1 ID 92 | PublicSubnet2ID: 93 | default: Public subnet 2 ID 94 | QSS3BucketName: 95 | default: Quick Start S3 bucket name 96 | QSS3BucketRegion: 97 | default: Quick Start S3 bucket Region 98 | QSS3KeyPrefix: 99 | default: Quick Start S3 key prefix 100 | RemoteAccessCIDR: 101 | default: Allowed bastion external access CIDR 102 | VPCID: 103 | default: VPC ID 104 | RootVolumeSize: 105 | default: Root volume size 106 | PermissionsBoundaryArn: 107 | default: Permissions boundary ARN 108 | RolePath: 109 | default: Role path 110 | EC2MetadataPutResponseHopLimit: 111 | default: Amazon EC2 metadata put response hop limit 112 | EC2MetadataHttpTokens: 113 | default: Amazon EC2 metadata HTTP tokens 114 | Parameters: 115 | BastionAMIOS: 116 | Type: String 117 | Description: The Linux distribution for the AMI to be used for the bastion host instances. 118 | AllowedValues: 119 | - Amazon-Linux2-HVM 120 | - Amazon-Linux2-HVM-ARM 121 | - Amazon-Linux2022 122 | - Amazon-Linux2022-ARM 123 | - Ubuntu-Server-20.04-LTS-HVM 124 | - Ubuntu-Server-22.04-LTS-HVM 125 | - Ubuntu-Server-22.04-LTS-HVM-ARM 126 | Default: Amazon-Linux2-HVM 127 | BastionHostName: 128 | Type: String 129 | Description: The value used for the name tag of the bastion host. 130 | Default: LinuxBastion 131 | BastionBanner: 132 | Type: String 133 | Description: >- 134 | Amazon S3 object URL for the text file with the content to display upon 135 | SSH login. The bastion host must have permission to download the file 136 | from the S3 bucket. 137 | AllowedPattern: ^(s3:\/\/[0-9a-z]+([0-9a-z-]*[0-9a-z])*/.+)?$ 138 | ConstraintDescription: >- 139 | Must be either a valid Amazon S3 object URL 140 | (example: s3://bucket/key/file.txt) or empty. 141 | Default: '' 142 | BastionTenancy: 143 | Type: String 144 | Description: Bastion VPC tenancy (dedicated or default). 145 | AllowedValues: [dedicated, default] 146 | Default: default 147 | BastionInstanceType: 148 | Type: String 149 | Description: Amazon EC2 instance type for the bastion instances. 150 | Default: t3.micro 151 | EnableBanner: 152 | Type: String 153 | Description: Choose "true" to display a banner when connecting to the bastion using SSH. 154 | AllowedValues: ['true', 'false'] 155 | Default: 'false' 156 | EnableTCPForwarding: 157 | Type: String 158 | Description: Choose "true" to enable TCP forwarding. 159 | AllowedValues: ['true', 'false'] 160 | Default: 'false' 161 | EnableX11Forwarding: 162 | Type: String 163 | Description: Choose "true" to enable X11 forwarding. 164 | AllowedValues: ['true', 'false'] 165 | Default: 'false' 166 | KeyPairName: 167 | Type: String 168 | Description: 169 | Name of an existing public/private key pair. If you do not have one in this AWS Region, 170 | please create it before continuing. If left empty, AWS Systems Manager Session Manager can still be used to connect to the instance. 171 | Default: '' 172 | NumBastionHosts: 173 | Type: String 174 | Description: The number of bastion hosts to create. The maximum number is four. 175 | AllowedValues: [1, 2, 3, 4] 176 | Default: 1 177 | OndemandPercentage: 178 | Type: Number 179 | Description: >- 180 | Percentage of on-demand instances versus spot instances. With the 181 | default of 100, the ratio will be 100% on-demand instances and 0% spot 182 | instances. 183 | Default: 100 184 | PublicSubnet1ID: 185 | Type: AWS::EC2::Subnet::Id 186 | Description: >- 187 | ID of the public subnet 1 that you want to provision the first bastion 188 | into (for example, subnet-a0246dcd). If RemoteAccessCIDR is set to 189 | 'disabled-onlyssmaccess', enter the ID of a private subnet instead. 190 | PublicSubnet2ID: 191 | Type: AWS::EC2::Subnet::Id 192 | Description: >- 193 | ID of the public subnet 2 that you want to provision the second bastion 194 | into (for example, subnet-e3246d8e). If RemoteAccessCIDR is set to 195 | 'disabled-onlyssmaccess', enter the ID of a private subnet instead. 196 | EC2MetadataPutResponseHopLimit: 197 | Type: String 198 | Description: >- 199 | The desired HTTP PUT response hop limit for instance metadata requests. 200 | The larger the number, the further instance metadata requests can travel. 201 | Default: 2 202 | EC2MetadataHttpTokens: 203 | Type: String 204 | Description: >- 205 | If set to "optional" instances will be able to use their IAM instance 206 | profile. If set to "required" amd "EC2MetadataPutResponseHopLimit" is set 207 | to 1, instances will not be able to access the IAM role. If set to 208 | "required" amd "EC2MetadataPutResponseHopLimit" is set greater than 1 209 | instances must send a signed token header with any instance metadata 210 | retrieval requests. 211 | AllowedValues: [optional, required] 212 | Default: required 213 | QSS3BucketName: 214 | Type: String 215 | Description: Name of the S3 bucket for your copy of the Quick Start assets. 216 | Keep the default name unless you are customizing the template. 217 | Changing the name updates code references to point to a new Quick 218 | Start location. This name can include numbers, lowercase letters, 219 | and hyphens, but do not start or end with a hyphen (-). 220 | See https://aws-quickstart.github.io/option1.html. 221 | MinLength: 3 222 | MaxLength: 63 223 | AllowedPattern: ^[0-9a-z]+([0-9a-z-]*[0-9a-z])*$ 224 | ConstraintDescription: 225 | The Quick Start bucket name can include numbers, lowercase 226 | letters, uppercase letters, and hyphens (-). It cannot start or end with a 227 | hyphen (-). 228 | Default: aws-quickstart 229 | QSS3BucketRegion: 230 | Type: String 231 | Description: The AWS Region where the Quick Start S3 bucket (QSS3BucketName) is hosted. When using your own bucket, you must specify this value. 232 | Default: us-east-1 233 | QSS3KeyPrefix: 234 | Type: String 235 | Description: 236 | S3 key prefix that is used to simulate a directory for your copy of the 237 | Quick Start assets. Keep the default prefix unless you are customizing 238 | the template. Changing this prefix updates code references to point to 239 | a new Quick Start location. This prefix can include numbers, lowercase 240 | letters, uppercase letters, hyphens (-), and forward slashes (/). End 241 | with a forward slash. 242 | See https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingMetadata.html 243 | and https://aws-quickstart.github.io/option1.html. 244 | AllowedPattern: ^([0-9a-zA-Z-.]+/)*$ 245 | ConstraintDescription: 246 | The Quick Start S3 key prefix can include numbers, lowercase letters, 247 | uppercase letters, hyphens (-), and forward slashes (/). 248 | Default: quickstart-linux-bastion/ 249 | RemoteAccessCIDR: 250 | Type: String 251 | Description: >- 252 | Allowed CIDR block or prefix list for external SSH access to the 253 | bastions. 254 | 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]))$ 255 | ConstraintDescription: CIDR block parameter must be disabled-onlyssmaccess or in the format "x.x.x.x/x". 256 | Default: disabled-onlyssmaccess 257 | VPCID: 258 | Type: AWS::EC2::VPC::Id 259 | Description: ID of the VPC (for example, vpc-0343606e). 260 | AlternativeInitializationScript: 261 | Type: String 262 | Description: >- 263 | HTTPS format Amazon S3 object URL for your custom initialization script 264 | to run during setup. The bastion host must have permission to download 265 | the file from the S3 bucket. 266 | AllowedPattern: ^https.*|^$ 267 | ConstraintDescription: >- 268 | Must be either a valid Amazon S3 object URL 269 | (example: https://bucket/key/file.txt) or empty. 270 | Default: '' 271 | OSImageOverride: 272 | Type: String 273 | Description: The Region-specific image to use for the instance. 274 | Default: '' 275 | AlternativeIAMRole: 276 | Type: String 277 | Description: 278 | An existing IAM role name to attach to the bastion. If left blank, 279 | a new role will be created. 280 | Default: '' 281 | EnvironmentVariables: 282 | Type: String 283 | Description: A comma-separated list of environment variables for use in 284 | bootstrapping. Variables must be in the format "key=value". "Value" cannot 285 | contain commas. 286 | Default: '' 287 | RootVolumeSize: 288 | Type: Number 289 | Description: The size in GB for the root EBS volume. 290 | Default: 10 291 | PermissionsBoundaryArn: 292 | Type: String 293 | Description: Will be attached to all created IAM roles to satisfy security requirements. 294 | Default: '' 295 | RolePath: 296 | Type: String 297 | Description: Will be attached to all created IAM roles to satisfy security requirements. 298 | Default: '' 299 | Rules: 300 | SubnetsInVPC: 301 | Assertions: 302 | - Assert: !EachMemberIn 303 | - !ValueOfAll [AWS::EC2::Subnet::Id, VpcId] 304 | - !RefAll AWS::EC2::VPC::Id 305 | AssertDescription: All subnets must exist in the VPC. 306 | ArmInstance: 307 | RuleCondition: !Contains 308 | - - Amazon-Linux2-HVM-ARM 309 | - Amazon-Linux2022-ARM 310 | - Ubuntu-Server-22.04-LTS-HVM-ARM 311 | - !Ref BastionAMIOS 312 | Assertions: 313 | - Assert: !Contains 314 | - - t4g.nano 315 | - t4g.micro 316 | - t4g.small 317 | - t4g.medium 318 | - t4g.large 319 | - t4g.xlarge 320 | - t4g.2xlarge 321 | - m6g.medium 322 | - m6g.large 323 | - m6g.xlarge 324 | - m6g.2xlarge 325 | - !Ref BastionInstanceType 326 | AssertDescription: >- 327 | You selected an ARM AMI operating system, so you must also enter an 328 | ARM instance type, such as t4g.micro. For additional details, see 329 | https://aws.amazon.com/ec2/instance-types/. 330 | X86_64Instance: 331 | RuleCondition: !Not 332 | - !Contains 333 | - - Amazon-Linux2-HVM-ARM 334 | - Amazon-Linux2022-ARM 335 | - Ubuntu-Server-22.04-LTS-HVM-ARM 336 | - !Ref BastionAMIOS 337 | Assertions: 338 | - Assert: !Not 339 | - !Contains 340 | - - t4g.nano 341 | - t4g.micro 342 | - t4g.small 343 | - t4g.medium 344 | - t4g.large 345 | - t4g.xlarge 346 | - t4g.2xlarge 347 | - m6g.medium 348 | - m6g.large 349 | - m6g.xlarge 350 | - m6g.2xlarge 351 | - !Ref BastionInstanceType 352 | AssertDescription: >- 353 | You selected a x86_64 AMI operating system, so you must also enter a 354 | x86_64 instance type, such as t3.micro. For additional details, see 355 | https://aws.amazon.com/ec2/instance-types/. 356 | Mappings: 357 | AWSAMIRegionMap: 358 | af-south-1: 359 | AMZNLINUX2: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}' 360 | AMZNLINUX2ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2}}' 361 | AMZNLINUX2022: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-x86_64}}' 362 | AMZNLINUX2022ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-arm64}}' 363 | US2004HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}' 364 | US2204HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}' 365 | US2204HVMARM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/arm64/hvm/ebs-gp2/ami-id}}' 366 | ap-east-1: 367 | AMZNLINUX2: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}' 368 | AMZNLINUX2ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2}}' 369 | AMZNLINUX2022: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-x86_64}}' 370 | AMZNLINUX2022ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-arm64}}' 371 | US2004HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}' 372 | US2204HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}' 373 | US2204HVMARM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/arm64/hvm/ebs-gp2/ami-id}}' 374 | ap-northeast-1: 375 | AMZNLINUX2: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}' 376 | AMZNLINUX2ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2}}' 377 | AMZNLINUX2022: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-x86_64}}' 378 | AMZNLINUX2022ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-arm64}}' 379 | US2004HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}' 380 | US2204HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}' 381 | US2204HVMARM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/arm64/hvm/ebs-gp2/ami-id}}' 382 | ap-northeast-2: 383 | AMZNLINUX2: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}' 384 | AMZNLINUX2ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2}}' 385 | AMZNLINUX2022: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-x86_64}}' 386 | AMZNLINUX2022ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-arm64}}' 387 | US2004HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}' 388 | US2204HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}' 389 | US2204HVMARM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/arm64/hvm/ebs-gp2/ami-id}}' 390 | ap-northeast-3: 391 | AMZNLINUX2: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}' 392 | AMZNLINUX2ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2}}' 393 | AMZNLINUX2022: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-x86_64}}' 394 | AMZNLINUX2022ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-arm64}}' 395 | US2004HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}' 396 | US2204HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}' 397 | US2204HVMARM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/arm64/hvm/ebs-gp2/ami-id}}' 398 | ap-south-1: 399 | AMZNLINUX2: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}' 400 | AMZNLINUX2ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2}}' 401 | AMZNLINUX2022: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-x86_64}}' 402 | AMZNLINUX2022ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-arm64}}' 403 | US2004HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}' 404 | US2204HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}' 405 | US2204HVMARM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/arm64/hvm/ebs-gp2/ami-id}}' 406 | ap-south-2: 407 | AMZNLINUX2: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}' 408 | AMZNLINUX2ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2}}' 409 | AMZNLINUX2022: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-x86_64}}' 410 | AMZNLINUX2022ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-arm64}}' 411 | US2004HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}' 412 | US2204HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}' 413 | US2204HVMARM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/arm64/hvm/ebs-gp2/ami-id}}' 414 | ap-southeast-1: 415 | AMZNLINUX2: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}' 416 | AMZNLINUX2ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2}}' 417 | AMZNLINUX2022: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-x86_64}}' 418 | AMZNLINUX2022ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-arm64}}' 419 | US2004HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}' 420 | US2204HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}' 421 | US2204HVMARM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/arm64/hvm/ebs-gp2/ami-id}}' 422 | ap-southeast-2: 423 | AMZNLINUX2: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}' 424 | AMZNLINUX2ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2}}' 425 | AMZNLINUX2022: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-x86_64}}' 426 | AMZNLINUX2022ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-arm64}}' 427 | US2004HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}' 428 | US2204HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}' 429 | US2204HVMARM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/arm64/hvm/ebs-gp2/ami-id}}' 430 | ap-southeast-3: 431 | AMZNLINUX2: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}' 432 | AMZNLINUX2ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2}}' 433 | AMZNLINUX2022: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-x86_64}}' 434 | AMZNLINUX2022ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-arm64}}' 435 | US2004HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}' 436 | US2204HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}' 437 | US2204HVMARM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/arm64/hvm/ebs-gp2/ami-id}}' 438 | ap-southeast-4: 439 | AMZNLINUX2: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}' 440 | AMZNLINUX2ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2}}' 441 | AMZNLINUX2022: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-x86_64}}' 442 | AMZNLINUX2022ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-arm64}}' 443 | US2004HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}' 444 | US2204HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}' 445 | US2204HVMARM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/arm64/hvm/ebs-gp2/ami-id}}' 446 | ca-central-1: 447 | AMZNLINUX2: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}' 448 | AMZNLINUX2ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2}}' 449 | AMZNLINUX2022: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-x86_64}}' 450 | AMZNLINUX2022ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-arm64}}' 451 | US2004HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}' 452 | US2204HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}' 453 | US2204HVMARM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/arm64/hvm/ebs-gp2/ami-id}}' 454 | eu-central-1: 455 | AMZNLINUX2: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}' 456 | AMZNLINUX2ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2}}' 457 | AMZNLINUX2022: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-x86_64}}' 458 | AMZNLINUX2022ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-arm64}}' 459 | US2004HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}' 460 | US2204HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}' 461 | US2204HVMARM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/arm64/hvm/ebs-gp2/ami-id}}' 462 | eu-central-2: 463 | AMZNLINUX2: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}' 464 | AMZNLINUX2ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2}}' 465 | AMZNLINUX2022: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-x86_64}}' 466 | AMZNLINUX2022ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-arm64}}' 467 | US2004HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}' 468 | US2204HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}' 469 | US2204HVMARM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/arm64/hvm/ebs-gp2/ami-id}}' 470 | eu-north-1: 471 | AMZNLINUX2: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}' 472 | AMZNLINUX2ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2}}' 473 | AMZNLINUX2022: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-x86_64}}' 474 | AMZNLINUX2022ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-arm64}}' 475 | US2004HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}' 476 | US2204HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}' 477 | US2204HVMARM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/arm64/hvm/ebs-gp2/ami-id}}' 478 | eu-south-1: 479 | AMZNLINUX2: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}' 480 | AMZNLINUX2ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2}}' 481 | AMZNLINUX2022: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-x86_64}}' 482 | AMZNLINUX2022ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-arm64}}' 483 | US2004HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}' 484 | US2204HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}' 485 | US2204HVMARM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/arm64/hvm/ebs-gp2/ami-id}}' 486 | eu-south-2: 487 | AMZNLINUX2: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}' 488 | AMZNLINUX2ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2}}' 489 | AMZNLINUX2022: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-x86_64}}' 490 | AMZNLINUX2022ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-arm64}}' 491 | US2004HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}' 492 | US2204HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}' 493 | US2204HVMARM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/arm64/hvm/ebs-gp2/ami-id}}' 494 | eu-west-1: 495 | AMZNLINUX2: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}' 496 | AMZNLINUX2ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2}}' 497 | AMZNLINUX2022: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-x86_64}}' 498 | AMZNLINUX2022ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-arm64}}' 499 | US2004HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}' 500 | US2204HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}' 501 | US2204HVMARM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/arm64/hvm/ebs-gp2/ami-id}}' 502 | eu-west-2: 503 | AMZNLINUX2: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}' 504 | AMZNLINUX2ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2}}' 505 | AMZNLINUX2022: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-x86_64}}' 506 | AMZNLINUX2022ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-arm64}}' 507 | US2004HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}' 508 | US2204HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}' 509 | US2204HVMARM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/arm64/hvm/ebs-gp2/ami-id}}' 510 | eu-west-3: 511 | AMZNLINUX2: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}' 512 | AMZNLINUX2ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2}}' 513 | AMZNLINUX2022: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-x86_64}}' 514 | AMZNLINUX2022ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-arm64}}' 515 | US2004HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}' 516 | US2204HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}' 517 | US2204HVMARM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/arm64/hvm/ebs-gp2/ami-id}}' 518 | me-central-1: 519 | AMZNLINUX2: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}' 520 | AMZNLINUX2ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2}}' 521 | AMZNLINUX2022: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-x86_64}}' 522 | AMZNLINUX2022ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-arm64}}' 523 | US2004HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}' 524 | US2204HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}' 525 | US2204HVMARM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/arm64/hvm/ebs-gp2/ami-id}}' 526 | me-south-1: 527 | AMZNLINUX2: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}' 528 | AMZNLINUX2ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2}}' 529 | AMZNLINUX2022: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-x86_64}}' 530 | AMZNLINUX2022ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-arm64}}' 531 | US2004HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}' 532 | US2204HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}' 533 | US2204HVMARM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/arm64/hvm/ebs-gp2/ami-id}}' 534 | sa-east-1: 535 | AMZNLINUX2: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}' 536 | AMZNLINUX2ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2}}' 537 | AMZNLINUX2022: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-x86_64}}' 538 | AMZNLINUX2022ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-arm64}}' 539 | US2004HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}' 540 | US2204HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}' 541 | US2204HVMARM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/arm64/hvm/ebs-gp2/ami-id}}' 542 | us-east-1: 543 | AMZNLINUX2: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}' 544 | AMZNLINUX2ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2}}' 545 | AMZNLINUX2022: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-x86_64}}' 546 | AMZNLINUX2022ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-arm64}}' 547 | US2004HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}' 548 | US2204HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}' 549 | US2204HVMARM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/arm64/hvm/ebs-gp2/ami-id}}' 550 | us-east-2: 551 | AMZNLINUX2: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}' 552 | AMZNLINUX2ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2}}' 553 | AMZNLINUX2022: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-x86_64}}' 554 | AMZNLINUX2022ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-arm64}}' 555 | US2004HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}' 556 | US2204HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}' 557 | US2204HVMARM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/arm64/hvm/ebs-gp2/ami-id}}' 558 | us-west-1: 559 | AMZNLINUX2: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}' 560 | AMZNLINUX2ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2}}' 561 | AMZNLINUX2022: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-x86_64}}' 562 | AMZNLINUX2022ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-arm64}}' 563 | US2004HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}' 564 | US2204HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}' 565 | US2204HVMARM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/arm64/hvm/ebs-gp2/ami-id}}' 566 | us-west-2: 567 | AMZNLINUX2: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}' 568 | AMZNLINUX2ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2}}' 569 | AMZNLINUX2022: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-x86_64}}' 570 | AMZNLINUX2022ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-arm64}}' 571 | US2004HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}' 572 | US2204HVM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id}}' 573 | US2204HVMARM: '{{resolve:ssm:/aws/service/canonical/ubuntu/server/22.04/stable/current/arm64/hvm/ebs-gp2/ami-id}}' 574 | us-gov-east-1: 575 | AMZNLINUX2: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}' 576 | AMZNLINUX2ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2}}' 577 | AMZNLINUX2022: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-x86_64}}' 578 | AMZNLINUX2022ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-arm64}}' 579 | US2004HVM: ami-0cfbbbb41dd6a9cad 580 | US2204HVM: ami-0c4bea13c0e0c588f 581 | US2204HVMARM: ami-0dbcf7fc866b67aed 582 | us-gov-west-1: 583 | AMZNLINUX2: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}' 584 | AMZNLINUX2ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2}}' 585 | AMZNLINUX2022: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-x86_64}}' 586 | AMZNLINUX2022ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-arm64}}' 587 | US2004HVM: ami-0b152eed9cb83f2bd 588 | US2204HVM: ami-0585fd40760ad42a3 589 | US2204HVMARM: ami-0f0aac22ded9e2425 590 | cn-north-1: 591 | AMZNLINUX2: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}' 592 | AMZNLINUX2ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2}}' 593 | AMZNLINUX2022: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-x86_64}}' 594 | AMZNLINUX2022ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-arm64}}' 595 | US2004HVM: ami-0ee5d3b4bc88442f4 596 | US2204HVM: ami-05739266c542f05d5 597 | US2204HVMARM: ami-0d41564e295b1064e 598 | cn-northwest-1: 599 | AMZNLINUX2: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}' 600 | AMZNLINUX2ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-arm64-gp2}}' 601 | AMZNLINUX2022: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-x86_64}}' 602 | AMZNLINUX2022ARM: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-default-arm64}}' 603 | US2004HVM: ami-05de738393a8dcebf 604 | US2204HVM: ami-0528ba5522b075ac5 605 | US2204HVMARM: ami-076f450c832df8f9b 606 | LinuxAMINameMap: 607 | Amazon-Linux2-HVM: 608 | Code: AMZNLINUX2 609 | OS: Amazon 610 | Amazon-Linux2-HVM-ARM: 611 | Code: AMZNLINUX2ARM 612 | OS: Amazon 613 | Amazon-Linux2022: 614 | Code: AMZNLINUX2022 615 | OS: Amazon 616 | Amazon-Linux2022-ARM: 617 | Code: AMZNLINUX2022ARM 618 | OS: Amazon 619 | Ubuntu-Server-20.04-LTS-HVM: 620 | Code: US2004HVM 621 | OS: Ubuntu 622 | Ubuntu-Server-22.04-LTS-HVM: 623 | Code: US2204HVM 624 | OS: Ubuntu 625 | Ubuntu-Server-22.04-LTS-HVM-ARM: 626 | Code: US2204HVMARM 627 | OS: Ubuntu 628 | Conditions: 629 | RolePathProvided: !Not [!Equals ['', !Ref RolePath]] 630 | PermissionsBoundaryProvided: !Not [!Equals ['', !Ref PermissionsBoundaryArn]] 631 | 2BastionConditionHost: !Or [!Equals [!Ref NumBastionHosts, 2], !Condition 3BastionCondition, !Condition 4BastionCondition] 632 | 3BastionConditionHost: !Or [!Equals [!Ref NumBastionHosts, 3], !Condition 4BastionCondition] 633 | 4BastionConditionHost: !Equals [!Ref NumBastionHosts, 4] 634 | 2BastionCondition: !And [!Condition NeedsEip, !Condition 2BastionConditionHost] 635 | 3BastionCondition: !And [!Condition NeedsEip, !Condition 3BastionConditionHost] 636 | 4BastionCondition: !And [!Condition NeedsEip, !Condition 4BastionConditionHost] 637 | HasRemoteCIDR: !And 638 | - !Not [!Equals [!Ref RemoteAccessCIDR, disabled-onlyssmaccess]] 639 | - !Not [!Condition HasPrefixList] 640 | HasPrefixList: !Equals [!Select [0, !Split ['-', !Ref RemoteAccessCIDR]], pl] 641 | NeedsEip: !Or [!Condition HasRemoteCIDR, !Condition HasPrefixList] 642 | UseAlternativeInitialization: !Not [!Equals [!Ref AlternativeInitializationScript, '']] 643 | CreateIAMRole: !Equals [!Ref AlternativeIAMRole, ''] 644 | UseOSImageOverride: !Not [!Equals [!Ref OSImageOverride, '']] 645 | UsingDefaultBucket: !Equals [!Ref QSS3BucketName, aws-quickstart] 646 | DefaultBanner: !Equals [!Ref BastionBanner, ''] 647 | UseKeyPair: !Not [!Equals [!Ref KeyPairName, '']] 648 | Resources: 649 | BastionMainLogGroup: 650 | Type: AWS::Logs::LogGroup 651 | SSHMetricFilter: 652 | Type: AWS::Logs::MetricFilter 653 | Properties: 654 | LogGroupName: !Ref BastionMainLogGroup 655 | FilterPattern: ON FROM USER PWD 656 | MetricTransformations: 657 | - MetricName: SSHCommandCount 658 | MetricValue: 1 659 | MetricNamespace: !Sub AWSQuickStart/${AWS::StackName} 660 | BastionHostRole: 661 | Condition: CreateIAMRole 662 | Type: AWS::IAM::Role 663 | Properties: 664 | Path: !If [RolePathProvided, !Ref RolePath, !Ref AWS::NoValue] 665 | PermissionsBoundary: 666 | !If [PermissionsBoundaryProvided, !Ref PermissionsBoundaryArn, !Ref AWS::NoValue] 667 | AssumeRolePolicyDocument: 668 | Version: 2012-10-17 669 | Statement: 670 | - Effect: Allow 671 | Action: sts:AssumeRole 672 | Principal: 673 | Service: 674 | - !Sub ec2.${AWS::URLSuffix} 675 | ManagedPolicyArns: 676 | - !Sub arn:${AWS::Partition}:iam::aws:policy/AmazonSSMManagedInstanceCore 677 | - !Sub arn:${AWS::Partition}:iam::aws:policy/CloudWatchAgentServerPolicy 678 | BastionHostPolicy: 679 | Type: AWS::IAM::Policy 680 | Condition: CreateIAMRole 681 | Properties: 682 | PolicyName: BastionPolicy 683 | PolicyDocument: 684 | Version: 2012-10-17 685 | Statement: 686 | - Sid: ListQSS3BucketObjects 687 | Effect: Allow 688 | Action: s3:ListBucket 689 | Resource: !Sub 690 | - arn:${AWS::Partition}:s3:::${S3Bucket} 691 | - S3Bucket: !If [UsingDefaultBucket, !Sub '${QSS3BucketName}-${AWS::Region}', !Ref QSS3BucketName] 692 | - Sid: GetQSS3Objects 693 | Effect: Allow 694 | Action: 695 | - s3:GetObject 696 | - s3:GetObjectVersion 697 | Resource: !Sub 698 | - arn:${AWS::Partition}:s3:::${S3Bucket}/${QSS3KeyPrefix}* 699 | - S3Bucket: !If [UsingDefaultBucket, !Sub '${QSS3BucketName}-${AWS::Region}', !Ref QSS3BucketName] 700 | - Sid: WriteToCloudWatchLogs 701 | Effect: Allow 702 | Action: 703 | - logs:CreateLogStream 704 | - logs:GetLogEvents 705 | - logs:PutLogEvents 706 | - logs:DescribeLogGroups 707 | - logs:DescribeLogStreams 708 | - logs:PutRetentionPolicy 709 | - logs:PutMetricFilter 710 | - logs:CreateLogGroup 711 | Resource: !Sub arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:${BastionMainLogGroup}:* 712 | - Sid: Global 713 | Effect: Allow 714 | Action: 715 | - ec2:DescribeAddresses 716 | Resource: '*' 717 | - !If 718 | - NeedsEip 719 | - Sid: AssociateStackEips 720 | Effect: Allow 721 | Action: ec2:AssociateAddress 722 | Resource: '*' 723 | Condition: 724 | StringEquals: 725 | ec2:ResourceTag/aws:cloudformation:stack-id: !Ref AWS::StackId 726 | - !Ref AWS::NoValue 727 | Roles: 728 | - !If [CreateIAMRole, !Ref BastionHostRole, !Ref AlternativeIAMRole] 729 | BastionHostProfile: 730 | Type: AWS::IAM::InstanceProfile 731 | Properties: 732 | Roles: 733 | - !If [CreateIAMRole, !Ref BastionHostRole, !Ref AlternativeIAMRole] 734 | Path: !If [CreateIAMRole, /, /account-managed/] 735 | EIP1: 736 | Type: AWS::EC2::EIP 737 | Condition: NeedsEip 738 | Properties: 739 | Domain: vpc 740 | EIP2: 741 | Type: AWS::EC2::EIP 742 | Condition: 2BastionCondition 743 | Properties: 744 | Domain: vpc 745 | EIP3: 746 | Type: AWS::EC2::EIP 747 | Condition: 3BastionCondition 748 | Properties: 749 | Domain: vpc 750 | EIP4: 751 | Type: AWS::EC2::EIP 752 | Condition: 4BastionCondition 753 | Properties: 754 | Domain: vpc 755 | BastionAutoScalingGroup: 756 | Type: AWS::AutoScaling::AutoScalingGroup 757 | Properties: 758 | VPCZoneIdentifier: [!Ref PublicSubnet1ID, !Ref PublicSubnet2ID] 759 | MinSize: !Ref NumBastionHosts 760 | MaxSize: !Ref NumBastionHosts 761 | Cooldown: 900 762 | DesiredCapacity: !Ref NumBastionHosts 763 | MixedInstancesPolicy: 764 | LaunchTemplate: 765 | LaunchTemplateSpecification: 766 | LaunchTemplateId: !Ref BastionLaunchTemplate 767 | Version: !GetAtt BastionLaunchTemplate.LatestVersionNumber 768 | InstancesDistribution: 769 | OnDemandPercentageAboveBaseCapacity: !Ref OndemandPercentage 770 | SpotInstancePools: 1 771 | Tags: 772 | - Key: Name 773 | Value: !Ref BastionHostName 774 | PropagateAtLaunch: true 775 | CreationPolicy: 776 | ResourceSignal: 777 | Count: !Ref NumBastionHosts 778 | Timeout: PT60M 779 | AutoScalingCreationPolicy: 780 | MinSuccessfulInstancesPercent: 100 781 | UpdatePolicy: 782 | AutoScalingReplacingUpdate: 783 | WillReplace: true 784 | BastionLaunchTemplate: 785 | Type: AWS::EC2::LaunchTemplate 786 | Metadata: 787 | AWS::CloudFormation::Authentication: 788 | S3AccessCreds: 789 | type: S3 790 | roleName: !If [CreateIAMRole, !Ref BastionHostRole, !Ref AlternativeIAMRole] 791 | buckets: 792 | - !If [UsingDefaultBucket, !Sub '${QSS3BucketName}-${AWS::Region}', !Ref QSS3BucketName] 793 | AWS::CloudFormation::Init: 794 | config: 795 | files: 796 | /tmp/auditd.rules: 797 | mode: 000550 798 | owner: root 799 | group: root 800 | content: | 801 | -a exit,always -F arch=b64 -S execve 802 | -a exit,always -F arch=b32 -S execve 803 | /tmp/auditing_configure.sh: 804 | source: !Sub 805 | - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/auditing_configure.sh 806 | - S3Bucket: !If [UsingDefaultBucket, !Sub 'aws-quickstart-${AWS::Region}', !Ref QSS3BucketName] 807 | S3Region: !If [UsingDefaultBucket, !Ref AWS::Region, !Ref QSS3BucketRegion] 808 | mode: 000550 809 | owner: root 810 | group: root 811 | authentication: S3AccessCreds 812 | /tmp/bastion_bootstrap.sh: 813 | source: !If 814 | - UseAlternativeInitialization 815 | - !Ref AlternativeInitializationScript 816 | - !Sub 817 | - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/bastion_bootstrap.sh 818 | - S3Bucket: !If [UsingDefaultBucket, !Sub 'aws-quickstart-${AWS::Region}', !Ref QSS3BucketName] 819 | S3Region: !If [UsingDefaultBucket, !Ref AWS::Region, !Ref QSS3BucketRegion] 820 | mode: 000550 821 | owner: root 822 | group: root 823 | authentication: S3AccessCreds 824 | commands: 825 | a-add_auditd_rules: 826 | cwd: /tmp/ 827 | env: 828 | BASTION_OS: !FindInMap [LinuxAMINameMap, !Ref BastionAMIOS, OS] 829 | command: ./auditing_configure.sh 830 | b-bootstrap: 831 | cwd: /tmp/ 832 | env: 833 | REGION: !Sub ${AWS::Region} 834 | URL_SUFFIX: !Sub ${AWS::URLSuffix} 835 | BANNER_REGION: !If [UsingDefaultBucket, !Ref AWS::Region, !Ref QSS3BucketRegion] 836 | command: !Sub 837 | - ./bastion_bootstrap.sh --banner ${BannerUrl} --enable ${EnableBanner} --tcp-forwarding ${EnableTCPForwarding} --x11-forwarding ${EnableX11Forwarding} 838 | - BannerUrl: !If 839 | - DefaultBanner 840 | - !Sub 841 | - s3://${S3Bucket}/${QSS3KeyPrefix}scripts/banner_message.txt 842 | - S3Bucket: !If [UsingDefaultBucket, !Sub 'aws-quickstart-${AWS::Region}', !Ref QSS3BucketName] 843 | - !Ref BastionBanner 844 | Properties: 845 | LaunchTemplateData: 846 | Placement: 847 | Tenancy: !Ref BastionTenancy 848 | KeyName: !If [UseKeyPair, !Ref KeyPairName, !Ref AWS::NoValue] 849 | ImageId: !If 850 | - UseOSImageOverride 851 | - !Ref OSImageOverride 852 | - !FindInMap [AWSAMIRegionMap, !Ref AWS::Region, !FindInMap [LinuxAMINameMap, !Ref BastionAMIOS, Code]] 853 | InstanceType: !Ref BastionInstanceType 854 | IamInstanceProfile: 855 | Arn: !GetAtt BastionHostProfile.Arn 856 | NetworkInterfaces: 857 | - DeviceIndex: 0 858 | AssociatePublicIpAddress: !If [NeedsEip, true, false] 859 | Groups: 860 | - !Ref BastionSecurityGroup 861 | BlockDeviceMappings: 862 | - DeviceName: /dev/xvda 863 | Ebs: 864 | VolumeSize: !Ref RootVolumeSize 865 | VolumeType: gp2 866 | Encrypted: true 867 | DeleteOnTermination: true 868 | UserData: 869 | Fn::Base64: !Sub 870 | - | 871 | #!/usr/bin/env bash 872 | set -x 873 | for e in $(echo "${EnvironmentVariables}" | tr ',' ' '); do 874 | export $e 875 | echo "$e" >> /root/.bashrc 876 | done 877 | export PATH=$PATH:/usr/local/bin 878 | yum install -y git unzip wget curl || apt-get install -y git unzip wget curl || zypper -n install git unzip wget curl 879 | 880 | #cfn signaling functions 881 | cfn_fail() { 882 | cfn-signal -e 1 --stack ${AWS::StackName} --region ${AWS::Region} --resource BastionAutoScalingGroup 883 | exit 1 884 | } 885 | 886 | cfn_success() { 887 | cfn-signal -e 0 --stack ${AWS::StackName} --region ${AWS::Region} --resource BastionAutoScalingGroup 888 | exit 0 889 | } 890 | 891 | pushd /tmp 892 | 893 | if [[ "a$(which aws)" == "a" ]] 894 | then 895 | echo "Installing AWS CLI..." 896 | uname=$(uname -m) 897 | wget -nv -O "./awscliv2.zip" "https://awscli.amazonaws.com/awscli-exe-linux-$uname.zip" 898 | unzip -q ./awscliv2.zip 899 | ./aws/install 900 | fi 901 | 902 | for (( i=0; i<=5; i++ )) 903 | do 904 | aws s3 cp --no-progress --region ${AWS::Region} "s3://${S3Bucket}/${QSS3KeyPrefix}scripts/cfn-tools.sh" . 905 | if [ $? -ne 0 ] 906 | then 907 | echo "Retrying..." 908 | fi 909 | done 910 | source ./cfn-tools.sh 911 | 912 | popd /tmp 913 | 914 | qs_update-os || qs_err; 915 | qs_bootstrap_pip || qs_err " pip bootstrap failed "; 916 | qs_aws-cfn-bootstrap || qs_err " cfn bootstrap failed "; 917 | 918 | EIP_LIST="${EIP1},${EIP2},${EIP3},${EIP4}" 919 | CLOUDWATCHGROUP=${BastionMainLogGroup} 920 | cfn-init -v --stack '${AWS::StackName}' --resource BastionLaunchTemplate --region ${AWS::Region} || cfn_fail 921 | [ $(qs_status) == 0 ] && cfn_success || cfn_fail 922 | - EIP1: !If [NeedsEip, !Ref EIP1, 'Null'] 923 | EIP2: !If [2BastionCondition, !Ref EIP2, 'Null'] 924 | EIP3: !If [3BastionCondition, !Ref EIP3, 'Null'] 925 | EIP4: !If [4BastionCondition, !Ref EIP4, 'Null'] 926 | S3Bucket: !If [UsingDefaultBucket, !Sub 'aws-quickstart-${AWS::Region}', !Ref QSS3BucketName] 927 | MetadataOptions: 928 | HttpEndpoint: enabled 929 | HttpPutResponseHopLimit: !Ref EC2MetadataPutResponseHopLimit 930 | HttpTokens: !Ref EC2MetadataHttpTokens 931 | BastionSecurityGroup: 932 | Type: AWS::EC2::SecurityGroup 933 | Properties: 934 | GroupDescription: Enables access to bastion hosts 935 | VpcId: !Ref VPCID 936 | BastionSecurityGroupCidrSshIngress: 937 | Type: AWS::EC2::SecurityGroupIngress 938 | Condition: HasRemoteCIDR 939 | Properties: 940 | GroupId: !Ref BastionSecurityGroup 941 | CidrIp: !Ref RemoteAccessCIDR 942 | IpProtocol: tcp 943 | FromPort: 22 944 | ToPort: 22 945 | BastionSecurityGroupCidrIcmpIngress: 946 | Type: AWS::EC2::SecurityGroupIngress 947 | Condition: HasRemoteCIDR 948 | Properties: 949 | GroupId: !Ref BastionSecurityGroup 950 | CidrIp: !Ref RemoteAccessCIDR 951 | IpProtocol: icmp 952 | FromPort: -1 953 | ToPort: -1 954 | BastionSecurityGroupPrefixListSshIngress: 955 | Type: AWS::EC2::SecurityGroupIngress 956 | Condition: HasPrefixList 957 | Properties: 958 | GroupId: !Ref BastionSecurityGroup 959 | SourcePrefixListId: !Ref RemoteAccessCIDR 960 | IpProtocol: tcp 961 | FromPort: 22 962 | ToPort: 22 963 | BastionSecurityGroupPrefixListIcmpIngress: 964 | Type: AWS::EC2::SecurityGroupIngress 965 | Condition: HasPrefixList 966 | Properties: 967 | GroupId: !Ref BastionSecurityGroup 968 | SourcePrefixListId: !Ref RemoteAccessCIDR 969 | IpProtocol: icmp 970 | FromPort: -1 971 | ToPort: -1 972 | Outputs: 973 | BastionAutoScalingGroup: 974 | Description: Auto Scaling group reference ID. 975 | Value: !Ref BastionAutoScalingGroup 976 | Export: 977 | Name: !Sub ${AWS::StackName}-BastionAutoScalingGroup 978 | EIP1: 979 | Condition: NeedsEip 980 | Description: Elastic IP 1 for bastion. 981 | Value: !Ref EIP1 982 | Export: 983 | Name: !Sub ${AWS::StackName}-EIP1 984 | EIP2: 985 | Condition: 2BastionCondition 986 | Description: Elastic IP 2 for bastion. 987 | Value: !Ref EIP2 988 | Export: 989 | Name: !Sub ${AWS::StackName}-EIP2 990 | EIP3: 991 | Condition: 3BastionCondition 992 | Description: Elastic IP 3 for bastion. 993 | Value: !Ref EIP3 994 | Export: 995 | Name: !Sub ${AWS::StackName}-EIP3 996 | EIP4: 997 | Condition: 4BastionCondition 998 | Description: Elastic IP 4 for bastion. 999 | Value: !Ref EIP4 1000 | Export: 1001 | Name: !Sub ${AWS::StackName}-EIP4 1002 | CloudWatchLogs: 1003 | Description: CloudWatch Logs GroupName. Your SSH logs will be stored here. 1004 | Value: !Ref BastionMainLogGroup 1005 | Export: 1006 | Name: !Sub ${AWS::StackName}-CloudWatchLogs 1007 | BastionSecurityGroupID: 1008 | Description: Bastion security group ID. 1009 | Value: !Ref BastionSecurityGroup 1010 | Export: 1011 | Name: !Sub ${AWS::StackName}-BastionSecurityGroupID 1012 | BastionHostRole: 1013 | Description: Bastion IAM role name. 1014 | Value: !If [CreateIAMRole, !Ref BastionHostRole, !Ref AlternativeIAMRole] 1015 | Export: 1016 | Name: !Sub ${AWS::StackName}-BastionHostRole 1017 | Postdeployment: 1018 | Description: See the deployment guide for post-deployment steps. 1019 | Value: https://fwd.aws/YqpXk? 1020 | -------------------------------------------------------------------------------- /templates/linux-bastion-entrypoint-new-vpc.template.yaml: -------------------------------------------------------------------------------- 1 | AWSTemplateFormatVersion: 2010-09-09 2 | Description: >- 3 | AWS CloudFormation template for deploying Linux bastion hosts in an 4 | auto-scaling group in a new VPC. (qs-1qup6ra9p) 5 | Metadata: 6 | QuickStartDocumentation: 7 | EntrypointName: Launch into a new VPC 8 | Order: 1 9 | LICENSE: Apache License, Version 2.0 10 | AWS::CloudFormation::Interface: 11 | ParameterGroups: 12 | - Label: 13 | default: Network configuration 14 | Parameters: 15 | - AvailabilityZones 16 | - VPCCIDR 17 | - PrivateSubnet1CIDR 18 | - PrivateSubnet2CIDR 19 | - PublicSubnet1CIDR 20 | - PublicSubnet2CIDR 21 | - RemoteAccessCIDR 22 | - VPCTenancy 23 | - Label: 24 | default: IAM configuration 25 | Parameters: 26 | - RolePath 27 | - PermissionsBoundaryArn 28 | - Label: 29 | default: Amazon EC2 configuration 30 | Parameters: 31 | - KeyPairName 32 | - BastionAMIOS 33 | - BastionInstanceType 34 | - RootVolumeSize 35 | - Label: 36 | default: Linux bastion configuration 37 | Parameters: 38 | - NumBastionHosts 39 | - OndemandPercentage 40 | - BastionHostName 41 | - BastionTenancy 42 | - EnableBanner 43 | - BastionBanner 44 | - EnableTCPForwarding 45 | - EnableX11Forwarding 46 | - EC2MetadataPutResponseHopLimit 47 | - EC2MetadataHttpTokens 48 | - Label: 49 | default: Alternative configurations 50 | Parameters: 51 | - AlternativeInitializationScript 52 | - OSImageOverride 53 | - AlternativeIAMRole 54 | - EnvironmentVariables 55 | - Label: 56 | default: AWS Quick Start configuration 57 | Parameters: 58 | - QSS3BucketName 59 | - QSS3KeyPrefix 60 | - QSS3BucketRegion 61 | ParameterLabels: 62 | AlternativeIAMRole: 63 | default: Alternative IAM role 64 | AlternativeInitializationScript: 65 | default: Alternative initialization script URL 66 | AvailabilityZones: 67 | default: Availability Zones 68 | BastionAMIOS: 69 | default: Bastion AMI operating system 70 | BastionHostName: 71 | default: Bastion host name 72 | BastionTenancy: 73 | default: Bastion tenancy 74 | BastionBanner: 75 | default: SSH banner content file URL 76 | BastionInstanceType: 77 | default: Bastion instance type 78 | EnableBanner: 79 | default: Bastion banner 80 | EnableTCPForwarding: 81 | default: TCP forwarding 82 | EnableX11Forwarding: 83 | default: X11 forwarding 84 | EnvironmentVariables: 85 | default: Environment variables 86 | KeyPairName: 87 | default: Key pair name 88 | NumBastionHosts: 89 | default: Number of bastion hosts 90 | OndemandPercentage: 91 | default: On-demand percentage 92 | OSImageOverride: 93 | default: Operating system override 94 | PrivateSubnet1CIDR: 95 | default: Private subnet 1 CIDR 96 | PrivateSubnet2CIDR: 97 | default: Private subnet 2 CIDR 98 | PublicSubnet1CIDR: 99 | default: Public subnet 1 CIDR 100 | PublicSubnet2CIDR: 101 | default: Public subnet 2 CIDR 102 | VPCTenancy: 103 | default: VPC tenancy 104 | QSS3BucketName: 105 | default: Quick Start S3 bucket name 106 | QSS3BucketRegion: 107 | default: Quick Start S3 bucket Region 108 | QSS3KeyPrefix: 109 | default: Quick Start S3 key prefix 110 | RemoteAccessCIDR: 111 | default: Allowed bastion external access CIDR 112 | VPCCIDR: 113 | default: VPC CIDR 114 | RootVolumeSize: 115 | default: Root volume size 116 | PermissionsBoundaryArn: 117 | default: Permissions boundary ARN 118 | RolePath: 119 | default: Role path 120 | EC2MetadataPutResponseHopLimit: 121 | default: Amazon EC2 metadata put response hop limit 122 | EC2MetadataHttpTokens: 123 | default: Amazon EC2 metadata HTTP tokens 124 | Parameters: 125 | AvailabilityZones: 126 | Type: List 127 | Description: List of Availability Zones to use for the subnets in the VPC. 128 | BastionAMIOS: 129 | Type: String 130 | Description: The Linux distribution for the AMI to be used for the bastion host instances. 131 | AllowedValues: 132 | - Amazon-Linux2-HVM 133 | - Amazon-Linux2-HVM-ARM 134 | - Amazon-Linux2022 135 | - Amazon-Linux2022-ARM 136 | - Ubuntu-Server-20.04-LTS-HVM 137 | - Ubuntu-Server-22.04-LTS-HVM 138 | - Ubuntu-Server-22.04-LTS-HVM-ARM 139 | Default: Amazon-Linux2-HVM 140 | BastionHostName: 141 | Type: String 142 | Description: The value used for the name tag of the bastion host. 143 | Default: LinuxBastion 144 | BastionBanner: 145 | Type: String 146 | Description: >- 147 | Amazon S3 object URL for the text file with the content to display upon 148 | SSH login. The bastion host must have permission to download the file 149 | from the S3 bucket. 150 | AllowedPattern: ^(s3:\/\/[0-9a-z]+([0-9a-z-]*[0-9a-z])*/.+)?$ 151 | ConstraintDescription: >- 152 | Must be either a valid Amazon S3 object URL 153 | (example: s3://bucket/key/file.txt) or empty. 154 | Default: '' 155 | BastionTenancy: 156 | Type: String 157 | Description: Bastion VPC tenancy (dedicated or default). 158 | AllowedValues: [dedicated, default] 159 | Default: default 160 | BastionInstanceType: 161 | Type: String 162 | Description: Amazon EC2 instance type for the bastion instances. 163 | Default: t3.micro 164 | EnableBanner: 165 | Type: String 166 | Description: Choose "true" to display a banner when connecting to the bastion using SSH. 167 | AllowedValues: ['true', 'false'] 168 | Default: 'false' 169 | EnableTCPForwarding: 170 | Type: String 171 | Description: Choose "true" to enable TCP forwarding. 172 | AllowedValues: ['true', 'false'] 173 | Default: 'false' 174 | EnableX11Forwarding: 175 | Type: String 176 | Description: Choose "true" to enable X11 forwarding. 177 | AllowedValues: ['true', 'false'] 178 | Default: 'false' 179 | KeyPairName: 180 | Type: String 181 | Description: 182 | Name of an existing public/private key pair, which allows you to securely connect to your instance 183 | after it launches. If left empty, AWS Systems Manager Session Manager can still be used to connect to the instance. 184 | Default: '' 185 | NumBastionHosts: 186 | Type: String 187 | Description: The number of bastion hosts to create. The maximum number is four. 188 | AllowedValues: [1, 2, 3, 4] 189 | Default: 1 190 | OndemandPercentage: 191 | Type: Number 192 | Description: >- 193 | Percentage of on-demand instances versus spot instances. With the 194 | default of 100, the ratio will be 100% on-demand instances and 0% spot 195 | instances. 196 | Default: 100 197 | PrivateSubnet1CIDR: 198 | Type: String 199 | Description: CIDR block for private subnet 1, located in Availability Zone 1. 200 | 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])(\/(1[6-9]|2[0-8]))$ 201 | ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 202 | Default: 10.0.0.0/19 203 | PrivateSubnet2CIDR: 204 | Type: String 205 | Description: CIDR block for private subnet 2, located in Availability Zone 2. 206 | 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])(\/(1[6-9]|2[0-8]))$ 207 | ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 208 | Default: 10.0.32.0/19 209 | PublicSubnet1CIDR: 210 | Type: String 211 | Description: CIDR block for the public DMZ subnet 1, located in Availability Zone 1. 212 | 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])(\/(1[6-9]|2[0-8]))$ 213 | ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 214 | Default: 10.0.128.0/20 215 | PublicSubnet2CIDR: 216 | Type: String 217 | Description: CIDR block for the public DMZ subnet 2, located in Availability Zone 2. 218 | 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])(\/(1[6-9]|2[0-8]))$ 219 | ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 220 | Default: 10.0.144.0/20 221 | VPCTenancy: 222 | Type: String 223 | Description: The allowed tenancy of instances launched into the VPC. 224 | AllowedValues: [default, dedicated] 225 | Default: default 226 | EC2MetadataPutResponseHopLimit: 227 | Type: String 228 | Description: >- 229 | The desired HTTP PUT response hop limit for instance metadata requests. 230 | The larger the number, the further instance metadata requests can travel. 231 | Default: 2 232 | EC2MetadataHttpTokens: 233 | Type: String 234 | Description: >- 235 | If set to "optional" instances will be able to use their IAM instance 236 | profile. If set to "required" amd "EC2MetadataPutResponseHopLimit" is set 237 | to 1, instances will not be able to access the IAM role. If set to 238 | "required" amd "EC2MetadataPutResponseHopLimit" is set greater than 1 239 | instances must send a signed token header with any instance metadata 240 | retrieval requests. 241 | AllowedValues: [optional, required] 242 | Default: required 243 | QSS3BucketName: 244 | Type: String 245 | Description: Name of the S3 bucket for your copy of the Quick Start assets. 246 | Keep the default name unless you are customizing the template. 247 | Changing the name updates code references to point to a new Quick 248 | Start location. This name can include numbers, lowercase letters, 249 | and hyphens, but do not start or end with a hyphen (-). 250 | See https://aws-quickstart.github.io/option1.html. 251 | MinLength: 3 252 | MaxLength: 63 253 | AllowedPattern: ^[0-9a-z]+([0-9a-z-]*[0-9a-z])*$ 254 | ConstraintDescription: 255 | The Quick Start bucket name can include numbers, lowercase 256 | letters, uppercase letters, and hyphens (-). It cannot start or end with a 257 | hyphen (-). 258 | Default: aws-quickstart 259 | QSS3KeyPrefix: 260 | Type: String 261 | Description: 262 | S3 key prefix that is used to simulate a directory for your copy of the 263 | Quick Start assets. Keep the default prefix unless you are customizing 264 | the template. Changing this prefix updates code references to point to 265 | a new Quick Start location. This prefix can include numbers, lowercase 266 | letters, uppercase letters, hyphens (-), and forward slashes (/). End 267 | with a forward slash. 268 | See https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingMetadata.html 269 | and https://aws-quickstart.github.io/option1.html. 270 | AllowedPattern: ^([0-9a-zA-Z-.]+/)*$ 271 | ConstraintDescription: 272 | The Quick Start S3 key prefix can include numbers, lowercase letters, 273 | uppercase letters, hyphens (-), and forward slashes (/). 274 | Default: quickstart-linux-bastion/ 275 | QSS3BucketRegion: 276 | Type: String 277 | Description: >- 278 | AWS Region where the Quick Start S3 bucket (QSS3BucketName) is 279 | hosted. Keep the default Region unless you are customizing the template. 280 | Changing this Region updates code references to point to a new Quick Start location. 281 | When using your own bucket, specify the Region. 282 | See https://aws-quickstart.github.io/option1.html. 283 | Default: us-east-1 284 | RemoteAccessCIDR: 285 | Type: String 286 | Description: >- 287 | Allowed CIDR block or prefix list for external SSH access to the 288 | bastions. 289 | 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]))$ 290 | ConstraintDescription: CIDR block parameter must be disabled-onlyssmaccess or in the format "x.x.x.x/x". 291 | Default: disabled-onlyssmaccess 292 | VPCCIDR: 293 | Type: String 294 | Description: CIDR block for the VPC. 295 | 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])(\/(1[6-9]|2[0-8]))$ 296 | ConstraintDescription: CIDR block parameter must be in the format "x.x.x.x/16-28". 297 | Default: 10.0.0.0/16 298 | AlternativeInitializationScript: 299 | Type: String 300 | Description: >- 301 | HTTPS format Amazon S3 object URL for your custom initialization script 302 | to run during setup. The bastion host must have permission to download 303 | the file from the S3 bucket. 304 | AllowedPattern: ^https.*|^$ 305 | ConstraintDescription: >- 306 | Must be either a valid Amazon S3 object URL 307 | (example: https://bucket/key/file.txt) or empty. 308 | Default: '' 309 | OSImageOverride: 310 | Type: String 311 | Description: The Region-specific image to use for the instance. 312 | Default: '' 313 | AlternativeIAMRole: 314 | Type: String 315 | Description: 316 | An existing IAM role name to attach to the bastion. If left blank, 317 | a new role will be created. 318 | Default: '' 319 | EnvironmentVariables: 320 | Type: String 321 | Description: A comma-separated list of environment variables for use in 322 | bootstrapping. Variables must be in the format "key=value". "Value" cannot 323 | contain commas. 324 | Default: '' 325 | RootVolumeSize: 326 | Type: Number 327 | Description: The size in GB for the root EBS volume. 328 | Default: 10 329 | PermissionsBoundaryArn: 330 | Type: String 331 | Description: Will be attached to all created IAM roles to satisfy security requirements. 332 | Default: '' 333 | RolePath: 334 | Type: String 335 | Description: Will be attached to all created IAM roles to satisfy security requirements. 336 | Default: '' 337 | Conditions: 338 | NeedsEip: !Not [!Equals [!Ref RemoteAccessCIDR, disabled-onlyssmaccess]] 339 | UsingDefaultBucket: !Equals [!Ref QSS3BucketName, aws-quickstart] 340 | Resources: 341 | VPCStack: 342 | Type: AWS::CloudFormation::Stack 343 | Properties: 344 | TemplateURL: !Sub 345 | - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}submodules/quickstart-aws-vpc/templates/aws-vpc.template.yaml 346 | - S3Bucket: !If [UsingDefaultBucket, !Sub 'aws-quickstart-${AWS::Region}', !Ref QSS3BucketName] 347 | S3Region: !If [UsingDefaultBucket, !Ref AWS::Region, !Ref QSS3BucketRegion] 348 | Parameters: 349 | AvailabilityZones: !Join [',', !Ref AvailabilityZones] 350 | NumberOfAZs: 2 351 | PrivateSubnet1ACIDR: !Ref PrivateSubnet1CIDR 352 | PrivateSubnet2ACIDR: !Ref PrivateSubnet2CIDR 353 | PublicSubnet1CIDR: !Ref PublicSubnet1CIDR 354 | PublicSubnet2CIDR: !Ref PublicSubnet2CIDR 355 | VPCCIDR: !Ref VPCCIDR 356 | VPCTenancy: !Ref VPCTenancy 357 | BastionStack: 358 | Type: AWS::CloudFormation::Stack 359 | Properties: 360 | TemplateURL: !Sub 361 | - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}templates/linux-bastion-entrypoint-existing-vpc.template.yaml 362 | - S3Bucket: !If [UsingDefaultBucket, !Sub 'aws-quickstart-${AWS::Region}', !Ref QSS3BucketName] 363 | S3Region: !If [UsingDefaultBucket, !Ref AWS::Region, !Ref QSS3BucketRegion] 364 | Parameters: 365 | BastionAMIOS: !Ref BastionAMIOS 366 | BastionHostName: !Ref BastionHostName 367 | BastionBanner: !Ref BastionBanner 368 | BastionInstanceType: !Ref BastionInstanceType 369 | BastionTenancy: !Ref BastionTenancy 370 | EnableBanner: !Ref EnableBanner 371 | EnableTCPForwarding: !Ref EnableTCPForwarding 372 | EnableX11Forwarding: !Ref EnableX11Forwarding 373 | KeyPairName: !Ref KeyPairName 374 | NumBastionHosts: !Ref NumBastionHosts 375 | OndemandPercentage: !Ref OndemandPercentage 376 | PublicSubnet1ID: !If [NeedsEip, !GetAtt VPCStack.Outputs.PublicSubnet1ID, !GetAtt VPCStack.Outputs.PrivateSubnet1AID] 377 | PublicSubnet2ID: !If [NeedsEip, !GetAtt VPCStack.Outputs.PublicSubnet2ID, !GetAtt VPCStack.Outputs.PrivateSubnet2AID] 378 | QSS3BucketRegion: !Ref QSS3BucketRegion 379 | QSS3BucketName: !Ref QSS3BucketName 380 | QSS3KeyPrefix: !Ref QSS3KeyPrefix 381 | RemoteAccessCIDR: !Ref RemoteAccessCIDR 382 | VPCID: !GetAtt VPCStack.Outputs.VPCID 383 | AlternativeInitializationScript: !Ref AlternativeInitializationScript 384 | AlternativeIAMRole: !Ref AlternativeIAMRole 385 | OSImageOverride: !Ref OSImageOverride 386 | EnvironmentVariables: !Ref EnvironmentVariables 387 | RootVolumeSize: !Ref RootVolumeSize 388 | PermissionsBoundaryArn: !Ref PermissionsBoundaryArn 389 | RolePath: !Ref RolePath 390 | EC2MetadataPutResponseHopLimit: !Ref EC2MetadataPutResponseHopLimit 391 | EC2MetadataHttpTokens: !Ref EC2MetadataHttpTokens 392 | Outputs: 393 | Postdeployment: 394 | Description: See the deployment guide for post-deployment steps. 395 | Value: https://fwd.aws/YqpXk? 396 | --------------------------------------------------------------------------------