martes, 23 de junio de 2015

Automatización segura de sistemas con Ansible Vault

Ansible es una herramienta de automatización y administración de configuraciones remotas desarrollada en Python. Es un sistema “clientless” que hace uso de SSH para realizar las conexiones a las máquinas administradas. Las acciones a realizar en los sistemas se organizan por acciones o “task” que a su vez se agrupan en “playbooks”, escritos usando una sintaxis amigable basada en YAML. A diferencia de otros sistemas que se conectan al servidor central para buscar actualizaciones en su configuración (“pull-based”), con Ansible el administrador elige cuando se realizan cambios en los servidores. Hace unos meses empezamos a utilizar Ansible como estándar para manejar despliegues y configuraciones en nuestro departamento de sistemas.

Utilizando Ansible como herramienta se planteaba un problema al lanzar playbooks contra varios servidores que requerían usar sudo para elevar privilegios. Por defecto, Ansible considera un solo usuario y contraseña en común para todo el conjunto de servidores objetivo de un playbook. Esto significa que todos los servidores deben tener un mismo usuario con permisos para ejecutar sudo y que además tuviera la misma contraseña en todos los servidores.

Frente a esto, existen alternativas como el uso de la directiva “NOPASSWD” de configuración de sudo o importar en cada momento la contraseña de sudo desde un fichero en texto plano mediante un motor de templates llamado jinja. Ambas evitan la necesidad de una contraseña común, pero implican otros problemas.

A partir de su versión 1.5, Ansible añade una herramienta muy útil que abre nuevas posibilidades a la hora de gestionar datos sensibles, Ansible Vault. Esta nueva característica permite almacenar en ficheros cifrados variables sensibles necesarias para la ejecución de un playbook. Valiéndose de Vault, el motor de templates jinja y claves compartidas SSH es posible mitigar de manera considerable los problemas de seguridad relacionados con administración de contraseñas.

Nuestra aproximación consiste en utilizar un fichero cifrado usando Vault para cada servidor, creando una especie de gestor de contraseñas al que Ansible accederá cuando requiera hacer sudo.

Crear los ficheros cifrados

Vault no es más que una herramienta que cifra ficheros. Estos pueden contener, entre otras variables privadas, la contraseña de sudo de un servidor. Para crear nuestro “gestor de contraseñas” necesitaremos un fichero por cada uno de los servidores en nuestro inventario.

Bucle en bash para crear los ficheros cifrados con Vault

La variable que definimos en cada uno de los ficheros es “ansible_sudo_pass”, el equivalente a la opción “--ask-sudo-pass” del comando “ansible-playbook”.
Declaración de la variable “ansible_sudo_pass” dentro del vault

Existen varios modos de generar los ficheros cifrados: usando las opciones “create” y “edit” o usando las opciones “encrypt” y “decrypt”, para las que el fichero ya debe existir. En el primer caso, el comando vim debe existir en el $PATH o, en su defecto, una variable $EDITOR apuntando al editor de texto deseado. La opción “rekey” se utiliza para cambiar la contraseña de cifrado de Vault si esto fuera necesario.

Una vez creados y cifrados los ficheros, falta añadirlos a nuestro playbook. Para ello basta con especificar el directorio que contiene los ficheros cifrados. De esta manera, indicamos al playbook que en cada iteración debe importar el fichero de contraseña cuyo nombre corresponde al del servidor objetivo especificado, usando la variable jinja inventory_hostname.

Sintaxis para importar contraseñas en un playbook

Finalmente, para lanzar el playbook hace falta añadir la opción “--ask-vault-pass”, la cual bloqueará el prompt a la espera de que se introduzca la contraseña con la que se cifraron los ficheros que se precisan y permitirá a Ansible leer su contenido.




Bartolomé Muñoz