#!/bin/bash usage(){ cat << EOF Usage: ssh-agent-start-or-restart [[-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 } createonly=false tokenonly=false readd=false keyonly=false remove=false while :; do case $1 in -c|--create-only) createonly=true shift ;; -t|--token-only) tokenonly=true shift ;; -k|--key-only) keyonly=true shift ;; -r|-f|--readd-token|--force) readd=true shift ;; --rm|--remove) remove=true shift ;; -h|--info) usage exit 0 ;; -*) echo "Unknown urgument: »$1«" exit 1 ;; *) #ssh_identity=${1-${SSH_DEFAULT_IDENTITY}} ssh_identity=${1} break ;; esac done SCRIPTENTRY [ -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; } logdebug "SSH_AGENTS_DIR: $SSH_AGENTS_DIR" >&2 logdebug "SSH_AGENT_SOCKETS_DIR: $SSH_AGENT_SOCKETS_DIR" >&2 logdebug "SSH_IDENTITIES_DIR: $SSH_IDENTITIES_DIR" >&2 logdebug "ssh-identität: $ssh_identity" >&2 [ -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" agent-start-or-restart () { ENTRY local ssh_identity local agentfile local agentsocket local ret if [ -n "${1+x}" ]; then ssh_identity="$1" identitydir=${SSH_IDENTITIES_DIR}/${ssh_identity} if [ -d ${identitydir} ]; then [ -e "${identitydir}/config" ] && . "${identitydir}/config" agentfile="${SSH_AGENTS_DIR}/agent-${ssh_identity}-$(hostname)" agentsocket="${SSH_AGENT_SOCKETS_DIR}/socket-${ssh_identity}-$(hostname)" logtrace "agentfile: $agentfile" >&2 logtrace "agentsocket: $agentsocket" >&2 logdebug "SSH_AGENT_OPTIONS: $SSH_AGENT_OPTIONS" if (! $keyonly && ! $tokenonly ) && $remove ; then loginfo "delete keys and tokens in ssh-agent $agentsocket" loginfo "$(ssh-runinagent $agentfile ssh-add -D 2>&1)" createonly=true else if [ -e $agentfile ]; then local msg # TODO make in runinagent msg="$(/bin/sh -c "unset SSH_AUTH_SOCK SSH_AGENT_PID; . $agentfile >/dev/null 2>&1; ssh-add -l 2>&1")" local ret=$? logtrace "$msg" case $ret in 0) loginfo "agent is running" >&2 ;; 1) #logwarn "command failed on ssh-agent" #logwarn "Output: $msg" loginfo "agent is running, but:" >&2 logwarn "$msg" ;; 2) loginfo "former agent is not running -> start it" >&2 [ -e $agentsocket ] && { logdebug -n "remove socketfile: $( rm -v "$agentsocket" )"; } logdebug "$(ssh-agent -a $agentsocket ${SSH_AGENT_OPTIONS} > $agentfile )" loginfo "agent started" >&2 ;; esac else loginfo "agent did not exist -> create it" >&2 #rm "$agentsocket" logdebug "ssh-agent -a $agentsocket \> $agentfile" logdebug "$(ssh-agent -a $agentsocket $SSH_AGENT_OPTIONS > $agentfile )" loginfo "agent started" >&2 fi fi logdebug "ssh-agent for identity »$ssh_identity«: $agentfile" $createonly && logdebug "current loaded keys after action: $(ssh-runinagent $agentfile ssh-add -l)" echo $agentfile ret=0 else logwarn "ssh-identity »$ssh_identity« is not configured. Please create $identitydir and add keys" ret=2 fi else if which gnome-keyring-daemon >/dev/null 2>&1; then loginfo "no identity given -> gnome-keyrings ssh-agent" agentfile="${SSH_AGENTS_DIR}/agent-gnome_session-$(hostname)" agentsocket="${SSH_AGENT_SOCKETS_DIR}/socket-gnome-session-$(hostname)" gnome-keyring-daemon -s > $agentfile logdebug "ssh-agent for identity »$ssh_identity«: $agentfile" logdebug "currently loaded keys after action: $(ssh-runinagent $agentfile ssh-add -l)" echo $agentfile ret=0 else logwarn "no identity given -> exit" ret=1 fi fi EXIT return $ret } agent-load-identity-keys () { ENTRY local ssh_identity local agentfile local agentsocket local fingerprints declare -a fingerprints local fingerprint local tokenfingerprint if [ -n "${1+x}" ]; then ssh_identity="$1" identitydir=${SSH_IDENTITIES_DIR}/${ssh_identity} if [ -d ${identitydir} ]; then [ -e "${identitydir}/config" ] && . "${identitydir}/config" agentfile="${SSH_AGENTS_DIR}/agent-${ssh_identity}-$(hostname)" agentsocket="${SSH_AGENT_SOCKETS_DIR}/socket-${ssh_identity}-$(hostname)" loginfo "ssh-identität: $ssh_identity" >&2 logdebug "SSH_ADD_OPTIONS: $SSH_ADD_OPTIONS" logtrace "agentfile: $agentfile" >&2 logtrace "agentsocket: $agentsocket" >&2 logtrace "identitydir: $identitydir" fingerprints=( $(ssh-runinagent $agentfile "ssh-add -l|awk '{print \$2}'") ) logdebug "fingerprints from loaded keys before action:" for f in ${fingerprints[*]};do logdebug "$f" done if ! $tokenonly ; then for key in $(ls ${SSH_IDENTITIES_DIR}/${ssh_identity}/id_*|grep -v "pub$\|so$\|config$\|public$"); do fingerprint=$(ssh-keygen -l -f $key|awk '{print $2}') if [[ ${fingerprints[*]} =~ "$fingerprint" ]]; then logdebug "key: $(basename $key) (with fp $fingerprint) is loaded" >&2 if $readd || $remove ; then $readd && logwarn "readd key $key" >&2 $remove && logwarn "remove key $key" >&2 loginfo "$(ssh-runinagent $agentfile ssh-add ${SSH_ADD_OPTIONS} -d ${key} 2>&1)" $remove || loginfo "$(ssh-runinagent $agentfile ssh-add ${SSH_ADD_OPTIONS} ${key} 2>&1)" fi else logwarn "key: $key is not loaded -> load it" >&2 #loginfo "$(ssh-runinagent $agentfile ssh-add ${SSH_ADD_OPTIONS} -d ${key} 2>&1)" $remove || loginfo "$(ssh-runinagent $agentfile ssh-add ${SSH_ADD_OPTIONS} ${key} 2>&1)" fi done fi if ! $keyonly ; then for token in $(ls ${SSH_IDENTITIES_DIR}/${ssh_identity}/*|grep "\.so$"); do tokenfingerprint="$(ssh-keygen -l -D $token|tr -s ' '|awk '{print $2}')" if [[ ${fingerprints[*]} =~ "$tokenfingerprint" ]]; then logdebug "token: $token ($fingerprint) is loaded" >&2 if $readd || $remove ; then $readd && logwarn "readd token $token" >&2 $remove && logwarn "remove token $token" >&2 loginfo "$(ssh-runinagent $agentfile ssh-add ${SSH_ADD_OPTIONS} -e ${token} 2>&1)" $remove || loginfo "$(ssh-runinagent $agentfile ssh-add ${SSH_ADD_OPTIONS} -s ${token} 2>&1)" fi else logwarn "token: $token is not loaded -> load it" >&2 loginfo "$(ssh-runinagent $agentfile ssh-add ${SSH_ADD_OPTIONS} -e ${token} 2>&1)" $remove || loginfo "$(ssh-runinagent $agentfile ssh-add ${SSH_ADD_OPTIONS} -s ${token} 2>&1)" fi done fi logdebug "currently loaded keys after action: $(ssh-runinagent $agentfile ssh-add -l)" else logwarn "ssh-identity $ssh_identity is not configured. Please create $identitydir and add keys" fi fi EXIT } ssh-runinagent () { ENTRY local agentfile local command local agentfile=${1} shift local sshcommand=${@} logtrace "run command »$sshcommand« in agent $agentfile" >&2 if [ -e "$agentfile" ]; then /bin/sh -c "unset SSH_AUTH_SOCK SSH_AGENT_PID; . $agentfile >/dev/null 2>/dev/null; $sshcommand" ret=$? else logwarn "agentfile not existent" >&2 ret=99 fi EXIT return $ret } agent-start-or-restart $ssh_identity ! $createonly && agent-load-identity-keys $ssh_identity SCRIPTEXIT exit $?