2022-03-28 10:05:26 -07:00
|
|
|
#!/bin/bash
|
|
|
|
|
2022-12-31 23:29:20 -08:00
|
|
|
_extractpubkey () {
|
|
|
|
name=${2:-$(basename $1)}
|
|
|
|
ssh-keygen -y -f $1 | sed "s/$/ ${name}/"
|
|
|
|
}
|
|
|
|
|
|
|
|
getkeyname () {
|
|
|
|
if [[ $(echo $1 | awk -F . '{print $NF}') == "pub" ]]; then
|
|
|
|
basename "$1" | rev | cut -f 2- -d '.' | rev
|
|
|
|
else
|
|
|
|
basename $1
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
|
|
|
extractpubkey () {
|
|
|
|
[[ $1 ]] || return 1
|
|
|
|
[[ -f $1 ]] && _extractpubkey $1 && return 0
|
|
|
|
# echo try pubkeys dir
|
|
|
|
[[ $SSH_PUB_KEYS_DIR ]] && [[ -f $SSH_PUB_KEYS_DIR/$1 ]] && _extractpubkey $SSH_PUB_KEYS_DIR/$1 && return 0
|
|
|
|
# echo try home
|
|
|
|
[[ -f $HOME/.ssh/$1 ]] && _extractpubkey $HOME/.ssh/$1 && return 0
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
|
|
|
|
# need to use full filename including any .pub
|
|
|
|
catpubkey () {
|
|
|
|
[[ $1 ]] || return 1
|
|
|
|
local key; local pub
|
|
|
|
key=$1
|
|
|
|
if [[ $(echo $1 | awk -F . '{print $NF}') == "pub" ]]; then
|
|
|
|
key=$(basename "$1" | rev | cut -f 2- -d '.' | rev)
|
|
|
|
pub=$1
|
|
|
|
else
|
|
|
|
pub="${1}.pub"
|
|
|
|
key=$(basename $1)
|
|
|
|
fi
|
|
|
|
# echo try agent $key
|
|
|
|
key=$(ssh-add -L | sed -n /$key/p)
|
|
|
|
[[ $key ]] && echo $key && return 0
|
|
|
|
# echo try $pub
|
|
|
|
[[ -f $pub ]] && cat $pub && return 0
|
|
|
|
# echo try $SSH_PUB_KEYS_DIR/$pub
|
|
|
|
[[ $SSH_PUB_KEYS_DIR ]] && [[ -f $SSH_PUB_KEYS_DIR/$pub ]] && cat $SSH_PUB_KEYS_DIR/$pub && return 0
|
|
|
|
# echo $HOME/.ssh/$pub
|
|
|
|
[[ -f $HOME/.ssh/$pub ]] && cat $HOME/.ssh/$pub && return 0
|
|
|
|
# echo try extract key from private key
|
|
|
|
extractpubkey $key
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-03-28 10:05:26 -07:00
|
|
|
#example:
|
|
|
|
# initial xfer of pubkey with a password
|
|
|
|
# sshpubkey <pubkey opts> host <ssh run options> -- <more ssh options>
|
|
|
|
|
2022-12-31 23:29:20 -08:00
|
|
|
# TODO way to get public key
|
|
|
|
# try agent first with sed ssh-add -L | sed -n /sysadmin.kebler.net/p
|
|
|
|
# then in current directory, in SSH_PUB_DIR directory, in .ssh directory (or within)
|
|
|
|
# try pub file, then extract from private key
|
2022-03-28 10:05:26 -07:00
|
|
|
|
|
|
|
export SSH_PUB_KEYS
|
|
|
|
module_load path
|
2024-02-21 11:33:37 -08:00
|
|
|
module_load net-utils
|
|
|
|
module_load remote
|
2022-03-28 10:05:26 -07:00
|
|
|
|
|
|
|
sshpubkey () {
|
|
|
|
|
2022-05-02 10:40:07 -07:00
|
|
|
# echo default pub key dir: $SSH_PUB_KEYS
|
2022-03-28 10:05:26 -07:00
|
|
|
|
2022-12-31 23:29:20 -08:00
|
|
|
local kname=id_rsa
|
2022-05-02 10:40:07 -07:00
|
|
|
local user
|
2022-12-31 23:29:20 -08:00
|
|
|
local opts;local dr="true";local rm; local ropts
|
2024-02-21 11:33:37 -08:00
|
|
|
local vkey; local kuser; local host; local upass; local replace
|
|
|
|
local _sudo; local list;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
help() {
|
|
|
|
|
|
|
|
cat <<EOF
|
|
|
|
usage: sshpubkey <pubkey opts> host <ssh run options> -- <more ssh options>
|
|
|
|
-a, <alternate user> put the key at another user on remote. if you want to put it to root use 'root' will require remote sudo
|
|
|
|
-u, <user> remote user if not available in host
|
|
|
|
-s, <paswd> sudo password for remote if needed
|
|
|
|
-k, <key> can be either the path to a public key file or the name of the key currently loaded in an ssh agent
|
|
|
|
-l, list the keys for the remote user
|
|
|
|
-r, remove the key from the user, use the comment identifier of the public key
|
|
|
|
-o, <options> additional ssh options
|
|
|
|
-e, required to actually make the remote changes, otherwise it's a dry run. This to avoid making a mistake and locking out of remote
|
|
|
|
-h, this help text
|
|
|
|
EOF
|
|
|
|
|
|
|
|
}
|
|
|
|
local OPTION;local OPTARG;local OPTIND
|
|
|
|
while getopts 'sp:hu:a:r:ek:o:s:l' OPTION; do
|
|
|
|
# echo OPTION $OPTION ARG $OPTARG
|
|
|
|
case "$OPTION" in
|
|
|
|
a)
|
|
|
|
# to put the key at another user on remote. will require sudo on remote
|
|
|
|
kuser="-u $OPTARG"
|
|
|
|
;;
|
|
|
|
u)
|
|
|
|
# user if not explicit from host
|
|
|
|
user=$OPTARG
|
|
|
|
;;
|
|
|
|
p)
|
|
|
|
upass="-p $OPTARG"
|
|
|
|
;;
|
|
|
|
l)
|
|
|
|
list=true
|
|
|
|
;;
|
|
|
|
r)
|
|
|
|
# remove key, must be "comment identifier in public key"
|
|
|
|
rm=$OPTARG
|
|
|
|
;;
|
|
|
|
k)
|
|
|
|
kpath=$OPTARG
|
|
|
|
key=$(getkeyname $kpath)
|
|
|
|
;;
|
|
|
|
o)
|
|
|
|
opts=$OPTARG
|
|
|
|
;;
|
|
|
|
e)
|
|
|
|
dr=""
|
|
|
|
;;
|
|
|
|
h)
|
|
|
|
help
|
|
|
|
;;
|
|
|
|
*)
|
|
|
|
echo unknown option -$OPTARG
|
|
|
|
help
|
|
|
|
# opts="$opts ${@:$OPTIND:1}"
|
|
|
|
# # ((OPTIND+=1))
|
|
|
|
# #echo remaining ${@:$OPTIND}
|
|
|
|
return 1
|
|
|
|
;;
|
|
|
|
esac
|
|
|
|
done
|
2022-03-28 10:05:26 -07:00
|
|
|
|
|
|
|
shift $((OPTIND - 1))
|
|
|
|
|
|
|
|
host=$1
|
2024-02-21 11:33:37 -08:00
|
|
|
shift 1
|
2022-03-28 10:05:26 -07:00
|
|
|
if [[ ! $host ]]; then
|
2024-02-21 11:33:37 -08:00
|
|
|
>&2 echo "no host supplied, aborting"
|
|
|
|
help
|
2022-03-28 10:05:26 -07:00
|
|
|
return 2
|
|
|
|
fi
|
2024-02-21 11:33:37 -08:00
|
|
|
|
|
|
|
# parse ssh arguments from the rest
|
|
|
|
# TODO change to a function to do this
|
|
|
|
if [[ ! $* =~ "--" ]]; then
|
|
|
|
debug $( ( IFS=$','; echo all arguments: "$*" ) )
|
|
|
|
for ((d=1; d<$#; ++d)); do
|
|
|
|
[[ ${!d} == "--" ]] && break
|
|
|
|
done
|
|
|
|
if [[ $d -lt $# ]]; then # if there are extra ssh arguments
|
|
|
|
debug found -- at $d
|
|
|
|
opts=("${@:$d+1:$#}")
|
|
|
|
debug $( ( IFS=$','; echo "ssh arguments: ${opts[*]}" ) )
|
|
|
|
# [[ ! ${sshargs[0]} ]] && { echo missing remote machine, must provide at least a hostname, -- hostname; return 3; }
|
|
|
|
ropts=("${@:1:$d-1}")
|
|
|
|
debug $( ( IFS=$','; echo "remaining arguments to parse: ${ropts[*]}" ) )
|
2022-03-28 10:05:26 -07:00
|
|
|
fi
|
2024-02-21 11:33:37 -08:00
|
|
|
fi
|
2022-03-28 10:05:26 -07:00
|
|
|
|
2024-02-21 11:33:37 -08:00
|
|
|
# if [[ ! $* =~ "--" ]]; then
|
|
|
|
# ropts=$*
|
|
|
|
# else
|
|
|
|
# ropts=$(sed 's/\(.*\)--.*/\1/' <<< "$*")
|
|
|
|
# opts=$(sed 's/.*--\(.*\)/\1/' <<< "$*")
|
|
|
|
# fi
|
|
|
|
|
|
|
|
debug KEY $key, HOST $host
|
|
|
|
debug ssh run opts ${ropts[*]}
|
|
|
|
debug additional ssh opts ${opts[*]}
|
2022-03-28 10:05:26 -07:00
|
|
|
|
|
|
|
# TODO add run remote function to ssh and this won't be required
|
2024-02-21 11:33:37 -08:00
|
|
|
# module_load array
|
|
|
|
# declare -a ret
|
|
|
|
# scmd="ssh -r ${ropts} ${host}"
|
|
|
|
# # echo "$cmd"
|
|
|
|
# String::split ret "$($scmd)" ,
|
|
|
|
# host=${ret[0]}; opts+=${ret[1]}; local sshpass=${ret[2]}
|
|
|
|
# # echo "$host;$opts;$sshpass"
|
|
|
|
# scmd="$sshpass $(which ssh) $opts $host"
|
2022-03-28 10:05:26 -07:00
|
|
|
|
2024-02-21 11:33:37 -08:00
|
|
|
user=${user:-$(get_user_host $host)}
|
|
|
|
[[ ! $user ]] && >&2 echo "unable to determine remote user, aborting" && return 2
|
2022-03-28 10:05:26 -07:00
|
|
|
|
2024-02-21 11:33:37 -08:00
|
|
|
# rfcmd () (
|
|
|
|
# local fn
|
|
|
|
# fn=$1
|
|
|
|
# shift 1
|
|
|
|
# echo "bash -c '$(declare -f $fn); $fn $*'"
|
|
|
|
# )
|
2022-03-28 10:05:26 -07:00
|
|
|
|
|
|
|
run () (
|
2024-02-21 11:33:37 -08:00
|
|
|
local func; local _sudo
|
|
|
|
func=$1; shift
|
|
|
|
if [[ "${kuser}" =~ "root" ]]; then
|
|
|
|
kuser=""
|
|
|
|
_sudo=-s
|
|
|
|
fi
|
|
|
|
remote_script $_sudo $kuser -x $func $host "$@" -- $upass
|
2022-03-28 10:05:26 -07:00
|
|
|
)
|
|
|
|
|
2022-05-02 10:40:07 -07:00
|
|
|
# echo remote user: $user
|
|
|
|
|
2024-02-21 11:33:37 -08:00
|
|
|
# if [[ $kuser ]]; then
|
|
|
|
# _sudo="echo '${supass}' | sudo -u ${kuser} --stdin"
|
|
|
|
# fi
|
2022-05-02 10:40:07 -07:00
|
|
|
|
|
|
|
if [[ $list ]]; then
|
|
|
|
run list_keys
|
|
|
|
return $?
|
|
|
|
fi
|
|
|
|
|
2022-03-28 10:05:26 -07:00
|
|
|
if [[ $rm ]]; then
|
|
|
|
############# REMOVE PUBLIC KEY #################
|
2022-05-02 10:40:07 -07:00
|
|
|
# todo allow removeall without access to public key
|
|
|
|
echo ">>>>> removing public key: \"$rm\" from ${kuser:-$user}"
|
|
|
|
[[ ! $dr ]] && replace=" -i"
|
|
|
|
run rm_key $replace $rm
|
|
|
|
return $?
|
|
|
|
fi
|
|
|
|
|
2022-12-31 23:29:20 -08:00
|
|
|
vkey=$(catpubkey $kpath) # get actaul content of public key
|
|
|
|
[[ $? -gt 0 ]] && echo no valid public key for $key at $kpath found && return 4
|
|
|
|
|
2024-02-21 11:33:37 -08:00
|
|
|
# ## Alternate remote user?
|
|
|
|
# if [[ $kuser ]]; then
|
|
|
|
# [[ ! $supass ]] && { echo remote user, $user, password must be supplied for sudo. use -s;return 7; }
|
|
|
|
# fi
|
2022-05-02 10:40:07 -07:00
|
|
|
|
|
|
|
if [[ $key ]] ; then
|
2022-03-28 10:05:26 -07:00
|
|
|
############## ADD PUBLIC KEY ########################
|
|
|
|
echo ">>>>>> sending key $key to remote user ${kuser:-$user}"
|
|
|
|
run cpy_key $vkey
|
2022-05-02 10:40:07 -07:00
|
|
|
return $?
|
2022-03-28 10:05:26 -07:00
|
|
|
fi
|
2022-05-02 10:40:07 -07:00
|
|
|
|
2022-03-28 10:05:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function cpy_key () {
|
|
|
|
|
|
|
|
vkey=$*
|
|
|
|
if [[ $(cat $HOME/.ssh/authorized_keys | grep "$vkey") ]]; then
|
|
|
|
echo key $key already in authorized_keys for remote user $USER
|
|
|
|
else
|
|
|
|
echo -e "\nInstalling key for $USER"
|
|
|
|
echo -e "\n############ appending key to -s$HOME/.ssh/authorized_keys ############"
|
|
|
|
cat $HOME/.ssh/authorized_keys
|
|
|
|
echo "###########################"
|
|
|
|
# echo "#################### adding ####################"
|
|
|
|
# echo $vkey
|
|
|
|
# echo "#################################################"
|
|
|
|
|
|
|
|
if [[ ! -f $HOME/.ssh/authorized_keys ]]; then
|
|
|
|
mkdir $HOME/.ssh >/dev/null 2>&1
|
|
|
|
touch $HOME/.ssh/authorized_keys >/dev/null 2>&1
|
|
|
|
chmod 600 $HOME/.ssh/authorized_keys >/dev/null 2>&1
|
|
|
|
ls -la $HOME/.ssh/authorized_keys
|
|
|
|
fi
|
|
|
|
|
|
|
|
echo "$vkey" >> $HOME/.ssh/authorized_keys
|
|
|
|
ls -la $HOME/.ssh/authorized_keys
|
|
|
|
echo "******** updated authorized_keys for $USER *******************"
|
|
|
|
cat $HOME/.ssh/authorized_keys
|
|
|
|
echo "******************************************************"
|
|
|
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
function rm_key () {
|
2022-05-02 10:40:07 -07:00
|
|
|
local kname; local replace; local found
|
2022-03-28 10:05:26 -07:00
|
|
|
[[ $1 = "-i" ]] && { replace=$1; shift 1; }
|
2022-05-02 10:40:07 -07:00
|
|
|
kname=$*
|
|
|
|
echo ""
|
2022-03-28 10:05:26 -07:00
|
|
|
if [[ ! -f $HOME/.ssh/authorized_keys ]]; then
|
|
|
|
echo no $HOME/authorized_keys file nothing to remove
|
2022-05-02 10:40:07 -07:00
|
|
|
else
|
|
|
|
# found=$(sed "\,$kname$,p" $HOME/.ssh/authorized_keys)
|
|
|
|
found=$(cat $HOME/.ssh/authorized_keys | grep "${kname}$")
|
|
|
|
if [[ $found ]]; then
|
2022-03-28 10:05:26 -07:00
|
|
|
echo key found in authorized_keys, removing...
|
2022-05-02 10:40:07 -07:00
|
|
|
echo "$found"
|
2022-03-28 10:05:26 -07:00
|
|
|
if [[ $replace ]]; then
|
|
|
|
echo "********updated authorized_keys file for $USER *******************"
|
2022-05-02 10:40:07 -07:00
|
|
|
sed $replace "\,$kname$,d" $HOME/.ssh/authorized_keys
|
2022-03-28 10:05:26 -07:00
|
|
|
cat $HOME/.ssh/authorized_keys
|
|
|
|
echo "******************************************************"
|
2022-05-02 10:40:07 -07:00
|
|
|
else
|
|
|
|
echo "--- this is a dry run by default ---"
|
|
|
|
echo "--- if you are SURE this is the key you want removed"
|
|
|
|
echo "--- run again with -e to actaully remove this key ---"
|
|
|
|
echo "!!! REMOVING THE WRONG KEY MAY RESULT IN LOOSING ACCESS TO THE MACHINE !!!"
|
2022-03-28 10:05:26 -07:00
|
|
|
fi
|
|
|
|
else
|
2022-05-02 10:40:07 -07:00
|
|
|
echo no key $kname found in the authorized_keys, nothing to remove
|
2022-03-28 10:05:26 -07:00
|
|
|
fi
|
|
|
|
fi
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2022-05-02 10:40:07 -07:00
|
|
|
function list_keys () {
|
|
|
|
echo "********authorized_keys file for user: $USER at host: $HOSTNAME *******************"
|
|
|
|
cat $HOME/.ssh/authorized_keys
|
|
|
|
echo "******************************************************"
|
|
|
|
}
|
|
|
|
|
2022-03-28 10:05:26 -07:00
|
|
|
|