Especifique una clave SSH para git push para un dominio dado

342

Tengo el siguiente caso de uso: me gustaría poder [email protected]:gitolite-adminusar la clave privada del usuario gitolite-admin, mientras quiero usar la clave privada [email protected]:some_repo'mi propia'. AFAIK, no puedo resolver esto usando ~/.ssh/config, porque el nombre de usuario y el nombre del servidor son idénticos en ambos casos. Como uso principalmente mi propia clave privada, la tengo definida ~/.ssh/configpara [email protected]. ¿Alguien sabe de una manera de anular la clave que se utiliza para una sola gitinvocación?

(Aparte: gitolite distingue quién está presionando en función de la clave, por lo que no es un problema, en términos de acceso, propiedad y auditoría, que la cadena usuario @ servidor sea idéntica para diferentes usuarios).

Confusión
fuente
Muy relacionado: stackoverflow.com/questions/4565700/…
Ciro Santilli 郝海东 郝海东 病 六四 事件 法轮功

Respuestas:

597

Incluso si el usuario y el host son iguales, aún se pueden distinguir ~/.ssh/config. Por ejemplo, si su configuración se ve así:

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

Luego solo usa gitolite-as-alicey en gitolite-as-boblugar del nombre de host en su URL:

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

Nota

Desea incluir la opción IdentitiesOnly yespara evitar el uso de identificadores predeterminados. De lo contrario, si también tiene archivos de identificación que coinciden con los nombres predeterminados, se probarán primero porque, a diferencia de otras opciones de configuración (que cumplen con "primero en victorias"), la IdentityFileopción se agrega a la lista de identidades para probar. Ver: /server/450796/how-could-i-stop-ssh-offering-a-wrong-key/450807#450807

Mark Longair
fuente
99
Genial gracias. No había entendido que podía elegir libremente un 'alias' para la especificación del Host en ~ / .ssh / config
Confusion
44
Gracias también por esta respuesta! Uno de mis problemas fue que IdentityFile necesita ser una ruta completa (solo puse id_rsa.rick como argumento para IdentityFile, y esto falló). Consulte la página del comando man ssh_config (5) para ver otra sintaxis de IdentityFile.
rickumali
1
Muchas gracias por la respuesta clara y muy útil. Intenté hacer que esto funcionara por un tiempo y me di por vencido antes con la suposición de que el mismo usuario tenía que usar el mismo archivo de clave privada id_rsa.
DrCord
77
La git@parte en el control remoto no es necesaria, ya que se proporciona en la Userlínea de la configuración.
dolmen
2
Estaba luchando con esta solución hasta que agregué otra línea que contenía IdentitiesOnly yesinmediatamente después de la línea con IdentityFileel host. Parece que estaba transmitiendo múltiples identidades y una de ellas tenía bloqueado el acceso al host.
Fitter Man
57

Un enfoque alternativo al ofrecido anteriormente por Mark Longair es usar un alias que ejecute cualquier comando git, en cualquier control remoto, con una clave SSH alternativa. La idea es básicamente cambiar su identidad SSH al ejecutar los comandos git.

Ventajas relativas al enfoque de alias de host en la otra respuesta:

  • Funcionará con cualquier comando git o alias, incluso si no puede especificar remoteexplícitamente.
  • Es más fácil trabajar con muchos repositorios porque solo necesita configurarlo una vez por máquina cliente, no una vez por repositorio en cada máquina cliente.

Yo uso algunos pequeños guiones y un alias git admin. De esa manera puedo hacer, por ejemplo:

git admin push 

Para pasar al control remoto predeterminado con la tecla SSH alternativa ("admin"). De nuevo, puede usar cualquier comando (no solo push) con este alias. Incluso podría hacer git admin clone ...para clonar un repositorio al que solo tendría acceso utilizando su clave "admin".

Paso 1: Cree las claves SSH alternativas, opcionalmente configure una frase de contraseña en caso de que esté haciendo esto en la máquina de otra persona.

Paso 2: Cree un script llamado "ssh-as.sh" que ejecute cosas que usen SSH, pero use una clave SSH dada en lugar de la predeterminada:

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

Paso 3: Cree un script llamado "git-as.sh" que ejecute comandos git usando la clave SSH dada.

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

Paso 4: Agregue un alias (usando algo apropiado para "PATH_TO_SCRIPTS_DIR" a continuación):

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

Más detalles en: http://noamlewis.wordpress.com/2013/01/24/git-admin-an-alias-for-running-git-commands-as-a-privileged-ssh-identity/

sinelaw
fuente
44
Muy buena respuesta. No olvides agregar comillas dobles alrededor $@-> "$@"para estar seguro.
kevinarpe
@sinelaw ¿Esto todavía funciona? Me sale error de permiso denegado todo el tiempo
Alok Kumar
55

Puede utilizar la variable de entorno git GIT_SSH_COMMAND. Ejecute esto en su terminal debajo de su repositorio git:

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

Reemplace ~/.ssh/your_private_keycon la ruta de la clave privada ssh que desea usar. Y se puede cambiar el comando git posterior (en el ejemplo es git submodule update --init) a otros les gusta git pull, git fetchetc.

Hustlion
fuente
1
El documento completo está en git-scm.com/docs/git#git-codeGITSSHcode ; aunque necesita un Git más reciente (> = 2.3. *).
Christian Ulbrich
2
Gracias por una solución simple que no requiere nada más que configurar una variable de entorno.
Noah Sussman
44
Tenga en cuenta que su ~ / .ssh / id_rsa (o cualquiera que sea su clave predeterminada) tendrá prioridad sobre la que ingrese a través de -i. Entonces, realmente desea usar GIT_SSH_COMMAND = 'ssh -i ~ / .ssh / your_private_key -o IdentitiesOnly = yes' para que ignore otras claves
staktrace
¿Cómo puedes actualizar Git Push? No pude encontrarlo en la documentación
lebed2045
Sería bueno crear alias bash o git, similar a la respuesta de sinelaw pero usando este método en lugar de tener que crear scripts en alguna parte.
Íñigo
14

En sistemas basados ​​en Unix (Linux, BSD, Mac OS X), la identidad predeterminada se almacena en el directorio $ HOME / .ssh , en 2 archivos: private key: $HOME/.ssh/id_rsa public key: $HOME/.ssh/id_rsa.pub cuando se usa sshsin opción -i, usa la clave privada predeterminada para autenticarse con el sistema remoto.

Si tiene otra clave privada que desea usar, por ejemplo $ HOME / .ssh / deploy_key , debe usarssh -i ~/.ssh/deploy_key ...

Esto es molesto. Puede agregar las siguientes líneas en su $ HOME / .bash_profile : ssh-add ~/.ssh/deploy_key ssh-add ~/.ssh/id_rsa

Entonces, cada vez que usa ssho gito scp(básicamente sshtambién), ya no tiene que usar la opción -i.

Puede agregar tantas claves como desee en el archivo $ HOME / .bash_profile .

Châu Hồng Lĩnh
fuente
10

Otra alternativa es usar ssh-ident, para administrar sus identidades ssh .

Se carga automáticamente y utiliza diferentes claves en función de su directorio de trabajo actual, las opciones de ssh, etc., lo que significa que puede tener fácilmente un directorio de trabajo / privado y un directorio que terminan de forma transparente usando diferentes claves e identidades con ssh.

rabexc
fuente
9

Estoy usando Git Bash en Win7. Lo siguiente funcionó para mí.

Cree un archivo de configuración en ~ / .ssh / config o c: / users / [your_user_name] /. Ssh / config. En el archivo ingrese:

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

Supongo que el host debe ser una URL y no solo un "nombre" o referencia para su host. Por ejemplo,

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

La ruta también se puede escribir en formato / c / users / [user_name] / ....

La solución proporcionada por Giordano Scalzo también es genial. https://stackoverflow.com/a/9149518/1738546

usuario1738546
fuente
9

Desde git 2.10 en adelante también es posible usar la configuración gitconfig sshCommand. Docs estado :

Si se establece esta variable, git fetch y git push utilizarán el comando especificado en lugar de ssh cuando necesiten conectarse a un sistema remoto. El comando tiene la misma forma que la variable de entorno GIT_SSH_COMMAND y se anula cuando se establece la variable de entorno.

Un ejemplo de uso sería: git config core.sshCommand "ssh -i ~/.ssh/[insert_your_keyname]

En algunos casos, esto no funciona porque ssh_config anula el comando, en este caso intente ssh -i ~/.ssh/[insert_your_keyname] -F /dev/nullno usar ssh_config.

aleta
fuente
8

Combiné y probé con github el siguiente enfoque, basado en la lectura de otras respuestas, que combina algunas técnicas:

  • configuración SSH correcta
  • reescritura de URL de git

La ventaja de este enfoque es que, una vez configurado, no requiere ningún trabajo adicional para hacerlo bien; por ejemplo, no es necesario cambiar las URL remotas o recordar clonar cosas de manera diferente: la reescritura de URL hace que todo funcione .

~/.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]

Siempre y cuando mantenga todos sus repositorios de trabajo en ~ / dev / work y cosas personales en otro lugar, git usará la clave SSH correcta al hacer pulls / clones / push al servidor, y también adjuntará la dirección de correo electrónico correcta a todos tus compromisos

Referencias

karlos
fuente
¿Cómo funciona esto con la clonación? includeIf¿Debería funcionar solo si hay un .gitdirectorio presente, pensé?
desvío
Espera, lo entiendo, es la reescritura de URL la que se encarga de eso. ¡Esta respuesta es increíblemente útil!
desvío
4

Si usa la versión de ssh de Git en Windows, la línea del archivo de identidad en la configuración de ssh se ve así

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

para donde /cesc:

Para comprobar, en git's bash do

cd ~/.ssh
pwd 
Andrew Murphy
fuente
3

Es posible que deba eliminar (o comentar) la configuración de host predeterminada .ssh / config

ViliusK
fuente
1

más especificado en la clave de configuración de archivo 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ú
fuente
0

Como alguien más mencionó, core.sshCommandconfig se puede usar para anular la clave SSH y otros parámetros.

Aquí hay un ejemplo donde tiene una clave alternativa nombrada ~/.ssh/workrsay desea usarla para todos los repositorios clonados debajo ~/work.

  1. Crea un nuevo .gitconfigarchivo en ~/work:
[core]
  sshCommand = "ssh -i ~/.ssh/workrsa"
  1. En su configuración global de git ~/.gitconfig, agregue:
[includeIf "gitdir:~/work/"]
  path = ~/work/.gitconfig
Mansour
fuente
0

Una posibilidad de usar ~/.ssh/configes usar la Matchrestricción en lugar de la Hostrestricción. En particular, Match Execllama a un comando de shell para decidir si aplica las declaraciones o no. En bash puedes usar el siguiente comando:

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

Esto usa el [comando bash para verificar si dos cadenas son iguales. En este caso, está probando si la cadena [email protected]:gitolite-admincoincide con la salida que se obtiene del $(git config --get remote.origin.url)''comando.

Puede usar cualquier otro comando que identifique el repositorio en el que se encuentra el shell. Para que esto funcione es importante tener la $SHELLvariable definida en su shell, en mi caso /bin/bash. El ejemplo completo sería el siguiente ~/.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

En este ejemplo supuse que ~/.ssh/yourOwnPrivateKeycontiene su propia clave privada y que ~/.ssh/gitolite-admincontiene la clave privada del usuario gitolite-admin. Incluí la IdentitiesOnly yesdeclaración para asegurarme de que solo se ofrezca una clave al servidor git, mencionada por Mark Longair . Las otras declaraciones son solo opciones ssh estándar para git.

Puede agregar esta configuración si tiene varias some_repoque desea usar con diferentes claves. Si tiene varios repositorios [email protected]y la mayoría de ellos los usa ~/.ssh/yourOwnPrivateKey, tiene más sentido incluir esta clave como predeterminada para el host. En este caso el ~/.ssh/configsería:

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

Tenga en cuenta que el orden importa y la Host git.company.comrestricción debe aparecer después del Match Execuno o los unos.

LuisR
fuente
0

Configure su repositorio usando git config. Por ejemplo:

git config --add --local core.sshCommand 'ssh -i ~/.ssh/<<<PATH_TO_SSH_KEY>>>'
episage
fuente