Automatizando gestão de acessos em escala: do Bash com cPanel/WHM à orquestração com Ansible
Voltar para blog

Automatizando gestão de acessos em escala: do Bash com cPanel/WHM à orquestração com Ansible

23/09/2026 · 4 min · DevOps

Quem administra múltiplos servidores Linux no dia a dia sabe que rotinas manuais de provisionamento de contas e controle de privilégios (sudo/wheel) são portas abertas para erros operacionais e inconsistências.

Em ambientes híbridos, onde parte das máquinas roda sob painéis como WHM/cPanel e parte opera em distribuições Linux puras, o desafio é ainda maior: como garantir que a mesma rotina de criação e remoção de usuários funcione de forma padronizada, segura e auditável em dezenas de servidores?

Neste artigo, compartilho a evolução prática de uma ferramenta de automação: desde a criação de um script Bash híbrido com auto-configuração de logrotate até a sua orquestração distribuída via Ansible sem precisar reescrever a lógica original.


1. O ponto de partida: o script Bash híbrido#

O objetivo inicial foi construir um utilitário CLI (jvx_mngr) capaz de automatizar a criação (-a) e a remoção (-d) de contas administrativas, adaptando-se automaticamente ao ambiente de destino.

Requisitos técnicos do script:#

  1. Validação de Execução e Parâmetros: Checar privilégios de root e validar argumentos via getopts.
  2. Abordagem Híbrida (WHM API vs. Linux Nativo):
  1. Proteção Contra Erros Humanos: Um array de contas protegidas (USUARIO_PROTEGIDO=(admin_master backup_user root_corp)) que bloqueia imediatamente qualquer tentativa de exclusão acidental.
  2. Auditoria Centralizada: Gravação de logs com data, hora, analista executor (whoami) e hostname em /var/log/jvx_mngr.log.

Auto-provisionamento inteligente do logrotate#

Para evitar que o log crescesse indefinidamente e sem exigir que a equipe configurasse regras manuais em cada máquina, incluí uma função interna de auto-provisionamento do logrotate:

# --- Configuração do Logrotate ---
function configurar_logrotate() {
    local LOGROTATE_CONFIG="/etc/logrotate.d/jvx_mngr"

    if [[ -f "${LOGROTATE_CONFIG}" ]]; then
        return 0
    fi

    print_info "Criando arquivo de configuração para o logrotate em ${LOGROTATE_CONFIG}..."

    cat <<'EOF' > "${LOGROTATE_CONFIG}"
# Configuração do Logrotate para o script jvx_mngr
/var/log/jvx_mngr.log {
    monthly
    rotate 6
    compress
    delaycompress
    missingok
    notifempty
    create 640 root root
}
EOF

    if [[ $? -eq 0 ]]; then
        chmod 644 "${LOGROTATE_CONFIG}"
        print_success "Arquivo de configuração do logrotate criado com sucesso."
        log "Criada configuração do logrotate em ${LOGROTATE_CONFIG}."
    else
        print_error "Falha ao criar o arquivo de configuração do logrotate."
        log "ERRO: Falha ao criar a configuração do logrotate em ${LOGROTATE_CONFIG}."
    fi
}

Ao rodar essa função no início da execução principal (main), o script garante idempotência: se o arquivo já existir em /etc/logrotate.d/, ele segue silencioso; se não existir, cria a regra de rotação mensal com compressão, retenção de 6 ciclos e permissão 640.


2. O desafio de escalar: orquestrar sem reescrever#

Com o script testado e homologado localmente, o passo seguinte foi rodar essa mesma operação em múltiplos servidores simultaneamente usando Ansible.

Muitas equipes caem na tentação de tentar converter toda a lógica procedural do Bash para dezenas de tarefas nativas do Ansible. Na prática, essa reescrita gera riscos de regressão em chamadas complexas de API (como a whmapi1) e fallbacks de terminal. A abordagem mais inteligente é adotar o Ansible como o orquestrador/maestro e manter o script Bash como a ferramenta especialista.

Divisão em dois playbooks#

Para manter o ambiente desacoplado e limpo:

  1. Playbook de Instalação (instalar_jvx_mngr.yml): Copia o script para /usr/local/bin (ou caminho padronizado na infraestrutura) e define a permissão 0755. É executado apenas no provisionamento do servidor ou em atualizações de versão.
  2. Playbook de Operação Diária (usar_jvx_mngr.yml): Responsável por interagir com o operador no terminal e disparar o comando existente nos servidores remotos.

3. Resolvendo desafios de interface no Ansible#

Durante a criação do playbook operacional, surgiram dois obstáculos visuais e de fluxo de entrada:

Problema 1: Banner ASCII quebrado no módulo debug#

Ao exibir um banner de boas-vindas com o módulo nativo debug: msg:, o Ansible interpretou as quebras de linha como caracteres escapados (\n) dentro de um envelope JSON:

TASK [Mostrando o banner de execução do Ansible] **************************************
ok: [localhost] => {
    "msg": "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⢴⣃\n⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⢴⣫⢗⡯⡖..."
}

Solução: O módulo debug formata variáveis, não arte textual crua. A solução foi executar uma tarefa em localhost usando o módulo shell com um Here Document (cat <<'EOF'), que envia o fluxo diretamente ao stdout do terminal:

    - name: Mostrando o banner com o módulo shell
      shell: |
        cat <<'EOF'
        [ARTE ASCII AQUI]
        EOF
      args:
        warn: false

Problema 2: Exibir instruções antes do vars_prompt#

O vars_prompt do Ansible é bloqueante e dispara antes de qualquer task do play. Para exibir orientações (como avisar que na opção de deletar -d basta teclar [Enter] nos campos de e-mail e nível), estruturamos a execução em dois plays encadeados no mesmo arquivo YAML:


4. O playbook operacional completo#

# usar_jvx_mngr.yml

# --- Play 1: Interface e Instruções na Máquina Local ---
- name: Exibir Banner e Instruções
  hosts: localhost
  gather_facts: no

  tasks:
    - name: Mostrando o banner
      shell: |
        cat <<'EOF'
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⢴⣃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⢴⣫⢗⡯⡖⠀⠀⠀⠀⠀⢠⡄⠀⠀⠀⠀⠀⠀⠀⠀⢠⡤⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⢨⢷⡹⢮⣳⠇⠀⠀⠀⠀⠀⠈⠁⠀⠀⠀⠀⠀⠀⠀⠀⠈⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠠⠐⣀⠂⡀⢸⢧⡻⣝⢮⡏⠀⠀⠀⠀⠀⢸⡇⢀⣾⠟⠿⠻⠿⣷⠀⢸⣏⠀⣿⡟⠿⠻⠿⣶⡀⢸⣿⠀⠀⠀⢀⣿⠃⢸⡏⠀⠙⢿⣦⣀⣼⡟⠁⠀⠀
⠀⠀⠤⠑⡈⢡⠀⠆⡁⢢⣉⠓⢯⡳⡇⠀⠀⠀⠀⠀⢸⡇⠨⣿⠀⠀⠀⠀⣿⡁⢸⡧⠀⣿⡂⠀⠀⠀⢿⡃⢸⡷⠀⠀⢠⣾⠋⠀⢸⡗⠀⠀⠀⣹⣿⣇⠀⠀⠀⠀
⠀⠀⠀⠀⠁⠂⡌⠐⡄⢡⠢⡙⢤⠉⠇⠀⠀⠀⠀⠀⢸⡇⠈⣿⣤⣤⣤⣴⡿⠁⢸⡧⠀⣿⡅⠀⠀⠀⢿⡇⢘⣿⣤⡾⠟⠁⠀⠀⢸⡧⠀⢠⣾⠟⠈⢻⣦⡀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠡⠐⢨⡑⠘⠀⠀⠀⠀⠀⠀⠀⠀⣸⡇⠀⠀⠉⠉⠉⠈⠁⠀⠈⠁⠀⠉⠀⠀⠀⠀⠉⠁⠀⠉⠁⠀⠀⠀⠀⠀⠈⠁⠀⠉⠁⠀⠀⠀⠉⠉⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠿⠻⠟⠟⠁⠀Gerenciamento de Usuários via Ansible
        EOF
      args:
        warn: false

    - name: Mostrando as instruções de uso
      shell: |
        cat <<'EOF'
------------------------------------------------------------------------------------
INSTRUÇÕES:
- A seguir, informe os dados para a operação nos servidores de destino.
- Para a ação de DELETAR (-d), você pode pressionar [Enter] nos campos "email" e "nível".
------------------------------------------------------------------------------------
        EOF
      args:
        warn: false

# --- Play 2: Coleta de Dados e Execução Remota nos Servidores ---
- name: Usar o script jvx_mngr para gerenciar usuários
  hosts: servidores_alvo
  become: yes

  vars_prompt:
    - name: "acao"
      prompt: "Qual ação deseja executar? ('-a' para adicionar, '-d' para deletar)"
      private: no
    - name: "usuario"
      prompt: "Digite o nome do usuário"
      private: no
    - name: "email"
      prompt: "Digite o email (pressione Enter se estiver deletando)"
      private: no
      default: ""
    - name: "nivel"
      prompt: "Digite o nível de ACL (n1, n2, n3) (pressione Enter se estiver deletando)"
      private: no
      default: ""

  tasks:
    - name: Executando jvx_mngr nos hosts remotos
      command:
        cmd: "/usr/local/bin/jvx_mngr {{ acao }} {{ usuario }} {{ email }} {{ nivel }}"
      register: command_output

    - name: Exibir a saída da execução remota
      debug:
        var: command_output.stdout_lines

Lições aprendidas e boas práticas#

  1. Evite o Refactoring Desnecessário: Scripts consolidados em Bash com tratamento fino de APIs legadas (como whmapi1) funcionam muito bem quando combinados com a capacidade de entrega e paralelismo do Ansible.
  2. Desacople Instalação de Uso: Separar o playbook de implantação do playbook de rotina operacional economiza tráfego de rede e torna o uso diário mais rápido e direto.
  3. Ergonomia no Terminal Importa: Formatar saídas de forma legível e exibir avisos antes de campos de entrada evita falhas humanas em manutenções em lote.

Este artigo foi útil?

Deixe uma reação rápida para apoiar o conteúdo:

CC BY-NC

Este post está licenciado sob CC BY-NC.

Comentários

Participe da discussão abaixo.

0 comentários