En el artículo Cómo autenticar con clave pública en SSH expliqué detalladamente todos los pasos necesarios para autenticar con clave pública un usuario a través de SSH.

Para que el usuario con el que ejecutamos ansible (en este caso root) sea capaz de autenticar con clave pública (sin contraseña) en los servidores, será necesario agregar la clave pública del mismo en cada archivo authorized_keys perteneciente al usuario con el cual queremos autenticar en cada sistema remoto. Es una tarea tediosa, pero debe realizarse una única vez.

Es posible copiar nuestra clave pública por SSH, concatenando al archivo authorized_keys del usuario en cuestión (por supuesto autenticando con contraseña). Si el usuario con el que queremos autenticar remotamente no posee contraseña, es posible habilitar el acceso por SSH como root de manera temporal (cambiando a PermitRootLogin yes en el archivo sshd_config y recargando el demonio sshd).

Por seguridad no es recomendable autenticar sin contraseña en servidores remotos como root (directamente se debe impedir el ingreso por SSH como root, para mayor seguridad, configuración por defecto en la mayoría de las distribuciones GNU/Linux). Es decir, para autenticar a través de Ansible sobre los sistemas a administrar de manera centralizada, utilizar un usuario no privilegiado ("ansible", "sysadmin", o cualquier otro). Crear un usuario nuevo para el caso si no se dispone de uno.

Supongamos que deseo autenticar como el usuario "sysadmin" en el servidor "www-devel.linuxito.com" sin utilizar contraseña. Una vez copiado el contenido la clave pública del usuario con el que corre ansible (~/.ssh/id_dsa.pub) dentro del archivo /home/sysadmin/.ssh/authorized_keys del servidor "www-devel.linuxito.com", sólo basta con agregar el nuevo sistema al inventario.

A tal fin voy a definir un nuevo grupo llamado "devel-debian8". Mi idea inicial es separar mis servidores en grupos por entorno y versión de sistema operativo. De esta forma voy a organizar mis servidores en "prod-debian7", "devel-debian7", "prod-debian8", "devel-debian8", y así sucesivamente.

[root@hal9000 /opt/ansible]# nano ~/ansible_hosts
127.0.0.1

[devel-debian8]
www-devel.linuxito.com:2222 ansible_user=sysadmin

Luego ya es posible lanzar un comando hacia el nuevo grupo, en este caso un simple "ping":

[root@hal9000 /opt/ansible]# ansible devel-debian8 -m ping
The authenticity of host '[www-devel.linuxito.com]:2222 ([192.168.42.38]:2222)' can't be established.
ECDSA key fingerprint is SHA256:saraza.com.
No matching host key fingerprint found in DNS.
Are you sure you want to continue connecting (yes/no)? yes
www-devel.linuxito.com | SUCCESS => {
    "changed": false, 
    "failed": false, 
    "ping": "pong"
}

Como toda vez que se inicia una conexión SSH por primera vez, se solicita almacenar el fingerprint del sistema remoto. Luego ya no aparece dicho warning. Notar cómo no solicita la contraseña para el usuario "sysadmin" en el sistema "www-devel.linuxito.com":

[root@hal9000 /opt/ansible]# ansible devel-debian8 -m ping
www-devel.linuxito.com | SUCCESS => {
    "changed": false, 
    "failed": false, 
    "ping": "pong"
}

Ya es posible lanzar cualquier comando con el módulo "shell":

[root@hal9000 /opt/ansible]# ansible devel-debian8 -m shell -a "uname -r"
www-devel.linuxito.com | SUCCESS | rc=0 >>
3.16.0-4-amd64

Cabe destacar que al utilizar un usuario no privilegiado, será necesario que cuente con una configuración de sudo adecuada para ejecutar los comandos deseados sin tener problemas de autorización:

[root@hal9000 /opt/ansible]# ansible devel-debian8 -m shell -a "sudo apt-get update"
 [WARNING]: Consider using 'become', 'become_method', and 'become_user' rather than running sudo

www-devel.linuxito.com | SUCCESS | rc=0 >>
Ign http://ftp.br.debian.org jessie InRelease
Obj http://ftp.br.debian.org jessie Release.gpg
Obj http://ftp.br.debian.org jessie Release
Obj http://ftp.br.debian.org jessie/main amd64 Packages
Obj http://ftp.br.debian.org jessie/contrib amd64 Packages
Obj http://ftp.br.debian.org jessie/contrib Translation-en
Obj http://ftp.br.debian.org jessie/main Translation-es
Obj http://ftp.br.debian.org jessie/main Translation-en
Obj http://security.debian.org jessie/updates InRelease
Obj http://security.debian.org jessie/updates/main amd64 Packages
Obj http://security.debian.org jessie/updates/contrib amd64 Packages
Obj http://security.debian.org jessie/updates/contrib Translation-en
Obj http://security.debian.org jessie/updates/main Translation-en
Leyendo lista de paquetes...

Durante la ejecución de este comando, es posible notar el funcionamiento de Ansible en el target, ejecutando ps:

sysadmin 13034  0.0  0.4  86812  5012 ?        S    14:31   0:00 sshd: sysadmin@pts/1
sysadmin 13087  0.0  0.0   4336   812 pts/1    Ss+  14:35   0:00 /bin/sh -c /usr/bin/python /home/sysadmin/.ansible/tmp/
sysadmin 13088  0.5  1.0  33168 10312 pts/1    S+   14:35   0:00 /usr/bin/python /home/sysadmin/.ansible/tmp/ansible-tmp
sysadmin 13089  1.2  1.2  37400 12572 pts/1    S+   14:35   0:00 /usr/bin/python /tmp/ansible_v6Is8E/ansible_module_comm
root     13090  0.0  0.3  44656  3588 pts/1    S+   14:35   0:00 sudo apt-get update
root     13091 23.7  2.3  55640 24420 pts/1    R+   14:35   0:00 apt-get update

Se observa (a grandes rasgos) que se inicia la conexión SSH como "sysadmin", la cual a su vez abre una shell sh desde donde se ejecuta el intérprete de Python (/usr/bin/python), el cual levanta un script temporal que termina ejecutando el comando solicitado.

En el próximo artículo sobre Ansible trataré el tema de los playbooks, el cual probablemente abarque más de un episodio. Por el momento esto es todo.

Referencias


Tal vez pueda interesarte


Compartí este artículo