Specifica una chiave SSH per git push per un determinato dominio


342

Ho il seguente caso d'uso: vorrei poter spingere per git@git.company.com:gitolite-adminusare la chiave privata dell'utente gitolite-admin, mentre voglio spingere per git@git.company.com:some_repousare la 'mia' chiave privata. AFAIK, non posso risolverlo usando ~/.ssh/config, perché il nome utente e il nome del server sono identici in entrambi i casi. Poiché utilizzo principalmente la mia chiave privata, ho definito in ~/.ssh/configper git@git.company.com. Qualcuno conosce un modo per sovrascrivere la chiave utilizzata per una singola gitchiamata?

(A parte: gitolite distingue chi sta facendo il push in base alla chiave, quindi non è un problema, in termini di accesso, proprietà e controllo, che la stringa user @ server sia identica per diversi utenti.)


Risposte:


597

Anche se l'utente e l'host sono uguali, è comunque possibile distinguerli ~/.ssh/config. Ad esempio, se la configurazione è simile alla seguente:

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

Quindi basta usare gitolite-as-alicee gitolite-as-bobinvece del nome host nel tuo URL:

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

Nota

Si desidera includere l'opzione IdentitiesOnly yesper impedire l'uso di ID predefiniti. Altrimenti, se hai anche file ID corrispondenti ai nomi predefiniti, verranno prima provati perché a differenza di altre opzioni di configurazione (che rispettano "first in wins") l' IdentityFileopzione si aggiunge all'elenco di identità da provare. Vedi: /server/450796/how-could-i-stop-ssh-offering-a-wrong-key/450807#450807


9
Fantastico, grazie. Non avevo capito che potevi scegliere liberamente un 'alias' per la specifica Host in ~ / .ssh / config
Confusion

4
Grazie anche per questa risposta! Un problema per me è che IdentityFile deve essere un percorso completo (ho solo messo id_rsa.rick come argomento per IdentityFile, e questo non è riuscito). Vedere la pagina man ssh_config (5) per altre sintassi per IdentityFile.
rickumali,

1
Grazie mille per la risposta chiara e molto utile. Avevo provato a farlo funzionare per un po 'e avevo rinunciato prima supponendo che lo stesso utente dovesse usare lo stesso file di chiave privata id_rsa.
DrCord,

7
La git@parte nel telecomando non è necessaria in quanto è indicata nella Userriga della configurazione.
dolmen,

2
Ho avuto difficoltà con questa soluzione fino a quando non ho aggiunto un'altra riga contenente IdentitiesOnly yesimmediatamente dopo la riga IdentityFileper l'host. Sembra che stesse attraversando più identità e uno di questi è stato bloccato dall'accesso all'host.
Fitter Man,

57

Un approccio alternativo a quello offerto sopra da Mark Longair è l'uso di un alias che eseguirà qualsiasi comando git, su qualsiasi telecomando, con una chiave SSH alternativa. L'idea è fondamentalmente di cambiare l'identità SSH quando si eseguono i comandi git.

Vantaggi relativi all'approccio alias host nell'altra risposta:

  • Funzionerà con qualsiasi comando o alias git, anche se non è possibile specificare remoteesplicitamente.
  • Lavorare più facilmente con molti repository perché è necessario configurarlo solo una volta per computer client, non una volta per repository su ciascun computer client.

Uso alcuni piccoli script e un alias git admin. In questo modo posso fare, ad esempio:

git admin push 

Per passare al telecomando predefinito utilizzando la chiave SSH alternativa ("admin"). Ancora una volta, è possibile utilizzare qualsiasi comando (non solo push) con questo alias. Potresti anche fare git admin clone ...per clonare un repository a cui avresti accesso solo usando la tua chiave "admin".

Passaggio 1: crea le chiavi SSH alternative, facoltativamente imposta una passphrase nel caso in cui lo stai facendo sulla macchina di qualcun altro.

Passaggio 2: creare uno script chiamato "ssh-as.sh" che esegue elementi che utilizzano SSH, ma utilizza una determinata chiave SSH anziché quella predefinita:

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

Passaggio 3: creare uno script chiamato "git-as.sh" che esegue i comandi git utilizzando la chiave SSH fornita.

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

Passaggio 4: aggiungi un alias (utilizzando qualcosa di appropriato per "PATH_TO_SCRIPTS_DIR" di seguito):

# 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"

Maggiori dettagli su: http://noamlewis.wordpress.com/2013/01/24/git-admin-an-alias-for-running-git-commands-as-a-privileged-ssh-identity/


4
Risposta molto bella. Non dimenticare di aggiungere virgolette doppie in giro $@-> "$@"per sicurezza.
Kevinevpe,

@sinelaw Funziona ancora? Ottengo sempre l'errore di autorizzazione negata
Alok Kumar,

56

È possibile utilizzare la variabile di ambiente git GIT_SSH_COMMAND. Esegui questo nel tuo terminale sotto il tuo repository git:

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

Sostituisci ~/.ssh/your_private_keycon il percorso della chiave privata ssh che vuoi usare. E si può cambiare il successivo comando git (nell'esempio è git submodule update --init) ad altri come git pull, git fetchecc


1
Il documento completo è disponibile all'indirizzo git-scm.com/docs/git#git-codeGITSSHcode ; necessita però di un Git recente (> = 2.3. *).
Christian Ulbrich,

2
Grazie per una soluzione semplice che non richiede nulla tranne l'impostazione di una variabile di ambiente.
Noah Sussman,

4
Nota che ~ / .ssh / id_rsa (o qualunque sia la tua chiave predefinita) avrà la precedenza su quello che passi in -i. Quindi vuoi davvero usare GIT_SSH_COMMAND = 'ssh -i ~ / .ssh / your_private_key -o IdentitiesOnly = yes' per farlo ignorare altre chiavi
staktrace

come si aggiorna git push? Non sono riuscito a trovarlo nella documentazione
lebed2045,

Sarebbe bello creare alias bash o git - simile alla risposta di sinelaw ma usando questo metodo invece di creare script da qualche parte.
Inigo,

14

Un sistema basato su Unix (Linux, BSD, Mac OS X), l'identità predefinita è memorizzata nella directory $ HOME / .ssh , in 2 file: private key: $HOME/.ssh/id_rsa public key: $HOME/.ssh/id_rsa.pub quando si utilizza sshsenza opzione -i, utilizza la chiave privata predefinita per l'autenticazione con il sistema remoto.

Se si dispone di un'altra chiave privata che si desidera utilizzare, ad esempio $ HOME / .ssh / deploy_key , è necessario utilizzaressh -i ~/.ssh/deploy_key ...

È noioso. Puoi aggiungere le seguenti righe al tuo $ HOME / .bash_profile : ssh-add ~/.ssh/deploy_key ssh-add ~/.ssh/id_rsa

Quindi ogni volta che usi ssho gito scp(sostanzialmente sshanche), non devi più usare l'opzione -i.

Puoi aggiungere tutte le chiavi che vuoi nel file $ HOME / .bash_profile .


10

Un'altra alternativa è usare ssh-ident, per gestire le tue identità ssh .

Carica automaticamente e utilizza chiavi diverse in base alla directory di lavoro corrente, alle opzioni ssh e così via ... il che significa che puoi avere facilmente una directory di lavoro / e privata / che finisce con l'uso di chiavi e identità diverse con ssh.


9

Sto usando Git Bash su Win7. Quanto segue ha funzionato per me.

Crea un file di configurazione in ~ / .ssh / config oppure c: / users / [nome_utente] /. Ssh / config. Nel file inserisci:

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

Immagino che l'host debba essere un URL e non solo un "nome" o un riferimento per il tuo host. Per esempio,

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

Il percorso può anche essere scritto nel formato / c / users / [nome_utente] / ....

Ottima anche la soluzione fornita da Giordano Scalzo. https://stackoverflow.com/a/9149518/1738546


9

Da git 2.10 in poi è anche possibile usare l'impostazione gitconfig sshCommand. Stato dei documenti :

Se questa variabile è impostata, git fetch e git push useranno il comando specificato invece di ssh quando devono connettersi a un sistema remoto. Il comando ha la stessa forma della variabile d'ambiente GIT_SSH_COMMAND e viene sovrascritto quando viene impostata la variabile d'ambiente.

Un esempio di utilizzo sarebbe: git config core.sshCommand "ssh -i ~/.ssh/[insert_your_keyname]

In alcuni casi questo non funziona perché ssh_config ha la precedenza sul comando, in questo caso prova ssh -i ~/.ssh/[insert_your_keyname] -F /dev/nulla non usare ssh_config.


8

Ho paralizzato e testato con github il seguente approccio, basato sulla lettura di altre risposte, che combina alcune tecniche:

  • corretta configurazione SSH
  • riscrittura URL git

Il vantaggio di questo approccio è che, una volta impostato, non richiede alcun lavoro aggiuntivo per farlo correttamente - ad esempio, non è necessario modificare gli URL remoti o ricordare di clonare le cose in modo diverso - la riscrittura degli URL fa funzionare tutto .

~/.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 = personal@personal.email

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

[url "github-work:work-github-org/"]
    insteadOf = git@github.com:work-github-org/

~/dev/work/.gitconfig

[user]
    email = work@work.email

Fintanto che manterrai tutti i repository di lavoro sotto ~ / dev / work e cose personali altrove, git utilizzerà la chiave SSH corretta quando eseguirà pull / cloni / push sul server e collegherà l'indirizzo di posta elettronica corretto a tutti i tuoi impegni.

Riferimenti:


Come funziona con la clonazione? includeIfdovrebbe funzionare solo se c'è una .gitdirectory presente che ho pensato?
detly

Aspetta che lo capisca, è la riscrittura dell'URL che se ne occupa. Questa risposta è incredibilmente utile!
detly

4

Se si utilizza la versione di ssh di Git su Windows, appare la riga del file di identità nella configurazione di ssh

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

dove /csta perc:

Per verificare, in bash di Git

cd ~/.ssh
pwd 

3

Potrebbe essere necessario rimuovere (o commentare) la configurazione host predefinita .ssh / config


1

più specificato nella chiave di configurazione del file 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

0

Come indicato da qualcun altro, core.sshCommandconfig può essere utilizzato per sovrascrivere la chiave SSH e altri parametri.

Ecco un esempio in cui hai una chiave alternativa denominata ~/.ssh/workrsae vuoi usarla per tutti i repository clonati in ~/work.

  1. Crea un nuovo .gitconfigfile sotto ~/work:
[core]
  sshCommand = "ssh -i ~/.ssh/workrsa"
  1. Nella tua configurazione globale di git ~/.gitconfig, aggiungi:
[includeIf "gitdir:~/work/"]
  path = ~/work/.gitconfig

0

Una possibilità da utilizzare ~/.ssh/configè utilizzare la Matchrestrizione anziché la Hostrestrizione. In particolare Match Execchiama un comando shell per decidere se applicare o meno le dichiarazioni. In bash puoi usare il seguente comando:

[ git@git.company.com:gitolite-admin = $(git config --get remote.origin.url)'' ]

Questo utilizza il [comando bash per verificare se due stringhe sono uguali. In questo caso sta verificando se la stringa git@git.company.com:gitolite-admincorrisponde all'output ottenuto dal $(git config --get remote.origin.url)''comando.

È possibile utilizzare qualsiasi altro comando che identifichi il repository su cui si trova la shell. Perché questo funzioni è importante avere la $SHELLvariabile definita sulla shell, nel mio caso /bin/bash. L'esempio completo sarebbe quindi il seguente ~/.ssh/config:

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

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

In questo esempio ho assunto che ~/.ssh/yourOwnPrivateKeycontenga la tua chiave privata e che ~/.ssh/gitolite-admincontenga la chiave privata dell'utente gitolite-admin. Ho incluso la IdentitiesOnly yesdichiarazione per assicurarmi che al server git sia offerta una sola chiave, menzionata da Mark Longair . Le altre dichiarazioni sono solo opzioni ssh standard per git.

Puoi aggiungere questa configurazione se ne hai diversi some_repoche vuoi usare con chiavi diverse. Se si dispone di più repository git@git.company.come la maggior parte di essi utilizza la funzione, ~/.ssh/yourOwnPrivateKeyè più sensato includere questa chiave come predefinita per l'host. In questo caso ~/.ssh/configsarebbe:

Match Exec "[ git@git.company.com: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

Si noti che l'ordine è importante e la Host git.company.comrestrizione dovrebbe apparire dopo Match Execquella o quelle.


0

Configura il tuo repository utilizzando git config. Per esempio:

git config --add --local core.sshCommand 'ssh -i ~/.ssh/<<<PATH_TO_SSH_KEY>>>'
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.