Docu review done: Mon 03 Jul 2023 17:13:12 CEST
Table of content
General
This small snippet should help you in your (work) live.
Often admins have to ssh with a different user and gather then higher permissions, e.g. by using sudo
or thinks like that.
sshc
want to make that a bit easier for you, buy performing the connection and becoming any other user (e.g. root) for you.
And it is the older brother of sshc
Requirements
To make use of ssht
, you some applications or functions are needed in your system
tmux
- Password store with CLI access e.g.
pass
- Being able to generate a list of hosts you want to ssh and fetch passwords e.g. your
~/.ssh/config
Installation
The installation is as simple as it can be (expected that you have tmux
, pwd store and your host list already in place.
Go to a place on your system where you store your .rc
files which get sourced by your shell
and either add there a new file or copy/past the below functions into an existing one.
The function below expects that your ssh host list comes from ~/.ssh/config
, if you dont have it like that, just search for it and replace it with the commands you need.
############################################
#
# TMUX ssh root login
#
function _tmux_login_usage() {
echo "-l <local tmux socket name> # as it says"
echo "-t <tmux connection string> # <session>:<window>(.<pane>)"
echo "-s <ssh remote server> # as it says"
echo "-p <match string> # string that is shown when requesting pwd (default: 'Password:')"
echo "-P <absolut path to pwd bin> # defines the absolutpath to the binary for fetching the pwd"
echo "-h # hows this help"
return 64
}
function tmux_login() {
local optstring="l:t:s:p:P:h"
tmux_socket_name=""
tmux_connect=""
ssh_server_name=""
pwd_question_matcher="Password:"
password_bin=""
while getopts ${optstring} c; do
case ${c} in
l) tmux_socket_name="${OPTARG}" ;;
t) tmux_connect="${OPTARG}" ;;
s) ssh_server_name="${OPTARG}" ;;
p) pwd_question_matcher="${OPTARG}" ;;
P) password_bin="${OPTARG}" ;;
h) _tmux_login_usage ; return 64 ;;
*) _tmux_login_usage ; return 64 ;;
esac
done
local pw
if pw=$("${password_bin}" "${ssh_server_name}") ; then
while_counter=20
while [[ $(tmux -L "${tmux_socket_name}" capture-pane -p -t "${tmux_connect}" | grep -v "^$" | tail -n 1) != "${pwd_question_matcher}" ]]; do
if (( while_counter > 0 )); then
sleep 0.3
let while_counter-=1
else
return 1
fi
done
&>/dev/null tmux -L "${tmux_socket_name}" send-keys -t "${tmux_connect}" "$pw" C-m
&>/dev/null tmux -L "${tmux_socket_name}" send-keys -t "${tmux_connect}" "printf '\033]2;${ssh_server_name}\033\\'" C-m
&>/dev/null tmux -L "${tmux_socket_name}" send-keys -t "${tmux_connect}" "printf '\033]2;${ssh_server_name}\033\\' ; clear" C-m
else
echo "failed to get pwd for ${ssh_server_name}"
fi
}
function _ssht_compl_zsh() {
compadd ${=${${${${${(f)"$(cat ~/.ssh/config(n) /dev/null)"}##[A-Z][a-z]* }## *[A-Z][a-z]* *}%%[# ]*}%%--*}//,/ }
}
function _ssht_compl_bash() {
if [ "${#COMP_WORDS[@]}" != "2" ]; then
return
fi
local IFS=$'\n'
local suggestions=($(compgen -W "$(sed -E '/^Host +[a-zA-Z0-9]/!d;s/Host //g' ~/.ssh/config | sort -u)" -- "${COMP_WORDS[1]}"))
if [ "${#suggestions[@]}" == "1" ]; then
local onlyonesuggestion="${suggestions[0]/%\ */}"
COMPREPLY=("${onlyonesuggestion}")
else
for i in "${!suggestions[@]}"; do
suggestions[$i]="$(printf '%*s' "-$COLUMNS" "${suggestions[$i]}")"
done
COMPREPLY=("${suggestions[@]}")
fi
}
function _ssht() {
server="${1}"
pane_nr="$(( ( RANDOM % 9999 ) + 1 ))"
sub_nr="$(( ( RANDOM % 9999 ) + 1 ))"
password_bin="<DEFAULT PWD FETCH COMMAND>"
if ! [ -x "${password_bin}" ]; then
echo "${password_bin} has no execution permission or does not exist on FS"
return 1
fi
( &>/dev/null tmux_login -s "${server}" -t "${pane_nr}:${sub_nr}" -l "ssh_root_sessions" -P "${password_bin}" & )
&>/dev/null tmux -L ssh_root_sessions -f ~/.tmux_ssh.conf new -s "${pane_nr}" -n ${sub_nr} "ssh -q -t ${server} \"su -\""
}
current_shell="$(ps -o comm -p $$ | tail -1)"
alias ssht="_ssht"
if [[ "${current_shell}" == "zsh" ]]; then
compdef _ssht_compl_zsh _ssht
elif [[ "${current_shell}" == "bash" ]]; then
complete -F _ssht_compl_bash ssht
fi
As an well trained engineer, you saw ofcourse that a different tmux
config was used, ~/.tmux_ssh.conf
Why do we load an additional tmux
config?
Easy to say, this ensures that mod+b
gets unset, so if you run tmux
on the destination server you will controle the remote one and not yours.
It will also sets alertings to inform the shell/terminal about alerts, the status bar will be removed to have the full view of your terminal and the scallback buffer got increased.
Also the title is getting enabled, as the above function will replace it so that your terminal title gets the hostname from the server. This can help you for faster switching to the open connection for example.
This is what it contains:
#tmux source-file .tmux_ssh.conf
unbind C-b
#Set alert if something happens
setw -g monitor-activity on
set -g visual-activity on
# scrollback buffer n lines
set -g history-limit 99999
# enable wm window titles
set -g set-titles on
# center align the window list
set -g status off
# Enable mouse mode to avoide scroll back issues
set -g mouse off
Now the time has tome to source it to your .rc
file.
Usage
To use it, you just have to run ssht
followed either by <tab><tab>
or type the full or beginning of the hostname + tab till you have the full name displayed in your shell.
Guess what, now just hit the enter key ;)
You will see that it cleans the output of your terminal (because it starts tmux
).
After that you will find on the to something like “Password:” which will disapear and you will get a shell on the remote host as root user.
When you close now the connection, it will look like before you perfmored the ssht
command.
And we are done.
If you want to know how the tab completion works, have a look at