From 8f7759285eb19619e070b9be672d16b195026fa6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakobus=20Sch=C3=BCrz?= Date: Thu, 3 Aug 2023 16:36:38 +0200 Subject: [PATCH] add new script for agentmanagement --- bin/sshstartagent | 277 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 277 insertions(+) create mode 100755 bin/sshstartagent diff --git a/bin/sshstartagent b/bin/sshstartagent new file mode 100755 index 0000000..4c45287 --- /dev/null +++ b/bin/sshstartagent @@ -0,0 +1,277 @@ +#!/bin/bash + +FILELOGLEVEL=DEBUG +DEFAULT_SOCKET_REMOTE=~/.ssh/ssh_from_remote_auth_sock +. $(dirname $0)/../logging +# loggerfactory +LANG=C + +usage(){ + cat << EOF + + Usage: $(basename $0) [[-c]|[--create-only]]|[[-t]|[--token-only]]|[[-k]|[--key-only]]|[[-r]|[-f]|[--readd]|[--force]] [] + + If started only with , the script looks up in configured identity-path \$SSH_IDENTITIES_DIR (${SSH_IDENTITIES_DIR}) if it can find a directory named after . + If no is given, the identity is set to \$SSH_DEFAULT_IDENTITY ($SSH_DEFAULT_IDENTITY) configured via Environment. + IF \$SSH_DEFAULT_IDENTITY is also not set, default is the SSH_DEFAULT_IDENTITY + + The output is the name of the file, where ssh-agent infomations are hold to load it to current shell for further actions. + Use "$ eval \$()", if you want to load the SSH_AUTH_SOCK and SSH_AGENT_PID in current shell or shorter "$ loadagent []" + + -c|--create-only Create or restart only the agent. Do not load any + key or token in it. + The Output is used for loading the agent in the current + shell. (loadagent ) + -t|--token-only To add or renew only configured pkcs11-hardware-token + configured in ${SSH_IDENTITIES_DIR}/, + just use this. + -k|--key-only To add or renew only configured keys configured in + ${SSH_IDENTITIES_DIR}/, just use this. + -r|-f|--readd-token|--force remove all in ${SSH_IDENTITIES_DIR}/ + configured keys and tokens and readd them again. + Depends on -t an -k Option to select wheter only + keys or tokens only. If no -t and -k is given, all + keys and token are removed and readded again. + Just to be asked for password again, if you plugged off + hardware-token and plugged it in again. + --rm|--remove remove keys and token instead of adding them. + -h|--info Show this info + + +EOF +} + +create_filenamebase() { + printf "%s" "${ssh_identity}-$(hostname)" +} + +create_agentfilename() { + printf "%s" "${SSH_AGENTS_DIR}/agent-$(create_filenamebase)" +} + +create_socketfilename() { + printf "%s" "${SSH_AGENT_SOCKETS_DIR}/socket-$(create_filenamebase)" +} + +ssh_runinagent() { + + local SSH_AUTH_SOCK + local SSH_AGENT_PID + local agentfile + local command + local agentfile=${1} + shift + local sshcommand=${@} + + logtrace "run command »$sshcommand« in agent $agentfile" + if [ -e "$agentfile" ]; then + /bin/sh -c "unset SSH_AUTH_SOCK SSH_AGENT_PID; \ + . $agentfile >/dev/null 2>/dev/null; \ + $sshcommand" + ret=$? + else + logwarning "agentfile not existent" + ret=99 + fi + + return $ret + +} + +set_and_load_identity_config() { + + # check if idendity directory an file config exists in it. + # if it exist, source it + ssh_identity="${1}" + ssh_identity_dir="${SSH_IDENTITIES_DIR}/${ssh_identity}" + loginfo "ssh-identity: ${ssh_identity_dir}" + if [ -d ${ssh_identity_dir} ]; then + loginfo "Directory identity-dir ${ssh_identity_dir} exists. Use it" + else + logwarning "Directory identity-dir ${ssh_identity_dir} does not exist. Use default-config" + ssh_identity=default + ssh_identity_dir="${SSH_IDENTITIES_DIR}/${ssh_identity}" + fi + + if [ -e "${ssh_identity_dir}/config" ]; then + logdebug "source ${ssh_identity_dir}/config" + unset SSH_AUTH_SOCK SSH_AGENT_PID PKCS11_MODULE SSH_AGENT_ALLOW_FROM_REMOTE SSH_ADD_OPTION + . "${ssh_identity_dir}/config" + fi + +} + +start_or_restart_local_agent() { + if [ -e "${ssh_agentfile}" ] + then + logdebug "agentfile ${ssh_agentfile} exists" + eval $(<$ssh_agentfile) >/dev/null 2>&1 + logdebug "SSH_AUTH_SOCK: ${SSH_AUTH_SOCK:-not set}" + logdebug "SSH_AGENT_PID: ${SSH_AGENT_PID:-not set}" + logdebug "PKCS11_MODULE: ${PKCS11_MODULE:-not set}" + for i in $(pgrep -f ${SSH_AUTH_SOCK}) + do + logdebug "found pid: $i" + [ -n "${SSH_AGENT_PID:+x}" ] \ + && [ $i -eq ${SSH_AGENT_PID} ] \ + || { logwarning "kill unused ssh-agent with pid $i"; kill $i; } + done + case $(pgrep -f ${SSH_AUTH_SOCK}|wc -l) in + 0) + logdebug "no ssh-agents for file ${ssh_socketfile}" + ret=2 + ;; + 1) + logdebug "one running agent for file ${ssh_socketfile}. Use it" + msg="$(ssh_runinagent $ssh_agentfile "ssh-add -l 2>&1")" + ret=$? + ;; + *) + logdebug "more than one ssh-agents for file ${ssh_socketfile}" + return 3 + ;; + esac + logdebug "ret: $ret" + #msg="$(ssh-add -l 2>&1)" + logtrace "Output from check for running agent: $msg" + case $ret in + 0) + logdebug "agent is running" + ;; + 1) + logdebug "agent is running, but:" + logwarning "$msg" + ;; + 2|99) + logdebug "former agent is not running -> start it" + logdebug "remove socketfile: $( rm -v -f "$ssh_socketfile" )" + logdebug "remove agentfile: $( rm -v -f "$ssh_agentfile" )" + ;; + esac + else + logdebug "ssh_agentfile ${ssh_agentfile} does not exist" + fi + logdebug "SSH_AGENT_OPTIONS: $SSH_AGENT_OPTIONS" + logtrace "$(ssh-agent -a $ssh_socketfile ${SSH_AGENT_OPTIONS} > $ssh_agentfile )" + logdebug "PKCS11_MODULE: ${PKCS11_MODULE:-not set}" + sed '/^PKCS11_MODULE/d' ${ssh_agentfile} + [ -n "${PKCS11_MODULE:+x}" ] && logdebug "add PKCS11_MODULE to ${ssh_agentfile}" + [ -n "${PKCS11_MODULE:+x}" ] && echo "PKCS11_MODULE=$PKCS11_MODULE; export PKCS11_MODULE" >> ${ssh_agentfile} + logdebug "agent started" + +} + + +check_and_link_socket() { + + if ${SSH_AGENT_ALLOW_FROM_REMOTE:-false} + then + logdebug "Remote agent allowed." + if [ -e ${DEFAULT_SOCKET_REMOTE} ] + then + logdebug "Link remote socket to ${ssh_socketfile}" + ln -f -s $(readlink -f ${DEFAULT_SOCKET_REMOTE}) ${ssh_socketfile} + [ -e ~/.ssh/p11m ] && . ~/.ssh/p11m + logdebug "Write new agentfile ${ssh_agentfile}" + cat << EOF > ${ssh_agentfile} +SSH_AUTH_SOCK=$ssh_socketfile; export SSH_AUTH_SOCK; +${P11M:+PKCS11_MODULE=${P11M}; export PKCS11_MODULE} +EOF + else + logdebug "Use local agent" + start_or_restart_local_agent + fi + else + logdebug "Only local agent allowed" + if [ -L ${ssh_socketfile} ] + then + logdebug "${ssh_socketfile} is symlinked to $(readlink -f ${ssh_socketfile}). Remove it" + rm ${ssh_socketfile} + else + if [ -e ${ssh_socketfile} -a $(pgrep -f ${ssh_socketfile} >/dev/null 2>&2; echo $?) ] + then + logdebug "Socket and agent for ${ssh_socketfile} are up and a running agent exist. Use it" + else + logdebug "No agent for socket ${ssh_socketfile} or socket does not exist, remove both if possible" + rm -f ${ssh_socketfile} + pkill -f ${ssh_socketfile} + fi + + fi + start_or_restart_local_agent + fi + +} + +load_or_reload_identities() { + + logdebug "Now load all identities for $ssh_identitiy from $ssh_identity_dir" + logdebug "PKCS11_MODULE: ${PKCS11_MODULE:-not set}" + +} + +################################################## +SCRIPTENTRY + +createonly=false +tokenonly=false +readd=false +keyonly=false +remove=false +while :; do + case $1 in + -c|--create-only) + createonly=true + shift + ;; + -h|--info) + usage + exit 0 + ;; + -*) + echo "Unknown urgument: »$1«" >&2 + exit 1 + ;; + *) + #ssh_identity=${1-${SSH_DEFAULT_IDENTITY}} + ssh_identity=${1} + break + ;; + esac +done +[ -z "${SSH_IDENTITIES_DIR+x}" ] && { SSH_IDENTITIES_DIR="${SSH_IDENTITIES_DEFAULT_DIR-${HOME}/.ssh/identities}"; export SSH_IDENTITIES_DIR; } +[ -z "${SSH_AGENTS_DIR+x}" ] && { SSH_AGENTS_DIR=${SSH_AGENTS_DEFAULT_DIR-~/.ssh/agents}; export SSH_AGENTS_DIR; } +[ -z "${SSH_AGENT_SOCKETS_DIR+x}" ] && { SSH_AGENT_SOCKETS_DIR=${SSH_AGENT_SOCKETS_DEFAULT_DIR-~/.ssh/agents}; export SSH_AGENT_SOCKETS_DIR; } +[ -z "${SSH_AGENT_OPTIONS+x}" ] && { SSH_AGENT_OPTIONS=${SSH_AGENT_DEFAULT_OPTIONS--t 7200 }; export SSH_AGENT_OPTIONS; } +logtrace " SSH_AGENTS_DIR: $SSH_AGENTS_DIR" +logtrace "SSH_AGENT_SOCKETS_DIR: $SSH_AGENT_SOCKETS_DIR" +logtrace " SSH_IDENTITIES_DIR: $SSH_IDENTITIES_DIR" +[ -z "${SSH_AGENTS_DIR-x}" ] || mkdir -vp "$SSH_AGENTS_DIR" +[ -z "${SSH_AGENT_SOCKETS_DIR-x}" ] || mkdir -vp "$SSH_AGENT_SOCKETS_DIR" +[ -z "${SSH_IDENTITIES_DIR-x}" ] || mkdir -vp "$SSH_IDENTITIES_DIR" + + +set_and_load_identity_config ${1} +loginfo " SSH_ADD_OPTIONS=${SSH_ADD_OPTIONS:-not set}" +loginfo "SSH_AGENT_ALLOW_FROM_REMOTE=${SSH_AGENT_ALLOW_FROM_REMOTE:-not set}" +loginfo " PKCS11_MODULE=${PKCS11_MODULE:-not set}" +loginfo " P11M=${P11M:-not set}" +loginfo " SSH_AUTH_SOCK=${SSH_AUTH_SOCK:-not set}" +loginfo " SSH_AUTH_SOCK_REMOTE=${SSH_AUTH_SOCK_REMOTE:-not set}" + +ssh_agentfile=$(create_agentfilename) +ssh_socketfile=$(create_socketfilename) +logdebug "AGENT: ${ssh_agentfile}" +logdebug "SOCKET: ${ssh_socketfile}" + +[ -e $ssh_agentfile ] && eval $(<$ssh_agentfile) >&2 +check_and_link_socket +load_or_reload_identities +$createonly && printf "%s" "${ssh_agentfile}" +logdebug "cat ${ssh_agentfile} +$(cat ${ssh_agentfile})" + + +SCRIPTEXIT +loginfo "return with $res" +exit $res