Correction des erreurs d'escalade de privilèges Ansible avec Become et Sudo

Corrigez les erreurs Ansible become et sudo avec des paramètres de playbook corrects, des variables d'inventaire, des règles sudoers et des diagnostics.

Correction des erreurs d'escalade de privilèges Ansible avec Become et Sudo

Les erreurs d'escalade de privilèges Ansible apparaissent généralement lorsqu'une tâche nécessite un accès root mais que votre utilisateur de connexion ne peut pas utiliser sudo correctement. Vous pourriez voir "permission refusée", "mot de passe sudo manquant" ou une tâche qui fonctionne via SSH mais échoue à l'intérieur d'un playbook.

La solution est généralement une combinaison des paramètres become d'Ansible et de la configuration sudoers de l'hôte cible. Ce guide présente les deux aspects.

Comprendre le mécanisme become d'Ansible

À la base, Ansible se connecte aux hôtes cibles, généralement via SSH, et exécute des commandes en tant qu'utilisateur distant. De nombreuses tâches administratives nécessitent cependant des privilèges élevés (par exemple, l'accès root sur les systèmes Linux). C'est là qu'intervient la fonctionnalité become d'Ansible. Le mécanisme become permet à Ansible de "devenir" un autre utilisateur, généralement root, pour exécuter des tâches spécifiques ou des plays entiers avec des permissions élevées.

Pourquoi become est nécessaire

Exécuter toutes les tâches Ansible directement en tant qu'utilisateur root est généralement une mauvaise pratique de sécurité. Au lieu de cela, vous vous connectez généralement à vos hôtes distants en tant qu'utilisateur normal et non privilégié (souvent appelé ansible_user) puis utilisez become pour élever temporairement les privilèges pour les tâches qui en ont besoin. Cela respecte le principe du moindre privilège, minimisant l'impact potentiel d'une brèche de sécurité.

Méthodes become

Ansible prend en charge plusieurs méthodes d'escalade de privilèges, chacune correspondant à différents utilitaires système. La méthode la plus courante et la plus utilisée, surtout sur les systèmes Linux/Unix, est sudo (Substitute User Do). D'autres méthodes incluent su, pbrun, doas, etc., mais ce guide se concentrera principalement sur sudo en raison de sa prévalence.

Configuration des paramètres become dans Ansible

Ansible offre plusieurs façons de configurer les paramètres become, des configurations globales aux surcharges spécifiques aux tâches. Comprendre ces portées est crucial pour une gestion efficace des privilèges.

1. Configuration globale dans ansible.cfg

Pour les cas d'utilisation généraux dans de nombreux playbooks, vous pouvez définir des paramètres become par défaut dans votre fichier ansible.cfg. Celui-ci se trouve généralement dans le répertoire où vous exécutez Ansible, ~/.ansible.cfg, ou /etc/ansible/ansible.cfg.

# ansible.cfg
[privilege_escalation]
become=True
become_method=sudo
become_user=root
become_ask_pass=False ; Mettre à True si vous voulez qu'Ansible demande le mot de passe
  • become=True: Active l'escalade de privilèges par défaut pour tous les plays.
  • become_method=sudo: Spécifie sudo comme méthode d'escalade de privilèges.
  • become_user=root: Spécifie root comme utilisateur cible à devenir.
  • become_ask_pass=False: Contrôle si Ansible doit demander le mot de passe become. Mettre à True si vous ne fournissez pas le mot de passe par d'autres moyens.

2. Par play ou par tâche dans les playbooks

Pour un contrôle plus granulaire, les paramètres become peuvent être définis directement dans vos playbooks, soit au niveau du play (affectant toutes les tâches de ce play), soit au niveau de la tâche individuelle.

Configuration au niveau du play :

---
- name: Installer Nginx avec des privilèges élevés
  hosts: webservers
  become: yes          # Activer become pour toutes les tâches de ce play
  become_user: root
  become_method: sudo

  tasks:
    - name: S'assurer que Nginx est installé
      ansible.builtin.apt:
        name: nginx
        state: present
      # Cette tâche s'exécutera en tant que root via sudo

    - name: Copier la configuration Nginx
      ansible.builtin.copy:
        src: nginx.conf
        dest: /etc/nginx/nginx.conf
      # Cette tâche s'exécutera également en tant que root via sudo

Configuration au niveau de la tâche :

---
- name: Gérer des fichiers en tant qu'utilisateurs différents
  hosts: all

  tasks:
    - name: Créer un fichier en tant qu'ansible_user (par défaut)
      ansible.builtin.file:
        path: /tmp/unprivileged_file.txt
        state: touch
        mode: '0644'

    - name: Créer un fichier appartenant à root en utilisant become
      ansible.builtin.file:
        path: /root/privileged_file.txt
        state: touch
        mode: '0600'
      become: yes          # Seule cette tâche utilisera become
      become_user: root
      become_method: sudo

3. Via les variables d'inventaire

Les paramètres become peuvent également être définis dans votre inventaire Ansible, vous permettant de spécifier différentes stratégies d'escalade de privilèges pour différents hôtes ou groupes.

Exemple 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

Ici, ansible_become, ansible_become_method et ansible_become_user sont des variables d'inventaire qui correspondent aux paramètres become. Elles peuvent être définies au niveau all:vars, au niveau du groupe ou au niveau de l'hôte.

4. Utilisation des arguments CLI ansible-playbook

Pour des surcharges rapides ou une exécution interactive, vous pouvez passer les paramètres become directement via la ligne de commande :

  • --become ou -b : Active become.
  • --become-method <METHOD> : Spécifie la méthode become (par exemple, sudo).
  • --become-user <USER> : Spécifie l'utilisateur cible (par exemple, root).
  • --ask-become-pass ou -K : Demande le mot de passe become pendant l'exécution. Utile pour les tests mais généralement pas pour l'automatisation.

Exemple :

ansible-playbook my_playbook.yml --become --become-user root --ask-become-pass

Assurer les droits sudo pour l'utilisateur become

Configurer correctement become dans Ansible n'est que la moitié de la bataille. L'utilisateur auquel Ansible se connecte (le ansible_user) doit avoir les privilèges sudo nécessaires sur l'hôte cible pour devenir le become_user. Ceci est configuré sur l'hôte cible dans le fichier /etc/sudoers ou un fichier sous /etc/sudoers.d/.

Configuration de sudoers

Le fichier sudoers définit qui peut exécuter quelles commandes, et en tant que qui. Une entrée courante pour permettre à un utilisateur de connexion Ansible (devops_user dans cet exemple) d'exécuter n'importe quelle commande en tant que n'importe quel utilisateur sans demande de mot de passe est :

# /etc/sudoers.d/devops
devops_user ALL=(ALL) NOPASSWD: ALL

Explication :

  • devops_user : Le nom d'utilisateur sous lequel Ansible se connecte (ansible_user).
  • ALL : Cet utilisateur peut exécuter des commandes depuis n'importe quel terminal.
  • (ALL) : Cet utilisateur peut exécuter des commandes en tant que n'importe quel utilisateur.
  • NOPASSWD: : Spécifie qu'aucun mot de passe n'est requis pour les opérations sudo.
  • ALL : Cet utilisateur peut exécuter toutes les commandes.

Avertissement : Accorder NOPASSWD: ALL donne à ansible_user un accès root illimité sans mot de passe, ce qui peut être un risque de sécurité important. N'utilisez cela que si c'est vraiment nécessaire et assurez-vous que les identifiants de votre ansible_user sont hautement sécurisés. Pour une sécurité plus stricte, vous pouvez spécifier les commandes exactes ou les ensembles de commandes que l'utilisateur est autorisé à exécuter.

Vérification de l'accès sudo

Avant d'exécuter votre playbook, vous pouvez vérifier manuellement si votre ansible_user a un accès sudo sur un hôte cible. Connectez-vous en SSH à l'hôte en tant que ansible_user et exécutez :

# Vérifier si vous pouvez utiliser sudo vers root sans mot de passe
sudo -n whoami

# Si un mot de passe est requis, vous serez invité. Testez avec une commande simple :
sudo whoami

# Lister les privilèges sudo pour l'utilisateur actuel :
sudo -l

# Lister les privilèges sudo pour un utilisateur spécifique (par exemple, devops_user) :
sudo -l -U devops_user

Si sudo -n whoami renvoie root sans demande de mot de passe, votre configuration NOPASSWD est probablement correcte. Si elle demande un mot de passe, votre entrée sudoers manque peut-être NOPASSWD ou est mal configurée.

Diagnostic des erreurs d'escalade de privilèges

Ansible fournit généralement des messages d'erreur informatifs, mais les problèmes liés aux privilèges peuvent parfois être cryptiques. Voici les erreurs courantes et leurs solutions :

1. "Permission refusée"

Cela signifie généralement que la tâche s'est exécutée en tant qu'utilisateur de connexion non privilégié au lieu de root.

Vérifiez le play ou la tâche :

- name: Installer un paquet nécessitant root
  ansible.builtin.package:
    name: nginx
    state: present
  become: true

Confirmez ensuite quel utilisateur Ansible utilise :

ansible webservers -m ansible.builtin.command -a 'whoami'
ansible webservers -b -m ansible.builtin.command -a 'whoami'

La deuxième commande devrait renvoyer root lorsque sudo fonctionne.

2. "Mot de passe sudo manquant"

Cela se produit lorsque l'hôte cible nécessite un mot de passe sudo mais qu'Ansible n'en a pas reçu.

Pour une exécution interactive, utilisez :

ansible-playbook site.yml --ask-become-pass

Pour l'automatisation, évitez de stocker des mots de passe en texte clair dans l'inventaire. Utilisez Ansible Vault pour ansible_become_password si sudo sans mot de passe n'est pas autorisé dans votre environnement.

ansible-vault encrypt group_vars/webservers/vault.yml

Exemple de nom de variable chiffrée avant chiffrement :

ansible_become_password: "remplacer-par-mot-de-passe-réel"

3. "L'utilisateur n'est pas dans le fichier sudoers"

C'est un problème de configuration de l'hôte cible. Ansible ne peut pas le résoudre à moins de pouvoir déjà se connecter en tant qu'utilisateur avec suffisamment de privilèges.

Sur l'hôte cible, utilisez visudo ou un fichier sous /etc/sudoers.d/ :

devops_user ALL=(ALL) NOPASSWD: /usr/bin/systemctl, /usr/bin/apt, /usr/bin/yum

C'est plus restreint que NOPASSWD: ALL, mais cela ne fonctionne que si vos playbooks nécessitent ces commandes exactes. Les modules de paquets peuvent appeler différents binaires selon le système d'exploitation, alors testez soigneusement.

4. Mauvais become_user

La plupart des tâches d'administration Linux utilisent become_user: root. Si vous définissez become_user sur un compte d'application, cet utilisateur peut encore manquer de permissions pour modifier les fichiers système ou gérer les services.

Utilisez une vérification rapide :

- name: Confirmer l'utilisateur effectif
  ansible.builtin.command: whoami
  become: true
  changed_when: false

Si la sortie n'est pas l'utilisateur attendu, vérifiez les variables du playbook, les variables d'inventaire et ansible.cfg pour des valeurs become_user conflictuelles.

Une liste de vérification de dépannage sécurisée

Travaillez de l'hôte cible vers le playbook :

  1. Connectez-vous en SSH à l'hôte en tant que ansible_user.
  2. Exécutez sudo -l et confirmez que l'utilisateur a les droits nécessaires.
  3. Exécutez sudo -n whoami si vous attendez sudo sans mot de passe.
  4. Exécutez ansible all -b -m command -a 'whoami' sur un hôte de test.
  5. Ajoutez -vvv à l'exécution du playbook qui échoue si l'erreur n'est toujours pas claire.

Point clé à retenir

become d'Ansible indique seulement à Ansible d'élever les privilèges. L'hôte cible doit toujours permettre à l'utilisateur de connexion de le faire via sudo ou une autre méthode become. Corrigez les deux côtés : définissez become là où la tâche en a besoin, puis vérifiez les droits sudo directement sur l'hôte.