| #!/usr/bin/env bash |
| # Copyright 2018 The Fuchsia Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| readonly SCRIPT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" |
| readonly FUCHSIA_ROOT="${SCRIPT_ROOT}/../.." |
| readonly _ERROR_NO_KEY=112 |
| readonly _ERROR_MISMATCHED_KEYS=113 |
| |
| description="${USER}@$(hostname -f) Generated by Fuchsia tree on $(date)" |
| no_new_key=false |
| |
| if [[ "$1" == "--no-new-key" ]]; then |
| no_new_key=true |
| elif [[ "$1" == "--description" ]]; then |
| shift |
| description="${description}: $@" |
| fi |
| |
| function copy_ssh_keys { |
| local orig_key dest_key orig_auth_keys dest_auth_keys dest_dir |
| orig_key="$1" |
| dest_key="$2" |
| orig_auth_keys="$3" |
| dest_auth_keys="$4" |
| |
| dest_dir="$(dirname "${dest_key}")" |
| |
| ( |
| # force subshell to limit scope of umask |
| umask 077 && mkdir -p "${dest_dir}" |
| umask 177 |
| cp "${orig_key}" "${dest_key}" |
| umask 133 |
| |
| # Documentation previously recommended copying default SSH identity files |
| # (private keys) and authorized_keys files, but not public key files. When |
| # missing, these are skipped. |
| if [[ -f "${orig_key}.pub" ]]; then |
| cp "${orig_key}.pub" "${dest_key}.pub" |
| fi |
| cat "${orig_auth_keys}" >>"${dest_auth_keys}" |
| ) |
| } |
| |
| function mismatched_keys { |
| cat 1>&2 <<EOF |
| ERROR: You have different Fuchsia SSH credentials in HOME and in FUCHSIA_DIR. |
| |
| - If you most recently successfully paved a device from the Fuchsia tree |
| (fx pave), the SSH credentials in your Fuchsia tree are probably more |
| relevant. In this case, backup and delete Fuchsia SSH keys in \$HOME/.ssh/fuchsia_* |
| |
| - If you most recently successfully paved a device outside the Fuchsia tree |
| (like the GN SDK, using fpave.sh), the SSH credentials in \$HOME/.ssh are |
| probably more relevant. In this case, backup and delete Fuchsia SSH keys in |
| FUCHSIA_DIR/.ssh/pkey* |
| |
| After removing one of the two credentials, execute //tools/ssh-keys/gen-ssh-keys.sh |
| so that they can be synchronized. |
| EOF |
| } |
| |
| function normalize_local_keys { |
| local intree="${FUCHSIA_ROOT}/.ssh/pkey" |
| local inhome="${HOME}/.ssh/fuchsia_ed25519" |
| |
| local have_in_tree=false |
| local have_in_home=false |
| test -f "$intree" && have_in_tree=true |
| test -f "$inhome" && have_in_home=true |
| |
| if $have_in_tree && $have_in_home && ! cmp --silent "$intree" "$inhome"; then |
| mismatched_keys |
| exit $_ERROR_MISMATCHED_KEYS |
| elif $have_in_tree && ! $have_in_home; then |
| echo "Copying existing SSH credentials from //.ssh/pkey to ~/.ssh/fuchsia_ed25519" |
| copy_ssh_keys "$intree" "$inhome" \ |
| "${FUCHSIA_ROOT}/.ssh/authorized_keys" \ |
| "${HOME}/.ssh/fuchsia_authorized_keys" |
| elif ! $have_in_tree && $have_in_home; then |
| echo "Copying existing SSH credentials from ~/.ssh/fuchsia_ed25519 to //.ssh/pkey" |
| copy_ssh_keys "$inhome" "$intree" \ |
| "${HOME}/.ssh/fuchsia_authorized_keys" \ |
| "${FUCHSIA_ROOT}/.ssh/authorized_keys" |
| fi |
| } |
| |
| # $INFRA_RECIPES is a variable set by infra bots. This keeps the infra recipes |
| # running inside its per-build directory without seeking keys in a user's home |
| # directory. See fxr/415297. |
| if [[ "${INFRA_RECIPES}" == "1" ]]; then |
| readonly SSH_DIR="${FUCHSIA_ROOT}/.ssh" |
| readonly keyfile="${SSH_DIR}/pkey" |
| readonly authfile="${SSH_DIR}/authorized_keys" |
| else |
| readonly SSH_DIR="${HOME}/.ssh" |
| readonly keyfile="${SSH_DIR}/fuchsia_ed25519" |
| readonly authfile="${SSH_DIR}/fuchsia_authorized_keys" |
| normalize_local_keys |
| fi |
| |
| if [[ ! -f "${keyfile}" ]]; then |
| if $no_new_key; then |
| { |
| echo "ERROR: SSH key doesn't exist: ${keyfile}." |
| echo "Run //tools/ssh-keys/gen-ssh-keys.sh to generate a new one." |
| } 1>&2 |
| exit $_ERROR_NO_KEY |
| fi |
| # force subshell to limit scope of umask |
| ( umask 077 && mkdir -p "${SSH_DIR}"; ) |
| ssh-keygen -N "" -t ed25519 -f "${keyfile}" -C "${description}" |
| ssh-keygen -y -f "${keyfile}" >>"${authfile}" |
| |
| if [[ "${INFRA_RECIPES}" != "1" ]]; then |
| # normalize again, so that the key created is kept in sync |
| normalize_local_keys |
| fi |
| fi |
| |
| if [[ -f "${FUCHSIA_ROOT}/.fx-ssh-path" ]]; then |
| { read old_keyfile && read old_authfile; } < "${FUCHSIA_ROOT}/.fx-ssh-path" |
| if [[ "${old_keyfile}" == "${keyfile}" && "${old_authfile}" == "${authfile}" ]]; then |
| exit 0 |
| fi |
| fi |
| |
| echo -e "${keyfile}\n${authfile}" >"${FUCHSIA_ROOT}/.fx-ssh-path" |