Corrección de Errores de Escalación de Privilegios en Ansible Usando Become y Sudo
Corrige errores de become y sudo en Ansible con configuraciones correctas de playbook, variables de inventario, reglas de sudoers y diagnósticos.
Corrección de Errores de Escalación de Privilegios en Ansible Usando Become y Sudo
Los errores de escalación de privilegios en Ansible suelen aparecer cuando una tarea necesita acceso root pero tu usuario de conexión no puede usar sudo correctamente. Puedes ver "permiso denegado", "falta la contraseña de sudo" o una tarea que funciona por SSH pero falla dentro de un playbook.
La solución suele ser una combinación de la configuración de become de Ansible y la configuración de sudoers en el host de destino. Esta guía muestra ambos lados.
Entendiendo el Mecanismo become de Ansible
En esencia, Ansible se conecta a los hosts de destino, típicamente por SSH, y ejecuta comandos como el usuario remoto. Sin embargo, muchas tareas administrativas requieren privilegios elevados (por ejemplo, acceso root en sistemas Linux). Aquí es donde entra en juego la función become de Ansible. El mecanismo become permite a Ansible "convertirse" en otro usuario, generalmente root, para ejecutar tareas específicas o plays completos con permisos elevados.
Por qué es Necesario become
Ejecutar todas las tareas de Ansible directamente como usuario root es generalmente una mala práctica de seguridad. En su lugar, normalmente te conectas a tus hosts remotos como un usuario regular sin privilegios (a menudo llamado ansible_user) y luego usas become para escalar privilegios temporalmente para las tareas que lo requieren. Esto sigue el principio de mínimo privilegio, minimizando el impacto potencial de una brecha de seguridad.
Métodos de become
Ansible soporta varios métodos para la escalación de privilegios, cada uno correspondiente a diferentes utilidades del sistema. El método más común y ampliamente utilizado, especialmente en sistemas Linux/Unix, es sudo (Substitute User Do). Otros métodos incluyen su, pbrun, doas, y más, pero esta guía se centrará principalmente en sudo debido a su prevalencia.
Configurando Ajustes de become en Ansible
Ansible ofrece múltiples formas de configurar los ajustes de become, desde configuraciones globales hasta anulaciones específicas de tareas. Entender estos alcances es crucial para una gestión efectiva de privilegios.
1. Configuración Global en ansible.cfg
Para casos de uso general en muchos playbooks, puedes establecer parámetros predeterminados de become en tu archivo ansible.cfg. Este se encuentra típicamente en el directorio donde ejecutas Ansible, ~/.ansible.cfg, o /etc/ansible/ansible.cfg.
# ansible.cfg
[privilege_escalation]
become=True
become_method=sudo
become_user=root
become_ask_pass=False ; Establece a True si quieres que Ansible solicite la contraseña
become=True: Habilita la escalación de privilegios por defecto para todos los plays.become_method=sudo: Especificasudocomo el método de escalación de privilegios.become_user=root: Especificarootcomo el usuario objetivo al que convertirse.become_ask_pass=False: Controla si Ansible debe solicitar la contraseña debecome. Establece aTruesi no proporcionas la contraseña por otros medios.
2. Por Play o Por Tarea en Playbooks
Para un control más granular, los ajustes de become se pueden definir directamente dentro de tus playbooks, ya sea a nivel de play (afectando a todas las tareas en ese play) o a nivel de tarea individual.
Configuración a nivel de play:
---
- name: Instalar Nginx con privilegios elevados
hosts: webservers
become: yes # Habilita become para todas las tareas en este play
become_user: root
become_method: sudo
tasks:
- name: Asegurar que Nginx esté instalado
ansible.builtin.apt:
name: nginx
state: present
# Esta tarea se ejecutará como root a través de sudo
- name: Copiar configuración de Nginx
ansible.builtin.copy:
src: nginx.conf
dest: /etc/nginx/nginx.conf
# Esta tarea también se ejecutará como root a través de sudo
Configuración a nivel de tarea:
---
- name: Gestionar archivos como diferentes usuarios
hosts: all
tasks:
- name: Crear un archivo como ansible_user (predeterminado)
ansible.builtin.file:
path: /tmp/unprivileged_file.txt
state: touch
mode: '0644'
- name: Crear un archivo propiedad de root usando become
ansible.builtin.file:
path: /root/privileged_file.txt
state: touch
mode: '0600'
become: yes # Solo esta tarea usará become
become_user: root
become_method: sudo
3. A Través de Variables de Inventario
Los ajustes de become también se pueden definir en tu inventario de Ansible, permitiéndote especificar diferentes estrategias de escalación de privilegios para diferentes hosts o grupos.
Ejemplo de hosts.ini:
[webservers]
web1.example.com
web2.example.com
[dbservers]
db1.example.com
[all:vars]
ansible_user=devops_user
ansible_become=true
ansible_become_method=sudo
ansible_become_user=root
Aquí, ansible_become, ansible_become_method y ansible_become_user son variables de inventario que corresponden a los ajustes de become. Se pueden establecer a nivel de all:vars, a nivel de grupo o a nivel de host.
4. Usando Argumentos de CLI de ansible-playbook
Para anulaciones rápidas o ejecución interactiva, puedes pasar parámetros de become directamente desde la línea de comandos:
--becomeo-b: Activabecome.--become-method <MÉTODO>: Especifica el método de become (por ejemplo,sudo).--become-user <USUARIO>: Especifica el usuario objetivo (por ejemplo,root).--ask-become-passo-K: Solicita la contraseña debecomedurante la ejecución. Esto es útil para pruebas pero generalmente no para automatización.
Ejemplo:
ansible-playbook my_playbook.yml --become --become-user root --ask-become-pass
Asegurando Derechos de sudo para el Usuario de become
Configurar correctamente become en Ansible es solo la mitad de la batalla. El usuario al que Ansible se conecta (el ansible_user) debe tener los privilegios sudo necesarios en el host de destino para convertirse en el become_user. Esto se configura en el host de destino dentro del archivo /etc/sudoers o un archivo bajo /etc/sudoers.d/.
Configurando sudoers
El archivo sudoers define quién puede ejecutar qué comandos, y como quién. Una entrada común para permitir que un usuario de conexión de Ansible (devops_user en este ejemplo) ejecute cualquier comando como cualquier usuario sin solicitud de contraseña es:
# /etc/sudoers.d/devops
devops_user ALL=(ALL) NOPASSWD: ALL
Explicación:
devops_user: El nombre de usuario con el que Ansible se conecta (ansible_user).ALL: Este usuario puede ejecutar comandos desde cualquier terminal.(ALL): Este usuario puede ejecutar comandos como cualquier usuario.NOPASSWD:: Especifica que no se requiere contraseña para las operacionessudo.ALL: Este usuario puede ejecutar todos los comandos.
Advertencia: Otorgar NOPASSWD: ALL le da al ansible_user acceso root sin restricciones sin contraseña, lo que puede ser un riesgo de seguridad significativo. Solo usa esto si es realmente necesario y asegúrate de que las credenciales de tu ansible_user sean altamente seguras. Para una seguridad más estricta, puedes especificar comandos exactos o conjuntos de comandos que el usuario puede ejecutar.
Verificando el Acceso sudo
Antes de ejecutar tu playbook, puedes verificar manualmente si tu ansible_user tiene acceso sudo en un host de destino. Conéctate por SSH al host como ansible_user y ejecuta:
# Verificar si puedes hacer sudo a root sin contraseña
sudo -n whoami
# Si se requiere una contraseña, se te solicitará. Prueba con un comando simple:
sudo whoami
# Listar privilegios de sudo para el usuario actual:
sudo -l
# Listar privilegios de sudo para un usuario específico (por ejemplo, devops_user):
sudo -l -U devops_user
Si sudo -n whoami devuelve root sin solicitud de contraseña, tu configuración NOPASSWD probablemente sea correcta. Si solicita una contraseña, tu entrada de sudoers podría carecer de NOPASSWD o estar configurada incorrectamente.
Diagnosticando Errores de Escalación de Privilegios
Ansible típicamente proporciona mensajes de error informativos, pero los problemas relacionados con privilegios a veces pueden ser crípticos. Aquí hay errores comunes y sus soluciones:
1. "permiso denegado"
Esto generalmente significa que la tarea se ejecutó como el usuario de conexión sin privilegios en lugar de root.
Verifica el play o la tarea:
- name: Instalar paquete que requiere root
ansible.builtin.package:
name: nginx
state: present
become: true
Luego confirma qué usuario está usando Ansible:
ansible webservers -m ansible.builtin.command -a 'whoami'
ansible webservers -b -m ansible.builtin.command -a 'whoami'
El segundo comando debería devolver root cuando sudo está funcionando.
2. "Falta la contraseña de sudo"
Esto ocurre cuando el host de destino requiere una contraseña de sudo pero Ansible no recibió ninguna.
Para una ejecución interactiva, usa:
ansible-playbook site.yml --ask-become-pass
Para automatización, evita almacenar contraseñas en texto plano en el inventario. Usa Ansible Vault para ansible_become_password si no se permite sudo sin contraseña en tu entorno.
ansible-vault encrypt group_vars/webservers/vault.yml
Ejemplo de nombre de variable encriptada antes de la encriptación:
ansible_become_password: "reemplazar-con-contraseña-real"
3. "el usuario no está en el archivo sudoers"
Este es un problema de configuración del host de destino. Ansible no puede solucionarlo a menos que ya pueda conectarse como un usuario con suficientes privilegios.
En el host de destino, usa visudo o un archivo bajo /etc/sudoers.d/:
devops_user ALL=(ALL) NOPASSWD: /usr/bin/systemctl, /usr/bin/apt, /usr/bin/yum
Esto es más restrictivo que NOPASSWD: ALL, pero solo funciona si tus playbooks necesitan esos comandos exactos. Los módulos de paquetes pueden llamar a diferentes binarios dependiendo del sistema operativo, así que prueba cuidadosamente.
4. become_user Incorrecto
La mayoría de las tareas de administración de Linux usan become_user: root. Si estableces become_user a una cuenta de aplicación, ese usuario puede carecer de permiso para modificar archivos del sistema o gestionar servicios.
Usa una verificación rápida:
- name: Confirmar usuario efectivo
ansible.builtin.command: whoami
become: true
changed_when: false
Si la salida no es el usuario que esperabas, verifica las variables del playbook, las variables del inventario y ansible.cfg en busca de valores conflictivos de become_user.
Una Lista de Verificación Segura para Solucionar Problemas
Trabaja desde el host de destino de vuelta al playbook:
- Conéctate por SSH al host como
ansible_user. - Ejecuta
sudo -ly confirma que el usuario tiene los derechos necesarios. - Ejecuta
sudo -n whoamisi esperas sudo sin contraseña. - Ejecuta
ansible all -b -m command -a 'whoami'contra un host de prueba. - Agrega
-vvva la ejecución del playbook que falla si el error aún no está claro.
Conclusión Clave
become de Ansible solo le dice a Ansible que escale privilegios. El host de destino aún debe permitir que el usuario de conexión haga eso a través de sudo u otro método de become. Arregla ambos lados: establece become donde la tarea lo necesite, luego verifica los derechos de sudo directamente en el host.