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,40 +1,103 @@
#!/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/' <<< "$@")
help() {
cat <<EOF
usage: remote_script <remote_script options> host script <script args> -- <ssh script options>
host and script are required, script can be either path to a file containing a script to a UCI module
-s, execute remote script using sudo
-f, run a function in the passed script, otherwise script is assumed to be bash executed.
-d, dry run. don't run the rscript just output the command that will be run
-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 OPTION
local OPTARG local OPTARG
local OPTIND local OPTIND
while getopts 'u:s:f:p:' OPTION; do while getopts 'hdu:sf:p:x:' OPTION; do
# echo OPTION $OPTION ARG $OPTARG INDX $OPTIND # echo OPTION $OPTION ARG $OPTARG INDX $OPTIND
case "$OPTION" in case "$OPTION" in
s) s)
# script filename to run # using sudo, password will come from ssh user password or if you supply it with -p
file=$OPTARG 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
# will force running as root on remote if ruser is not specified
supass=$OPTARG 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
@ -42,56 +105,68 @@ local OPTION
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) host=$1;
[[ ! $file ]] && { echo no module or script at $file to run; return 1; } [[ ! $host ]] && echo fatal: no host was passed unable to excute a remote script && return 3
user=$(get_user_host $host)
[[ ! $user ]] && echo fatal: unable to determine user at host $host, aborting remote script && return 4
hostname=$(get_hostname_host $host)
shift 1
# script can come from
if [[ $rfn ]]; then
if ! declare -f $rfn >/dev/null; then
if ! module_load $2; then
[[ -f $2 ]] && source $2
fi fi
if ! declare -f $rfn >/dev/null; then echo fatal: remote-script, unable to source funtion $rfn, aborting; return 1; fi
# remaining script arguments shift
args=$*
# echo arguments for script: $args
script=$file
# if script loads a module then use bundler
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 fi
local file
local _sudo script=$(mkrfilename temp_function)
if [[ $user ]]; then declare -f $rfn > $script
[[ ! $supass ]] && { echo password must be supplied for connecting sudo account. use -s;return 7; } cfn="-f $rfn"
# echo running script remotely as user $user
_sudo="echo '${supass}' | sudo --stdin -u ${user} 2>/dev/null"
else else
script=$2
shift 1
fi
[[ ! -f $script ]] && echo fatal: must pass a script to remote run && help && return 1
debug echo host: $host user: $user hostname:$hostname script:$script function to run: $cfn
bscript=$(mkrfilename bundle_script )
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 if [[ $supass ]]; then
_sudo="echo '${supass}' | sudo --stdin 2>/dev/null" usesudo="echo '${supass}' | sudo -u ${ruser:-root} --stdin 2>/dev/null"
# echo running script remotely as root echo remote script to be run as ${ruser:-root} using sudo
fi
fi fi
src="$(cat $script);" debug remote script arguments $(remote_args "$@")
if [[ $fn ]]; then debug ssh arguments $(remote_args "${sshargs[@]}")
# echo running function
cmd="bash -c '$src $fn ${args[*]}'" 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
[[ ${args} ]] && sargs="$(printf '%s\n' "set -- ${args}"); "
cmd="bash -c '$sargs $src'"
fi 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,46 +1,115 @@
#!/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
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 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
[[ ! $DPATH ]] && >&2 echo fatal: scp requires a destination file path && return 1
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 fi
# echo DHOST $DHOST DDIR $DDIR
[[ $DHOST && $SHOST && (! $DHOST = "$SHOST") ]] && { echo full remote copy must be same hosts; return 2; } [[ $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
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 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}) cmd="ssh -r ${sshargs[*]} ${DHOST:-$SHOST}"
String::split ret "$($cmd)" ,
local host=${ret[0]}; local sshopts=${ret[1]}; local sshpass=${ret[2]}
[[ -d $SPATH && ! $SHOST ]] && args+=(" -r")
# todo test remote to local copy
local cmd="$sshpass scp ${args[*]} $sshopts $([[ $SHOST ]] && echo "${host}:")$SPATH $([[ $DHOST ]] && echo "${host}:")$DPATH"
# echo $cmd # echo $cmd
String::split ret "$(ssh -r ${SOPTS} ${DHOST:-$SHOST})" , if $([[ $dr ]] && echo "echo ") $cmd; then
local host=${ret[0]}; local opts=${ret[1]}; local sshpass=${ret[2]} debug copy success
debug $(ssh ${sshargs[*]} ${DHOST:-$SHOST} ls -la $DPATH)
[[ -d $SDIR && ! $SHOST ]] && OPTS+=" -r" else
if [[ $SHOST ]]; then >&2 echo remote copy failed
[[ $(ssh $SOPTS $SHOST test -d $SDIR ) ]] && OPTS+=" -r" >&2 echo $cmd
return 1
fi fi
local cmd="$sshpass scp $opts $OPTS $([[ $SHOST ]] && echo "${host}:")$SDIR $([[ $DHOST ]] && echo "${host}:")$DDIR"
echo $cmd
$cmd
return 0
} }

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,25 +70,41 @@ 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
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 # echo OPTION $OPTION ARG $OPTARG
case "$OPTION" in case "$OPTION" in
a) a)
# to put the key at another user on remote. will require sudo on remote # to put the key at another user on remote. will require sudo on remote
kuser=$OPTARG kuser="-u $OPTARG"
;; ;;
u) u)
# user if not explicit from host # user if not explicit from host
user=$OPTARG user=$OPTARG
;; ;;
s) p)
supass=$OPTARG upass="-p $OPTARG"
;; ;;
l) l)
list=true list=true
@ -106,8 +123,12 @@ sshpubkey () {
e) e)
dr="" dr=""
;; ;;
h)
help
;;
*) *)
echo unknown option -$OPTARG echo unknown option -$OPTARG
help
# opts="$opts ${@:$OPTIND:1}" # opts="$opts ${@:$OPTIND:1}"
# # ((OPTIND+=1)) # # ((OPTIND+=1))
# #echo remaining ${@:$OPTIND} # #echo remaining ${@:$OPTIND}
@ -119,63 +140,76 @@ sshpubkey () {
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
# TODO change to a function to do this
if [[ ! $* =~ "--" ]]; then if [[ ! $* =~ "--" ]]; then
ropts=$* debug $( ( IFS=$','; echo all arguments: "$*" ) )
else for ((d=1; d<$#; ++d)); do
ropts=$(sed 's/\(.*\)--.*/\1/' <<< "$*") [[ ${!d} == "--" ]] && break
opts=$(sed 's/.*--\(.*\)/\1/' <<< "$*") 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 fi
# echo KEY $key # if [[ ! $* =~ "--" ]]; then
# echo HOST $host # ropts=$*
# echo ROPTS $ropts # else
# echo OPTS $opts # 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 # TODO add run remote function to ssh and this won't be required
module_load array # module_load array
declare -a ret # declare -a ret
scmd="ssh -r ${ropts} ${host}" # scmd="ssh -r ${ropts} ${host}"
# echo "$cmd" # # echo "$cmd"
String::split ret "$($scmd)" , # String::split ret "$($scmd)" ,
host=${ret[0]}; opts+=${ret[1]}; local sshpass=${ret[2]} # host=${ret[0]}; opts+=${ret[1]}; local sshpass=${ret[2]}
# echo "$host;$opts;$sshpass" # # echo "$host;$opts;$sshpass"
scmd="$sshpass $(which ssh) $opts $host" # scmd="$sshpass $(which ssh) $opts $host"
user=${user:-$(get_user_host $host)}
[[ ! $user ]] && >&2 echo "unable to determine remote user, aborting" && return 2
if [[ ! $user ]]; then # rfcmd () (
if [[ $host =~ "@" ]]; then # local fn
user=$(sed 's/\(.*\)@.*/\1/' <<< "$host") # fn=$1
else # shift 1
user=$(ssh_config_get -u $host) # echo "bash -c '$(declare -f $fn); $fn $*'"
[[ ! $user ]] && user=${DEFAULT_USER:-ubuntu} # )
fi
fi
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