Spécifiez une clé SSH pour git push pour un domaine donné

342

J'ai le cas d'utilisation suivant: je voudrais pouvoir pousser à [email protected]:gitolite-adminutiliser la clé privée de l'utilisateur gitolite-admin, tandis que je veux pousser à [email protected]:some_repoutiliser «ma» clé privée. AFAIK, je ne peux pas résoudre ce problème en utilisant ~/.ssh/config, car le nom d'utilisateur et le nom du serveur sont identiques dans les deux cas. Comme j'utilise principalement ma propre clé privée, je l'ai définie ~/.ssh/configpour [email protected]. Quelqu'un connaît-il un moyen de remplacer la clé utilisée pour une seule gitinvocation?

(À part: gitolite distingue qui fait le push en fonction de la clé, donc ce n'est pas un problème, en termes d'accès, de propriété et d'audit, que la chaîne user @ server soit identique pour différents utilisateurs.)

Confusion
la source
Étroitement liés: stackoverflow.com/questions/4565700/…
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

Réponses:

597

Même si l'utilisateur et l'hôte sont identiques, ils peuvent toujours être distingués ~/.ssh/config. Par exemple, si votre configuration ressemble à ceci:

Host gitolite-as-alice
  HostName git.company.com
  User git
  IdentityFile /home/whoever/.ssh/id_rsa.alice
  IdentitiesOnly yes

Host gitolite-as-bob
  HostName git.company.com
  User git
  IdentityFile /home/whoever/.ssh/id_dsa.bob
  IdentitiesOnly yes

Ensuite, vous utilisez simplement gitolite-as-aliceet gitolite-as-bobau lieu du nom d'hôte dans votre URL:

git remote add alice git@gitolite-as-alice:whatever.git
git remote add bob git@gitolite-as-bob:whatever.git

Remarque

Vous souhaitez inclure l'option IdentitiesOnly yespour empêcher l'utilisation d'ID par défaut. Sinon, si vous avez également des fichiers id correspondant aux noms par défaut, ils seront essayés en premier car, contrairement aux autres options de configuration (qui respectent "first in wins"), l' IdentityFileoption s'ajoute à la liste des identités à essayer. Voir: /server/450796/how-could-i-stop-ssh-offering-a-wrong-key/450807#450807

Mark Longair
la source
9
Super merci. Je n'avais pas compris que vous pouviez librement choisir un 'alias' pour la spécification Host dans le ~ / .ssh / config
Confusion
4
Merci aussi pour cette réponse! Un problème pour moi était que IdentityFile doit être un chemin complet (j'ai seulement mis id_rsa.rick comme argument pour IdentityFile, et cela a échoué). Voir la page de manuel ssh_config (5) pour une autre syntaxe pour IdentityFile.
rickumali
1
Merci beaucoup pour la réponse claire et très utile. J'avais essayé de faire fonctionner cela pendant un certain temps et j'ai abandonné auparavant en supposant que le même utilisateur devait utiliser le même fichier de clé privée id_rsa.
DrCord
7
La git@partie dans la télécommande n'est pas nécessaire car elle est indiquée dans la Userligne de la configuration.
dolmen
2
Je me battais avec cette solution jusqu'à ce que j'ajoute une autre ligne contenant IdentitiesOnly yesimmédiatement après la ligne avec IdentityFilepour l'hôte. Il semble qu'il transmettait plusieurs identités et l'une d'entre elles n'a pas pu accéder à l'hôte.
Fitter Man
57

Une approche alternative à celle proposée ci-dessus par Mark Longair consiste à utiliser un alias qui exécutera n'importe quelle commande git, sur n'importe quelle télécommande, avec une clé SSH alternative. L'idée est essentiellement de changer votre identité SSH lors de l'exécution des commandes git.

Avantages par rapport à l'approche d'alias d'hôte dans l'autre réponse:

  • Fonctionne avec toutes les commandes ou alias git, même si vous ne pouvez pas spécifier remoteexplicitement le.
  • Plus facile à utiliser avec de nombreux référentiels car vous n'avez besoin de le configurer qu'une seule fois par machine client, et non une seule fois par référentiel sur chaque machine client.

J'utilise quelques petits scripts et un alias git admin. De cette façon, je peux faire, par exemple:

git admin push 

Pour pousser vers la télécommande par défaut à l'aide de la clé SSH alternative ("admin"). Encore une fois, vous pouvez utiliser n'importe quelle commande (pas seulement push) avec cet alias. Vous pourriez même faire git admin clone ...pour cloner un référentiel auquel vous n'auriez accès qu'en utilisant votre clé "admin".

Étape 1: Créez les clés SSH alternatives, définissez éventuellement une phrase secrète au cas où vous le feriez sur la machine de quelqu'un d'autre.

Étape 2: Créez un script appelé «ssh-as.sh» qui exécute des éléments qui utilisent SSH, mais utilise une clé SSH donnée plutôt que la valeur par défaut:

#!/bin/bash
exec ssh ${SSH_KEYFILE+-i "$SSH_KEYFILE"} "$@"

Étape 3: Créez un script appelé «git-as.sh» qui exécute les commandes git en utilisant la clé SSH donnée.

#!/bin/bash
SSH_KEYFILE=$1 GIT_SSH=${BASH_SOURCE%/*}/ssh-as.sh exec git "${@:2}"

Étape 4: Ajoutez un alias (en utilisant quelque chose de approprié pour «PATH_TO_SCRIPTS_DIR» ci-dessous):

# Run git commands as the SSH identity provided by the keyfile ~/.ssh/admin
git config --global alias.admin \!"PATH_TO_SCRIPTS_DIR/git-as.sh ~/.ssh/admin"

Plus de détails sur: http://noamlewis.wordpress.com/2013/01/24/git-admin-an-alias-for-running-git-commands-as-a-privileged-ssh-identity/

sinelaw
la source
4
Très belle réponse. N'oubliez pas d'ajouter des guillemets $@-> "$@"pour être sûr.
kevinarpe
@sinelaw Cela fonctionne-t-il toujours? J'obtiens l'erreur Autorisation refusée tout le temps
Alok Kumar
56

Vous pouvez utiliser la variable d'environnement git GIT_SSH_COMMAND. Exécutez ceci dans votre terminal sous votre référentiel git:

GIT_SSH_COMMAND='ssh -i ~/.ssh/your_private_key' git submodule update --init

Remplacez ~/.ssh/your_private_keypar le chemin de la clé privée ssh que vous souhaitez utiliser. Et vous pouvez modifier la commande git ultérieure (dans l'exemple est git submodule update --init) à d' autres comme git pull, git fetch, etc.

Hustlion
la source
1
La documentation complète se trouve sur git-scm.com/docs/git#git-codeGITSSHcode ; il a cependant besoin d'un Git récent (> = 2.3. *).
Christian Ulbrich
2
Merci pour une solution simple qui ne nécessite rien d'autre que de définir une variable d'environnement.
Noah Sussman
4
Notez que votre ~ / .ssh / id_rsa (ou quelle que soit votre clé par défaut) aura priorité sur celle que vous passez via -i. Donc, vous voulez vraiment utiliser GIT_SSH_COMMAND = 'ssh -i ~ / .ssh / your_private_key -o IdentitiesOnly = yes' pour lui faire ignorer les autres clés
staktrace
comment mettre à jour git push? Je ne l'ai pas trouvé dans la documentation
lebed2045
Ce serait bien de créer des alias bash ou git - similaire à la réponse de sinelaw mais en utilisant cette méthode au lieu d'avoir à créer des scripts quelque part.
Inigo
14

Un système basé sur Unix (Linux, BSD, Mac OS X), l'identité par défaut est stockée dans le répertoire $ HOME / .ssh , dans 2 fichiers: private key: $HOME/.ssh/id_rsa public key: $HOME/.ssh/id_rsa.pub lorsque vous utilisez sshsans option -i, il utilise la clé privée par défaut pour s'authentifier auprès du système distant.

Si vous souhaitez utiliser une autre clé privée, par exemple $ HOME / .ssh / deploy_key , vous devez utiliserssh -i ~/.ssh/deploy_key ...

C'est ennuyant. Vous pouvez ajouter les lignes suivantes à votre $ HOME / .bash_profile : ssh-add ~/.ssh/deploy_key ssh-add ~/.ssh/id_rsa

Ainsi, chaque fois que vous utilisez sshou gitou scp(en gros sshaussi), vous n'avez plus besoin d'utiliser l'option -i.

Vous pouvez ajouter autant de clés que vous le souhaitez dans le fichier $ HOME / .bash_profile .

Châu Hồng Lĩnh
la source
10

Une autre alternative consiste à utiliser ssh-ident, pour gérer vos identités ssh .

Il charge et utilise automatiquement différentes clés en fonction de votre répertoire de travail actuel, des options ssh, etc. ... ce qui signifie que vous pouvez facilement avoir un répertoire work / et private / directory qui finit de manière transparente par utiliser différentes clés et identités avec ssh.

rabexc
la source
9

J'utilise Git Bash sur Win7. Ce qui suit a fonctionné pour moi.

Créez un fichier de configuration dans ~ / .ssh / config ou c: / users / [votre_nom_utilisateur] /. Ssh / config. Dans le fichier, entrez:

Host your_host.com
     IdentityFile [absolute_path_to_your_.ssh]\id_rsa

Je suppose que l'hôte doit être une URL et pas seulement un "nom" ou une référence pour votre hôte. Par exemple,

Host github.com
     IdentityFile c:/users/[user_name]/.ssh/id_rsa

Le chemin peut également être écrit au format / c / users / [nom_utilisateur] / ....

La solution fournie par Giordano Scalzo est également excellente. https://stackoverflow.com/a/9149518/1738546

user1738546
la source
9

À partir de git 2.10, il est également possible d'utiliser le paramètre gitconfig sshCommand. Les documents indiquent :

Si cette variable est définie, git fetch et git push utiliseront la commande spécifiée au lieu de ssh lorsqu'ils doivent se connecter à un système distant. La commande se présente sous la même forme que la variable d'environnement GIT_SSH_COMMAND et est remplacée lorsque la variable d'environnement est définie.

Un exemple d'utilisation serait: git config core.sshCommand "ssh -i ~/.ssh/[insert_your_keyname]

Dans certains cas, cela ne fonctionne pas car ssh_config écrase la commande, dans ce cas, essayez ssh -i ~/.ssh/[insert_your_keyname] -F /dev/nullde ne pas utiliser ssh_config.

firfin
la source
8

J'ai regroupé et testé avec github l'approche suivante, basée sur la lecture d'autres réponses, qui combine quelques techniques:

  • configuration SSH correcte
  • réécriture d'URL git

L'avantage de cette approche est qu'une fois configurée, elle ne nécessite aucun travail supplémentaire pour bien faire les choses - par exemple, vous n'avez pas besoin de modifier les URL distantes ou de ne pas oublier de cloner les choses différemment - la réécriture d'URL fait tout fonctionner .

~/.ssh/config

# Personal GitHub
Host github.com
  HostName github.com
  User git
  AddKeysToAgent yes
  UseKeychain yes
  IdentityFile ~/.ssh/github_id_rsa

# Work GitHub
Host github-work
  HostName github.com
  User git
  AddKeysToAgent yes
  UseKeychain yes
  IdentityFile ~/.ssh/work_github_id_rsa

Host *
  IdentitiesOnly yes

~/.gitconfig

[user]
    name = My Name
    email = [email protected]

[includeIf "gitdir:~/dev/work/"]
    path = ~/dev/work/.gitconfig

[url "github-work:work-github-org/"]
    insteadOf = [email protected]:work-github-org/

~/dev/work/.gitconfig

[user]
    email = [email protected]

Tant que vous gardez tous vos dépôts de travail sous ~ / dev / work et vos données personnelles ailleurs, git utilisera la bonne clé SSH lors des pulls / clones / pushs sur le serveur, et il joindra également l'adresse e-mail correcte à tous vos engagements.

Références:

karlos
la source
Comment cela fonctionne-t-il avec le clonage? includeIfne devrait fonctionner que s'il y a un .gitrépertoire que je pensais?
15h57
Attendez, je comprends, c'est la réécriture d'URL qui s'en occupe. Cette réponse est incroyablement utile!
16h06
4

Si vous utilisez la version de ssh de Git sur Windows, la ligne du fichier d'identité dans la configuration ssh ressemble à

IdentityFile /c/Users/Whoever/.ssh/id_rsa.alice

/cest pourc:

Pour vérifier, dans git's bash do

cd ~/.ssh
pwd 
Andrew Murphy
la source
3

Vous devrez peut-être supprimer (ou commenter) la configuration d'hôte par défaut .ssh / config

ViliusK
la source
1

vous avez le plus spécifié dans le fichier de configuration clé ssh:

# Default GitHub user
Host one
 HostName gitlab.com
 User git
 PreferredAuthentications publickey
 IdentityFile ~/.ssh/key-one
 IdentitiesOnly yes

#two user
Host two
 HostName gitlab.com
 User git
 PreferredAuthentications publickey
 IdentityFile ~/.ssh/key-two
 IdentitiesOnly yes
Diego Santa Cruz Mendezú
la source
0

Comme quelqu'un d'autre l'a mentionné, la core.sshCommandconfiguration peut être utilisée pour remplacer la clé SSH et d'autres paramètres.

Voici un exemple où vous avez une autre clé nommée ~/.ssh/workrsaet que vous souhaitez utiliser pour tous les référentiels clonés ~/work.

  1. Créez un nouveau .gitconfigfichier sous ~/work:
[core]
  sshCommand = "ssh -i ~/.ssh/workrsa"
  1. Dans votre configuration git globale ~/.gitconfig, ajoutez:
[includeIf "gitdir:~/work/"]
  path = ~/work/.gitconfig
Mansour
la source
0

Une possibilité d'utilisation ~/.ssh/configconsiste à utiliser la Matchrestriction au lieu de la Hostrestriction. Appelle en particulier Match Execune commande shell pour décider d'appliquer ou non les déclarations. En bash, vous pouvez utiliser la commande suivante:

[ [email protected]:gitolite-admin = $(git config --get remote.origin.url)'' ]

Cela utilise la [commande bash pour vérifier si deux chaînes sont égales. Dans ce cas, il teste si la chaîne [email protected]:gitolite-admincorrespond à la sortie obtenue à partir de la $(git config --get remote.origin.url)''commande.

Vous pouvez utiliser n'importe quelle autre commande qui identifie le référentiel sur lequel se trouve le shell. Pour que cela fonctionne, il est important d'avoir la $SHELLvariable définie dans votre shell, dans mon cas /bin/bash. L'exemple complet serait alors le suivant ~/.ssh/config:

Match Exec "[ [email protected]:gitolite-admin = $(git config --get remote.origin.url)'' ]"
  IdentityFile ~/.ssh/gitolite-admin
  IdentitiesOnly yes
  ForwardAgent no
  ForwardX11 no
  ForwardX11Trusted no

Match Exec "[ [email protected]:some_repo = $(git config --get remote.origin.url)'' ]"
  IdentityFile ~/.ssh/yourOwnPrivateKey
  IdentitiesOnly yes
  ForwardAgent no
  ForwardX11 no
  ForwardX11Trusted no

Dans cet exemple, j'ai supposé qu'il ~/.ssh/yourOwnPrivateKeycontient votre propre clé privée et que ~/.ssh/gitolite-admincontient la clé privée de l'utilisateur gitolite-admin. J'ai inclus la IdentitiesOnly yesdéclaration pour m'assurer qu'une seule clé est offerte au serveur git, mentionnée par Mark Longair . Les autres déclarations ne sont que des options ssh standard pour git.

Vous pouvez ajouter cette configuration si vous en avez plusieurs some_repoque vous souhaitez utiliser avec différentes clés. Si vous avez plusieurs référentiels sur [email protected]et la plupart d'entre eux utilisent le, ~/.ssh/yourOwnPrivateKeyil est plus logique d'inclure cette clé par défaut pour l'hôte. Dans ce cas, ce ~/.ssh/configserait:

Match Exec "[ [email protected]:gitolite-admin = $(git config --get remote.origin.url)'' ]"
  IdentityFile ~/.ssh/gitolite-admin
  IdentitiesOnly yes

Host git.company.com
  IdentityFile ~/.ssh/yourOwnPrivateKey
  IdentitiesOnly yes
  ForwardAgent no
  ForwardX11 no
  ForwardX11Trusted no

Notez que la commande est importante et que la Host git.company.comrestriction doit apparaître après Match Execcelle ou celles.

LuisR
la source
0

Configurez votre référentiel à l'aide de git config. Par exemple:

git config --add --local core.sshCommand 'ssh -i ~/.ssh/<<<PATH_TO_SSH_KEY>>>'
épisage
la source