Existe-t-il un moyen pratique de s’assurer que toutes les connexions d’un utilisateur donné (c’est-à-dire moi) utilisent le même agent ssh? J'ai piraté un script pour que cela fonctionne la plupart du temps, mais je soupçonnais tout le temps qu'il y avait un moyen de le faire que je venais juste de manquer. De plus, depuis cette époque, la technologie informatique a connu d’énormes progrès, comme par exemple ce site Web.
Donc, le but ici est que
ssh-agent
en cours d'exécution, un est démarré, les variables d'environnement exportées et ssh-add
appelé.Cette fonctionnalité est particulièrement utile lorsque la boîte en question est utilisée comme point de relais lorsque ssh
est inséré dans une troisième boîte. Dans ce cas, cela évite de devoir taper la phrase secrète de la clé privée chaque fois que vous faites ssh puis que vous voulez, par exemple, faire git Push
ou quelque chose d'autre.
Le script donné ci-dessous le fait de manière très fiable, bien qu'il ait échoué récemment lorsque X s'est écrasé et que j'ai ensuite démarré une autre session graphique. Il se peut qu'il y ait eu d'autres problèmes dans ce cas.
Voici mon mauvais scénario. Je source ceci de mon .bashrc
.
# ssh-agent-procure.bash
# v0.6.4
# ensures that all shells sourcing this file in profile/rc scripts use the same ssh-agent.
# copyright me, now; licensed under the DWTFYWT license.
mkdir -p "$HOME/etc/ssh";
function ssh-procure-launch-agent {
eval `ssh-agent -s -a ~/etc/ssh/ssh-agent-socket`;
ssh-add;
}
if [ ! $SSH_AGENT_PID ]; then
if [ -e ~/etc/ssh/ssh-agent-socket ] ; then
SSH_AGENT_PID=`ps -fC ssh-agent |grep 'etc/ssh/ssh-agent-socket' |sed -r 's/^\S+\s+(\S+).*$/\1/'`;
if [[ $SSH_AGENT_PID =~ [0-9]+ ]]; then
# in this case the agent has already been launched and we are just attaching to it.
##++ It should check that this pid is actually active & belongs to an ssh instance
export SSH_AGENT_PID;
SSH_AUTH_SOCK=~/etc/ssh/ssh-agent-socket; export SSH_AUTH_SOCK;
else
# in this case there is no agent running, so the socket file is left over from a graceless agent termination.
rm ~/etc/ssh/ssh-agent-socket;
ssh-procure-launch-agent;
fi;
else
ssh-procure-launch-agent;
fi;
fi;
S'il vous plaît dites-moi qu'il existe un meilleur moyen de le faire. Veuillez également ne pas cocher les incohérences/gaffes (par exemple, mettre des éléments var
dans etc
); Je l'ai écrit il y a quelque temps et j'ai depuis appris beaucoup de choses.
Je pourrais aussi bien ajouter ma propre variation au mélange:
function sshagent_findsockets {
find /tmp -uid $(id -u) -type s -name agent.\* 2>/dev/null
}
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! Deleting!"
rm -f $SSH_AUTH_SOCK
return 4
else
echo "Found ssh-agent $SSH_AUTH_SOCK"
return 0
fi
else
echo "$SSH_AUTH_SOCK is not a socket!"
return 3
fi
}
function sshagent_init {
# ssh agent sockets can be attached to a ssh daemon process or an
# ssh-agent process.
AGENTFOUND=0
# Attempt to find and use the ssh-agent in the current environment
if sshagent_testsocket ; then AGENTFOUND=1 ; 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
for agentsocket in $(sshagent_findsockets) ; do
if [ $AGENTFOUND != 0 ] ; then break ; fi
if sshagent_testsocket $agentsocket ; then AGENTFOUND=1 ; fi
done
fi
# If at this point we still haven't located an agent, it's time to
# start a new one
if [ $AGENTFOUND = 0 ] ; then
eval `ssh-agent`
fi
# Clean up
unset AGENTFOUND
unset agentsocket
# Finally, show what keys are currently in the agent
ssh-add -l
}
alias sagent="sshagent_init"
Et puis à chaque fois que je me connecte, si je souhaite un agent attaché (ce que je ne fais pas toujours), je tape simplement sagent
.
ssh -A [user@]remotehost
Je pense que c'est peut-être ce que vous recherchez. Utilisez le commutateur -A lors de l'exécution de ssh pour transférer votre agent-ssh. Voici un cas d'utilisation:
J'ai un serveur distant qui contient des dépôts Git avec un pointeur distant pointant vers github. Sans un agent ssh exécuté dans une session d'écran, je dois entrer le mot de passe composé pour ma clé afin de faire un "git pull Origin master". Booo! De plus, je dois avoir ma clé privée privée sur le serveur distant - plus Boooo!
Au lieu de cela, le simple fait d'utiliser ssh -A [user@]remotehost
transmet mon agent ssh exécuté localement. Maintenant, je n'ai plus besoin de ma clé privée pour exister même sur l'hôte distant. Je ne crois pas que vous ayez besoin de faire du script avec ssh-agent.
En voici une jolie qui fonctionne aussi dans Cygwin:
SSH_ENV=$HOME/.ssh/environment
function start_agent {
echo "Initialising new SSH agent..."
/usr/bin/ssh-agent | sed 's/^echo/#echo/' > ${SSH_ENV}
echo succeeded
chmod 600 ${SSH_ENV}
. ${SSH_ENV} > /dev/null
/usr/bin/ssh-add;
}
# Source SSH settings, if applicable
if [ -f "${SSH_ENV}" ]; then
. ${SSH_ENV} > /dev/null
#ps ${SSH_AGENT_PID} doesn't work under cywgin
ps -efp ${SSH_AGENT_PID} | grep ssh-agent$ > /dev/null || {
start_agent;
}
else
start_agent;
fi
Ajoutez-le à votre profil .bash ou .bashrc
Source: http://www.cygwin.com/ml/cygwin/2001-06/msg00537.html
Essayez d'utiliser le trousseau, c'est fait pour ça. http://www.gentoo.org/doc/en/keychain-guide.xml
J'ai récemment commencé à utiliser:
https://github.com/ccontavalli/ssh-ident
Tout ce que j'ai à faire est d'ajouter:
alias ssh=/path/to/ssh-ident
Dans mon fichier .bashrc. Le script prend en charge:
Je préfère garder les choses aussi simples que possible: (extrait de ~/.profile
)
check-ssh-agent() {
[ -S "$SSH_AUTH_SOCK" ] && { ssh-add -l >& /dev/null || [ $? -ne 2 ]; }
}
# attempt to connect to a running agent
check-ssh-agent || export SSH_AUTH_SOCK="$(< ~/.tmp/ssh-agent.env)"
# if agent.env data is invalid, start a new one
check-ssh-agent || {
eval "$(ssh-agent -s)" > /dev/null
echo "$SSH_AUTH_SOCK" > ~/.tmp/ssh-agent.env
}
Je n'avais pas pensé à utiliser -a
auparavant, mais cela pourrait être plus simple:
check-ssh-agent || export SSH_AUTH_SOCK=~/.tmp/ssh-agent.sock
check-ssh-agent || eval "$(ssh-agent -s -a ~/.tmp/ssh-agent.sock)" > /dev/null
Dans mon cas, j'ai posh-git installé dans PowerShell et je voulais que cygwin utilise le même agent ssh. J'ai dû faire quelques manipulations de chemin car ils utilisent différents dossiers tmp, et le fichier .env créé était UTF16 avec BOM et CR\LF, donc c'était amusant à gérer. L'ajout de ce qui suit au .bashrc utilisé par cygwin devrait fonctionner:
# Connect to ssh-agent started by posh-git
SSH_AGENT_ENV=$(cygpath "$LOCALAPPDATA\Temp")
if [ -z $SSH_AUTH_SOCK ] && [ -z $SSH_TTY ]; then # if no agent & not in ssh
if [ -f "$SSH_AGENT_ENV/.ssh/SSH_AUTH_SOCK.env" ]; then
AUTH_SOCK=$(iconv -c -f UTF-16LE -t US-ASCII "$SSH_AGENT_ENV/.ssh/SSH_AUTH_SOCK.env" | tr -d '\r\n')
export SSH_AUTH_SOCK="${AUTH_SOCK/\/tmp/$SSH_AGENT_ENV}"
ssh-add -l > /dev/null
if [ $? = 2 ] ; then
echo "Failed to setup posh-git ssh-agent using $AUTH_SOCK"
unset SSH_AUTH_SOCK
else
echo "Found posh-git ssh-agent $AUTH_SOCK"
fi
else #Start new agent if you want (not shared by posh-git)
echo "failed to setup posh-git ssh-agent"
#eval `ssh-agent -s` > /dev/null
fi
fi
Encore un exemple à mettre dans votre fichier .bash_profile immédiatement et demandant d’ajouter votre clé par défaut lors de la connexion. Le transfert n'était pas une option dans mon cas.
do-ssh-agent() {
# function to start the ssh-agent and store the agent details for later logon
ssh-agent -s > ~/.ssh-agent.conf 2> /dev/null
. ~/.ssh-agent.conf > /dev/null
}
# set time a key should be kept in seconds
keyage=3600
if [ -f ~/.ssh-agent.conf ] ; then
. ~/.ssh-agent.conf > /dev/null
ssh-add -l > /dev/null 2>&1
# $?=0 means the socket is there and it has a key
# $?=1 means the socket is there but contains no key
# $?=2 means the socket is not there or broken
stat=$?
if [ $stat -eq 1 ] ; then
ssh-add -t $keyage > /dev/null 2>&1
Elif [ $stat -eq 2 ] ; then
rm -f $SSH_AUTH_SOCK
do-ssh-agent
ssh-add -t $keyage > /dev/null 2>&1
fi
else
do-ssh-agent
ssh-add -t $keyage > /dev/null 2>&1
fi
créer le fichier ~/ssh-agent.sh
agent_out_file="$HOME/ssh-agent.out"
function initialize {
pgrep ssh-agent && kill $(pgrep ssh-agent)
ssh-agent -s > $agent_out_file
. $agent_out_file
}
pgrep ssh-agent
if [ $? -eq 0 ]; then # ssh agent running
ssh-add -l > /dev/null 2>&1
status=$?
if [ $status -eq 0 ]; then # can connect to ssh agent and keys available
echo nothing to do
Elif [ $status -eq 1 ]; then # can connect to ssh agent and no keys available
echo nothing to do
Elif [ $status -eq 2 ]; then # cannot connect to ssh agent
. $agent_out_file
fi
else # ssh agent not running
initialize
fi
inclure le fichier dans .bashrc
. ~/ssh-agent.sh
Voici ma solution, adaptée de https://superuser.com/a/141233/5255 (dans ce fil):
# attempt to connect to a running agent - cache SSH_AUTH_SOCK in ~/.ssh/
sagent()
{
[ -S "$SSH_AUTH_SOCK" ] || export SSH_AUTH_SOCK="$(< ~/.ssh/ssh-agent.env)"
# if cached agent socket is invalid, start a new one
[ -S "$SSH_AUTH_SOCK" ] || {
eval "$(ssh-agent)"
ssh-add -t 25920000 -K ~/.ssh/id_rsa
echo "$SSH_AUTH_SOCK" > ~/.ssh/ssh-agent.env
}
}
C'est quelque chose que j'ai ajouté qui fonctionne pour moi. Il vérifie d'abord si un agent est en cours d'exécution. Dans l'affirmative, il définira les environnements appropriés, sinon, il le créera. Élimine également la création d'agents supplémentaires:
Il suffit de le mettre dans votre .bashrc
function start_agent() {
killall ssh-agent 2> /dev/null
ssh-agent | sed 's/ Agent pid//' > $SSH_ENV
. $SSH_ENV > $SSH_PID_FILE
ssh-add ~/.ssh/bb_readonly_rsa 2> /dev/null
}
mkdir -p "$HOME/.ssh/agent"
SSH_ENV="$HOME/.ssh/agent/env"
SSH_PID_FILE="$HOME/.ssh/agent/pid"
if [[ -e $SSH_PID_FILE ]]; then
SSH_PID=$(< $SSH_PID_FILE)
PROCESS=$(ps -p $SSH_PID -o comm=)
if [[ $PROCESS == 'ssh-agent' ]]; then
. $SSH_ENV > $SSH_PID_FILE
else
start_agent
fi
else
start_agent
fi
Voici mon tour sur ceci. Je ' source ' le script ci-dessous à partir de my . bash_profile :
MYAGENTS=(`pgrep -U $USER -f ^ssh-agent$|sort -n`)
echo "Found ${#MYAGENTS[@]} ssh-agents."
# Let's try to take over the agents, like we do everynight Pinky!
if [[ "${MYAGENTS[@]}" ]];then
KEEPER=${MYAGENTS[0]}
echo KEEPER: $KEEPER
OUTCAST=${MYAGENTS[@]:1}
[[ "$OUTCAST" ]] && { echo "Goodbye agent $OUTCAST"; kill $OUTCAST; }
SSH_AUTH_SOCK=`awk '/tmp\/ssh/ {print $NF}' /proc/$KEEPER/net/unix`
export SSH_AUTH_SOCK;
SSH_AGENT_PID=$KEEPER; export SSH_AGENT_PID;
else
NEWAGENT="`ssh-agent`"
echo $NEWAGENT;
eval $NEWAGENT
fi
ssh-add -l | grep "The agent has no identities" && ssh-add
J'ai aussi une variation sur ce problème, tirée directement de mon .bashrc:
# File for storing SSH agent information
OSH=".agent.${HOSTNAME}"
# Test if an agent file exists
if [ -f ${OSH} ];
# We have one, so let's use it
then eval `cat ${OSH}` >/dev/null
else
# No file exists, so we must spawn a new agent
eval `ssh-agent | tee ${OSH}` >/dev/null
fi
# Try to list agent keys
ssh-add -l &>/dev/null
# Determine the agent status
case $? in
# Current and SSH keys installed, nothing to do here
0) ;;
# Current but no SSH keys installed, so we must add them
1) ssh-add ;;
# Stale, so we must redo from scratch with a new agent, then add keys
*) eval `ssh-agent | tee ${OSH}` >/dev/null && ssh-add ;;
esac
Cette solution stocke une copie des informations sur l'agent SSH dans votre répertoire de base. Si vous avez un répertoire personnel monté automatiquement par NFS qui peut être partagé entre plusieurs hôtes, le nom d'hôte est utilisé comme partie du nom du fichier pour les différencier. Ainsi, la connexion à partir d'une machine n'empêchera pas le fichier d'agent utilisé par une autre.
Comportement:
1) Les premières sessions utilisateur sont invitées à saisir un mot de passe composé.
2) Les deuxième, troisième et quatrième sessions (et cetera) héritent de l'agent SSH et de la ou des clés ajoutées dans la première.
3) Si l'agent est tué ou se bloque, la première session suivante crée un nouvel agent, remplace le fichier d'agent par le nouveau - et invite à nouveau une phrase secrète de clé. Les sessions créées ultérieurement se comporteront comme le scénario 2), tant que le nouvel agent SSH reste en cours d'exécution.
(cela concerne le post 2 plus haut, je n'ai pas pu ajouter de commentaire)
@raghavan: Votre exemple est utile, mais suggérerait de changer les deux lignes qui ont
pgrep ssh-agent
à
pgrep -u $ ssh-agent USER>/dev/null
de sorte que seuls les agents exécutés sous l'utilisateur actuel soient trouvés et que le pid ne soit pas renvoyé à l'écran (plus propre).
Souge également de modifier $ HOME/ssh-agent.out en $ HOME/.ssh-agent.out
Cordialement
J'ai constaté que plusieurs processus ssh-agent
étaient en cours d'exécution et que le PID à l'intérieur du nom de fichier du socket ne correspondait jamais au PID d'un ssh-agent
en cours d'exécution. J'ai donc piraté quelque chose pour essayer de récupérer ces conditions, à partir des nombreux exemples ci-dessus.
C’est une fonction unique, elle utilise une variable Zsh pour l’ID utilisateur s’il existe et essaie de passer moins de temps à analyser d’éventuels énormes répertoires /tmp
en restreignant un peu plus find(1)
.
Il est probablement toujours sujet à des erreurs et compliqué, mais quelques tests superficiels indiquent qu'il fonctionne principalement pour mes cas d'utilisation, alors voici:
attach_ssh_agent () { if [-n "$ SSH_AGENT_PID"]; alors ssh-add -l>/dev/null ret = $? if [$ ret -ge 2]; then echo "L'agent pid $ SSH_AGENT_PID est moins qu'utile (ret = $ ret) - tuer ..." tuer $ SSH_AGENT_PID non défini $ SSH_AGENT_PID Elif [$ ret = 1]; then echo "L'agent pid $ SSH_AGENT_PID est moins qu'utile (ret = $ ret) - l'ensemencera ..." else echo "Agent pid $ SSH_AGENT_PID" renvoie fi fi si [-S "$ SSH_AUTH_SOCK"]; alors ssh-add -l> /dev/null ret = $? if [$ ret = 2]; then echo "La socket $ SSH_AUTH_SOCK est morte - suppression ..." rm -f $ SSH_AUTH_SOCK non définie SSH_AUTH_SOCK Elif [$ ret = 1]; then echo "La socket $ SSH_AUTH_SOCK pointe vers un agent sans clé ..." ssh-add else echo "Trouvé ssh-agent $ SSH_AUTH_SOCK ( ret = $ ret) " renvoie fi fi pour sf dans $ (find/tmp/-mindepth 2 -maxdepth 2 -uid $ {UID: - $ (id -u)} -path '/tmp/ssh-*/agent.*' -type s); faire tester -r $ sf || continuer exporter SSH_AUTH_SOCK = $ sf SSH_AGENT_PID = $ (nom de base $ SSH_AUTH_SOCK | cut -d. -f2) # exécute d'autres processus, argh try = 50 Tant que [$ try -gt 0]; do try = $ (($ try-1)) export SSH_AGENT_PID = $ (($ SSH_AGENT_PID + 1)) echo "Test de $ SSH_AUTH_SOCK -> $ SSH_AGENT_PID" ssh_agent_running = $ (ps -u $ USER | grep ssh-agent) if [-z "$ ssh_agent_running"]; then echo "La socket $ SSH_AUTH_SOCK ne contient pas de lien vers un agent en cours d'exécution - suppression ..." rm -f $ SSH_AUTH_SOCK continue fi si echo "$ ssh_agent_running" |\ awk '$ 1 ==' $ SSH_AGENT_PID '{ trouvé = 1; sortie (0); } END { if (! found) { print "n'a pas trouvé l'exécution du PID '$ SSH_AGENT_PID'"; exit (1); } } ' ; alors ssh-add -l> /dev/null ret = $? if [$ ret -ge 2]; then echo "La socket $ SSH_AUTH_SOCK ne contient pas de lien vers un agent utile à $ SSH_AGENT_PID - suppression ..." rm -f $ SSH_AUTH_SOCK kill $ SSH_AGENT_PID unset SSH_AGENT_PID continuer 2 Elif [$ ret = 1]; then echo "La socket $ SSH_AUTH_SOCK contient un lien vers un agent peu utile à $ SSH_AGENT_PID - Seeding ..." ssh-add if! ssh-add -l>/dev/null; then echo "La socket $ SSH_AUTH_SOCK contient toujours un lien vers un agent peu utile à $ SSH_AGENT_PID - annulation." return else break fi else break fi else # echo "Impossible de faire correspondre la socket $ SSH_AUTH_SOCK à l'agent PID $ SSH_AGENT_PID - saute ... " continue fi terminé si [$ try -gt 0]; then echo "Agent ssh trouvé $ SSH_AUTH_SOCK" echo "Agent pid $ SSH_AGENT_PID" return f terminé . if [-n "$ try" -a -n "$ SSH_AUTH_SOCK" -a -n "$ ssh_agent_running"]; then echo "Nous avons essayé plusieurs fois, mais nous n'avons pu associer $ SSH_AUTH_SOCK à aucun des agents en cours d'exécution, soupir" echo "$ ssh_agent_running" echo "Laissant ces restes derrière et démarrer un nouvel agent ... " fi eval $ (ssh-agent -t 28800) ssh-add }
J'ai lu votre solution initiale et un certain nombre de solutions suggérées, mais j'ai décidé de simplifier le processus pour mon propre usage. C'est ce que j'ai ajouté dans mon propre .bashrc:
# get active ssh-agent, or launch new
SSH_AGENT_PID=$(ps -fC ssh-agent | grep "ssh-agent -a ${HOME}/.ssh/ssh-agent-socket" | awk '{print $2}')
if [ -z "${SSH_AGENT_PID}" ]; then
# If there is no ssh-agent running, we'll make sure one hasn't left a socket file dangling
rm ${HOME}/.ssh/ssh-agent-socket &> /dev/null
# And of course start one
eval $(ssh-agent -a ${HOME}/.ssh/ssh-agent-socket)
else
# We found a process matching our requirements, so sticking with that
export SSH_AGENT_PID
export SSH_AUTH_SOCK="${HOME}/.ssh/ssh-agent-socket"
fi
J'ai fait quelques hypothèses ici:
Dans l'ensemble, je pense que cela semble être une solution simple.