Especifique una clave SSH para git push para un dominio dado


342

Tengo el siguiente caso de uso: me gustaría poder git@git.company.com:gitolite-adminusar la clave privada del usuario gitolite-admin, mientras quiero usar la clave privada git@git.company.com: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 git@git.company.com. ¿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).


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


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/


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.


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 .


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.


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


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.


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 = 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

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


¿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 

3

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


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

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

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:

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

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 git@git.company.comy 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 "[ 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

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


0

Configure su repositorio usando git config. Por ejemplo:

git config --add --local core.sshCommand 'ssh -i ~/.ssh/<<<PATH_TO_SSH_KEY>>>'
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.