¿Cómo decirle a git qué clave privada usar?

618

sshtiene la -iopción de indicar qué archivo de clave privada usar al autenticar:

-i identity_file

    Selecciona un archivo del que se lee la identidad (clave privada) para la autenticación RSA o DSA. El valor predeterminado es ~/.ssh/identitypara la versión 1 del protocolo ~/.ssh/id_rsay ~/.ssh/id_dsapara la versión 2 del protocolo. Los archivos de identidad también pueden especificarse por host en el archivo de configuración. Es posible tener múltiples -iopciones (y múltiples identidades especificadas en los archivos de configuración).

¿Hay una manera similar de saber gitqué archivo de clave privada usar en un sistema con múltiples claves privadas en el ~/.sshdirectorio?

jrdioko
fuente
2
También relacionado serverfault.com/questions/194567/…
Machavity

Respuestas:

653

En ~/.ssh/config, agregue:

host github.com
 HostName github.com
 IdentityFile ~/.ssh/id_rsa_github
 User git

Ahora puedes hacerlo git clone [email protected]:username/repo.git.

NOTA: Verifique que los permisos en IdentityFile sean 400. SSH rechazará, de una manera no claramente explícita, las claves SSH que son demasiado legibles. Simplemente se verá como un rechazo de credenciales. La solución, en este caso, es:

chmod 400 ~/.ssh/id_rsa_github
concha
fuente
107
¿Qué sucede si necesita conectarse al mismo host con diferentes claves?
Valentin Klinghammer
66
@Quelltextfabrik: puede agregar otra sección con un Host diferente: nerderati.com/2011/03/…
Ben Challenor
1
@Cliff Nop, en mi página de manual: " HostName: especifica el nombre de host real para iniciar sesión. Esto se puede usar para especificar apodos o abreviaturas para hosts". Mi versión ssh es openssh-6.7p1.
Grissiom
1
@Grissiom Eso es exactamente lo que dice. Pero parece que entiendes el significado al revés. Se requiere host (o Match). Para crear un apodo de host, coloque el apodo en la línea de Host y el nombre de host real en la línea de HostName. Ejemplos: saltycrane.com/blog/2008/11/…
Cliff
10
Si el archivo de configuración es nuevo, no olvide hacerlochmod 600 ~/.ssh/config
elysch
324

Variable de entorno GIT_SSH_COMMAND:

Desde Git versión 2.3.0, puede usar la variable de entorno GIT_SSH_COMMANDcomo esta:

GIT_SSH_COMMAND="ssh -i ~/.ssh/id_rsa_example" git clone example

Tenga en cuenta que a -iveces puede ser anulado por su archivo de configuración, en cuyo caso, debe darle a SSH un archivo de configuración vacío, como este:

GIT_SSH_COMMAND="ssh -i ~/.ssh/id_rsa_example -F /dev/null" git clone example

Configuración core.sshCommand:

¡Desde Git versión 2.10.0, puede configurar esto por repositorio o globalmente, por lo que ya no tiene que configurar la variable de entorno!

git config core.sshCommand "ssh -i ~/.ssh/id_rsa_example -F /dev/null"
git pull
git push
Flimm
fuente
1
Tuve que exportar la variable de shell a una variable de entorno para que esto funcionara, es decir export GIT_SSH_COMMAND="ssh -i ~/.ssh/id_rsa_example", luegogit clone example
Abdull
66
@Abdull En Bash, hacer la asignación en la misma línea que el comando exporta la variable de entorno solo para ese comando. Inténtelo: example=hello /usr/bin/env | grep example.
Flimm
3
las cosas han mejorado aún más: a partir de Git 2.10, puede almacenar el comando en su configuración de Git: stackoverflow.com/a/38474220/520162
eckes
2
@Noitidart /dev/nulles solo un nombre de archivo válido en sistemas operativos tipo UNIX, no funciona en Windows.
Flimm
2
Para mí GIT_SSH_COMMANDno funcionó hasta que usé IdentitiesOnly, como este comando: GIT_SSH_COMMAND="ssh -i ~/.ssh/mysubdir/id_rsa -o 'IdentitiesOnly yes'" git push.
Tyler Collier
100

No hay una forma directa de saber gitqué clave privada usar, ya que depende sshde la autenticación del repositorio. Sin embargo, todavía hay algunas maneras de lograr su objetivo:

Opción 1: ssh-agent

Puede usar ssh-agentpara autorizar temporalmente su clave privada.

Por ejemplo:

$ ssh-agent sh -c 'ssh-add ~/.ssh/id_rsa; git fetch user@host'

Opcion 2: GIT_SSH_COMMAND

Pase los argumentos ssh utilizando la GIT_SSH_COMMANDvariable de entorno (Git 2.3.0+).

Por ejemplo:

$ GIT_SSH_COMMAND='ssh -i ~/.ssh/id_rsa -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no' \
  git clone user@host

Puede escribir todo esto en una línea: ignore $y omita el \.

Opcion 3: GIT_SSH

Pase los argumentos ssh utilizando la GIT_SSHvariable de entorno para especificar sshbinarios alternativos .

Por ejemplo:

$ echo 'ssh -i ~/.ssh/id_rsa -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no $*' > ssh
$ chmod +x ssh
$ GIT_TRACE=1 GIT_SSH='./ssh' git clone user@host

Nota: Las líneas anteriores son líneas de comando de shell (terminal) que debe pegar en su terminal. Crearán un archivo llamado ssh, lo harán ejecutable y (indirectamente) lo ejecutarán.

Nota: GIT_SSHestá disponible desde v0.99.4 (2005).

Opcion 4: ~/.ssh/config

Utilice el ~/.ssh/configarchivo como se sugiere en otras respuestas para especificar la ubicación de su clave privada, p. Ej.

Host github.com
  User git
  Hostname github.com
  IdentityFile ~/.ssh/id_rsa
kenorb
fuente
1
//, ¿Qué pasa si tu identidad en ssh-agent se reenvía, como en esta pregunta? superuser.com/questions/971732/...
Nathan Basanese
1
Me permití reformatear esta publicación: OMI, esta es, con mucho, la respuesta más completa. En su diseño original, un escaneo rápido sugirió que la publicación describía una única solución complicada para el problema, por lo que me la perdí.
Alberto
3
$ ssh-agent sh -c 'ssh-add ~/.ssh/id_rsa; git fetch user@host'funcionó para mí cuando nada más lo haría. Prestigio.
Daniel Dewhurst
1
Tuve que usar el ~/.ssh/configmétodo, los embalajes no me funcionaron ...
Greg Dubicki
1
GIT_SSHestá disponible desde v0.99.4 (agosto de 2005) , así que básicamente desde que existe Git (abril de 2005).
Dominik
32

Escriba una secuencia de comandos que llame sshcon los argumentos que desee y coloque el nombre de archivo de la secuencia de comandos $GIT_SSH. O simplemente ponga su configuración ~/.ssh/config.

Ignacio Vazquez-Abrams
fuente
2
Otra explicación de cómo hacer esto.
Sithsu
1
~/.ssh/configEs el camino a seguir.
hek2mgl
Trabajo en una máquina (A) desde la que puedo enviar a un servidor (B) que solo acepta autenticación de clave ssh. Si bien mi configuración ~ / .ssh / config en (A) funciona perfectamente bien cuando trabajo directamente en esa máquina, no lo hace cuando inicio sesión desde otra ubicación (C). El uso $GIT_SSHy un script resolvieron este problema. ¡Gracias!
bsumirak
18

Si no desea tener que especificar variables de entorno cada vez que ejecuta git, no desea otro script de contenedor, no puede / no puede ejecutar ssh-agent (1), ni desea descargar otro paquete solo para esto, use el git -remote-ext (1) transporte externo:

$ git clone 'ext::ssh -i $HOME/.ssh/alternate_id git.example.com %S /path/to/repository.git'
Cloning into 'repository'
(...)
$ cd repository
$ git remote -v
origin  ext::ssh -i $HOME/.ssh/alternate_id git.example.com %S /path/to/repository.git (fetch)
origin  ext::ssh -i $HOME/.ssh/alternate_id git.example.com %S /path/to/repository.git (push)

Considero que esta solución es superior porque:

  • Es repositorio / remoto específico
  • Evite la hinchazón del script de envoltura
  • No necesita el agente SSH: útil si desea clones / push / pull desatendidos (por ejemplo, en cron)
  • Definitivamente, no se necesita herramienta externa
flaviovs
fuente
2
Esta respuesta fue exactamente lo que necesitaba para obligar a los gitrecursos de Chef a usar claves de implementación específicas del repositorio para clonar / buscar desde repositorios privados de Github. La ventaja adicional de este método sobre los basados ​​en el entorno / script es que, dado que la ruta de la clave está codificada en la configuración del repositorio de trabajo, utilizará la misma clave tanto en el clon inicial como en las recuperaciones / empujes posteriores.
Adam Franco
2
¡GUAUU! Esto es simplemente genial, no sabía sobre esto. Gracias por la respuesta, muy útil también en entornos de títeres, para evitar la molestia adicional de gestionar, .ssh/configetc. ¡+1!
gf_
1
Esta solución no funciona junto con el indicador --recursive. Los submódulos no se obtienen con la clave especificada y, por lo tanto, fallan si requieren autenticación.
Daniele Testa
1
Cada submódulo es un repositorio completamente diferente, con su propio conjunto de controles remotos. Git los une para su conveniencia, pero de ninguna manera los controles remotos de un submódulo están vinculados a los del repositorio principal. Me temo que debe configurar el control remoto utilizando el exttransporte en cada submódulo para que la recursividad en el padre funcione.
flaviovs
2
Si encuentra el siguiente error fatal: transport 'ext' not allowed, debe incluir en la lista blanca el protocolo ext a través de export GIT_ALLOW_PROTOCOL=ext. Básicamente, el ayudante remoto git-remote-ext (que admite URL "ext :: ssh example.com% S foo / repo") permite la ejecución arbitraria de comandos. Esto normalmente no es una preocupación porque el usuario siempre ve y confía en la URL que pasa a git. Sin embargo, los submódulos git, a través del archivo .gitmodules, permiten que un atacante solicite al cliente que busque URL arbitrarias de git. hackerone.com/reports/104465
Gomino
17

Utilice la configuración de host personalizada ~/.ssh/config, como esta:

Host gitlab-as-thuc  
    HostName github.com
    User git
    IdentityFile ~/.ssh/id_rsa.thuc
    IdentitiesOnly yes

luego use su nombre de host personalizado como este:

git remote add thuc git@gitlab-as-thuc:your-repo.git  
Thucnguyen
fuente
2
Esta es la respuesta que estaba buscando, ya que tengo cuentas separadas de GitHub para el hogar y el trabajo. Solo tenía que configurar Host work.github.com HostName github.com IdentityFile ~/.ssh/worky reemplazar "github.com" por "work.github.com" cada vez que clonaba un repositorio de trabajo. Todavía se conecta a "github.com", pero usando un par de claves no predeterminado.
Mikkel
1
La URL para detalles (" itblog.study.land / ..." ) ya no funciona :(
Carl Smotricz
@CarlSmotricz el original se mudó aquí: medium.com/@thucnc/…
thucnguyen
3
¡¡¡FINALMENTE!!! Esta respuesta en realidad muestra cómo puedes utilizar lo que pones en el ~/.ssh/configarchivo. En cualquier otra respuesta se pierde cómo puede configurar el host cuando agrega el origen, lo que automáticamente le permite a git usar el archivo de clave correcto. ¡¡GRACIAS!!
BrianVPS
Bien, eso era lo que estaba buscando :)
Lucas D'Avila
15

Después de mi lucha, $GIT_SSHme gustaría compartir lo que funcionó para mí.

A través de mis ejemplos, asumiré que tiene su clave privada ubicada en/home/user/.ssh/jenkins

Error a evitar: el valor GIT_SSH incluye opciones

$ export GIT_SSH="ssh -i /home/user/.ssh/jenkins"

o cualquier error similar, ya que git intentará ejecutar el valor como un archivo . Por esa razón, tienes que crear un script.

Ejemplo de trabajo del script $ GIT_SSH /home/user/gssh.sh

El script se invocará de la siguiente manera:

$ $GIT_SSH [username@]host [-p <port>] <command>

El funcionamiento del script de muestra podría verse así:

#!/bin/sh
ssh -i /home/user/.ssh/jenkins $*

Tenga $*en cuenta que al final, es una parte importante de la misma.

Una alternativa aún más segura, que evitaría cualquier posible conflicto con cualquier cosa en su archivo de configuración predeterminado (además de mencionar explícitamente el puerto a usar) sería:

#!/bin/sh
ssh -i /home/user/.ssh/jenkins -F /dev/null -p 22 $*

Suponiendo que el guión esté dentro /home/user/gssh.sh, usted deberá:

$ export GIT_SSH=/home/user/gssh.sh

y todo funcionará.

Jan Vlcinsky
fuente
Gracias. Solo tenga en cuenta: use "$ @" en lugar de $ * para los argumentos de paso, ya que el primero se comporta correctamente cuando los argumentos contienen espacios en blanco.
Piotr Findeisen
@PiotrFindeisen Gracias por tu nota. Sin embargo, no lo entiendo completamente: en zsh me ayuda a mantener las cadenas con espacio en una sola pieza, pero en bash no. ¿Me puede decir más o señalar alguna explicación? No quiero agregar alguna modificación a ciegas.
Jan Vlcinsky
Debes eliminar la primera mitad de tu respuesta. Nadie está interesado en una solución que no funciona, y una lectura desperdiciada que ofusca la respuesta correcta en la parte inferior, que funciona de maravilla.
Cerin
@Cerin Si te refieres a eliminar el "Error para evitar" voy a mantenerlo allí. Comparte trampas comunes para evitar y es muy corto. Estoy seguro de que alguien intentaría optimizar la solución proporcionando todas las cosas en variable (esto me sucedió a mí), así que traté de acortar el camino hacia el éxito.
Jan Vlcinsky
5

Puede usar ssh-ident en lugar de crear su propio contenedor.

Puede leer más en: https://github.com/ccontavalli/ssh-ident

Carga las claves ssh a pedido cuando se necesita por primera vez, una vez, incluso con múltiples sesiones de inicio de sesión, xterms o hogares compartidos NFS.

Con un pequeño archivo de configuración, puede cargar automáticamente diferentes claves y mantenerlas separadas en diferentes agentes (para el reenvío de agentes) dependiendo de lo que necesite hacer.

rabexc
fuente
4

Tenía un cliente que necesitaba una cuenta de github separada. Así que necesitaba usar una clave separada solo para este proyecto.

Mi solución fue agregar esto a mi .zshrc / .bashrc:

alias infogit="GIT_SSH_COMMAND=\"ssh -i ~/.ssh/id_specialkey\" git $@"

Cada vez que quiero usar git para ese proyecto, reemplazo "infogit" con git:

infogit commit -am "Some message" && infogit push

Para mí, es más fácil de recordar.

Michael Cole
fuente
4

Así que configuré la variable GIT_SSH env en $HOME/bin/git-ssh.

Para permitir que mi configuración de repositorio dicte qué identidad ssh usar, mi ~/bin/git-ssharchivo es este:

#!/bin/sh
ssh -i $(git config --get ssh.identity) -F /dev/null -p 22 $*

Luego tengo una configuración de configuración global de git:

$ git config --global ssh.identity ~/.ssh/default_id_rsa

Y dentro de cualquier repositorio de git, solo puedo establecer un ssh.identityvalor de configuración de git local :

$ git config --local ssh.identity ~/.ssh/any_other_id_rsa

Voila!

Si puede tener una dirección de correo electrónico diferente para cada identidad, se vuelve aún más simple, porque solo puede nombrar sus claves después de sus direcciones de correo electrónico y luego hacer que el usuario email de git config maneje la selección de claves de ~/bin/git-sshesta manera:

#!/bin/sh
ssh -i $HOME/.ssh/$(git config --get user.email) -F /dev/null -p 22 $*
Brendan Baldwin
fuente
2

Mi solución fue esta:

crear un guión:

#!/bin/bash
KEY=dafault_key_to_be_used
PORT=10022 #default port...
for i in $@;do
   case $i in
    --port=*)
        PORT="${i:7}";;
    --key=*)KEY="${i:6}";;
   esac
done
export GIT_SSH_COMMAND="ssh -i $HOME/.ssh/${KEY} -p ${PORT}"
echo Command: $GIT_SSH_COMMAND

entonces cuando tienes que cambiar la ejecución var:

. ./thescript.sh [--port=] [--key=]

¡No olvides el punto extra! esto hace que el script establezca los entornos vars !! --key y --port son opcionales.

Salsicha
fuente
2

Construyo sobre @shellholic y este hilo SO con unos cuantos tragos. Utilizo GitHub como ejemplo y supongo que tiene una clave privada ~/.ssh/github(de lo contrario, vea este hilo SO ) y que agregó la clave pública a su perfil de GitHub (de lo contrario, consulte la ayuda de GitHub ).

Si es necesario, cree un nuevo archivo de configuración SSH en ~/.ssh/configy cambie los permisos a 400

touch ~/.ssh/config
chmod 600 ~/.ssh/config

Agregue esto al ~/.ssh/configarchivo:

Host github.com
    IdentityFile ~/.ssh/github
    IdentitiesOnly yes

Si ya tiene una configuración remota, es posible que desee eliminarla; de lo contrario, es posible que se le solicite su nombre de usuario y contraseña:

git remote rm origin

Luego agregue un control remoto al repositorio git y observe los dos puntos antes del nombre de usuario:

git remote add origin [email protected]:user_name/repo_name.git

Y luego los comandos git funcionan normalmente, por ejemplo:

git push origin master
git pull origin 

@HeyWatchThis en este hilo SO sugirió agregar IdentitiesOnly yespara evitar el comportamiento predeterminado de SSH de enviar el archivo de identidad que coincida con el nombre de archivo predeterminado para cada protocolo. Vea ese hilo para más información y referencias.

mmorin
fuente
Este fue mi error: "Si ya tienes una configuración remota ...". ¡¡¡Muchas gracias!!!
Allan Andrade
error común --- esta es la respuesta
Goddard
1

En general, desea utilizar ~/.ssh/configpara esto. Simplemente empareje las direcciones del servidor con las claves que desea utilizar para ellos de la siguiente manera:

Host github.com
  IdentityFile ~/.ssh/id_rsa.github
Host heroku.com
  IdentityFile ~/.ssh/id_rsa.heroku
Host *
  IdentityFile ~/.ssh/id_rsa

Host *denota cualquier servidor, por lo que lo uso para establecer ~/.ssh/id_rsacomo la clave predeterminada para usar.

Zaz
fuente
1

Solo usa ssh-agenty ssh-addcomandos.

# create an agent
ssh-agent

# add your default key
ssh-add ~/.ssh/id_rsa

# add your second key
ssh-add ~/.ssh/<your key name>

Después de ejecutar los comandos anteriores, puede usar ambas teclas al mismo tiempo. Sólo tipo

git clone [email protected]:<yourname>/<your-repo>.git

para clonar tu repositorio.

Debe ejecutar el comando anterior después de reiniciar su máquina.

Jinmiao Luo
fuente
Explique el proceso, incluido ¿Cómo puedo crear un agente
Srikrushna
0

Estoy usando git versión 2.16 y no necesito una sola secuencia de comandos, ni siquiera una configuración o comandos modificados.

  • Acabo de copiar mi clave privada a .ssh / id_rsa
  • establecer permisos a 600

Y git lee la tecla automáticamente. No pregunto nada y no arroja un error. Solo funciona bien.

akprajapati
fuente
¿Notó que la pregunta es sobre "un sistema con múltiples claves privadas en el ~/.sshdirectorio"?
Scott
0

Si bien la pregunta no lo solicita, esta respuesta para cualquier persona que busque resolver el mismo problema específicamente para .

La solución de gitlab

Intenté usar el enfoque de , pero incluso la documentación de git recomienda usar ~/.ssh/configpara algo más que el caso simple. En mi caso, estoy presionando a un servidor , y quería hacerlo como un usuario específico, que por supuesto se define mediante la durante la y no el nombre de usuario git. Una vez implementado, simplemente realizo lo siguiente:

~/myrepo> git mycommit -m "Important Stuff"
~/myrepo> git mypush
[proceed to enter passphrase for private key...]

Preparar

Recordemos la ubicación de su /myfolder/.ssh/my_gitlab_id_rsa en mi caso.

Agregar una entrada en ~/.ssh/config:

Host gitlab-delegate
    HostName gitlab.mydomain.com
    User git
    IdentityFile /myfolder/.ssh/my_gitlab_id_rsa
    IdentitiesOnly yes

Agrega el en ~/.gitconfig:

mypush = "!f() { \
           path=$(git config --get remote.origin.url | cut -d':' -f2); \
           branch=$(git rev-parse --abbrev-ref HEAD); \
           git remote add gitlab_as_me git@gitlab-delegate:$path && \
           git push gitlab_as_me $branch && \
           git pull origin $branch; \
           git remote remove gitlab_as_me; \
         }; f"

Como beneficio adicional, realizo mis confirmaciones en este mismo host como un usuario específico con este :

mycommit = "!f() { \
             git -c "user.name=myname" -c "[email protected]" commit \"$@\"; \
           }; f"

Explicación

Todo lo anterior supone que el control remoto relevante es originy la rama relevante está actualmente desprotegida. Como referencia me encontré con varios elementos que debían abordarse:

  • La solución requiere crear un nuevo control remoto gitlab_as_me, y no me gustó ver el control remoto adicional colgando en mi árbol de registro, así que lo elimino cuando termine
  • Para crear el control remoto, es necesario generar la url del control remoto sobre la marcha; en el caso de gitlab, esto se logró con un simple bash
  • Al realizar un impulso gitlab_as_me, debe ser específico sobre qué rama está presionando
  • Después de realizar el empuje, su originpuntero local debe ser "actualizado" para que coincida gitlab_as_me( git pull origin $branchesto lo hace)
dtmland
fuente
0

Cuando tienes varias cuentas git y quieres una clave ssh diferente

Debe seguir el mismo paso para generar la clave ssh, pero asegúrese de

ssh-keygen -t ed25519 -C "[email protected]" 

Ingrese la ruta que desea guardar (Ej: my-pc / Desktop / .ssh / ed25519)

Agregue la clave pública a su gitlab ( Cómo agregar clave ssh a gitlab )

Tienes que crear una nueva identidad ssh usando el siguiente comando

ssh-add ~/my-pc/Desktop/.ssh/ed25519
Srikrushna
fuente
(1) ¿Estás citando a alguien o algo? Si es así, identifique la fuente. De lo contrario, no utilice el formato de presupuesto. (2) ¿Qué es “ed25519”? ... ... ... ... ... ... ... ... ... ... ... Por favor no responda en los comentarios; edite  su respuesta para que sea más clara y completa.
Scott,