blob: ec3195dc11fe7a1f98c7aba046fa3ed65913ec7f [file] [log] [blame]
#!/bin/bash
# Copyright 2020 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.
### Test fx verify_default_keys library
BT_FILE_DEPS=(
"tools/devshell/lib/verify-default-keys.sh"
)
declare ssh_mock scp_mock \
check_ssh_config_mock compare_remote_and_local_mock normalize_local_key_mock \
normalize_remote_key_mock
export HOME="${BT_TEMP_DIR}/HOME"
# These are functions defined in //tools/devshell/lib/vars.sh which
# are referenced in the script under test. They are faked here to
# make testing more simple.
fx-warn() {
echo "$@"
}
fx-error() {
echo "$@"
}
BT_SET_UP() {
source "${BT_TEMP_DIR}/tools/devshell/tests/lib/fuchsia-mock.sh"
ssh_mock=$(btf::make_mock_binary "ssh")
btf::add_binary_to_path "$ssh_mock"
scp_mock=$(btf::make_mock_binary "scp")
btf::add_binary_to_path "$scp_mock"
# make mock scripts of relevant methods, so that we can play around with
# its inputs/outputs
compare_remote_and_local_mock="${BT_TEMP_DIR}/tools/ssh-keys/compare_remote_and_local.sh"
normalize_remote_key_mock="${BT_TEMP_DIR}/tools/ssh-keys/normalize_remote_key.sh"
normalize_local_key_mock="${BT_TEMP_DIR}/tools/ssh-keys/normalize_local_key.sh"
check_ssh_config_mock="${BT_TEMP_DIR}/tools/ssh-keys/check_ssh_config.sh"
btf::make_mock "${compare_remote_and_local_mock}"
btf::make_mock "${normalize_remote_key_mock}"
btf::make_mock "${normalize_local_key_mock}"
btf::make_mock "${check_ssh_config_mock}"
{
echo "function compare_remote_and_local { ${compare_remote_and_local_mock} \"\$@\"; }"
echo "function normalize_remote_key { ${normalize_remote_key_mock} \"\$@\"; }"
echo "function normalize_local_key { ${normalize_local_key_mock} \"\$@\"; }"
echo "function check-ssh-config { ${check_ssh_config_mock} \"\$@\"; }"
} >> "${BT_TEMP_DIR}/tools/devshell/lib/verify-default-keys.sh"
source "${BT_TEMP_DIR}/tools/devshell/lib/verify-default-keys.sh"
}
# test if local keys are copied to remote if necessary
TEST_sshkeys-localhas-remotedoesnt() {
# key exists in local
echo 0 > "${normalize_local_key_mock}.mock_status"
# key does not exist in remote
echo 1 > "${normalize_remote_key_mock}.mock_status"
local out="${BT_TEMP_DIR}/output.log"
mkdir -p "$HOME/.ssh"
echo "myauthkeys mock" > "$HOME/.ssh/fuchsia_authorized_keys"
# check if verify_default_keys executes with success status
BT_EXPECT verify_default_keys "$BT_TEMP_DIR" "myhost" "fuchsia" >>${out} 2>&1
# check if scp was executed as expected
btf::expect-mock-args "${scp_mock}" -q -p "$HOME/.ssh/fuchsia_ed25519" "myhost:.ssh/"
# check if ssh was executed as expected
btf::expect-mock-args "${ssh_mock}" myhost "cat >> .ssh/fuchsia_authorized_keys"
}
# test if remote keys are copied to local if necessary
TEST_sshkeys-remotehas-localdoesnt() {
# key exists in remote
echo 0 > "${normalize_remote_key_mock}.mock_status"
# key does not exist in local
echo 1 > "${normalize_local_key_mock}.mock_status"
local out="${BT_TEMP_DIR}/output.log"
# check if verify_default_keys executes with success status
BT_EXPECT verify_default_keys "$BT_TEMP_DIR" "myhost" "fuchsia" >>${out} 2>&1
# check if scp was executed as expected
btf::expect-mock-args "${scp_mock}" -q -p \
"myhost:.ssh/fuchsia_ed25519" "$HOME/.ssh"
# check if ssh was executed as expected
btf::expect-mock-args "${ssh_mock}" myhost cat .ssh/fuchsia_authorized_keys
}
# test if verify-default-keys fail if keys exist on remote and local but differ
TEST_sshkeys-remotehas-localhas-mismatch() {
# key exists in remote
echo 0 > "${normalize_remote_key_mock}.mock_status"
# key exists in local
echo 0 > "${normalize_local_key_mock}.mock_status"
# keys don't match
echo 1 > "${compare_remote_and_local_mock}.mock_status"
local out="${BT_TEMP_DIR}/output.log"
# check if verify_default_keys executes with fail status
# a subshell is needed because of 'exit' statements inside verify_default_keys
BT_EXPECT_FAIL "( verify_default_keys \"$BT_TEMP_DIR\" myhost fuchsia )" >>${out} 2>&1
}
# test if verify-default-keys succeeds if keys exist on remote and local and are
# the same
TEST_sshkeys-remotehas-localhas() {
# key exists in remote
echo 0 > "${normalize_remote_key_mock}.mock_status"
# key exists in local
echo 0 > "${normalize_local_key_mock}.mock_status"
# keys match
echo 0 > "${compare_remote_and_local_mock}.mock_status"
local out="${BT_TEMP_DIR}/output.log"
# check if verify_default_keys executes with success status
BT_EXPECT verify_default_keys "$BT_TEMP_DIR" myhost fuchsia >>${out} 2>&1
}
# test if a new key is generated in remote if no keys exist anywhere
# and if the key is copied to local after being generated
TEST_sshkeys-nokeys() {
# no key in remote
echo 1 > "${normalize_remote_key_mock}.mock_status"
# no key in local
echo 1 > "${normalize_local_key_mock}.mock_status"
cat > "${check_ssh_config_mock}.mock_side_effects" <<EOF
mkdir -p "$HOME/.ssh"
echo "priv-key" > "$HOME/.ssh/fuchsia_ed25519"
echo "pub-key" > "$HOME/.ssh/fuchsia_authorized_keys"
EOF
local out="${BT_TEMP_DIR}/output.log"
# check if verify_default_keys executes with success status
BT_EXPECT verify_default_keys "$BT_TEMP_DIR" myhost fuchsia >>${out} 2>&1
# check if scp was executed as expected
btf::expect-mock-args "${scp_mock}" -q -p \
"$HOME/.ssh/fuchsia_ed25519" "myhost:.ssh/"
# check if ssh was executed as expected
btf::expect-mock-args "${ssh_mock}" myhost cat\ \>\>\ .ssh/fuchsia_authorized_keys
}
# test if scp is executed with the expected "-o ControlPath" if "-S" is
# specified in the ssh_args argument. "-S" is the equivalent of
# "-o ControlPath" for "ssh", but it is not supported in "scp", so
# verify_default_keys converts it.
TEST_sshkeys-controlpath-scp() {
# key exists in remote
echo 0 > "${normalize_remote_key_mock}.mock_status"
# key does not exist in local
echo 1 > "${normalize_local_key_mock}.mock_status"
local out="${BT_TEMP_DIR}/output.log"
# check if verify_default_keys executes with success status
BT_EXPECT verify_default_keys "$BT_TEMP_DIR" myhost fuchsia -S mycontrolfile >>${out} 2>&1
# check if scp was executed as expected, with "-o ControlPath" instead of "-S"
btf::expect-mock-args "${scp_mock}" -o ControlPath=mycontrolfile -q -p \
"myhost:.ssh/fuchsia_ed25519" "$HOME/.ssh"
# check if ssh was executed as expected, with "-o ControlPath" instead of "-S"
btf::expect-mock-args "${ssh_mock}" -o ControlPath=mycontrolfile myhost cat .ssh/fuchsia_authorized_keys
}
# test if the code path executes fine with an empty ssh_args. If not
# handled properly, empty arrays crash the old bash version that comes
# with Mac if "set -u" is used, like it is used by GN SDK, so if this
# test passes, the ssh_args array is being handled correctly.
TEST_sshkeys-empty-ssharg() {
# key exists in remote
echo 0 > "${normalize_remote_key_mock}.mock_status"
# key exists in local
echo 0 > "${normalize_local_key_mock}.mock_status"
# keys match
echo 0 > "${compare_remote_and_local_mock}.mock_status"
local out="${BT_TEMP_DIR}/output.log"
# check if verify_default_keys executes with success status
(
set -u
verify_default_keys "$BT_TEMP_DIR" myhost fuchsia >>${out} 2>&1
status=$?
)
BT_EXPECT_GOOD_STATUS $status "verify_default_keys failed"
# no output is expected. If empty ssh_args is not handled properly,
# on old Bash scripts the code above will print an error ("Unbound variable")
# although the exit code will still be valid.
BT_EXPECT_FILE_CONTAINS ${out} ""
}
BT_RUN_TESTS "$@"