#!/bin/bash _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 } #example: # initial xfer of pubkey with a password # sshpubkey host -- # 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 export SSH_PUB_KEYS module_load path module_load net-utils module_load remote sshpubkey () { # echo default pub key dir: $SSH_PUB_KEYS local kname=id_rsa local user local opts;local dr="true";local rm; local ropts local vkey; local kuser; local host; local upass; local replace local _sudo; local list; help() { cat < host -- -a, put the key at another user on remote. if you want to put it to root use 'root' will require remote sudo -u, remote user if not available in host -s, sudo password for remote if needed -k, 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, 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 shift $((OPTIND - 1)) host=$1 shift 1 if [[ ! $host ]]; then >&2 echo "no host supplied, aborting" help return 2 fi # 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[*]}" ) ) fi fi # 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[*]} # TODO add run remote function to ssh and this won't be required # 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" user=${user:-$(get_user_host $host)} [[ ! $user ]] && >&2 echo "unable to determine remote user, aborting" && return 2 # rfcmd () ( # local fn # fn=$1 # shift 1 # echo "bash -c '$(declare -f $fn); $fn $*'" # ) run () ( local func; local _sudo func=$1; shift if [[ "${kuser}" =~ "root" ]]; then kuser="" _sudo=-s fi remote_script $_sudo $kuser -x $func $host "$@" -- $upass ) # echo remote user: $user # if [[ $kuser ]]; then # _sudo="echo '${supass}' | sudo -u ${kuser} --stdin" # fi if [[ $list ]]; then run list_keys return $? fi if [[ $rm ]]; then ############# REMOVE PUBLIC KEY ################# # 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 vkey=$(catpubkey $kpath) # get actaul content of public key [[ $? -gt 0 ]] && echo no valid public key for $key at $kpath found && return 4 # ## Alternate remote user? # if [[ $kuser ]]; then # [[ ! $supass ]] && { echo remote user, $user, password must be supplied for sudo. use -s;return 7; } # fi if [[ $key ]] ; then ############## ADD PUBLIC KEY ######################## echo ">>>>>> sending key $key to remote user ${kuser:-$user}" run cpy_key $vkey return $? fi } 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 () { local kname; local replace; local found [[ $1 = "-i" ]] && { replace=$1; shift 1; } kname=$* echo "" if [[ ! -f $HOME/.ssh/authorized_keys ]]; then echo no $HOME/authorized_keys file nothing to remove else # found=$(sed "\,$kname$,p" $HOME/.ssh/authorized_keys) found=$(cat $HOME/.ssh/authorized_keys | grep "${kname}$") if [[ $found ]]; then echo key found in authorized_keys, removing... echo "$found" if [[ $replace ]]; then echo "********updated authorized_keys file for $USER *******************" sed $replace "\,$kname$,d" $HOME/.ssh/authorized_keys cat $HOME/.ssh/authorized_keys echo "******************************************************" 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 !!!" fi else echo no key $kname found in the authorized_keys, nothing to remove fi fi } function list_keys () { echo "********authorized_keys file for user: $USER at host: $HOSTNAME *******************" cat $HOME/.ssh/authorized_keys echo "******************************************************" }