Mejor un Sólo Agente

Si decidimos poner la línea eval `ssh-agent` en nuestro ~/.bash_profile (véase .bash_profile vs .bashrc) tenemos un problema: con cada sesión se lanza una nueva copia del agente ssh. Es cierto que el asunto no es preocupante si sólo abrimos una o dos cónsolas, pero si - como es mi caso - abrimos muchas en una sesión X tendremos que escribir la passphrase bastantes veces. Un único agente debería ser suficiente.

Otro problema son las tareas automáticas que usan cron. Las tareas arrancadas mediante cron no heredan las variables de entorno SSH_AUTH_SOCK y SSH_AGENT_PID y por tanto no saben que proceso ssh-agent deben contactar.

ssh-agent y Sesiones X

Es común ver que en ciertos Unix el arranque de la sesión X lleva aparejado el arranque de un agente SSH. Si ese es nuestro caso, tenemos la mayor parte del trabajo hecho. Por ejemplo en una configuración típica de Kubuntu vemos lo siguiente:

$ cat -n /etc/X11/Xsession.options
 1  # $Id: Xsession.options 189 2005-06-11 00:04:27Z branden $
 2  #
 3  # configuration options for /etc/X11/Xsession
 4  # See Xsession.options(5) for an explanation of the available options.
 5  allow-failsafe
 6  allow-user-resources
 7  allow-user-xsession
 8  use-ssh-agent
 9  use-session-dbus

La opción use-ssh-agent hace que se dispare un agente en el momento de arrancar las X. En efecto si vemos los procesos en el sistema descubrimos la presencia de un agente:

casiano@europa:~$ ps -fA | grep agent
casiano   6976  6911  0 10:57 ?        00:00:00 /usr/bin/ssh-agent x-session-manager
casiano   8018  7625  0 11:07 pts/3    00:00:00 grep agent
Viendo las variables de entorno podemos ver el lugar en el que está el socket:
casiano@europa:~$ env | grep -i ssh
SSH_AGENT_PID=6976
SSH_AUTH_SOCK=/tmp/ssh-qkuycC6911/agent.6911
Podemos ver que el socket tiene los permisos puestos para que pueda ser accedida por el usuario que arrancó las X:
casiano@europa:~$ ls -ld /tmp/ssh-qkuycC6911/
drwx------ 2 casiano casiano 4096 2009-04-27 10:57 /tmp/ssh-qkuycC6911/
casiano@europa:~$ ls -l /tmp/ssh-qkuycC6911/
total 0
srw------- 1 casiano casiano 0 2009-04-27 10:57 agent.6911
por tanto el usuario que arrancó las X puede acceder a ese agente. Veamos que claves están en ese agente:
rw------- 1 casiano casiano 0 2009-04-27 10:57 agent.6911
casiano@europa:~$ ssh-add -l
1024 49:4c:e1:b4:1a:ea:e6:73:fc:a1:e5:6b:54:c9:da:62 /home/casiano/.ssh/id_dsa (DSA)
Ya esta la clave /home/casiano/.ssh/id_dsa. Probablemente lo haya hecho en alguna prueba anterior. Para empezar esta nueva prueba desde una situación inicial vamos a suprimir todas las claves del agente.
casiano@europa:~$ ssh-add -D
All identities removed.
Si ahora intento conectarme a una máquina con esa clave, me es solicitada la passphrase:
casiano@europa:~$ ssh orion
Enter passphrase for key '/home/casiano/.ssh/id_dsa':
^C
Interrumpo la conexión pulsando CTRL-C y paso a añadir la clave al agente:
casiano@europa:~$ ssh-add /home/casiano/.ssh/id_dsa
Enter passphrase for /home/casiano/.ssh/id_dsa:
Identity added: /home/casiano/.ssh/id_dsa (/home/casiano/.ssh/id_dsa)
Ahora puedo hacer la conexión sin necesidad de introducir la passphrase:
casiano@europa:~$ ssh orion
Linux orion 2.6.8-2-686 #1 Tue Aug 16 13:22:48 UTC 2005 i686 GNU/Linux

Arrancando el Agente en KDE

Una solución parcial es arrancar el agente tan pronto como se inicia la sesión del escritorio. El siguiente procedimiento funciona en un escritorio KDE:

La opción recomendada es aprovechar el agente ssh creado al arrancar las X. Puede que quiera que las identidades se añadan tan pronto como entra en su escritorio KDE. En ese caso cambie los contenidos de /.kde/env/ssh-agent.sh por algo parecido a esto:

someone@localhost:~/.kde/env$ cat -n ssh-agent.sh
     1  #!/bin/sh
     2  /usr/bin/ssh-add $HOME/.ssh/id_dsa
     3  /usr/bin/ssh-add $HOME/.ssh/thatmachinebackupidentity

Introducción a keychain

La metodología usada en los párrafos anteriores no es válida si no somos el usuario que arranca las X. Este es el caso si estamos ya en una sesión ssh o hemos cambiado de usuario ejecutando su (switch user) o bien queremos ejecutar un proceso por lotes bajo un cron.

En estos casos keychain puede ayudar.

Suprimiendo los Agentes Activos con keychain

Comencemos usando la opción -k para suprimir los agentes activos y asegurarnos que empezamos desde una situación inicial:

lusasoft@LusaSoft:~/.ssh$ keychain -k all

KeyChain 2.6.8; http://www.gentoo.org/proj/en/keychain/
Copyright 2002-2004 Gentoo Foundation; Distributed under the GPL

 * All lusasoft's ssh-agent(s) (5678) are now stopped
 * All lusasoft's gpg-agent(s) (6823) are now stopped

La opción -k tiene la sintáxis:

     -k which
Las siguientes opciones son válidas para which:

Funcionamiento de keychain

Cuando se ejecuta keychain comprueba si existe ya un agente ssh-agent ejecutándose. Si no es el caso arranca uno. Si existe no cargará uno nuevo. Sin embargo es necesario que el usuario o el script llamen a ~/.keychain/europa-sh para tener acceso al agente.

lusasoft@LusaSoft:~/.ssh$ keychain ~/.ssh/id_dsa

KeyChain 2.6.8; http://www.gentoo.org/proj/en/keychain/
Copyright 2002-2004 Gentoo Foundation; Distributed under the GPL

 * Initializing /home/lusasoft/.keychain/LusaSoft-sh file...
 * Initializing /home/lusasoft/.keychain/LusaSoft-csh file...
 * Initializing /home/lusasoft/.keychain/LusaSoft-fish file...
 * Starting ssh-agent
 * Initializing /home/lusasoft/.keychain/LusaSoft-sh-gpg file...
 * Initializing /home/lusasoft/.keychain/LusaSoft-csh-gpg file...
 * Initializing /home/lusasoft/.keychain/LusaSoft-fish-gpg file...
 * Starting gpg-agent
 * Adding 1 ssh key(s)...
Identity added: /home/lusasoft/.ssh/id_dsa (/home/lusasoft/.ssh/id_dsa)
Salva las variables de entorno en ~/.keychain/${HOSTNAME}-sh,
lusasoft@LusaSoft:~$ tree .keychain/
.keychain/
|-- LusaSoft-csh
|-- LusaSoft-csh-gpg
|-- LusaSoft-fish
|-- LusaSoft-fish-gpg
|-- LusaSoft-sh
`-- LusaSoft-sh-gpg
Estos ficheros contienen los comandos para establecer las variables de entorno. Por ejemplo:
$ cat -n .keychain/europa-sh
     1  SSH_AUTH_SOCK=/tmp/ssh-ctTDo22823/agent.22823; export SSH_AUTH_SOCK;
     2  SSH_AGENT_PID=22824; export SSH_AGENT_PID;
De este modo las subsiguientes llamadas no interactivas a ssh - por ejemplo, cron jobs - pueden hacer un source del correspondiente guión y conectarse con el único agente obviando asi la necesidad de solicitar las claves.
$ source ~/.keychain/europa-sh
$ ssh orion
Linux orion 2.6.8-2-686 #1 Tue Aug 16 13:22:48 UTC 2005 i686 GNU/Linux
Si abrimos otra terminal deberemos hacer de nuevo la llamada a source ~/.keychain/europa-sh. Por supuesto, lo mejor es poner la llamada a keychain y a source ~/.keychain/europa-sh en nuestro fichero de arranque ~/.bashrc o bash_profile.

/usr/bin/keychain ~/.ssh/id_dsa
source ~/.keychain/europa-sh

Cuando el Agente no Conoce la Clave

Cuando se ejecuta, keychain verifica que la clave especificada es conocida por el agente. Si no es así nos solicitará la passphrase.

Véase la siguiente secuencia de comandos. Primero ponemos una passphrase a la identidad por defecto:

lusasoft@LusaSoft:~$ ssh-keygen -p
Enter file in which the key is (/home/lusasoft/.ssh/id_rsa): /home/lusasoft/.ssh/id_dsa
Key has comment '/home/lusasoft/.ssh/id_dsa'
Enter new passphrase (empty for no passphrase): ***************
Enter same passphrase again: ***************
Your identification has been saved with the new passphrase.
A continuación limpiamos los agentes:
lusasoft@LusaSoft:~$ keychain --clear

KeyChain 2.6.8; http://www.gentoo.org/proj/en/keychain/
Copyright 2002-2004 Gentoo Foundation; Distributed under the GPL

 * Found existing ssh-agent (6927)
 * Found existing gpg-agent (6951)
 * ssh-agent: All identities removed.
 * gpg-agent: All identities removed.

Cargamos de nuevo keychain con la identidad por defecto:

lusasoft@LusaSoft:~$ keychain ~/.ssh/id_dsa

KeyChain 2.6.8; http://www.gentoo.org/proj/en/keychain/
Copyright 2002-2004 Gentoo Foundation; Distributed under the GPL

 * Found existing ssh-agent (6927)
 * Found existing gpg-agent (6951)
 * Adding 1 ssh key(s)...
Identity added: /home/lusasoft/.ssh/id_dsa (/home/lusasoft/.ssh/id_dsa)
Ahora se nos solicita la passphrase (por defecto mediante ssh-askpass). Después de escribirla la identidad es añadida al agente.

lusasoft@LusaSoft:~$ keychain --nogui ~/.ssh/id_dsa

KeyChain 2.6.8; http://www.gentoo.org/proj/en/keychain/
Copyright 2002-2004 Gentoo Foundation; Distributed under the GPL

 * Found existing ssh-agent (6927)
 * Found existing gpg-agent (6951)
 * Adding 1 ssh key(s)...
Enter passphrase for /home/lusasoft/.ssh/id_dsa: *********************
Identity added: /home/lusasoft/.ssh/id_dsa (/home/lusasoft/.ssh/id_dsa)

Tipos de Agentes

keychain soporta también gpg-agent. Por defecto arranca todos los agentes disponibles. Se puede limitar los agentes arrancados usando la opción --agents. Por ejemplo --agents 'gpg,ssh'

Agentes en Mal Estado

La llamada a keychain creará un nuevo agente si el fichero /home/pp2/.keychain/europa-sh queda obsoleto (por ejemplo, si SSH_AUTH_SOCK referencia un socket que no existe o no existe un proceso con pid el referenciado en SSH_AGENT_PID). Véase la siguiente sesión de comandos:

pp2@europa:~$ ps -fA | grep agent
casiano   6976  6911  0 10:57 ?        00:00:00 /usr/bin/ssh-agent x-session-manager
pp2      22824     1  0 12:42 ?        00:00:00 ssh-agent
pp2      22848     1  0 12:42 ?        00:00:00 gpg-agent --daemon
pp2      32569 30843  0 13:06 pts/13   00:00:00 grep agent
pp2@europa:~$ kill -9 22824
pp2@europa:~$ ps -fA | grep agent
pp2       3165 30843  0 13:07 pts/13   00:00:00 grep agent
casiano   6976  6911  0 10:57 ?        00:00:00 /usr/bin/ssh-agent x-session-manager
pp2      22848     1  0 12:42 ?        00:00:00 gpg-agent --daemon
pp2@europa:~$ keychain

KeyChain 2.6.8; http://www.gentoo.org/proj/en/keychain/
Copyright 2002-2004 Gentoo Foundation; Distributed under the GPL

 * Initializing /home/pp2/.keychain/europa-sh file...
 * Initializing /home/pp2/.keychain/europa-csh file...
 * Initializing /home/pp2/.keychain/europa-fish file...
 * Starting ssh-agent
 * Found existing gpg-agent (22848)

pp2@europa:~$ ps -fA | grep agent
pp2       3198     1  0 13:07 ?        00:00:00 ssh-agent
pp2       3225 30843  0 13:08 pts/13   00:00:00 grep agent
casiano   6976  6911  0 10:57 ?        00:00:00 /usr/bin/ssh-agent x-session-manager
pp2      22848     1  0 12:42 ?        00:00:00 gpg-agent --daemon

La opción -eval de keychain

La opción -eval de keychain hace que keychain envíe a stdout el contenido del script. Así podemos arrancar el agente y añadirle la clave en un paso con:

pp2@europa:~/Lbook$ eval `keychain -eval ~/.ssh/id_dsa`

Véase También



Subsecciones
Casiano Rodriguez León 2015-06-18