Last active
August 21, 2022 22:23
-
-
Save nekwebdev/eeb070f88344ce24506b0ceafabaeb4c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
############################################################################ | |
## ██╗ ██████╗ █████╗ ███████╗███████╗ ███████╗███████╗██╗ ██╗ ## | |
## ██║ ██╔══██╗██╔══██╗██╔════╝██╔════╝ ██╔════╝██╔════╝██║ ██║ ## | |
## ██║ ██████╔╝███████║███████╗███████╗█████╗███████╗███████╗███████║ ## | |
## ██║ ██╔═══╝ ██╔══██║╚════██║╚════██║╚════╝╚════██║╚════██║██╔══██║ ## | |
## ███████╗██║ ██║ ██║███████║███████║ ███████║███████║██║ ██║ ## | |
## ╚══════╝╚═╝ ╚═╝ ╚═╝╚══════╝╚══════╝ ╚══════╝╚══════╝╚═╝ ╚═╝ ## | |
############################################################################ | |
## Preparation: | |
## Create a secure SSH note in LastPass named: 'SSH: <key name>' | |
## Make sure the Passphrase and Private Key fields are correct | |
## Extra: Set LPASS_USER environment variable to your LastPass username | |
## | |
## You can also copy this script to the secure SSH note "notes" field | |
## Then use this command to download this script and run it | |
## | |
## Added the time option set to 8h in this example | |
## | |
## bash <(lpass show 'SSH: <key name>' --notes) <key name> -t 8 | |
## | |
## Useful function for this command: lpass-ssh <key name> <time> (optional) | |
## | |
## lpass-ssh() { | |
## if [ -z ${2} ]; then 2=8 fi | |
## bash (lpass show 'SSH: $1' --notes) $1 -t $2 | |
## } | |
## | |
## Fish shell version | |
## | |
## bash (lpass show 'SSH: <key name>' --notes | psub) <key name> -t 8 | |
## | |
## Useful function for this command: lpass-ssh <key name> <time> (optional) | |
## | |
## function lpass-ssh --argument-names key_name time | |
## if test -z $time | |
## set time 8 | |
## end | |
## bash (lpass show "SSH: $key_name" --notes | psub) $key_name -t $time | |
## end | |
## | |
############################################################################ | |
# Display help screen | |
_display_help() { | |
echo " Preparation:" | |
echo " Create a secure SSH note in LastPass named: 'SSH: <key name>'." | |
echo " Make sure the Passphrase and Private Key fields are correct." | |
echo | |
echo " Usage:" | |
echo " lpass-ssh [-u | --user <username>] [-t | --time <hours>] (<key name>)" | |
echo " lpass-ssh [-h | --help]" | |
echo | |
echo " Options:" | |
echo " -h --help Show this screen." | |
echo " -u --user <username> Optional LastPass username." | |
echo " Will use LPASS_USER environment variable or prompt for it." | |
echo " -t --time <hours> Optional, defaults to 8 hours." | |
echo " Hours the ssh key will remain in the agent." | |
echo " <key name> LastPass will look for a secure note named SSH: <key name>." | |
echo | |
echo " The ssh key will be download and added to the agent for a set duration." | |
echo | |
echo " Once added the key is deleted from the drive." | |
echo | |
} | |
# ########################################################################### | |
# # Terminal output helpers | |
# ########################################################################### | |
# _echo_equals() outputs a line with = | |
# seq does not exist under OpenBSD | |
_echo_equals() { | |
COUNTER=0 | |
while [ $COUNTER -lt "$1" ]; do | |
printf '=' | |
(( COUNTER=COUNTER+1 )) | |
done | |
} | |
# _echo_title() outputs a title padded by =, in yellow. | |
_echo_title() { | |
TITLE=$1 | |
NCOLS=$(tput cols) | |
NEQUALS=$(((NCOLS-${#TITLE})/2-1)) | |
tput setaf 3 # 3 = yellow | |
_echo_equals "$NEQUALS" | |
printf " %s " "$TITLE" | |
_echo_equals "$NEQUALS" | |
tput sgr 0 0 # reset terminal | |
echo | |
} | |
# _echo_step() outputs a step collored in cyan, without outputing a newline. | |
_echo_step() { | |
tput setaf 6 # 6 = cyan | |
echo -n "$1" | |
tput sgr 0 0 # reset terminal | |
} | |
# _echo_step_info() outputs additional step info in cyan, without a newline. | |
_echo_step_info() { | |
tput setaf 6 # 6 = cyan | |
echo -n " ($1)" | |
tput sgr 0 0 # reset terminal | |
} | |
# _echo_right() outputs a string at the rightmost side of the screen. | |
_echo_right() { | |
TEXT=$1 | |
echo | |
tput cuu1 | |
tput cuf "$(tput cols)" | |
tput cub ${#TEXT} | |
echo "$TEXT" | |
} | |
# _echo_failure() outputs [ FAILED ] in red, at the rightmost side of the screen. | |
_echo_failure() { | |
tput setaf 1 # 1 = red | |
_echo_right "[ FAILED ]" | |
tput sgr 0 0 # reset terminal | |
} | |
# _echo_success() outputs [ OK ] in green, at the rightmost side of the screen. | |
_echo_success() { | |
tput setaf 2 # 2 = green | |
_echo_right "[ OK ]" | |
tput sgr 0 0 # reset terminal | |
} | |
# _echo_warning() outputs a message and [ WARNING ] in yellow, at the rightmost side of the screen. | |
_echo_warning() { | |
tput setaf 3 # 3 = yellow | |
_echo_right "[ WARNING ]" | |
tput sgr 0 0 # reset terminal | |
echo " ($1)" | |
} | |
# _exit_with_message() outputs and logs a message before exiting the script. | |
_exit_with_message() { | |
echo | |
echo "$1" | |
echo | |
exit 1 | |
} | |
# _exit_with_failure() calls _echo_failure() and _exit_with_message(). | |
_exit_with_failure() { | |
_echo_failure | |
_exit_with_message "FAILURE: $1" 1 | |
} | |
# ################################################################################################ | |
# # Main script | |
# ################################################################################################ | |
# Parse the command arguments | |
ssh_key="" | |
while (( "$#" )); do | |
case "$1" in | |
-h|--help) | |
_display_help | |
exit 0 | |
shift | |
;; | |
-u|--user) | |
if [ -n "$2" ] && [ ${2:0:1} != "-" ]; then | |
lpass_user=$2 | |
shift 2 | |
fi | |
;; | |
-k|--key) | |
if [ -n "$2" ] && [ ${2:0:1} != "-" ]; then | |
ssh_key=$2 | |
shift 2 | |
else | |
echo "Error: Argument for $1 is missing" >&2 | |
exit 1 | |
fi | |
;; | |
-t|--time) | |
if [ -n "$2" ] && [ ${2:0:1} != "-" ]; then | |
valid_for=$2 | |
shift 2 | |
fi | |
;; | |
-*|--*=) # unsupported flags | |
echo "Error: Unsupported flag $1" >&2 | |
exit 1 | |
;; | |
*) # preserve positional arguments | |
ssh_key="$ssh_key $1" | |
shift | |
;; | |
esac | |
done | |
# Require the key name argument | |
if [ -z "${ssh_key}" ]; then | |
_exit_with_failure "You need to specify a key name. lpass-ssh <key name>" | |
fi | |
# If this key is already in the agent we don't need to do anything | |
if ( ssh-add -l | grep -q "${ssh_key}" ); then | |
_exit_with_failure "Key already present." | |
fi | |
# Ensure we are logged into LastPass | |
_echo_step "LastPass login" | |
status=$(lpass status) | |
if [ $? -ne 0 ] | |
then | |
if [ "$status" = 'Not logged in.' ] | |
then | |
# Check for username argument | |
if [ -z "${lpass_user}" ]; then | |
# Check the environment variable | |
lpass_user=$LPASS_USER | |
if [ -z "${lpass_user}" ]; then | |
echo | |
_echo_step_info "Please enter your LastPass username:" | |
read lpass_user | |
fi | |
fi | |
# Make sure DISPLAY is set for some reason and log into lastpass | |
echo | |
_echo_step_info "Logging into LastPass as ${lpass_user}..."; echo | |
DISPLAY=${DISPLAY:-:0} lpass login "${lpass_user}" 1>&2 | |
else | |
_exit_with_failure "Lastpass error: $status" 1>&2 | |
fi | |
fi | |
_echo_success | |
# Check for time argument | |
if [ -z "${valid_for}" ]; then | |
valid_for=4 | |
fi | |
# Set our environment variables | |
export DISPLAY=${DISPLAY:-:0} | |
export SSH_ASKPASS="/tmp/lpass-ssh-askpass" | |
lastpass_key="SSH: $(basename ${ssh_key})" | |
# Write our pass agent to disk | |
cat > /tmp/lpass-ssh-askpass <<EOF | |
#!/bin/sh | |
lpass show --field Passphrase "${lastpass_key}" | |
EOF | |
chmod +x /tmp/lpass-ssh-askpass | |
_echo_step "Adding Private Key '${ssh_key}' for ${valid_for}h";echo | |
# Fetch and add our pruvate key to the agent. | |
lpass show "${lastpass_key}" --field="Private Key" | setsid ssh-add -t "${valid_for}h" /dev/stdin | |
if ! [ $? -eq 0 ]; then | |
_exit_with_failure "Unable to get ssh key." | |
fi | |
_echo_success | |
# Clean up | |
rm -rf /tmp/lpass-ssh-askpass |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment