Risoluzione degli errori di escalation dei privilegi in Ansible utilizzando Become e Sudo

Risolvi gli errori di become e sudo in Ansible con impostazioni corrette del playbook, variabili di inventario, regole sudoers e diagnostica.

Risoluzione degli errori di escalation dei privilegi in Ansible utilizzando Become e Sudo

Gli errori di escalation dei privilegi in Ansible compaiono solitamente quando un'attività necessita dell'accesso root ma l'utente di connessione non può usare sudo correttamente. Potresti vedere "permission denied", "missing sudo password" o un'attività che funziona tramite SSH ma fallisce all'interno di un playbook.

La soluzione è solitamente una combinazione delle impostazioni become di Ansible e della configurazione sudoers sull'host di destinazione. Questa guida mostra entrambi gli aspetti.

Comprendere il meccanismo become di Ansible

Alla base, Ansible opera connettendosi agli host di destinazione, tipicamente tramite SSH, ed eseguendo comandi come utente remoto. Molte attività amministrative, tuttavia, richiedono privilegi elevati (ad esempio, accesso root su sistemi Linux). Qui entra in gioco la funzionalità become di Ansible. Il meccanismo become consente ad Ansible di "diventare" un altro utente, solitamente root, per eseguire attività specifiche o interi play con permessi elevati.

Perché become è necessario

Eseguire tutte le attività di Ansible direttamente come utente root è generalmente una cattiva pratica di sicurezza. Invece, ti connetti tipicamente ai tuoi host remoti come un utente normale e non privilegiato (spesso chiamato ansible_user) e poi usi become per escalare temporaneamente i privilegi per le attività che lo richiedono. Questo aderisce al principio del minimo privilegio, minimizzando il potenziale impatto di una violazione della sicurezza.

Metodi di become

Ansible supporta diversi metodi per l'escalation dei privilegi, ciascuno corrispondente a diverse utilità di sistema. Il metodo più comune e ampiamente utilizzato, specialmente su sistemi Linux/Unix, è sudo (Substitute User Do). Altri metodi includono su, pbrun, doas e altri, ma questa guida si concentrerà principalmente su sudo a causa della sua prevalenza.

Configurare le impostazioni become in Ansible

Ansible offre diversi modi per configurare le impostazioni become, dalle configurazioni globali alle sovrascritture specifiche per attività. Comprendere questi ambiti è cruciale per una gestione efficace dei privilegi.

1. Configurazione globale in ansible.cfg

Per casi d'uso generali su molti playbook, puoi impostare parametri become predefiniti nel tuo file ansible.cfg. Questo si trova tipicamente nella directory in cui esegui Ansible, ~/.ansible.cfg o /etc/ansible/ansible.cfg.

# ansible.cfg
[privilege_escalation]
become=True
become_method=sudo
become_user=root
become_ask_pass=False ; Imposta a True se vuoi che Ansible richieda la password
  • become=True: Abilita l'escalation dei privilegi per impostazione predefinita per tutti i play.
  • become_method=sudo: Specifica sudo come metodo per l'escalation dei privilegi.
  • become_user=root: Specifica root come utente target da diventare.
  • become_ask_pass=False: Controlla se Ansible deve richiedere la password become. Imposta a True se non fornisci la password tramite altri mezzi.

2. Per play o per attività nei playbook

Per un controllo più granulare, le impostazioni become possono essere definite direttamente nei tuoi playbook, sia a livello di play (influenzando tutte le attività in quel play) che a livello di singola attività.

Configurazione a livello di play:

---
- name: Installare Nginx con privilegi elevati
  hosts: webservers
  become: yes          # Abilita become per tutte le attività in questo play
  become_user: root
  become_method: sudo

  tasks:
    - name: Assicurarsi che Nginx sia installato
      ansible.builtin.apt:
        name: nginx
        state: present
      # Questa attività verrà eseguita come root tramite sudo

    - name: Copiare la configurazione di Nginx
      ansible.builtin.copy:
        src: nginx.conf
        dest: /etc/nginx/nginx.conf
      # Anche questa attività verrà eseguita come root tramite sudo

Configurazione a livello di attività:

---
- name: Gestire file come utenti diversi
  hosts: all

  tasks:
    - name: Creare un file come ansible_user (predefinito)
      ansible.builtin.file:
        path: /tmp/unprivileged_file.txt
        state: touch
        mode: '0644'

    - name: Creare un file di proprietà di root usando become
      ansible.builtin.file:
        path: /root/privileged_file.txt
        state: touch
        mode: '0600'
      become: yes          # Solo questa attività userà become
      become_user: root
      become_method: sudo

3. Tramite variabili di inventario

Le impostazioni become possono anche essere definite nel tuo inventario Ansible, permettendoti di specificare diverse strategie di escalation dei privilegi per host o gruppi diversi.

Esempio 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

Qui, ansible_become, ansible_become_method e ansible_become_user sono variabili di inventario che corrispondono alle impostazioni become. Possono essere impostate a livello all:vars, a livello di gruppo o a livello di host.

4. Utilizzo degli argomenti CLI di ansible-playbook

Per sovrascritture rapide o esecuzione interattiva, puoi passare parametri become direttamente tramite la riga di comando:

  • --become o -b: Attiva become.
  • --become-method <METODO>: Specifica il metodo become (ad esempio, sudo).
  • --become-user <UTENTE>: Specifica l'utente target (ad esempio, root).
  • --ask-become-pass o -K: Richiede la password become durante l'esecuzione. Questo è utile per i test ma generalmente non per l'automazione.

Esempio:

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

Garantire i diritti sudo per l'utente become

Configurare correttamente become in Ansible è solo metà della battaglia. L'utente con cui Ansible si connette (l'ansible_user) deve avere i privilegi sudo necessari sull'host di destinazione per diventare il become_user. Questo viene configurato sull'host di destinazione all'interno del file /etc/sudoers o di un file sotto /etc/sudoers.d/.

Configurare sudoers

Il file sudoers definisce chi può eseguire quali comandi e come quale utente. Una voce comune per consentire a un utente di connessione Ansible (devops_user in questo esempio) di eseguire qualsiasi comando come qualsiasi utente senza richiesta di password è:

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

Spiegazione:

  • devops_user: Il nome utente con cui Ansible si connette (ansible_user).
  • ALL: Questo utente può eseguire comandi da qualsiasi terminale.
  • (ALL): Questo utente può eseguire comandi come qualsiasi utente.
  • NOPASSWD:: Specifica che non è richiesta alcuna password per le operazioni sudo.
  • ALL: Questo utente può eseguire tutti i comandi.

Attenzione: Concedere NOPASSWD: ALL dà all'ansible_user accesso root illimitato senza password, il che può rappresentare un rischio significativo per la sicurezza. Usalo solo se veramente necessario e assicurati che le credenziali del tuo ansible_user siano altamente sicure. Per una sicurezza più rigorosa, puoi specificare comandi o set di comandi esatti che l'utente può eseguire.

Verificare l'accesso sudo

Prima di eseguire il tuo playbook, puoi verificare manualmente se il tuo ansible_user ha accesso sudo su un host di destinazione. Connettiti tramite SSH all'host come ansible_user ed esegui:

# Controlla se puoi eseguire sudo come root senza password
sudo -n whoami

# Se è richiesta una password, ti verrà richiesta. Testa con un comando semplice:
sudo whoami

# Elenca i privilegi sudo per l'utente corrente:
sudo -l

# Elenca i privilegi sudo per un utente specifico (ad esempio, devops_user):
sudo -l -U devops_user

Se sudo -n whoami restituisce root senza richiedere la password, la tua configurazione NOPASSWD è probabilmente corretta. Se richiede una password, la tua voce sudoers potrebbe mancare di NOPASSWD o essere configurata in modo errato.

Diagnosticare gli errori di escalation dei privilegi

Ansible fornisce tipicamente messaggi di errore informativi, ma i problemi relativi ai privilegi possono talvolta essere criptici. Ecco errori comuni e le loro soluzioni:

1. "permission denied"

Questo di solito significa che l'attività è stata eseguita come utente di connessione non privilegiato invece che come root.

Controlla il play o l'attività:

- name: Installare un pacchetto che richiede root
  ansible.builtin.package:
    name: nginx
    state: present
  become: true

Poi conferma quale utente sta usando Ansible:

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

Il secondo comando dovrebbe restituire root quando sudo funziona.

2. "Missing sudo password"

Questo accade quando l'host di destinazione richiede una password sudo ma Ansible non ne ha ricevuta una.

Per un'esecuzione interattiva, usa:

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

Per l'automazione, evita di memorizzare password in testo semplice nell'inventario. Usa Ansible Vault per ansible_become_password se sudo senza password non è consentito nel tuo ambiente.

ansible-vault encrypt group_vars/webservers/vault.yml

Esempio di nome di variabile crittografata prima della crittografia:

ansible_become_password: "sostituisci-con-password-reale"

3. "user is not in the sudoers file"

Questo è un problema di configurazione dell'host di destinazione. Ansible non può risolverlo a meno che non possa già connettersi come un utente con privilegi sufficienti.

Sull'host di destinazione, usa visudo o un file sotto /etc/sudoers.d/:

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

Questo è più restrittivo di NOPASSWD: ALL, ma funziona solo se i tuoi playbook necessitano di quei comandi esatti. I moduli dei pacchetti potrebbero chiamare binari diversi a seconda del sistema operativo, quindi testa attentamente.

4. become_user sbagliato

La maggior parte delle attività di amministrazione Linux usa become_user: root. Se imposti become_user su un account applicativo, quell'utente potrebbe comunque non avere il permesso di modificare file di sistema o gestire servizi.

Usa un controllo rapido:

- name: Confermare l'utente effettivo
  ansible.builtin.command: whoami
  become: true
  changed_when: false

Se l'output non è l'utente che ti aspettavi, controlla le variabili del playbook, le variabili dell'inventario e ansible.cfg per valori become_user in conflitto.

Una checklist di risoluzione dei problemi sicura

Lavora dall'host di destinazione al playbook:

  1. Connettiti tramite SSH all'host come ansible_user.
  2. Esegui sudo -l e conferma che l'utente abbia i diritti necessari.
  3. Esegui sudo -n whoami se ti aspetti sudo senza password.
  4. Esegui ansible all -b -m command -a 'whoami' contro un host di test.
  5. Aggiungi -vvv all'esecuzione del playbook che fallisce se l'errore è ancora poco chiaro.

Punto chiave

become di Ansible dice solo ad Ansible di escalare i privilegi. L'host di destinazione deve comunque consentire all'utente di connessione di farlo tramite sudo o un altro metodo become. Risolvi entrambi i lati: imposta become dove l'attività lo richiede, poi verifica i diritti sudo direttamente sull'host.