Skip to content

Commit

Permalink
Closes #6 by adding support for ssh-keyscan(1) to the add-host-key co…
Browse files Browse the repository at this point in the history
…mmand.
  • Loading branch information
Anthony Shortland committed Dec 4, 2012
1 parent bfbca21 commit f1dbe3f
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 18 deletions.
2 changes: 1 addition & 1 deletion commands/add-host-key/metadata
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@
# Sun Nov 18 08:46:36 PST 2012
NAME=add-host-key
DESCRIPTION="Adds a public key to the specified known hosts file"
OPTIONS="hostname public-key type known-hosts-file"
OPTIONS="hostname type known-hosts-file host-key"
9 changes: 4 additions & 5 deletions commands/add-host-key/options.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Generated by stubbs:add-option. Do not edit, if using stubbs.
# Created: Sun Nov 18 09:05:34 PST 2012
# Created: Mon Dec 3 15:36:32 PST 2012
#
#/ usage: ssh:add-host-key --hostname <> --public-key <> [ --type <dsa>] [ --known-hosts-file <$HOME/.ssh/known_hosts>]
#/ usage: ssh:add-host-key --hostname <> [ --type <dsa>] [ --known-hosts-file <$HOME/.ssh/known_hosts>] [ --host-key <>]

# _rerun_options_parse_ - Parse the command arguments and set option variables.
#
Expand All @@ -23,9 +23,9 @@ rerun_options_parse() {
OPT="$1"
case "$OPT" in
--hostname) rerun_option_check $# ; HOSTNAME=$2 ; shift ;;
--public-key) rerun_option_check $# ; PUBLIC_KEY=$2 ; shift ;;
--type) rerun_option_check $# ; TYPE=$2 ; shift ;;
--known-hosts-file) rerun_option_check $# ; KNOWN_HOSTS_FILE=$2 ; shift ;;
--host-key) rerun_option_check $# ; HOST_KEY=$2 ; shift ;;
# help option
-?)
rerun_option_usage
Expand All @@ -43,7 +43,6 @@ rerun_options_parse() {
[ -z "$KNOWN_HOSTS_FILE" ] && KNOWN_HOSTS_FILE="$HOME/.ssh/known_hosts"
# Check required options are set
[ -z "$HOSTNAME" ] && { echo >&2 "missing required option: --hostname" ; return 2 ; }
[ -z "$PUBLIC_KEY" ] && { echo >&2 "missing required option: --public-key" ; return 2 ; }
# If option variables are declared exportable, export them.

#
Expand All @@ -53,8 +52,8 @@ rerun_options_parse() {

# Initialize the options variables to null.
HOSTNAME=
PUBLIC_KEY=
TYPE=
KNOWN_HOSTS_FILE=
HOST_KEY=


18 changes: 12 additions & 6 deletions commands/add-host-key/script
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
# and show its options.
#
#/ command: ssh:add-host-key: "Adds a public key to the specified known hosts file"
#/ usage: rerun ssh:add-host-key --hostname <> --public-key <> [ --type <dsa>] [ --known-hosts-file <$HOME/.ssh/known_hosts>]
#/ usage: rerun ssh:add-host-key --hostname <> [ --type <dsa>] [ --known-hosts-file <$HOME/.ssh/known_hosts>] [ --host-key <>]

# Load common functions
# ---------------------
Expand Down Expand Up @@ -47,7 +47,7 @@ set -o nounset -o pipefail
# declared by `rerun` or by the option parser function.

#/ rerun-variables: RERUN, RERUN_VERSION, RERUN_MODULES, RERUN_MODULE_DIR
#/ option-variables: HOSTNAME PUBLIC_KEY TYPE KNOWN_HOSTS_FILE
#/ option-variables: HOSTNAME TYPE KNOWN_HOSTS_FILE HOST_KEY

# The `rerun_options_parse` function processes the command line
# arguments. Each accepted command line flag results in setting
Expand All @@ -63,18 +63,24 @@ rerun_options_parse "$@"
# Put the command implementation here.
# - - -

# If the host key was not provided on the command line use ssh-keyscan(1) to acquire it.
if [[ -z $HOST_KEY ]]
then
HOST_KEY=$(ssh-keyscan -t ${TYPE} ${HOSTNAME} 2>/dev/null | cut -d' ' -f3)
fi

if [[ -r ${KNOWN_HOSTS_FILE} ]]
then
# Eliminate other entries for this key, if they are not identical to the one specified.

if grep -q "^${HOSTNAME} ssh-${TYPE} ${PUBLIC_KEY}$" ${KNOWN_HOSTS_FILE}
if grep -q "^${HOSTNAME} ssh-${TYPE} ${HOST_KEY}$" ${KNOWN_HOSTS_FILE}
then
echo "INFO: entry already exists, skipping" 1>&2
else
TMP_KNOWN_HOSTS_FILE=$(mktemp)

# Ignore the exit code since it's an indeterminate indication of success in this case.
if fgrep -v "${PUBLIC_KEY}" ${KNOWN_HOSTS_FILE} > ${TMP_KNOWN_HOSTS_FILE}
if fgrep -v "${HOST_KEY}" ${KNOWN_HOSTS_FILE} > ${TMP_KNOWN_HOSTS_FILE}
then
:
fi
Expand All @@ -88,7 +94,7 @@ then
rm -f ${TMP_KNOWN_HOSTS_FILE}

# Compose and append the entry to the specified known hosts file.
echo "${HOSTNAME} ssh-${TYPE} ${PUBLIC_KEY}" >> ${KNOWN_HOSTS_FILE}
echo "${HOSTNAME} ssh-${TYPE} ${HOST_KEY}" >> ${KNOWN_HOSTS_FILE}

echo "INFO: replaced existing entrie(s)" 1>&2
fi
Expand All @@ -97,7 +103,7 @@ else
[[ -d $(dirname ${KNOWN_HOSTS_FILE}) ]] || mkdir $(dirname ${KNOWN_HOSTS_FILE}) && chmod 700 $(dirname ${KNOWN_HOSTS_FILE})

# Create the known hosts file with default permissions, if it doesn't already exist.
echo "${HOSTNAME} ssh-${TYPE} ${PUBLIC_KEY}" > ${KNOWN_HOSTS_FILE}
echo "${HOSTNAME} ssh-${TYPE} ${HOST_KEY}" > ${KNOWN_HOSTS_FILE}

echo "INFO: added entry to new known hosts file" 1>&2
fi
Expand Down
2 changes: 1 addition & 1 deletion metadata
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
NAME=ssh
DESCRIPTION="Rerun module for managing secure shell client and server usage"
INTERPRETER="bash"
VERSION=1.0.1
VERSION=1.1.1
REQUIRES=
EXTERNALS=
META_MODULE=
12 changes: 12 additions & 0 deletions options/host-key/metadata
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# option metadata
# generated by stubbs:add-option
# Mon Dec 3 15:36:04 PST 2012
NAME=host-key
DESCRIPTION="Public key of the specified host"
ARGUMENTS=true
REQUIRED=false
SHORT=
LONG=host-key
DEFAULT=
EXPORT=false

36 changes: 31 additions & 5 deletions tests/add-host-key-1-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,31 +14,57 @@

describe "add-host-key"

it_works_with_a_new_key_and_a_duplicate() {
# Tests generating a DSA public host key and adding it to a temporary known hosts file.
it_works_with_a_new_and_duplicate_key() {
# Generate a new key-pair into a temporary directory.
TMPDIR=$(mktemp -d)
rerun ssh:keygen --key-file ${TMPDIR}/id_dsa

# Get the fields from the generated public key file.
TYPE=$(cut -d' ' -f1 < ${TMPDIR}/id_dsa.pub | cut -d- -f2)
PUBLIC_KEY=$(cut -d' ' -f2 < ${TMPDIR}/id_dsa.pub)
COMMENT=$(cut -d' ' -f3- < ${TMPDIR}/id_dsa.pub)

# Add the key to a new empty known hosts file and make sure its the same as the original public key:
rerun ssh:add-host-key --public-key "${PUBLIC_KEY}" --known-hosts-file ${TMPDIR}/.ssh/known_hosts --type ${TYPE} --hostname localhost
rerun ssh:add-host-key --host-key "${PUBLIC_KEY}" --known-hosts-file ${TMPDIR}/.ssh/known_hosts --type ${TYPE} --hostname localhost
echo "localhost ssh-${TYPE} ${PUBLIC_KEY}" > ${TMPDIR}/known_hosts.test
diff ${TMPDIR}/known_hosts.test ${TMPDIR}/.ssh/known_hosts

# Add the key a second time and make sure its the same as the original public key thus proving a duplicate entry was avoided:
rerun ssh:add-host-key --public-key "${PUBLIC_KEY}" --known-hosts-file ${TMPDIR}/.ssh/known_hosts --type ${TYPE} --hostname localhost
rerun ssh:add-host-key --host-key "${PUBLIC_KEY}" --known-hosts-file ${TMPDIR}/.ssh/known_hosts --type ${TYPE} --hostname localhost
echo "localhost ssh-${TYPE} ${PUBLIC_KEY}" > ${TMPDIR}/known_hosts.test
diff ${TMPDIR}/known_hosts.test ${TMPDIR}/.ssh/known_hosts

# Add the key a third time with a different hostname proving the existing entry is replaced:
rerun ssh:add-host-key --public-key "${PUBLIC_KEY}" --known-hosts-file ${TMPDIR}/.ssh/known_hosts --type ${TYPE} --hostname $HOSTNAME
rerun ssh:add-host-key --host-key "${PUBLIC_KEY}" --known-hosts-file ${TMPDIR}/.ssh/known_hosts --type ${TYPE} --hostname $HOSTNAME
echo "$HOSTNAME ssh-${TYPE} ${PUBLIC_KEY}" > ${TMPDIR}/known_hosts.test
diff ${TMPDIR}/known_hosts.test ${TMPDIR}/.ssh/known_hosts

rm -rf ${TMPDIR}
}

# Tests using ssh-keyscan(1) to get the localhost's DSA public host key and add it to a temporary known hosts file
it_works_when_no_host_key_is_provided() {
# Generate a new key-pair into a temporary directory.
TMPDIR=$(mktemp -d)

# Get the fields from the generated public key file.
TYPE=dsa
PUBLIC_KEY=$(ssh-keyscan -t dsa localhost 2>/dev/null | cut -d' ' -f3)

# Add the key to a new empty known hosts file and make sure its the same as the original public key:
rerun ssh:add-host-key --known-hosts-file ${TMPDIR}/.ssh/known_hosts --type ${TYPE} --hostname localhost
echo "localhost ssh-${TYPE} ${PUBLIC_KEY}" > ${TMPDIR}/known_hosts.test
diff ${TMPDIR}/known_hosts.test ${TMPDIR}/.ssh/known_hosts

# Add the key a second time and make sure its the same as the original public key thus proving a duplicate entry was avoided:
rerun ssh:add-host-key --known-hosts-file ${TMPDIR}/.ssh/known_hosts --type ${TYPE} --hostname localhost
echo "localhost ssh-${TYPE} ${PUBLIC_KEY}" > ${TMPDIR}/known_hosts.test
diff ${TMPDIR}/known_hosts.test ${TMPDIR}/.ssh/known_hosts

# Add the key a third time with a different hostname proving the existing entry is replaced:
rerun ssh:add-host-key --known-hosts-file ${TMPDIR}/.ssh/known_hosts --type ${TYPE} --hostname $HOSTNAME
echo "$HOSTNAME ssh-${TYPE} ${PUBLIC_KEY}" > ${TMPDIR}/known_hosts.test
diff ${TMPDIR}/known_hosts.test ${TMPDIR}/.ssh/known_hosts

rm -rf ${TMPDIR}
}

0 comments on commit f1dbe3f

Please sign in to comment.