Corrigindo Erros de Escalação de Privilégios no Ansible Usando Become e Sudo

Corrija erros de become e sudo no Ansible com configurações corretas de playbook, variáveis de inventário, regras sudoers e diagnósticos.

Corrigindo Erros de Escalação de Privilégios no Ansible Usando Become e Sudo

Erros de escalação de privilégios no Ansible geralmente aparecem quando uma tarefa precisa de acesso root, mas seu usuário de conexão não consegue usar sudo corretamente. Você pode ver "permissão negada", "senha sudo ausente" ou uma tarefa que funciona via SSH, mas falha dentro de um playbook.

A correção geralmente é uma combinação das configurações de become do Ansible e da configuração sudoers no host de destino. Este guia mostra ambos os lados.

Entendendo o Mecanismo become do Ansible

Em sua essência, o Ansible opera conectando-se a hosts de destino, tipicamente via SSH, e executando comandos como o usuário remoto. Muitas tarefas administrativas, no entanto, requerem privilégios elevados (por exemplo, acesso root em sistemas Linux). É aqui que o recurso become do Ansible entra em ação. O mecanismo become permite que o Ansible "se torne" outro usuário, geralmente root, para executar tarefas específicas ou plays inteiros com permissões elevadas.

Por que become é Necessário

Executar todas as tarefas do Ansible diretamente como usuário root é geralmente uma má prática de segurança. Em vez disso, você normalmente se conecta aos seus hosts remotos como um usuário regular e sem privilégios (frequentemente chamado de ansible_user) e então usa become para escalar privilégios temporariamente para tarefas que exigem isso. Isso segue o princípio do menor privilégio, minimizando o impacto potencial de uma violação de segurança.

Métodos become

O Ansible suporta vários métodos para escalação de privilégios, cada um correspondendo a diferentes utilitários do sistema. O método mais comum e amplamente usado, especialmente em sistemas Linux/Unix, é sudo (Substitute User Do). Outros métodos incluem su, pbrun, doas e mais, mas este guia focará principalmente no sudo devido à sua prevalência.

Configurando as Opções become no Ansible

O Ansible oferece várias maneiras de configurar as opções become, desde configurações globais até substituições específicas de tarefas. Entender esses escopos é crucial para um gerenciamento eficaz de privilégios.

1. Configuração Global em ansible.cfg

Para casos de uso gerais em muitos playbooks, você pode definir parâmetros become padrão no seu arquivo ansible.cfg. Isso geralmente é encontrado no diretório onde você executa o Ansible, ~/.ansible.cfg ou /etc/ansible/ansible.cfg.

# ansible.cfg
[privilege_escalation]
become=True
become_method=sudo
become_user=root
become_ask_pass=False ; Defina como True se quiser que o Ansible solicite a senha
  • become=True: Habilita a escalação de privilégios por padrão para todos os plays.
  • become_method=sudo: Especifica sudo como o método para escalação de privilégios.
  • become_user=root: Especifica root como o usuário de destino a se tornar.
  • become_ask_pass=False: Controla se o Ansible deve solicitar a senha become. Defina como True se você não fornecer a senha por outros meios.

2. Por Play ou Por Tarefa em Playbooks

Para um controle mais granular, as opções become podem ser definidas diretamente dentro dos seus playbooks, seja no nível do play (afetando todas as tarefas naquele play) ou no nível da tarefa individual.

Configuração no nível do play:

---
- name: Instalar Nginx com privilégios elevados
  hosts: webservers
  become: yes          # Habilita become para todas as tarefas neste play
  become_user: root
  become_method: sudo

  tasks:
    - name: Garantir que o Nginx esteja instalado
      ansible.builtin.apt:
        name: nginx
        state: present
      # Esta tarefa será executada como root via sudo

    - name: Copiar configuração do Nginx
      ansible.builtin.copy:
        src: nginx.conf
        dest: /etc/nginx/nginx.conf
      # Esta tarefa também será executada como root via sudo

Configuração no nível da tarefa:

---
- name: Gerenciar arquivos como diferentes usuários
  hosts: all

  tasks:
    - name: Criar um arquivo como ansible_user (padrão)
      ansible.builtin.file:
        path: /tmp/unprivileged_file.txt
        state: touch
        mode: '0644'

    - name: Criar um arquivo de propriedade do root usando become
      ansible.builtin.file:
        path: /root/privileged_file.txt
        state: touch
        mode: '0600'
      become: yes          # Apenas esta tarefa usará become
      become_user: root
      become_method: sudo

3. Via Variáveis de Inventário

As opções become também podem ser definidas no seu inventário do Ansible, permitindo que você especifique diferentes estratégias de escalação de privilégios para diferentes hosts ou grupos.

Exemplo 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

Aqui, ansible_become, ansible_become_method e ansible_become_user são variáveis de inventário que correspondem às opções become. Elas podem ser definidas no nível all:vars, no nível do grupo ou no nível do host.

4. Usando Argumentos de CLI do ansible-playbook

Para substituições rápidas ou execução interativa, você pode passar parâmetros become diretamente via linha de comando:

  • --become ou -b: Ativa become.
  • --become-method <MÉTODO>: Especifica o método become (por exemplo, sudo).
  • --become-user <USUÁRIO>: Especifica o usuário de destino (por exemplo, root).
  • --ask-become-pass ou -K: Solicita a senha become durante a execução. Isso é útil para testes, mas geralmente não para automação.

Exemplo:

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

Garantindo Direitos sudo para o Usuário become

Configurar corretamente o become no Ansible é apenas metade da batalha. O usuário ao qual o Ansible se conecta (o ansible_user) deve ter os privilégios sudo necessários no host de destino para se tornar o become_user. Isso é configurado no host de destino dentro do arquivo /etc/sudoers ou em um arquivo sob /etc/sudoers.d/.

Configurando sudoers

O arquivo sudoers define quem pode executar quais comandos e como quem. Uma entrada comum para permitir que um usuário de conexão do Ansible (devops_user neste exemplo) execute qualquer comando como qualquer usuário sem solicitação de senha é:

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

Explicação:

  • devops_user: O nome de usuário ao qual o Ansible se conecta (ansible_user).
  • ALL: Este usuário pode executar comandos de qualquer terminal.
  • (ALL): Este usuário pode executar comandos como qualquer usuário.
  • NOPASSWD:: Especifica que nenhuma senha é necessária para operações sudo.
  • ALL: Este usuário pode executar todos os comandos.

Aviso: Conceder NOPASSWD: ALL dá ao ansible_user acesso root irrestrito sem senha, o que pode ser um risco de segurança significativo. Use isso apenas se realmente necessário e garanta que as credenciais do seu ansible_user sejam altamente seguras. Para uma segurança mais rigorosa, você pode especificar comandos exatos ou conjuntos de comandos que o usuário pode executar.

Verificando o Acesso sudo

Antes de executar seu playbook, você pode verificar manualmente se seu ansible_user tem acesso sudo em um host de destino. Faça SSH no host como ansible_user e execute:

# Verifique se você pode usar sudo para root sem senha
sudo -n whoami

# Se uma senha for necessária, você será solicitado. Teste com um comando simples:
sudo whoami

# Liste os privilégios sudo para o usuário atual:
sudo -l

# Liste os privilégios sudo para um usuário específico (por exemplo, devops_user):
sudo -l -U devops_user

Se sudo -n whoami retornar root sem solicitação de senha, sua configuração NOPASSWD provavelmente está correta. Se solicitar uma senha, sua entrada sudoers pode estar faltando NOPASSWD ou estar configurada incorretamente.

Diagnosticando Erros de Escalação de Privilégios

O Ansible geralmente fornece mensagens de erro informativas, mas problemas relacionados a privilégios podem às vezes ser enigmáticos. Aqui estão erros comuns e suas soluções:

1. "permissão negada"

Isso geralmente significa que a tarefa foi executada como o usuário de conexão sem privilégios em vez de root.

Verifique o play ou a tarefa:

- name: Instalar pacote que requer root
  ansible.builtin.package:
    name: nginx
    state: present
  become: true

Em seguida, confirme qual usuário o Ansible está usando:

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

O segundo comando deve retornar root quando o sudo estiver funcionando.

2. "Senha sudo ausente"

Isso acontece quando o host de destino requer uma senha sudo, mas o Ansible não recebeu uma.

Para uma execução interativa, use:

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

Para automação, evite armazenar senhas em texto simples no inventário. Use o Ansible Vault para ansible_become_password se o sudo sem senha não for permitido em seu ambiente.

ansible-vault encrypt group_vars/webservers/vault.yml

Exemplo de nome de variável criptografada antes da criptografia:

ansible_become_password: "substituir-pela-senha-real"

3. "usuário não está no arquivo sudoers"

Este é um problema de configuração do host de destino. O Ansible não pode corrigi-lo a menos que já possa se conectar como um usuário com privilégios suficientes.

No host de destino, use visudo ou um arquivo sob /etc/sudoers.d/:

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

Isso é mais restrito que NOPASSWD: ALL, mas funciona apenas se seus playbooks precisarem desses comandos exatos. Módulos de pacote podem chamar binários diferentes dependendo do SO, então teste com cuidado.

4. become_user Errado

A maioria das tarefas de administração Linux usa become_user: root. Se você definir become_user para uma conta de aplicação, esse usuário pode ainda não ter permissão para modificar arquivos do sistema ou gerenciar serviços.

Use uma verificação rápida:

- name: Confirmar usuário efetivo
  ansible.builtin.command: whoami
  become: true
  changed_when: false

Se a saída não for o usuário que você esperava, verifique as variáveis do playbook, variáveis de inventário e ansible.cfg em busca de valores conflitantes de become_user.

Uma Lista de Verificação Segura para Solução de Problemas

Trabalhe do host de destino de volta ao playbook:

  1. Faça SSH no host como ansible_user.
  2. Execute sudo -l e confirme que o usuário tem os direitos necessários.
  3. Execute sudo -n whoami se você espera sudo sem senha.
  4. Execute ansible all -b -m command -a 'whoami' contra um host de teste.
  5. Adicione -vvv à execução do playbook com falha se o erro ainda não estiver claro.

Conclusão Principal

O become do Ansible apenas diz ao Ansible para escalar privilégios. O host de destino ainda deve permitir que o usuário de conexão faça isso através do sudo ou outro método become. Corrija ambos os lados: defina become onde a tarefa precisa, depois verifique os direitos sudo diretamente no host.