22 – Como clonar un repo privado a un servidor remoto usando SSH Agent Forwarding
Hoy en día, la práctica recomendada es usar las llaves SSH para manejar la autenticación y autorización de tus repositorios privados en Github, Gitlab o Sourcehut.
Cuando creamos nuestra llave SSH en realidad creamos dos partes criptográficamente unidas, usando lo que se conoce como criptografía asimétrica, criptografía de dos partes o criptografía de clave pública.
La llave privada por convención id_rsa
ubicada en ~/.ssh/
se usa en el proceso de autenticación con cualquier servidor o servicio (Github/Gitlab/Sourcehut) que tenga conocimiento de tu llave pública id_rsa.pub
. Esta clave/llave privada se usa para desencriptar un mensaje encriptado con tu llave pública y solo con esa llave se puede desencriptar y por lo tanto validar que eres tú el dueño. Es decir si no tienes la llave privada, la llave pública no sirve de nada. Además, si alguien más tiene tu llave privada se puede hacer pasar por ti, así que nunca la compartas.
Nunca compartas tu llave privada, ya que cualquier persona con acceso a ella va a tener acceso a todos los productos donde te conectas por tu llave pública.
git clone
local con SSH
Cuando hacemos un git clone <remote-url>
en nuestra maquina local, ssh
junto a git
se encarga de autenticarnos y de poder acceder a nuestro repo remoto.
Por ejemplo, voy a clonar el siguiente repositorio privado en mi máquina local
git clone git@gitlab.com:we-make/prueba.git
Y, dado que tengo configurado en Gitlab mi llave pública, Gitlab me permite acceder al repositorio.
Cloning into 'prueba'...
remote: Enumerating objects: 358, done.
remote: Counting objects: 100% (358/358), done.
...
Resolving deltas: 100% (2443/2443), done.
Temporalmente voy a mover la llave privada de ~/.ssh/id_rsa
para simular que no tengo la credenciales necesarias.
mv ~/.ssh/id_rsa ~/backup
N.B.: en Mac OS Catalina tenemos que hacer un restart para que se aplique este cambio dado que el método de reiniciar no me funcionó:
sudo launchctl unload /System/Library/LaunchDaemons/ssh.plist
sudo launchctl load /System/Library/LaunchDaemons/ssh.plist
Ahora ejecuto el mismo comando de git clone
$ git clone git@gitlab.com:we-make/prueba.git
git@gitlab.com: Permission denied (publickey).
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
Como vemos me arroja un error de permission denied (publickey)
básicamente me dice que no tengo la llave necesaria para acceder.
Si ponemos de vuelta la llave privada, todo vuelve a la normalidad.
mv ~/backup ~/.ssh/id_rsa
git clone
en un servidor remoto
Entonces, ¿qué pasa cuando queremos hacer un clone en un servidor remoto? Si no tenemos la llave privada en el servidor entonces nos va a tirar el mismo error permission denied (publickey)
.
Podemos hacer tres cosas para solucionarlo. La primera es copiar la llave privada al servidor, y la segunda es crear una nueva llave privada en el servidor con ssh-keygen
e incluirla en nuestra cuenta de Gitlab/Github/Sourcehut (deployment keys).
La primera opción no es recomendada dado que estarías otorgándole todos los accesos al servidor. La segunda opción es algo más compleja ya que si tienes varios servidores tendrías que hacer la misma operación varias veces.
La tercera opción, y en este caso lo que yo recomiendo, es usar lo que se llama Agent Forwarding
. Lo que hace el Agent Forwarding
es “copiar” la clave privada al agente de SSH. Veamos como usarlo.
Usando SSH Agent Forwarding
El primer método para usar Agent Forwarding es usar el flag -A
cuando se ejecuta el comando de ssh
. Por ejemplo, si me quiero conectar al servidor example.com
con el usuario demo
usando Agent forwarding
el comando sería:
ssh -A demo@example.com
Luego, una vez dentro del servidor remoto puedo ejecutar el mismo comando git clone
como si estuviera en la computadora local.
$ git clone git@gitlab.com:we-make/prueba.git
Cloning into 'prueba'...
remote: Enumerating objects: 358, done.
remote: Counting objects: 100% (358/358), done.
...
Resolving deltas: 100% (2443/2443), done.
De esta manera, podemos hacer también los otros comandos de git git pull
o git push
, por ejemplo.
El segundo método para usar Agent Forwarding es agregarlo a la configuración de SSH en ~/.ssh/config
(si no tienen el archivo creen uno nuevo con el nombre). Podemos editarlo con el siguiente comando, o también pueden usar su editor de textos favorito:
vim ~/.ssh/config
En el archivo deberíamos incluir las siguientes líneas:
~/.ssh/config
...
Host example.com
ForwardAgent yes
...
De esta manera todas las conexiones con example.com tendrán -A
activados por defecto.
⚠️ Advertencia Importante: ⚠️
Si piensas modificar el file anterior para usar Agent Forwarding con todos los hosts (Host *
) ten en cuenta que eso probablemente sea una mala idea. El problema es que estarás compartiendo tu llave privada con todos y cada uno de los servidores con los cuales te conectas. Obviamente no van a tener la llave privada en sí, pero si tendrán acceso ilimitado mientras estés conectado. Solo agrega esta opción a servidores que confíes y en los cuales necesites usar agent forwarding.
Conclusión
Como vemos, usar este método de Agent forwarding
nos simplifica mucho nuestro proceso de despliegue a un servidor nuevo. Incluso Capistrano lo utiliza para los despliegues de aplicaciones en Ruby en Rails. Solo tenemos que tener en cuenta que hay que tener cuidado sobre el acceso que le estas otorgando al servidor remoto cuando permites el agent forwarding.