Skip to content

Instantly share code, notes, and snippets.

@Ralnoc
Last active March 25, 2022 23:23
Show Gist options
  • Save Ralnoc/e894708bac2ff1083b49 to your computer and use it in GitHub Desktop.
Save Ralnoc/e894708bac2ff1083b49 to your computer and use it in GitHub Desktop.
SSH Agent Management Bash Command
## SSH-Agent Manager
# Command list:
# sagent new - Generate new ssh-agent instance
# sagent [list] - List all ssh-agent instances along with keys they have loaded
# sagent <number> - Select ssh-agent instance based on number shown in sagent list
# sagent add </path/to/keyfile> - Add ssh key to currently selected ssh-agent
# sagent purgedead - Remove files related to dead ssh-agent instances
# Find existing sockets and store them in file_list
function sshagent_findsockets {
file_list=()
while IFS= read -r file ; do
file_list=("${file_list[@]}" "$file")
done < <(find /tmp -uid $(id -u) -type s -name agent.\* -printf "%T@ %Tc %p\n" 2>/dev/null | sort -n | awk '{print $9}')
}
# Print details of each socket in file_list
function sshagent_socketdetails {
for agentsocket in ${!file_list[@]} ; do
sshagent_testsocket ${file_list[$agentsocket]}
if [ "$?" -eq "0" ]; then
export SSH_AUTH_SOCK=${file_list[$agentsocket]}
if [ "$SSH_AUTH_SOCK" == "$TMP_SSH_AUTH_SOCK" ]; then
printf " *%s) SSH Agent [%s]: \n" "$agentsocket" "${file_list[$agentsocket]}"
else
printf " %s) SSH Agent [%s]: \n" "$agentsocket" "${file_list[$agentsocket]}"
fi
while read -r ssh_key ; do
printf " %s\n" "$ssh_key"
done <<< $(ssh-add -L | cut -d' ' -f 1,3)
unset SSH_AUTH_SOCK
unset ssh_key
fi
done
}
# Delete dead sockets in file_list
function sshagent_purgesockets {
for agentsocket in ${!file_list[@]} ; do
sshagent_testsocket ${file_list[$agentsocket]}
if [ "$?" -eq "4" ]; then
rm -rf ${file_list[$agentsocket]}
printf "Deleted Agent [%s]: \n" "${file_list[$agentsocket]}"
fi
done
}
# Select socket from file_list or explicitly
function sshagent_selectsocket {
IS_NUM='^[0-9]+$'
if [ ! -x "$(which ssh-add)" ] ; then
echo "ssh-add is not available; agent testing aborted"
return 1
fi
if [[ "$1" =~ $IS_NUM ]] ; then
export SSH_AUTH_SOCK=${file_list[$1]}
else
if [ X"$1" != X ] ; then
export SSH_AUTH_SOCK=$1
fi
fi
if [ X"$SSH_AUTH_SOCK" = X ] ; then
return 2
fi
if [ -S $SSH_AUTH_SOCK ] ; then
ssh-add -l > /dev/null
if [ $? = 2 ] ; then
echo "Socket $SSH_AUTH_SOCK is dead! Deleting!"
rm -f $SSH_AUTH_SOCK
unset SSH_AGENT_PID
unset SSH_AUTH_SOCK
return 4
else
echo "ssh-agent $SSH_AUTH_SOCK"
return 0
fi
else
echo "$SSH_AUTH_SOCK is not a socket!"
rm -f $SSH_AUTH_SOCK
unset SSH_AGENT_PID
unset SSH_AUTH_SOCK
return 3
fi
}
# Test if actually an active socket
function sshagent_testsocket {
if [ ! -x "$(which ssh-add)" ] ; then
echo "ssh-add is not available; agent testing aborted"
return 1
fi
if [ X"$1" != X ] ; then
export SSH_AUTH_SOCK=$1
fi
if [ X"$SSH_AUTH_SOCK" = X ] ; then
return 2
fi
if [ -S $SSH_AUTH_SOCK ] ; then
ssh-add -l > /dev/null
if [ $? = 2 ] ; then
echo "Socket $SSH_AUTH_SOCK is dead!"
unset SSH_AGENT_PID
unset SSH_AUTH_SOCK
return 4
else
unset SSH_AGENT_PID
unset SSH_AUTH_SOCK
return 0
fi
else
echo "$SSH_AUTH_SOCK is not a socket!"
unset SSH_AGENT_PID
unset SSH_AUTH_SOCK
return 3
fi
}
# Primary command function
function sshagent_init {
IS_NUM='^[0-9]+$'
SSH_CHOICE=$1
TMP_SSH_AUTH_SOCK=$SSH_AUTH_SOCK
unset SSH_AUTH_SOCK
# ssh agent sockets can be attached to a ssh daemon process or an
# ssh-agent process.
AGENTFOUND=0
if [ "${SSH_CHOICE,,}" = "new" ]; then
exec ssh-agent $SHELL
unset TMP_SSH_AUTH_SOCK
return
fi
if [ "${SSH_CHOICE,,}" = "add" ]; then
if [ -n "$TMP_SSH_AUTH_SOCK" ]; then export SSH_AUTH_SOCK=$TMP_SSH_AUTH_SOCK ; fi
ssh-add $2
return
fi
if [ "${SSH_CHOICE,,}" = "list" ]; then
sshagent_findsockets
echo "SSH Agents Found:"
sshagent_socketdetails
if [ -n "$TMP_SSH_AUTH_SOCK" ]; then export SSH_AUTH_SOCK=$TMP_SSH_AUTH_SOCK ; fi
return
fi
if [ "${SSH_CHOICE,,}" = "purgedead" ]; then
sshagent_findsockets
sshagent_purgesockets
return
fi
if [[ -n "${SSH_CHOICE}" ]] && ! [[ "${SSH_CHOICE}" =~ $IS_NUM ]]; then
echo "ERROR: ${SSH_CHOICE} is not a valid option."
return
fi
if [[ -z "${SSH_CHOICE}" ]]; then
sshagent_findsockets
echo "SSH Agents Found:"
sshagent_socketdetails
if [ -n "$TMP_SSH_AUTH_SOCK" ]; then export SSH_AUTH_SOCK=$TMP_SSH_AUTH_SOCK ; fi
return
fi
# If there is no agent in the environment, search /tmp for
# possible agents to reuse before starting a fresh ssh-agent
# process.
if [ $AGENTFOUND = 0 ] ; then
sshagent_findsockets
if [ -n "${SSH_CHOICE}" ]; then
if sshagent_selectsocket ${SSH_CHOICE} ; then AGENTFOUND=1 ; fi
fi
if [ -z "${SSH_CHOICE}" ] ; then
echo "SSH Agents Found:"
sshagent_socketdetails
fi
fi
if [ -n "$TMP_SSH_AUTH_SOCK" ] && [ -z "$SSH_AUTH_SOCK" ]; then
export SSH_AUTH_SOCK=$TMP_SSH_AUTH_SOCK
fi
# Finally, show what keys are currently in the agent
if [ $AGENTFOUND = 1 ] ; then
ssh-add -L | cut -d' ' -f 1,3
else
echo "No SSH agent selected."
fi
# Clean up
unset agentsocket
unset file_list
unset TMP_SSH_AUTH_SOCK
unset AGENTFOUND
unset SSH_CHOICE
}
alias sagent="sshagent_init"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment