Ansible en entornos regulados: idempotencia, inventarios y control de cambios
Cómo usar Ansible en organizaciones reguladas para que cada ejecución sea repetible y trazable: idempotencia como evidencia, inventarios por entorno, secretos fuera del repositorio y cambios ligados a su registro.
La automatización también es un control
En una organización regulada, cada cambio en producción tiene que poder explicarse: quién lo pidió, quién lo aprobó, qué se modificó exactamente y cómo se comprobó el resultado. Cuando esos cambios se hacen a mano, la evidencia depende de capturas de pantalla, notas en el ticket y la memoria del operador. Es frágil y cuesta reconstruirla cuando llega la auditoría.
Ansible cambia esa situación si se usa con disciplina. Un playbook versionado describe el estado esperado, la herramienta informa qué tareas cambiaron algo y cuáles no, y la ejecución deja un registro reproducible. El código pasa a ser parte del control, no solo una forma más rápida de hacer el trabajo. Pero esa ventaja no aparece sola: hay que diseñar inventarios, variables, secretos y ejecuciones pensando desde el inicio en el auditor y en el equipo de riesgo.
Este artículo recorre las decisiones que más pesan en ese diseño. No reemplaza tu marco de control interno ni la lectura de la norma que te aplica (por ejemplo, el Reglamento DORA en la Unión Europea o la regulación de tu supervisor local), pero sí traduce sus expectativas habituales sobre gestión de cambios a prácticas concretas.
Idempotencia y modo de verificación como evidencia
Un módulo idempotente lleva el sistema a un estado deseado y no hace nada si ese estado ya existe. Ejecutar dos veces el mismo playbook sobre el mismo servidor debería producir cambios la primera vez y ninguno la segunda. Esa propiedad tiene un valor que suele pasarse por alto: convierte el resultado de la ejecución en evidencia. El resumen final (PLAY RECAP) indica, por host, cuántas tareas quedaron en ok, cuántas en changed y cuántas fallaron.
Dos opciones de ansible-playbook son especialmente útiles en un proceso de cambios:
--checkejecuta el playbook en modo de verificación: los módulos que lo soportan informan qué cambiarían sin modificar nada.--diffmuestra las diferencias de contenido en archivos y plantillas, antes y después.
Combinadas, producen una vista previa del cambio que puede adjuntarse al registro antes de la ventana de mantenimiento. El comité o el aprobador ya no evalúa una descripción en prosa, sino el diff real que se aplicará.
Hay matices que conviene conocer. No todos los módulos soportan el modo de verificación, y las tareas con ansible.builtin.command o ansible.builtin.shell no saben si su comando cambia algo: en --check se omiten y, cuando se ejecutan, se reportan como changed. Para que la evidencia sea fiable, usa módulos específicos siempre que existan, declara changed_when en los comandos de solo lectura y marca con check_mode: false las consultas que deben correr también en la vista previa. Un playbook que reporta cambios en cada ejecución pierde valor como evidencia: nadie puede distinguir el cambio real del ruido.
Un buen indicador de salud del repositorio es justamente ese: después de aplicar un cambio, una segunda ejecución en modo de verificación debería terminar con cero tareas en changed. Si no es así, hay deriva de configuración o tareas mal escritas, y ambas cosas merecen atención.
Inventarios y variables por entorno
El segundo pilar es separar con claridad qué se ejecuta de dónde se ejecuta. El playbook debe ser el mismo en desarrollo, pruebas y producción; lo que cambia es el inventario y sus variables. Una estructura habitual es un directorio de inventario por entorno:
inventories/
dev/
hosts.yml
group_vars/
all.yml
prod/
hosts.yml
group_vars/
all/
vars.yml # valores no sensibles
vault.yml # cifrado con ansible-vault
web.yml
host_vars/
web01.yml
Esta separación tiene consecuencias de control. Primero, el entorno de destino queda explícito en el comando (-i inventories/prod) y se puede validar en el pipeline. Segundo, los permisos del repositorio o de la plataforma de ejecución pueden restringir quién modifica el inventario de producción. Tercero, el diff de una solicitud de cambio muestra si se tocó lógica (roles y playbooks) o datos (variables de un entorno), y cada caso puede requerir revisores distintos.
Algunas reglas que evitan problemas frecuentes:
- Define los valores por defecto en los roles (
defaults/main.yml) y sobrescribe engroup_varssolo lo que de verdad difiere por entorno. - Evita definir la misma variable en muchos niveles. Ansible tiene un orden de precedencia de variables extenso, y un valor que llega desde un lugar inesperado es una fuente clásica de incidentes.
- Limita el uso de
--extra-varsen producción a datos de la ejecución (por ejemplo, el identificador de cambio), no a configuración. Las extra vars tienen la precedencia más alta y no quedan versionadas. - Si el inventario es dinámico (nube, CMDB, hipervisor), versiona la configuración del plugin y documenta qué filtros determinan los hosts de producción.
Secretos: fuera del repositorio, siempre
Ninguna contraseña, clave privada ni token debe estar en texto claro en el repositorio, ni siquiera en uno privado. El historial de git lo conserva todo, y un secreto expuesto una vez debe considerarse comprometido y rotarse. Hay dos enfoques razonables, y muchas organizaciones combinan ambos.
Ansible Vault
Ansible Vault cifra archivos completos o valores individuales con AES256. El patrón habitual es guardar los secretos en un vault.yml cifrado, con nombres prefijados, y referenciarlos desde un vars.yml legible. Así cualquiera puede buscar dónde se usa una variable sin descifrar nada:
# inventories/prod/group_vars/all/vars.yml
db_user: app_pagos
db_password: "{{ vault_db_password }}" # el valor real vive en vault.yml, cifrado
Vault resuelve el cifrado en reposo, pero deja abierta la gestión de la clave de descifrado. Usa identificadores de vault distintos por entorno (opción --vault-id) para que quien opera desarrollo no pueda leer los secretos de producción, y guarda esas claves fuera del repositorio.
Gestor de secretos externo
Si la organización ya tiene un gestor de secretos (HashiCorp Vault, CyberArk o los servicios de secretos de AWS, Azure o Google Cloud), lo más limpio es que Ansible lea los secretos en tiempo de ejecución mediante plugins de lookup de las colecciones correspondientes. Así la rotación, la caducidad y la auditoría de accesos quedan en una plataforma diseñada para ello, y el repositorio no contiene secretos ni siquiera cifrados. Las plataformas de ejecución como AWX o Red Hat Ansible Automation Platform también permiten asociar credenciales a las plantillas de trabajo sin exponerlas a quien lanza la ejecución.
En cualquier caso, marca con no_log: true las tareas que manipulan secretos. Sin esa opción, un valor sensible puede aparecer en la salida de la ejecución y, con ella, en los registros que luego se conservan para auditoría.
Cada ejecución ligada a un registro de cambio
Una práctica básica de habilitación de cambios es que nada llegue a producción sin un registro aprobado. Con Ansible esto puede aplicarse en el propio código: el playbook exige un identificador de cambio y se detiene si falta o no tiene el formato esperado.
---
- name: Endurecer la configuración de SSH
hosts: web
become: true
vars:
change_id: "" # llega con -e change_id=... desde el pipeline o la plataforma
pre_tasks:
- name: Exigir un registro de cambio con formato válido
ansible.builtin.assert:
that:
- change_id is match('^CHG[0-9]{7}$')
fail_msg: "Ejecución bloqueada: falta un registro de cambio válido"
tasks:
- name: Deshabilitar el acceso de root por SSH
ansible.builtin.lineinfile:
path: /etc/ssh/sshd_config
regexp: '^#?PermitRootLogin'
line: 'PermitRootLogin no'
validate: /usr/sbin/sshd -t -f %s # no escribe el archivo si la sintaxis es inválida
notify: Reiniciar sshd
handlers:
- name: Reiniciar sshd
ansible.builtin.service:
name: sshd
state: restarted
La vista previa para el aprobador y la ejecución real usan el mismo comando, con y sin --check:
ansible-playbook -i inventories/prod playbooks/ssh.yml --check --diff -e change_id=CHG0012345
ansible-playbook -i inventories/prod playbooks/ssh.yml --diff -e change_id=CHG0012345
El formato del identificador es un ejemplo: ajústalo al de tu herramienta de gestión de servicios. El control puede ir más lejos. En lugar de validar solo el formato, una tarea puede consultar la API de la herramienta ITSM para confirmar que el cambio está aprobado y que la ejecución ocurre dentro de su ventana. Si esa consulta falla, el playbook debe detenerse, no continuar.
Cuando la ejecución ocurre desde una plataforma central y no desde la laptop de un operador, el vínculo se vuelve más sólido: la plantilla de trabajo fija el playbook, el inventario y las credenciales, y el control de acceso define quién puede lanzarla. El identificador de cambio queda en los parámetros del trabajo y en su salida.
Registro y trazabilidad para auditoría
La evidencia útil responde cuatro preguntas: qué código se ejecutó (repositorio y commit), contra qué hosts, con qué resultado por tarea, y quién lo lanzó bajo qué cambio. Ansible cubre parte de eso por sí mismo; el resto depende de cómo organices la ejecución.
- Registro local. La opción
log_pathdeansible.cfgescribe la salida de cada ejecución en un archivo. Es un mínimo útil para ejecuciones desde un nodo de control, pero sin protección contra modificaciones no sirve como evidencia. - Plugins de callback. Permiten emitir los resultados en otros formatos o enviarlos a otros sistemas, por ejemplo como salida estructurada que un SIEM o una plataforma de logs pueda indexar.
- Plataforma de ejecución. AWX y Ansible Automation Platform guardan el historial de trabajos con usuario, plantilla, inventario, revisión del proyecto y salida completa, y pueden reenviar eventos a un agregador de logs externo.
# ansible.cfg (fragmento)
[defaults]
log_path = /var/log/ansible/ansible.log
callbacks_enabled = ansible.posix.profile_tasks # agrega la duración de cada tarea a la salida
Para que el registro tenga valor de auditoría, envíalo a un repositorio central con retención definida y acceso de solo lectura para los operadores. Correlaciona además el identificador de cambio en todos los sistemas: ticket, commit, trabajo de Ansible y log. Con ese hilo, reconstruir un cambio deja de ser una investigación y pasa a ser una consulta.
Checklist para empezar
- Todo playbook de producción vive en un repositorio con revisión obligatoria antes de fusionar.
- Un inventario por entorno, con permisos más estrictos para producción.
- Ningún secreto en texto claro: Vault con claves por entorno o un gestor externo.
no_log: trueen toda tarea que maneje datos sensibles.- Vista previa con
--check --diffadjunta al registro de cambio. - El playbook exige el identificador de cambio y lo deja en la salida.
- Ejecución desde una plataforma central, no desde estaciones personales.
- Logs centralizados, con retención definida y sin posibilidad de edición por los operadores.
- Una segunda ejecución en modo de verificación después del cambio, para confirmar cero cambios pendientes.
No hace falta implementarlo todo a la vez. Si estás decidiendo qué procedimientos automatizar primero, el marco Valor × Complejidad ayuda a ordenar el backlog: los cambios frecuentes, de bajo riesgo y con alto aporte a la auditoría suelen caer en Victorias rápidas. Cuando el repositorio crezca, el siguiente paso es tratarlo como software, con roles, pruebas y pipelines, tema de Ansible a escala.
Fuentes
- Documentación oficial de Ansible: modo de verificación y diff, Ansible Vault, inventarios y precedencia de variables. https://docs.ansible.com/
- Reglamento (UE) 2022/2554 sobre la resiliencia operativa digital del sector financiero (DORA). https://eur-lex.europa.eu/eli/reg/2022/2554/oj
- NIST SP 800-53 Rev. 5, Security and Privacy Controls for Information Systems and Organizations, familia Configuration Management (CM).
¿Quieres aplicar esto en tu operación?
Solicitar diagnóstico