Démarrez ssh-agent à la connexion


262

J'ai un site en tant que dépôt Git distant tirant de Bitbucket.com en utilisant un alias SSH. Je peux démarrer manuellement l'agent ssh sur mon serveur mais je dois le faire à chaque fois que je me connecte via SSH.

Je démarre manuellement l'agent ssh:

eval ssh-agent $SHELL

Ensuite, j'ajoute l'agent:

ssh-add ~/.ssh/bitbucket_id

Ensuite, il apparaît quand je fais:

ssh-add -l

Et je suis prêt à partir. Existe-t-il un moyen d'automatiser ce processus pour ne pas avoir à le faire à chaque connexion? Le serveur exécute RedHat 6.2 (Santiago).


2
Tout ce que vous voulez faire chaque fois que vous vous connectez doit être dans .profile (connexions de terminal) ou .xinitrc (pour les connexions GUI).
Barmar

1
Ah! J'utilisais .bash_profile ... Quelle est la différence entre .profile et .bash_profile?
Pathsofdesign

1
Je ne sais pas pourquoi vous exécutez la commande de cette façon en premier lieu. ssh-agent <command>fonctionne <command>comme un sous-processus de ssh-agent, donc vous démarrez un nouveau shell. Je pense que tu veux eval ssh-agent.
Barmar

9
.bash_profileest spécifique à bash, .profileest générique pour tous les shells POSIX. bashrecherchera d'abord .bash_profile, puis par défaut .profile.
Barmar

5
La manière correcte d'apparaître ssh-agentpour un shell "standard" (compatible POSIX) est eval $(ssh-agent -s). Notez également que vous devez vous assurer de vous débarrasser correctement de l'agent lorsque vous vous déconnectez, il est donc également conseillé de mettre trap 'kill $SSH_AGENT_PID' EXITvotre .profileaprès la ligne qui démarre l'agent.
kostix

Réponses:


368

Veuillez parcourir cet article. Vous pouvez trouver cela très utile:

http://mah.everybody.org/docs/ssh

Juste au cas où le lien ci-dessus disparaîtrait un jour, je capture la partie principale de la solution ci-dessous:

Cette solution de Joseph M. Reagle par Daniel Starin:

Ajoutez ce qui suit à votre .bash_profile

SSH_ENV="$HOME/.ssh/agent-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 -ef | grep ${SSH_AGENT_PID} | grep ssh-agent$ > /dev/null || {
        start_agent;
    }
else
    start_agent;
fi

Cette version est particulièrement agréable car elle verra si vous avez déjà démarré ssh-agent et, si elle ne le trouve pas, le démarrera et stockera les paramètres afin qu'ils soient utilisables la prochaine fois que vous démarrez un coquille.


8
Le redémarrage de la machine n'est pas nécessaire. Vous pouvez simplement recharger à l' .bash_profileaide source ~/.bash_profilede votre session shell actuelle. Le redémarrage de la machine fonctionnera également car cela chargera de toute façon la nouvelle configuration.
Litmus

11
Utilisation SSH_ENV="$HOME/.ssh/env"(c'est-à-dire tout simplement pas / environnement) Pourquoi? sshd utilise ~ / .ssh / environnement (voir la page de manuel: PermitUserEnvironment). Github recommande également cela dans leur solution - help.github.com/articles/…
Andrew Murphy

7
Ce script a fonctionné pour moi lorsque je l'ai mis dans mon fichier ~ / .bashrc (pas mon ~ / .profile ou ~ / .bash_profile). La première fois que j'ouvre une console locale, il demande la phrase secrète, tout fonctionne à partir de ce moment sans autre invite. À votre santé.
andrew pate

3
L'ajout de la ssh-agentcommande de démarrage dans .bashrc empêchera la scpcommande de fonctionner.
Dzanvu

5
Toujours ennuyeux ... vous devez le faire à chaque fois que vous vous connectez ... même si vous n'utilisez pas ssh. Besoin de désactiver ce feu à chaque appel de ssh ... et idéalement, vous devriez être en mesure de configurer quels hôtes provoquent le chargement des clés.
Erik Aronesty du

99

Sur Arch Linux, les éléments suivants fonctionnent vraiment bien (devraient fonctionner sur toutes les distributions basées sur Systemd):

Créez un service utilisateur systemd en mettant ce qui suit à ~/.config/systemd/user/ssh-agent.service:

[Unit]
Description=SSH key agent

[Service]
Type=simple
Environment=SSH_AUTH_SOCK=%t/ssh-agent.socket
ExecStart=/usr/bin/ssh-agent -D -a $SSH_AUTH_SOCK

[Install]
WantedBy=default.target

Configurez le shell pour avoir une variable d'environnement pour le socket ( .bash_profile, .zshrc, ...):

export SSH_AUTH_SOCK="$XDG_RUNTIME_DIR/ssh-agent.socket"

Activez le service pour qu'il démarre automatiquement à la connexion et démarrez-le:

systemctl --user enable ssh-agent
systemctl --user start ssh-agent

Ajoutez le paramètre de configuration suivant à votre fichier de configuration ssh local ~/.ssh/config(cela fonctionne depuis SSH 7.2):

AddKeysToAgent  yes

Cela demandera au client ssh de toujours ajouter la clé à un agent en cours d'exécution, il n'est donc pas nécessaire de l'ajouter au préalable.


3
J'ai trouvé ce commentaire en essayant de le faire dans Ubuntu. Il semble jouer beaucoup mieux avec les systèmes intégrés que de pirater quelque chose dans les scripts de démarrage, du moins compte tenu de ma connaissance du fonctionnement du système.
xiterion

J'ai essayé cela sur Ubuntu 16.04 LTS. Malheureusement, chaque processus shell veut son ssh-agentprocessus individuel . Peut-être que je manque de connaissances même après avoir lu les documents.
Daisuke Aramaki

Vous pouvez également utiliser Type = simple . wiki.archlinux.org/index.php/…
Hans-J. Schmid

2
cette solution consiste-t-elle essentiellement à installer / configurer un service systemd (mais uniquement pour l'utilisateur)?
Trevor Boyd Smith

Cela ne définira pas la SSH_AGENT_PIDvariable d'environnement, cependant :(
MrMeszaros

73

Vieille question, mais je suis tombé sur une situation similaire. Ne pensez pas que la réponse ci-dessus réalise pleinement ce qui est nécessaire. La pièce manquante est keychain; installez-le s'il ne l'est pas déjà.

sudo apt-get install keychain

Ajoutez ensuite la ligne suivante à votre ~/.bashrc

eval $(keychain --eval id_rsa)

Cela démarrera ssh-agents'il n'est pas en cours d'exécution, connectez-vous si c'est le cas, chargez les ssh-agentvariables d'environnement dans votre shell et chargez votre clé ssh.

Modifiez id_rsala clé privée que ~/.sshvous souhaitez charger.

Référence

/unix/90853/how-can-i-run-ssh-add-automatically-without-password-prompt


porte-clés ne fonctionne pas pour moi selon les instructions données. J'ai ajouté à .bash_profile et ssh demande toujours le mot de passe à chaque fois. je l'ai essayé plusieurs fois dans le même shell. pas de dé. retour à l'approche de base des agents ssh
javadba

Ajouter eval keychain --eval id_[yourid file]à .bashrc
xelber

4
J'ai passé 20 minutes à rechercher une solution en raison du formatage des commentaires StackOverflow. Selon le commentaire de xelber ci-dessus, la bonne solution est eval `keychain --eval id_[yourid file]`de .bashrc. Les raccourcis nécessaires pour évaluer les variables d'environnement dans le shell actuel pour accéder à l'agent ssh en cours d'exécution.
James

2
Ceci est la solution correcte et simple. Si vous ne souhaitez pas voir le journal lorsque la commande du trousseau est exécutée, vous pouvez ajouter une -qoption pour le mode silencieux. Plus d'infos sur Keychain: funtoo.org/Keychain
Diki Ananta

4
Thx, c'est de loin la solution la plus élégante.
greenspand

37

La solution acceptée présente les inconvénients suivants:

  • c'est compliqué à entretenir;
  • il évalue le fichier de stockage qui peut conduire à des erreurs ou à une violation de la sécurité;
  • il démarre l'agent mais ne l'arrête pas, ce qui équivaut presque à laisser la clé en contact.

Si vos clés ne nécessitent pas de taper le mot de passe, je suggère la solution suivante. Ajoutez ce qui suit à votre .bash_profile toute fin (éditez la liste des clés selon vos besoins):

exec ssh-agent $BASH -s 10<&0 << EOF
    ssh-add ~/.ssh/your_key1.rsa \
            ~/.ssh/your_key2.rsa &> /dev/null
    exec $BASH <&10-
EOF

Il présente les avantages suivants:

  • solution beaucoup plus simple;
  • la session de l'agent se termine à la fin de la session bash.

Il présente des inconvénients possibles:

  • interactif ssh-add commande n'influencera qu'une seule session, ce qui n'est en fait un problème que dans des circonstances très atypiques;
  • inutilisable si la saisie d'un mot de passe est requise;
  • le shell démarré devient non-connecté (ce qui n'influence rien AFAIK).

Notez que plusieurs ssh-agentprocessus ne sont pas un inconvénient, car ils ne prennent pas plus de mémoire ou de temps CPU.


J'ai des clés SSH dans un répertoire en dehors de $ HOME dans Windows 10, en utilisant Git Bash. Changer le chemin vers le RSA était tout ce que je devais faire pour que cela fonctionne. TYVM!
kayleeFrye_onDeck

7
Je dirais que "Si vos clés ne nécessitent pas de taper le mot de passe" équivaut à laisser la clé dans le contact.
Bruno Bronosky

Au moins, c'est sur votre propre hôte, pas quelque part sur le réseau.
midenok

1
"Je dirais que" Si vos clés ne nécessitent pas de taper le mot de passe "équivaut à laisser la clé en position d'allumage." <- Expliquez comment? Parce que les clés sont beaucoup plus flexibles que les mots de passe, beaucoup plus faciles à révoquer (quoi? Vous n'utilisez les clés que pour les utilisateurs sudo avec un accès complet? Tsk tsk). Plusieurs jeux de clés pour plusieurs profils d'utilisateurs. Si vous souhaitez automatiser quoi que ce soit (comme le déploiement ou les contrôles de bout en bout), alors bonne chance en tapant constamment des mots de passe pendant "l'orchestration".
Scott Prive

2
Ne fais pas ça. Les clés sans mot de passe sont une mauvaise pratique.
user48678

26

Ajoutez-le à votre ~/.bashrc, puis déconnectez-vous et reconnectez-vous pour prendre effet.

if [ ! -S ~/.ssh/ssh_auth_sock ]; then
  eval `ssh-agent`
  ln -sf "$SSH_AUTH_SOCK" ~/.ssh/ssh_auth_sock
fi
export SSH_AUTH_SOCK=~/.ssh/ssh_auth_sock
ssh-add -l > /dev/null || ssh-add

Cela ne devrait vous demander un mot de passe que la première fois que vous vous connectez après chaque redémarrage. Il continuera à être réutilisé ssh-agenttant qu'il restera actif.


Que pourrions-nous utiliser à la place si nous avions plusieurs clés et qu'elles n'étaient pas nommées ~/.ssh/id_rsa? Il semble que la ssh-addpartie de votre réponse attend des noms de fichiers par défaut pour les clés.
Gabriel Staples le

Ouaip. Je crois que vous pouvez simplement ajouter les noms de fichiers à la toute fin de la dernière ligne si nécessaire
Collin Anderson

Mais vous ne pouvez toujours pas automatiser un script, tirer des trucs git par exemple sans entrer de mot de passe manuellement? Comment éviter ça?
trainoasis

7

J'ai donc utilisé les approches décrites ci-dessus, mais je préfère en quelque sorte que l'agent meure à la fin de ma dernière session bash. C'est un peu plus long que les autres solutions, mais c'est mon approche préférée. L'idée de base est que la première session bash démarre l'agent ssh. Ensuite, chaque session bash supplémentaire vérifie le fichier de configuration ( ~/.ssh/.agent_env). Si c'est le cas et qu'il y a une session en cours, sourcez l'environnement et créez un lien physique vers le fichier socket dans /tmp(doit être sur le même système de fichiers que le fichier socket d'origine). Lorsque les sessions bash sont fermées, chacune supprime son propre lien physique. La dernière session à fermer constatera que les liens physiques ont 2 liens (le lien physique et l'original), la suppression de la propre socket du processus et la suppression du processus se traduiront par 0, laissant un environnement propre après la dernière session bash.

# Start ssh-agent to keep you logged in with keys, use `ssh-add` to log in
agent=`pgrep ssh-agent -u $USER` # get only your agents           
if [[ "$agent" == "" || ! -e ~/.ssh/.agent_env ]]; then
    # if no agents or environment file is missing create a new one
    # remove old agents / environment variable files
    kill $agent running
    rm ~/.ssh/.agent_env 

    # restart
    eval `ssh-agent` 
    echo 'export SSH_AUTH_SOCK'=$SSH_AUTH_SOCK >> ~/.ssh/.agent_env             
    echo 'export SSH_AGENT_PID'=$SSH_AGENT_PID >> ~/.ssh/.agent_env             
fi

# create our own hardlink to the socket (with random name)           
source ~/.ssh/.agent_env                                                    
MYSOCK=/tmp/ssh_agent.${RANDOM}.sock                                        
ln -T $SSH_AUTH_SOCK $MYSOCK                                                
export SSH_AUTH_SOCK=$MYSOCK                                                

end_agent()                                                                     
{
    # if we are the last holder of a hardlink, then kill the agent
    nhard=`ls -l $SSH_AUTH_SOCK | awk '{print $2}'`                             
    if [[ "$nhard" -eq 2 ]]; then                                               
        rm ~/.ssh/.agent_env                                                    
        ssh-agent -k                                                            
    fi                                                                          
    rm $SSH_AUTH_SOCK                                                           
}                                                                               
trap end_agent EXIT                                                             
set +x              

si nous l'exécutons en tant que script BASH à la connexion de tout autre shell (autre que BASH), cela devrait aussi fonctionner, non?
hoijui

7

Juste pour ajouter une autre solution: P, je suis allé avec une combinaison des solutions de @spheenik et @ collin-anderson.

 # Ensure that we have an ssh config with AddKeysToAgent set to true
 if [ ! -f ~/.ssh/config ] || ! cat ~/.ssh/config | grep AddKeysToAgent | grep yes > /dev/null; then
     echo "AddKeysToAgent  yes" >> ~/.ssh/config
 fi
 # Ensure a ssh-agent is running so you only have to enter keys once
 if [ ! -S ~/.ssh/ssh_auth_sock ]; then
   eval `ssh-agent`
   ln -sf "$SSH_AUTH_SOCK" ~/.ssh/ssh_auth_sock
 fi
 export SSH_AUTH_SOCK=~/.ssh/ssh_auth_sock

Pourrait être un peu plus élégant mais c'est simple et lisible. Cette solution:

  • assure AddKeysToAgent yes est dans votre configuration ssh afin que les clés soient automatiquement ajoutées lors de l'utilisation
  • ne vous invite pas à saisir de phrase secrète lors de la connexion (encore une fois, la saisie d'une phrase secrète unique se produit lors de la première utilisation)
  • démarre silencieusement un agent ssh s'il n'en a pas déjà démarré un

Commentaires bienvenus :)


1
Cela a parfaitement fonctionné pour moi. Sur Kubuntu, je l'ai mis en .profile.
Shai

1
Bon à savoir sur le AddKeysToAgent yescadre. Merci.
Collin Anderson

3

Je résolu en ajoutant ceci à la / etc / profile - l' ensemble du système (ou locale utilisateur .profile ou _.bash_profile_):

# SSH-AGENT 
#!/usr/bin/env bash
SERVICE='ssh-agent'
WHOAMI=`who am i |awk '{print $1}'`

if pgrep -u $WHOAMI $SERVICE >/dev/null
then
    echo $SERVICE running.
else
    echo $SERVICE not running.
    echo starting
    ssh-agent > ~/.ssh/agent_env
fi
. ~/.ssh/agent_env

Cela démarre un nouvel agent ssh s'il n'est pas en cours d'exécution pour l'utilisateur actuel, ou réinitialise le paramètre env ssh-agent s'il est en cours d'exécution.


Merci d'avoir dit comment savoir si l'agent est déjà en cours d'exécution!
Mike Maxwell

Comment le if pgrep -u $WHOAMI $SERVICE >/dev/null marche?
Josh Desmond

3

Les utilisateurs de la coquille de poisson peuvent utiliser ce script pour faire la même chose.

# content has to be in .config/fish/config.fish
# if it does not exist, create the file
setenv SSH_ENV $HOME/.ssh/environment

function start_agent                                                                                                                                                                    
    echo "Initializing new SSH agent ..."
    ssh-agent -c | sed 's/^echo/#echo/' > $SSH_ENV
    echo "succeeded"
    chmod 600 $SSH_ENV 
    . $SSH_ENV > /dev/null
    ssh-add
end

function test_identities                                                                                                                                                                
    ssh-add -l | grep "The agent has no identities" > /dev/null
    if [ $status -eq 0 ]
        ssh-add
        if [ $status -eq 2 ]
            start_agent
        end
    end
end

if [ -n "$SSH_AGENT_PID" ] 
    ps -ef | grep $SSH_AGENT_PID | grep ssh-agent > /dev/null
    if [ $status -eq 0 ]
        test_identities
    end  
else
    if [ -f $SSH_ENV ]
        . $SSH_ENV > /dev/null
    end  
    ps -ef | grep $SSH_AGENT_PID | grep -v grep | grep ssh-agent > /dev/null
    if [ $status -eq 0 ]
        test_identities
    else 
        start_agent
    end  
end

2

J'utilise le ssh-ident outil pour cela.

Depuis sa page de manuel :

ssh-ident - Démarrez et utilisez ssh-agent et chargez les identités si nécessaire.


1

J'ai essayé quelques solutions de plusieurs sources, mais tout semblait trop compliqué. Enfin j'ai trouvé le plus simple :)

Si vous n'êtes pas encore familier avec zsh et oh-my-zsh, installez-le. Vous allez l'adorer :)

Puis éditez .zshrc

vim ~/.zshrc

trouver la pluginssection et la mettre à jour pour l'utiliser ssh-agentcomme ceci:

plugins=(ssh-agent git)

Et c'est tout! Vous aurez ssh-agentopérationnel à chaque fois que vous démarrez votre shell


1

J'aime beaucoup vos réponses. Cela a rendu le travail des cygwin / linuxhôtes beaucoup plus facile. J'ai combiné les fonctions de début et de fin pour le sécuriser.

SSH_ENV="$HOME/.ssh/.agent_env"

function start_agent {
    echo "Initialising new SSH agent..."

    eval `/usr/bin/ssh-agent`
    echo 'export SSH_AUTH_SOCK'=$SSH_AUTH_SOCK >> ${SSH_ENV}
    echo 'export SSH_AGENT_PID'=$SSH_AGENT_PID >> ${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 -ef | grep ${SSH_AGENT_PID} | grep ssh-agent$ > /dev/null || {
        start_agent;
    }
else
    start_agent;
fi

# create our own hardlink to the socket (with random name)
MYSOCK=/tmp/ssh_agent.${RANDOM}.sock
ln -T $SSH_AUTH_SOCK $MYSOCK
export SSH_AUTH_SOCK=$MYSOCK

end_agent()
{
    # if we are the last holder of a hardlink, then kill the agent
    nhard=`ls -l $SSH_AUTH_SOCK | awk '{print $2}'`
    if [[ "$nhard" -eq 2 ]]; then
        rm ${SSH_ENV}
        /usr/bin/ssh-agent -k
    fi
    rm $SSH_AUTH_SOCK
}
trap end_agent EXIT
set +x
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.