Major refactor upgrades for remote scripting and access via ssh

ssh-copy now uses options and has help and uses new helpers to prepare the scp command
remote module totally redone.  now uses sshcp (scp) to copy the file
   makes use of the much improved bundle function for bundling script
now that remote_script is refactored can use for
ssh-pub-key
and for the uci remote install function
cleaned up ssh function a bit
add parsing functions to net-utils for parsing host
master
David Kebler 2024-02-21 11:33:37 -08:00
parent c45418d313
commit a67d54e9dc
20 changed files with 653 additions and 290 deletions

View File

@ -1,39 +0,0 @@
#!/bin/bash
# assumes that bash is installed
#!/bin/bash
# must! be run as sudo
install_shell_base () {
# TODO have a cross distro package install
[[ ! $(which git) ]] && echo git must be installed first && return 1
[[ ! $EUID -eq 0 ]] && { echo ERROR script must be run as root; return 2; }
mkdir -p /shell/base
git clone https://git.kebler.net/bash/shell-base.git /shell/base
chown -R ${1:-$1000}:${1:-1000} /shell
chmod -R +r /shell
/bin/bash /shell/base/install/install.sh ${1:-$1000}
}
# remote_install_shell_base -r <remote host> <sudo pass if host not root> <user to install, default is $USER>
# module_load install-shell-base && remote_install_shell_base -r newboxr
remote_install_shell_base () {
module_load remote
local supass;local user
if [[ $1 == "-r" ]]; then
shift 1;
user=$2;
else
[[ ! $2 ]] && { echo sudo password for remote user required; return 2; }
supass="-p $2"
user=$3
fi
remote_script $supass install-shell-base $user -- $1
}
# # if script was executed then call the function
(return 0 2>/dev/null) || install_shell_base $@
# example
# $ module_load install-shell-base
# $ remote_install_shell_base -r portabler david

View File

@ -0,0 +1,30 @@
#!/bin/bash
# assumes that bash is installed
#!/bin/bash
# must! be run as sudo
install_shell_base () {
# TODO have a cross distro package install
module_load distro
set_distro
[[ ! $(command -v git) ]] && echo git must be installed first && $INSTALL_PKGS git
# TODO, avoid which in all scripts. or put which in environment if not on machine
[[ ! $(command -v which) ]] && echo 'which' must be installed first && $INSTALL_PKGS which
echo $USER, $EUID
[[ ! $EUID -eq 0 ]] && { echo ERROR script must be run as root; return 2; }
echo I am ROOT, now running script
echo UCI user: $1
# TODO make the repo and clone values dynamic or bundle current base on sending machine a archive
mkdir -p /shell/base
git clone https://git.kebler.net/bash/shell-base.git /shell/base
chown -R ${1:-$1000}:${1:-1000} /shell
chmod -R +r /shell
/bin/bash /shell/base/install/install.sh ${1:-1000}
}
# # if script was executed then call the function
( return 0 2>/dev/null ) || install_shell_base $@

View File

@ -37,26 +37,36 @@ lookup_host () {
# usage: lookup_host hostname < configfile > # usage: lookup_host hostname < configfile >
local config; local host; local lhost local config; local host; local lhost
config=$([[ $2 ]] && echo $2 || echo ${SSH_CONFIG:-$HOME/.ssh/config}) config=$([[ $2 ]] && echo $2 || echo ${SSH_CONFIG:-$HOME/.ssh/config})
host=$(parse_host $1) host=$(get_hostname_host $1)return
lhost=$(ssh -F $config -G $host | grep -w hostname | cut -d' ' -f2) lhost=$(ssh -F $config -G $host | grep -w hostname | cut -d' ' -f2)
[[ $lhost ]] && echo $lhost || echo $host [[ $lhost ]] && echo $lhost || echo $host
} }
parse_host () { get_hostname_host () {
# usage: parse_host <user/host> # usage: get_hostname_host <user/host>
# returns extracted host if passed user@host # returns extracted host if passed user@host
# otherwise return value passed # otherwise return value passed
[[ $1 =~ "@" ]] && { echo $(sed 's/.*@\(.*\)/\1/' <<< "$1");return 0; } # [[ $1 =~ "@" ]] && { echo $(sed 's/.*@\(.*\)/\1/' <<< "$1");return 0; }
echo $1 local hostname
return 1 hostname=$(cut -s -d@ -f2 <<< "$1")
if [[ ! $hostname ]] && type ssh_config_get &>/dev/null ; then
hostname=$(ssh_config_get -h $1)
fi
[[ $hostname ]] && echo $hostname || return 1
} }
parse_user () { get_user_host () {
# usage: parse_user <user/host> # [[ $1 =~ "@" ]] && { echo $(sed 's/\(.*\)@.*/\1/' <<< "$1"); return 0; } || return 1
# usage: get_user_host <user/host>
# returns extracted user if passed user@host # returns extracted user if passed user@host
# otherwise returns nothing # otherwise returns nothing
# return 1 no user in string # return 1 no user in string
[[ $1 =~ "@" ]] && { echo $(sed 's/\(.*\)@.*/\1/' <<< "$1"); return 0; } || return 1 local user
user=$(cut -s -d@ -f1 <<< "$1")
if [[ ! $user ]] && type ssh_config_get &>/dev/null ; then
user=$(ssh_config_get -u $1)
fi
[[ $user ]] && echo $user || return 1
} }

13
modules/nomachine.lib Normal file
View File

@ -0,0 +1,13 @@
/usr/NX/etc/server.cfg
sed
#AcceptedAuthenticationMethods all
to
AcceptedAuthenticationMethods NX-private-key
restrat the server
sdr nxserver
copy a public key to ~/.nx/config/authorized.crt

View File

@ -1,97 +1,172 @@
#!/bin/bash #!/bin/bash
module_load ssh module_load ssh
module_load bundle
module_load helpers
module_load ssh-copy
remote_function () {
[[ $2 ]] && module_load $2
if declare -f $1; then
local file
file=$(mkrfilename function)
$(declare -f $1) > $file
echo $file
else
>&2 echo fatal: unable to source funtion $1, aborting
return 1
fi
}
remote_script () { remote_script () {
# usage: remote_script script -- <ssh setup options> host <ssh options>
# see ssh function
#
local sshargs;local user;local supass;local fn;local args;local file
[[ "$*" =~ "--" ]] && sshargs=$(sed 's/.*--\(.*\)/\1/' <<< "$@") local sshargs;local user;local supass;local cfn; local rfn; local args;
[[ ! $sshargs ]] && { echo missing remote machine, must provide at least a hostname, -- hostname; return 3; } local script; local host; local dr; local supass
# reset arguments to just those before -- local hostname; local bscript; local ruser; local usesudo
set -- $(sed 's/\(.*\)--.*/\1/' <<< "$@")
local OPTION help() {
local OPTARG
local OPTIND cat <<EOF
while getopts 'u:s:f:p:' OPTION; do usage: remote_script <remote_script options> host script <script args> -- <ssh script options>
# echo OPTION $OPTION ARG $OPTARG INDX $OPTIND host and script are required, script can be either path to a file containing a script to a UCI module
case "$OPTION" in -s, execute remote script using sudo
s) -f, run a function in the passed script, otherwise script is assumed to be bash executed.
# script filename to run -d, dry run. don't run the rscript just output the command that will be run
file=$OPTARG -u, remote user to run script as. default is ssh host user or root if using sudo
;; -p, password for ssh login, will also be used for sudo assuming remote user is in sudo group
-x, create script from available function instead of module or file
-h, this help text
EOF
}
# parse ssh arguments from the rest
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
sshargs=("${@:$d+1:$#}")
debug $( ( IFS=$','; echo "ssh arguments: ${sshargs[*]}" ) )
# [[ ! ${sshargs[0]} ]] && { echo missing remote machine, must provide at least a hostname, -- hostname; return 3; }
args=("${@:1:$d-1}")
# reset script arguments to just those before --
set -- "${args[@]}"
debug $( ( IFS=$','; echo remaining arguments to parse: "$*" ) )
fi
# parse remote_script options
local OPTION
local OPTARG
local OPTIND
while getopts 'hdu:sf:p:x:' OPTION; do
# echo OPTION $OPTION ARG $OPTARG INDX $OPTIND
case "$OPTION" in
s)
# using sudo, password will come from ssh user password or if you supply it with -p
usesudo=true
;;
f) f)
# run a function within the script # run a function within the script
fn=$OPTARG # any function arguments appear after script
;; cfn="-f $OPTARG"
;;
d)
# dry run
dr=true
;;
u) u)
# run command as another user # run remote command as another user
user=$OPTARG ruser=$OPTARG
# usesudo=true
;;
x)
rfn=$OPTARG
;; ;;
p) p)
# password of sudo account for running as root or other user # password of sudo account for running as root or other user
supass=$OPTARG # will force running as root on remote if ruser is not specified
;; supass=$OPTARG
;;
h)
help
return 0
;;
*) *)
echo unknown remote script option -$OPTARG >&2 echo fatal: unknown remote script option $OPTION, aborting
help
return 1 return 1
;; ;;
esac esac
done done
shift $((OPTIND - 1)) shift $((OPTIND - 1))
[[ ! $file ]] && { file=$1;shift 1; } [[ $# -lt 1 ]] && echo fatal: remote_script requires a 'host' && help && return 1
if [[ ! -f $file ]]; then
file=$(module_find $file)
[[ ! $file ]] && { echo no module or script at $file to run; return 1; }
fi
# remaining script arguments host=$1;
args=$* [[ ! $host ]] && echo fatal: no host was passed unable to excute a remote script && return 3
# echo arguments for script: $args user=$(get_user_host $host)
[[ ! $user ]] && echo fatal: unable to determine user at host $host, aborting remote script && return 4
script=$file hostname=$(get_hostname_host $host)
# if script loads a module then use bundler shift 1
if [[ $(cat $script | grep module_load) ]]; then
# echo bundling modules with script
local temp
module_load bundle
script=$( mktemp -t TEMP_FILE_script.XXXXXXXX )
bundle $file $script
temp=true
fi
local _sudo # script can come from
if [[ $user ]]; then if [[ $rfn ]]; then
[[ ! $supass ]] && { echo password must be supplied for connecting sudo account. use -s;return 7; } if ! declare -f $rfn >/dev/null; then
# echo running script remotely as user $user if ! module_load $2; then
_sudo="echo '${supass}' | sudo --stdin -u ${user} 2>/dev/null" [[ -f $2 ]] && source $2
else fi
if [[ $supass ]]; then if ! declare -f $rfn >/dev/null; then echo fatal: remote-script, unable to source funtion $rfn, aborting; return 1; fi
_sudo="echo '${supass}' | sudo --stdin 2>/dev/null" shift
# echo running script remotely as root
fi fi
fi local file
script=$(mkrfilename temp_function)
declare -f $rfn > $script
cfn="-f $rfn"
else
script=$2
shift 1
fi
[[ ! -f $script ]] && echo fatal: must pass a script to remote run && help && return 1
src="$(cat $script);" debug echo host: $host user: $user hostname:$hostname script:$script function to run: $cfn
if [[ $fn ]]; then
# echo running function bscript=$(mkrfilename bundle_script )
cmd="bash -c '$src $fn ${args[*]}'" if ! bundle -c $cfn $script $bscript; then
>&2 echo fatal: remote_script unable to bundle script for sending, aborting; return 1;
fi
[[ $usesudo ]] && supass=$(parse_option "${sshargs[*]}" -p)
if [[ $supass ]]; then
usesudo="echo '${supass}' | sudo -u ${ruser:-root} --stdin 2>/dev/null"
echo remote script to be run as ${ruser:-root} using sudo
fi
debug remote script arguments $(remote_args "$@")
debug ssh arguments $(remote_args "${sshargs[@]}")
rscript=${save:-$(mkrfilename REMOTE_SCRIPT)}
if sshcp -d $host $bscript $rscript -- "${sshargs[@]}"; then
# make remote script excuteable
ssh "${sshargs[@]}" "$host" "chmod +x $rscript"
# run the script
ssh "${sshargs[@]}" "$host" "$usesudo" "$rscript" "$(remote_args "$@")"
# now delete it, save script if passed an explicit name
if ! ssh "${sshargs[@]}" $host rm -f $rscript; then echo unable to delete temporary remote file at $host:$rscript; fi
# ssh "${sshargs[@]}" "$host" "cat $rscript"
else else
# echo running as script >&2 echo fatal: remote_script failed because script could not be copied; return 1;
local sargs fi
[[ ${args} ]] && sargs="$(printf '%s\n' "set -- ${args}"); "
cmd="bash -c '$sargs $src'"
fi
# echo ssh $sshargs "$_sudo" "$cmd" rm -f $bscript
ssh $sshargs "$_sudo" "$cmd" [[ $rfn ]] && [[ "${script}" =~ "temp_function" ]] && rm -f $script
[[ $temp ]]&& rm -f $script
} }
# END REMOTE SCRIPT
# can be used with a file or HEREDOC # can be used with a file or HEREDOC
@ -99,12 +174,10 @@ ssh $sshargs "$_sudo" "$cmd"
remote_stdin () { remote_stdin () {
local file local file
# echo args $@ # echo args $@
file=$( mktemp -t TEMP_FILE_script.XXXXXXXX ) file=$( mkrfilename remote_script )
cat > $file cat > $file
echo remote_script -s "$file" "$@" remote_script $1 "$file" "$@"
#remote_script -s "$file" "$@" rm -f $file &> /dev/null
rm $file
} }
# # if script was executed then call the function # # if script was executed then call the function
@ -112,10 +185,41 @@ rm $file
# sudo rsync --exclude *[C]ache* -e '/usr/bin/ssh -F /home/david/.ssh/_config' --progress -aAru /opt/chromium seldon:/opt # remote_install_shell_base <script options> script command <sudo pass if host not root> <user to install, default is $USER>
remote_install_shell_base () {
module_load remote
remote_copy () { local supass;local user; local host
sudo rsync --exclude *[C]ache* -e '/usr/bin/ssh -F /home/david/.ssh/_config' --progress -aAru /opt/chromium seldon:/opt declare OPTION; declare OPTARG; declare OPTIND
while getopts 's:p:cf:x:' OPTION; do
case "$OPTION" in
p)
#both for login and sudo
upass="-p $OPTARG"
;;
u) user="$OPTARG"
;;
s)
# only for running sudo command for non-root use logged in via sshkey
supass="-p $OPTARG"
;;
*)
echo unknown bundle option $OPTION
;;
esac
done
} shift $(( OPTIND - 1 ))
host=$1
[[ ! $host ]] && >&2 echo remote_install_shell_base requires specifying a host
shift 1
user=${user:-$(get_user_host $host)}
[[ $user == "root" ]] && user="" && >&2 echo warning, will not set up any user than root for UCI shell
[[ ! $user ]] && >&2 echo unable to determin remote user for host $host, aborting && return 1
if [[ $supass ]] && [[ $upass ]]; then >&2 echo specify either -s or -p or neither but not both; return 1; fi
[[ $upass ]] && remote_script -s -f install_shell_base $host install-shell-base $user -- $upass "$@" && return $?
[[ $supass ]] && remote_script $supass -f install_shell_base $host install-shell-base $user -- $upass "$@" && return $?
remote_script -f install_shell_base $host install-shell-base $user -- "$@"
}

View File

@ -183,9 +183,9 @@ ssh_config_get () {
shift $((OPTIND - 1)) shift $((OPTIND - 1))
[[ ! $1 ]] && { echo must pass a config host; return 1; } [[ ! $1 ]] && { >&2 echo must pass a config host; return 1; }
[[ ! $(cat "$SSH_CONFIG" | grep "[Hh]ost" | grep $1) ]] && echo "no host alias $1" && return 2 [[ ! $(cat "$SSH_CONFIG" | grep "[Hh]ost" | grep $1) ]] && >&2 echo "no host alias $1" && return 2
props=$($ssh $1) props=$($ssh $1)
[[ $all ]] && { echo "$props"; return 0; } [[ $all ]] && { echo "$props"; return 0; }

View File

@ -1,45 +1,114 @@
#!/bin/bash #!/bin/bash
# usage: module_load ssh
# sshcp src dest <ssh run opts> -- <ssh opts> module_load debug
sshcp () { sshcp () {
local SRC=$1 local SHOST; local DHOST; local dr; local sshargs; local args
local DEST=$2 local OPTS; local SOPTS; local SRC; local DEST;
local SHOST; local DHOST local SPATH; local SPATH
local OPTS; local SOPTS
# echo remaining options: $* help() {
shift 2
echo $SRC to $DEST cat <<EOF
if [[ $SRC =~ ":" ]]; then usage:
sshcp <script options> src dest <scp options> -- <ssh options>
-d, destination host
-s, source host
-y, dry run. don't run the rscript just output the command that will be run
-h, this help text
EOF
}
# parse sshcp options
local OPTION
local OPTARG
local OPTIND
while getopts 'd:ys:h' OPTION; do
# echo OPTION $OPTION ARG $OPTARG INDX $OPTIND
case "$OPTION" in
s)
# script filename to run
SHOST=$OPTARG
;;
y)
# dry run
dr=true
;;
d)
# run remote command as another user
DHOST=$OPTARG
;;
h)
help
return 0
;;
*)
>&2 echo fatal: unknown remote script option $OPTION, aborting
help
return 1
;;
esac
done
shift $((OPTIND - 1))
[[ ! $1 ]] && >&2 echo fatal: scp requires a source path to send && return 1
SRC=$1; shift
if [[ $SRC =~ ":" ]]; then
# echo source is remote # echo source is remote
SHOST=$(sed 's/\(.*\):.*/\1/' <<< "$SRC") SHOST=${SHOST:-$(sed 's/\(.*\):.*/\1/' <<< "$SRC")}
SDIR=$(sed 's/.*:\(.*\)/\1/' <<< "$SRC") SPATH=$(sed 's/.*:\(.*\)/\1/' <<< "$SRC")
else else
# echo source is local # echo source is local
SDIR=$SRC SPATH=$SRC
fi fi
# echo SHOST $SHOST SDIR $SDIR
DEST=$1;shift
if [[ $DEST =~ ":" ]]; then if [[ $DEST =~ ":" ]]; then
# echo destination is remote destination is remote
DHOST=$(sed 's/\(.*\):.*/\1/' <<< "$DEST") DHOST=${DHOST:-$(sed 's/\(.*\):.*/\1/' <<< "$DEST")}
DDIR=$(sed 's/.*:\(.*\)/\1/' <<< "$DEST") DPATH=$(sed 's/.*:\(.*\)/\1/' <<< "$DEST")
else else
# echo destination is local DPATH=$DEST
DDIR=$DEST
fi fi
# echo DHOST $DHOST DDIR $DDIR [[ ! $DPATH ]] && >&2 echo fatal: scp requires a destination file path && return 1
[[ $DHOST && $SHOST && (! $DHOST = "$SHOST") ]] && { echo full remote copy must be same hosts; return 2; } if [[ ! $(get_user_host $DHOST) ]] && [[ ! $(get_user_host $SHOST ) ]]; then
>&2 echo fatal: need at least a valid remote source host $SHOST or remote destination host $DHOST, aborting remote copy
return 1
fi
[[ $DHOST && $SHOST && (! $DHOST = "$SHOST") ]] && { echo full remote copy must be same hosts; return 2; }
# echo parse: $*
if [[ ! $* =~ "--" ]]; then # parse ssh arguments from the rest
SOPTS=$* debug $( ( IFS=$','; echo all arguments: "$*" ) )
else for ((d=1; d<$#; ++d)); do
SOPTS=$(sed 's/\(.*\)--.*/\1/' <<< "$*") [[ ${!d} == "--" ]] && break
OPTS=$(sed 's/.*--\(.*\)/\1/' <<< "$*") done
fi
if [[ $d -lt $# ]]; then # if there are extra ssh arguments
debug found -- at $d
sshargs=("${@:$d+1:$#}")
debug $( ( IFS=$','; echo "ssh arguments: ${sshargs[*]}" ) )
# [[ ! ${sshargs[0]} ]] && { echo missing remote machine, must provide at least a hostname, -- hostname; return 3; }
args=("${@:1:$d-1}")
# reset script arguments to just those before --
# set -- "${args[@]}"
debug $( ( IFS=$','; echo remaining arguments to parse: "$*" ) )
fi
# # echo parse: $*
# if [[ ! $* =~ "--" ]]; then
# SOPTS=$*
# else
# SOPTS=$(sed 's/\(.*\)--.*/\1/' <<< "$*")
# OPTS=$(sed 's/.*--\(.*\)/\1/' <<< "$*")
# fi
# echo SOPTS $SOPTS # echo SOPTS $SOPTS
# echo OPTS $OPTS # echo OPTS $OPTS
@ -48,22 +117,25 @@
declare -a ret declare -a ret
# echo ssh -r "$SOPTS" "${DHOST:-$SHOST}" # echo ssh -r "$SOPTS" "${DHOST:-$SHOST}"
# return # return
module_load ssh
cmd=$(ssh -r ${SOPTS} ${DHOST:-$SHOST})
# echo $cmd
String::split ret "$(ssh -r ${SOPTS} ${DHOST:-$SHOST})" ,
local host=${ret[0]}; local opts=${ret[1]}; local sshpass=${ret[2]}
[[ -d $SDIR && ! $SHOST ]] && OPTS+=" -r" cmd="ssh -r ${sshargs[*]} ${DHOST:-$SHOST}"
if [[ $SHOST ]]; then String::split ret "$($cmd)" ,
[[ $(ssh $SOPTS $SHOST test -d $SDIR ) ]] && OPTS+=" -r" local host=${ret[0]}; local sshopts=${ret[1]}; local sshpass=${ret[2]}
fi
[[ -d $SPATH && ! $SHOST ]] && args+=(" -r")
# todo test remote to local copy
local cmd="$sshpass scp $opts $OPTS $([[ $SHOST ]] && echo "${host}:")$SDIR $([[ $DHOST ]] && echo "${host}:")$DDIR" local cmd="$sshpass scp ${args[*]} $sshopts $([[ $SHOST ]] && echo "${host}:")$SPATH $([[ $DHOST ]] && echo "${host}:")$DPATH"
echo $cmd # echo $cmd
$cmd if $([[ $dr ]] && echo "echo ") $cmd; then
return 0 debug copy success
debug $(ssh ${sshargs[*]} ${DHOST:-$SHOST} ls -la $DPATH)
else
>&2 echo remote copy failed
>&2 echo $cmd
return 1
fi
} }

View File

@ -60,7 +60,8 @@ catpubkey () {
export SSH_PUB_KEYS export SSH_PUB_KEYS
module_load path module_load path
module_load ssh module_load net-utils
module_load remote
sshpubkey () { sshpubkey () {
@ -69,113 +70,146 @@ sshpubkey () {
local kname=id_rsa local kname=id_rsa
local user local user
local opts;local dr="true";local rm; local ropts local opts;local dr="true";local rm; local ropts
local vkey; local kuser; local host; local supass; local replace local vkey; local kuser; local host; local upass; local replace
local scmd; local _sudo; local list local _sudo; local list;
local OPTION
local OPTARG
local OPTIND help() {
while getopts 'u:a:r:ek:o:s:l' OPTION; do
# echo OPTION $OPTION ARG $OPTARG cat <<EOF
case "$OPTION" in usage: sshpubkey <pubkey opts> host <ssh run options> -- <more ssh options>
a) -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
# to put the key at another user on remote. will require sudo on remote -u, <user> remote user if not available in host
kuser=$OPTARG -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
u) -l, list the keys for the remote user
# user if not explicit from host -r, remove the key from the user, use the comment identifier of the public key
user=$OPTARG -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
s) -h, this help text
supass=$OPTARG EOF
;;
l) }
list=true local OPTION;local OPTARG;local OPTIND
;; while getopts 'sp:hu:a:r:ek:o:s:l' OPTION; do
r) # echo OPTION $OPTION ARG $OPTARG
# remove key, must be "comment identifier in public key" case "$OPTION" in
rm=$OPTARG a)
;; # to put the key at another user on remote. will require sudo on remote
k) kuser="-u $OPTARG"
kpath=$OPTARG ;;
key=$(getkeyname $kpath) u)
;; # user if not explicit from host
o) user=$OPTARG
opts=$OPTARG ;;
;; p)
e) upass="-p $OPTARG"
dr="" ;;
;; l)
*) list=true
echo unknown option -$OPTARG ;;
# opts="$opts ${@:$OPTIND:1}" r)
# # ((OPTIND+=1)) # remove key, must be "comment identifier in public key"
# #echo remaining ${@:$OPTIND} rm=$OPTARG
return 1 ;;
;; k)
esac kpath=$OPTARG
done 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)) shift $((OPTIND - 1))
host=$1 host=$1
shift 1
if [[ ! $host ]]; then if [[ ! $host ]]; then
echo "no host supplied, aborting" >&2 echo "no host supplied, aborting"
echo "usage: sshpubkey <pubkey opts> host <ssh run options> -- <more ssh options>" help
return 2 return 2
fi fi
shift 1 # parse ssh arguments from the rest
if [[ ! $* =~ "--" ]]; then # TODO change to a function to do this
ropts=$* if [[ ! $* =~ "--" ]]; then
else debug $( ( IFS=$','; echo all arguments: "$*" ) )
ropts=$(sed 's/\(.*\)--.*/\1/' <<< "$*") for ((d=1; d<$#; ++d)); do
opts=$(sed 's/.*--\(.*\)/\1/' <<< "$*") [[ ${!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
# echo KEY $key
# echo HOST $host
# echo ROPTS $ropts
# echo 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"
if [[ ! $user ]]; then
if [[ $host =~ "@" ]]; then
user=$(sed 's/\(.*\)@.*/\1/' <<< "$host")
else
user=$(ssh_config_get -u $host)
[[ ! $user ]] && user=${DEFAULT_USER:-ubuntu}
fi
fi fi
rfcmd () ( # if [[ ! $* =~ "--" ]]; then
local fn # ropts=$*
fn=$1 # else
shift 1 # ropts=$(sed 's/\(.*\)--.*/\1/' <<< "$*")
echo "bash -c '$(declare -f $fn); $fn $*'" # 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 () ( run () (
# echo "$scmd" "$_sudo" local func; local _sudo
# echo "$(rfcmd "$*")" func=$1; shift
$scmd "$_sudo" "$(rfcmd "$*")" if [[ "${kuser}" =~ "root" ]]; then
kuser=""
_sudo=-s
fi
remote_script $_sudo $kuser -x $func $host "$@" -- $upass
) )
# echo remote user: $user # echo remote user: $user
if [[ $kuser ]]; then # if [[ $kuser ]]; then
_sudo="echo '${supass}' | sudo -u ${kuser} --stdin" # _sudo="echo '${supass}' | sudo -u ${kuser} --stdin"
fi # fi
if [[ $list ]]; then if [[ $list ]]; then
run list_keys run list_keys
@ -194,15 +228,14 @@ sshpubkey () {
vkey=$(catpubkey $kpath) # get actaul content of public key vkey=$(catpubkey $kpath) # get actaul content of public key
[[ $? -gt 0 ]] && echo no valid public key for $key at $kpath found && return 4 [[ $? -gt 0 ]] && echo no valid public key for $key at $kpath found && return 4
## Alternate remote user? # ## Alternate remote user?
if [[ $kuser ]]; then # if [[ $kuser ]]; then
[[ ! $supass ]] && { echo remote user, $user, password must be supplied for sudo. use -s;return 7; } # [[ ! $supass ]] && { echo remote user, $user, password must be supplied for sudo. use -s;return 7; }
fi # fi
if [[ $key ]] ; then if [[ $key ]] ; then
############## ADD PUBLIC KEY ######################## ############## ADD PUBLIC KEY ########################
echo ">>>>>> sending key $key to remote user ${kuser:-$user}" echo ">>>>>> sending key $key to remote user ${kuser:-$user}"
echo run command
run cpy_key $vkey run cpy_key $vkey
return $? return $?
fi fi

View File

@ -1,8 +1,8 @@
#!/bin/bash #!/bin/bash
# this will superceed the ssh binary in order to source all the config files # this will superceed the ssh binary in order to source all the config files
# "USAGE: ssh <run/setup options> host <SSH options> <commands to run on remote>" # "USAGE: ssh <ssh script options> <host,can set via -h> <SSH options> <commands to run on remote>"
# put any additional SSH (man ssh) options after the host, aborting"# # put any additional SSH (man ssh) options after the host
# if using ssh in another command use -r flag # if using ssh in another command use -r flag
# this returns a string that can be parsed into an array # this returns a string that can be parsed into an array
@ -23,7 +23,7 @@ module_load ssh-config
ssh() { ssh() {
local pw;local cfg;local opts;local mp; local sshpass; local dr; local sshcmd local pw;local cfg;local opts;local mp; local sshpass; local dr; local sshcmd; local term
local host; local user; local script; local ret ; local key; local efile; local tfile local host; local user; local script; local ret ; local key; local efile; local tfile
if [[ $SSH_CONFIG ]]; then if [[ $SSH_CONFIG ]]; then
@ -34,12 +34,15 @@ ssh() {
# echo passed: $* # echo passed: $*
local OPTION; local OPTARG; local OPTIND local OPTION; local OPTARG; local OPTIND
while getopts ':h:u:mdF:p:ro:k:' OPTION; do while getopts 'th:u:mdF:p:ro:k:' OPTION; do
# echo processing: option:$OPTION argument:$OPTARG index:$OPTIND remaining:${@:$OPTIND} # echo processing: option:$OPTION argument:$OPTARG index:$OPTIND remaining:${@:$OPTIND}
case "$OPTION" in case "$OPTION" in
h) h)
host=$OPTARG host=$OPTARG
;; ;;
t)
term=" -t "
;;
d) d)
dr=true dr=true
;; ;;
@ -99,19 +102,17 @@ ssh() {
[[ (! $host) && $1 ]] && { host=$1;shift; } [[ (! $host) && $1 ]] && { host=$1;shift; }
# echo extra ssh options and the command: $@ debug extra ssh options and the remote commands: $@
# echo host $host
# return
[[ ! $host ]] && echo host/ip required, aborting && return 2 [[ ! $host ]] && echo host/ip required, aborting && return 2
[[ ! $user ]] && user=$(parse_user $host) [[ ! $user ]] && user=$(get_user_host $host)
if [[ $mp ]]; then if [[ $mp ]]; then
user=${user:-ubuntu} user=${user:-ubuntu}
[[ ! $host ]] && echo multipass host/ip required, aborting && return 2 [[ ! $host ]] && echo multipass host/ip required, aborting && return 2
# echo multipass host:$host user:$user # echo multipass host:$host user:$user
module_load multipass module_load multipass
ip="$(multipass_get_ip $(parse_host $host))" ip="$(multipass_get_ip $(get_hostname_host $host))"
[[ ! $ip ]] && echo could not resolve ip for multipass instance $1 && return 5 [[ ! $ip ]] && echo could not resolve ip for multipass instance $1 && return 5
[[ ! $pw && ! $key ]] && opts+=" $(multipass_ssh_options)" [[ ! $pw && ! $key ]] && opts+=" $(multipass_ssh_options)"
host="$user@$ip" host="$user@$ip"
@ -130,10 +131,14 @@ if [[ $ret ]]; then
{ echo "$host,$opts $* ,$sshpass"; return 0; } { echo "$host,$opts $* ,$sshpass"; return 0; }
else else
# run remote commands right here # run remote commands right here
sshcmd="$sshpass $(which ssh) $opts $host" sshcmd="$sshpass $(which ssh) $term $opts $host"
# echo extra args: "$@" # echo extra args: "$@"
# echo running command: "$sshcmd" # echo running command: "$sshcmd"
[[ ! $dr ]] && $sshcmd "$@" || echo SSH Command Failed: $sshcmd "$@" if [[ $dr ]]; then
echo $sshcmd
else
$sshcmd "$@" || echo SSH Command Failed: $sshcmd "$@"
fi
fi fi
} # end ssh } # end ssh

View File

@ -101,7 +101,7 @@ function smount() {
echo "CMD=> $cmd" echo "CMD=> $cmd"
else else
[[ ! $MNTUSER == "_NONE_" ]] && MNTUSER=" as user $MNTUSER " || MNTUSER="" [[ ! $MNTUSER == "_NONE_" ]] && MNTUSER=" as user $MNTUSER " || MNTUSER=""
echo "mounted directory $dir from $(parse_host $host)${MNTUSER}at $MNT" echo "mounted directory $dir from $(get_hostname_host $host)${MNTUSER}at $MNT"
fi fi
fi fi
} }

1
ssh/etc/sshd_config Normal file
View File

@ -0,0 +1 @@
Include /etc/ssh/sshd_config.d/*.conf

View File

@ -0,0 +1,7 @@
PermitRootLogin no
UsePAM yes
KbdInteractiveAuthentication no
PubkeyAuthentication no
KbdInteractiveAuthentication no
PasswordAuthentication no

View File

@ -0,0 +1,3 @@
Match user rsk
X11Forwarding yes

View File

@ -0,0 +1,5 @@
#ubuntu/debian
# Subsystem sftp /usr/lib/openssh/sftp-server
# arch
Subsystem sftp /usr/lib/ssh/sftp-server

View File

@ -0,0 +1,2 @@
DenyUsers <put users here no spaces comma>

View File

@ -0,0 +1,5 @@
# allow only some users from some addresses
Match User <user>,,user> Address 10.10.0.2
PubkeyAuthentication yes
PermitRootLogin prohibit-password

116
ssh/etc/sshd_config.sample Normal file
View File

@ -0,0 +1,116 @@
# $OpenBSD: sshd_config,v 1.104 2021/07/02 05:11:21 dtucker Exp $
# This is the sshd server system-wide configuration file. See
# sshd_config(5) for more information.
# This sshd was compiled with PATH=/usr/local/sbin:/usr/local/bin:/usr/bin
# The strategy used for options in the default sshd_config shipped with
# OpenSSH is to specify options with their default value where
# possible, but leave them commented. Uncommented options override the
# default value.
#Port 22
#AddressFamily any
#ListenAddress 0.0.0.0
#ListenAddress ::
#HostKey /etc/ssh/ssh_host_rsa_key
#HostKey /etc/ssh/ssh_host_ecdsa_key
#HostKey /etc/ssh/ssh_host_ed25519_key
# Ciphers and keying
#RekeyLimit default none
# Logging
#SyslogFacility AUTH
#LogLevel INFO
# Authentication:
#LoginGraceTime 2m
#PermitRootLogin prohibit-password
#StrictModes yes
#MaxAuthTries 6
#MaxSessions 10
#PubkeyAuthentication yes
# The default is to check both .ssh/authorized_keys and .ssh/authorized_keys2
# but this is overridden so installations will only check .ssh/authorized_keys
AuthorizedKeysFile .ssh/authorized_keys
#AuthorizedPrincipalsFile none
#AuthorizedKeysCommand none
#AuthorizedKeysCommandUser nobody
# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
#HostbasedAuthentication no
# Change to yes if you don't trust ~/.ssh/known_hosts for
# HostbasedAuthentication
#IgnoreUserKnownHosts no
# Don't read the user's ~/.rhosts and ~/.shosts files
#IgnoreRhosts yes
# To disable tunneled clear text passwords, change to no here!
#PasswordAuthentication yes
#PermitEmptyPasswords no
# Change to no to disable s/key passwords
KbdInteractiveAuthentication no
# Kerberos options
#KerberosAuthentication no
#KerberosOrLocalPasswd yes
#KerberosTicketCleanup yes
#KerberosGetAFSToken no
# GSSAPI options
#GSSAPIAuthentication no
#GSSAPICleanupCredentials yes
# Set this to 'yes' to enable PAM authentication, account processing,
# and session processing. If this is enabled, PAM authentication will
# be allowed through the KbdInteractiveAuthentication and
# PasswordAuthentication. Depending on your PAM configuration,
# PAM authentication via KbdInteractiveAuthentication may bypass
# the setting of "PermitRootLogin prohibit-password".
# If you just want the PAM account and session checks to run without
# PAM authentication, then enable this but set PasswordAuthentication
# and KbdInteractiveAuthentication to 'no'.
UsePAM yes
#AllowAgentForwarding yes
#AllowTcpForwarding yes
#GatewayPorts no
#X11Forwarding no
#X11DisplayOffset 10
#X11UseLocalhost yes
#PermitTTY yes
PrintMotd no
#PrintLastLog yes
#TCPKeepAlive yes
#PermitUserEnvironment no
#Compression delayed
#ClientAliveInterval 0
#ClientAliveCountMax 3
#UseDNS no
#PidFile /run/sshd.pid
#MaxStartups 10:30:100
#PermitTunnel no
#ChrootDirectory none
#VersionAddendum none
# no default banner path
#Banner none
# override default of no subsystems
Subsystem sftp /usr/lib/ssh/sftp-server
# Example of overriding settings on a per-user basis
#Match User anoncvs
# X11Forwarding no
# AllowTcpForwarding no
# PermitTTY no
# ForceCommand cvs server

View File

@ -1,5 +0,0 @@
# if [[ $- == *i* ]]; then
# anything here will be executed, changing to a directory
# note anything to stdout here may make rsync and other network commands fail
#cd /opt
# fi

View File

@ -1,2 +0,0 @@
*anything in /session will be sourced if this is a remote ssh login session*
you may edit this in place but it's recommended to create an ssh folder in the host name repo instead

3
ssh/ssh.inst Normal file
View File

@ -0,0 +1,3 @@
TODO write a command to copy these to etc/ssh
should save a backup of that directory first
need to run as sudo