|
4 | 4 | # SPDX-License-Identifier: Apache-2.0 OR MIT |
5 | 5 | set -e |
6 | 6 |
|
7 | | -mkdir -p /home/ec2-user/.ssh/ |
8 | | -chmod 700 /home/ec2-user/.ssh/ |
9 | | -ssh_host_key_dir="/.bottlerocket/host-containers/admin/etc/ssh" |
10 | | -ssh_config_dir="/home/ec2-user/.ssh" |
| 7 | +log() { |
| 8 | + echo "$*" >&2 |
| 9 | +} |
11 | 10 |
|
12 | | -# Populate authorized_keys with all the public keys found in instance meta-data |
13 | | -# The URLs for keys include an index and the keypair name, e.g. |
14 | | -# http://169.254.169.254/latest/meta-data/public-keys/0=mykeypair/openssh-key |
15 | | -ssh_authorized_keys="${ssh_config_dir}/authorized_keys" |
16 | | -touch ${ssh_authorized_keys} |
17 | | -chmod 600 ${ssh_authorized_keys} |
18 | | -public_key_base_url="http://169.254.169.254/latest/meta-data/public-keys/" |
19 | | -imds_session_token=$(curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 60") |
20 | | -imds_request_add_header="X-aws-ec2-metadata-token: ${imds_session_token}" |
21 | | -public_key_indexes=($(curl -H "${imds_request_add_header}" -sf "${public_key_base_url}" \ |
22 | | - | cut -d= -f1 \ |
23 | | - | xargs)) |
| 11 | +declare -r local_user="ec2-user" |
| 12 | +declare -r ssh_host_key_dir="/.bottlerocket/host-containers/admin/etc/ssh" |
| 13 | +declare -r user_data="/.bottlerocket/host-containers/admin/user-data" |
| 14 | +declare -r user_ssh_dir="/home/${local_user}/.ssh" |
| 15 | +available_auth_methods=0 |
24 | 16 |
|
25 | | -for public_key_index in "${public_key_indexes[@]}"; do |
26 | | - public_key_data="$(curl -H "${imds_request_add_header}" -sf "${public_key_base_url}/${public_key_index}/openssh-key")" |
27 | | - if [[ ! "${public_key_data}" =~ ^"ssh" ]]; then |
28 | | - echo "Key ${public_key_data} with index ${public_key_index} looks invalid" >&2 |
29 | | - continue |
30 | | - fi |
31 | | - echo "${public_key_data}" >> "${ssh_authorized_keys}" |
32 | | - if ! grep -q "${public_key_data}" "${ssh_authorized_keys}"; then |
33 | | - echo "Failed to write key with index ${public_key_index} to authorized_keys" >&2 |
34 | | - continue |
35 | | - fi |
36 | | -done |
| 17 | +mkdir -p "${user_ssh_dir}" |
| 18 | +chmod 700 "${user_ssh_dir}" |
| 19 | + |
| 20 | +get_user_data_keys() { |
| 21 | + # Extract the keys from user-data json |
| 22 | + local raw_keys |
| 23 | + local key_type="${1:?}" |
| 24 | + if ! raw_keys=$(jq --arg key_type "${key_type}" -e -r '.["ssh"][$key_type][]' "${user_data}" 2>/dev/null); then |
| 25 | + log "Failed to parse ${key_type} from ${user_data}" |
| 26 | + return 1 |
| 27 | + fi |
| 28 | + |
| 29 | + # Map the keys to avoid improper splitting |
| 30 | + local mapped_keys |
| 31 | + mapfile -t mapped_keys <<< "${raw_keys}" |
| 32 | + |
| 33 | + # Verify the keys are valid |
| 34 | + local key |
| 35 | + local -a valid_keys |
| 36 | + for key in "${mapped_keys[@]}"; do |
| 37 | + if ! echo "${key}" | ssh-keygen -lf - &>/dev/null; then |
| 38 | + log "Failed to validate ${key}" |
| 39 | + continue |
| 40 | + fi |
| 41 | + valid_keys+=( "${key}" ) |
| 42 | + done |
| 43 | + |
| 44 | + ( IFS=$'\n'; echo "${valid_keys[*]}" ) |
| 45 | +} |
37 | 46 |
|
38 | | -# If we didn't write any keys at all, there's not much point in continuing |
39 | | -if [ ! -s "${ssh_authorized_keys}" ]; then |
40 | | - echo "Failed to write any valid public keys to authorized_keys" >&2 |
41 | | - exit 1 |
| 47 | +# Populate authorized_keys with all the authorized keys found in user-data |
| 48 | +if authorized_keys=$(get_user_data_keys "authorized_keys"); then |
| 49 | + ssh_authorized_keys="${user_ssh_dir}/authorized_keys" |
| 50 | + touch "${ssh_authorized_keys}" |
| 51 | + chmod 600 "${ssh_authorized_keys}" |
| 52 | + echo "${authorized_keys}" > "${ssh_authorized_keys}" |
| 53 | + ((++available_auth_methods)) |
42 | 54 | fi |
43 | 55 |
|
44 | | -chown ec2-user -R "${ssh_config_dir}" |
| 56 | +# Populate trusted_user_ca_keys with all the authorized keys found in user-data |
| 57 | +if trusted_user_ca_keys=$(get_user_data_keys "trusted_user_ca_keys"); then |
| 58 | + ssh_trusted_user_ca_keys="/etc/ssh/trusted_user_ca_keys.pub" |
| 59 | + touch "${ssh_trusted_user_ca_keys}" |
| 60 | + chmod 600 "${ssh_trusted_user_ca_keys}" |
| 61 | + echo "${trusted_user_ca_keys}" > "${ssh_trusted_user_ca_keys}" |
| 62 | + ((++available_auth_methods)) |
| 63 | +fi |
| 64 | + |
| 65 | +chown "${local_user}" -R "${user_ssh_dir}" |
| 66 | + |
| 67 | +# If there were no successful auth methods, then users cannot authenticate |
| 68 | +if [[ "${available_auth_methods}" -eq 0 ]]; then |
| 69 | + log "Failed to configure ssh authentication" |
| 70 | +fi |
45 | 71 |
|
46 | 72 | # Generate the server keys |
47 | 73 | mkdir -p "${ssh_host_key_dir}" |
48 | 74 | for key in rsa ecdsa ed25519; do |
49 | | - # If both of the keys exist, don't overwrite them |
50 | | - if [ -s "${ssh_host_key_dir}/ssh_host_${key}_key" ] && [ -s "${ssh_host_key_dir}/ssh_host_${key}_key.pub" ]; then |
51 | | - echo "${key} key already exists, will use existing key." >&2 |
52 | | - continue |
53 | | - fi |
| 75 | + # If both of the keys exist, don't overwrite them |
| 76 | + if [ -s "${ssh_host_key_dir}/ssh_host_${key}_key" ] && |
| 77 | + [ -s "${ssh_host_key_dir}/ssh_host_${key}_key.pub" ]; then |
| 78 | + log "${key} key already exists, will use existing key." |
| 79 | + continue |
| 80 | + fi |
54 | 81 |
|
55 | | - rm -rf \ |
56 | | - "${ssh_host_key_dir}/ssh_host_${key}_key" \ |
57 | | - "${ssh_host_key_dir}/ssh_host_${key}_key.pub" |
58 | | - if ssh-keygen -t "${key}" -f "${ssh_host_key_dir}/ssh_host_${key}_key" -q -N ""; then |
59 | | - chmod 600 "${ssh_host_key_dir}/ssh_host_${key}_key" |
60 | | - chmod 644 "${ssh_host_key_dir}/ssh_host_${key}_key.pub" |
61 | | - else |
62 | | - echo "Failure to generate host ${key} ssh keys" >&2 |
63 | | - exit 1 |
64 | | - fi |
| 82 | + rm -rf \ |
| 83 | + "${ssh_host_key_dir}/ssh_host_${key}_key" \ |
| 84 | + "${ssh_host_key_dir}/ssh_host_${key}_key.pub" |
| 85 | + if ssh-keygen -t "${key}" -f "${ssh_host_key_dir}/ssh_host_${key}_key" -q -N ""; then |
| 86 | + chmod 600 "${ssh_host_key_dir}/ssh_host_${key}_key" |
| 87 | + chmod 644 "${ssh_host_key_dir}/ssh_host_${key}_key.pub" |
| 88 | + else |
| 89 | + log "Failure to generate host ${key} ssh keys" |
| 90 | + fi |
65 | 91 | done |
66 | 92 |
|
67 | 93 | # Start a single sshd process in the foreground |
|
0 commit comments