lssh/lssh

165 lines
3.6 KiB
Bash
Executable File

#!/bin/sh
version="2020.01.17"
arg_options="hvp:t:"
key=""
pattern_prefix="SSH:"
key_locations="${HOME}/.ssh/"
key_types="id_ed25519 id_dsa id_rsa"
# Required: lpass (lastpass cli)
if ! command -v lpass > /dev/null; then
printf "LastPass CLI is required.\n"
exit 2
fi
# Required: expect
if ! command -v expect > /dev/null; then
printf "'expect' is required.\n"
exit 2
fi
show_help () {
cat > /dev/stdout << END
lssh [options] [ssh-key]
OPTIONAL FLAGS:
-h Show this help
-v Show current version info
-p [pattern prefix] Set LastPass prefix pattern (default "SSH:")
-t [type] Set key type
END
}
parse_input () {
if ! parsed=$(getopt $arg_options "$@"); then
printf "Invalid input\\n"
exit 2
fi
eval set -- "$parsed"
while true; do
case "$1" in
-h)
show_help
exit 0
;;
-v)
printf "%s\\n" "$version"
exit 0
;;
-p)
shift
pattern_prefix="$1"
shift
;;
-t)
shift
key_types="$1"
shift
;;
--)
shift
break
;;
*)
printf "Internal error."
exit 3
;;
esac
done
if [ $# -gt 0 ]; then
key="$1"
fi
}
main () {
# Load config, overwrites hardcoded defaults
if [ -n "$XDG_CONFIG_HOME" ]; then
config="${XDG_CONFIG_HOME}/lssh/config"
else
config="${HOME}/.config/lssh/config"
fi
if [ -f "$config" ]; then
# shellcheck disable=SC1090
. "$config"
fi
# env vars override config file
key_locations="${SSH_KEY_LOCATIONS:-${key_locations}}"
lastpass_user="${LASTPASS_USER:-${lastpass_user}}"
# command line switches override everything
parse_input "$@"
if [ -z "${key}" ]; then
printf "You need to specify a key name.\n"
exit 2
fi
# Try to find the passed key path / name from possible key locations.
# Add space-separated path locations for your keys to $SSH_KEY_LOCATIONS
# env variable.
for path in $key_locations; do
if [ -f "${path}${key}" ]; then
printf "Found key at: %s\\n" "${path}${key}"
KEY_ID="${path}${key}"
break;
fi
if [ -d "${path}${key}" ]; then
# check keys in order of crypto awesomeness
for type in $key_types; do
if [ -f "${path}${key}/${type}" ]; then
printf "Found key at: %s\\n" "${path}${key}/${type}"
KEY_ID="${path}${key}/${type}"
break;
fi
done
fi
done
# If no key is found there's nothing to activate. End script
if [ -z "$KEY_ID" ]; then
printf "Could not find key file.\n"
exit 1
fi
# If not logged into lastpass, do so now
while ! lpass status -q; do
if [ -z "${lastpass_user}" ]; then
printf "Lastpass Username: "
read -r lpass_user
lpass login --trust "${lpass_user}"
else
lpass login --trust "${lastpass_user}"
fi
done
# Retrieve key from LastPass. If logged in but not recently authenticated
# lastpass will prompt with pinentry. If no entry found, suppress error.
password=$(lpass show --password "${pattern_prefix} ${key}" 2> /dev/null)
# If the "SSH: xxx" pattern failed, try the key directly
if [ -z "$password" ]; then
password=$(lpass show --password "${key}" 2> /dev/null)
fi
# If we found a password, apply it to the key
if [ -n "$password" ]; then
# awkward tabbing due to EOF structure
expect <<EOF >/dev/null
spawn ssh-add -t 3600 ${KEY_ID}
expect "Enter passphrase"
send "$password\n"
expect eof
EOF
else
printf "Unable to get password. Activating key without password.\n"
ssh-add -t 3600 "${KEY_ID}"
fi
}
main "$@"