Verificando arquivos sudoers.d com Ansible

3

Eu tenho uma cartilha Ansible que uso para gerenciar nossos arquivos sudoers em nosso ambiente. Nós gostamos de manter um arquivo sudoers mínimo em / etc / sudoers, então qualquer coisa que queremos adicionar é colocada em arquivos separados em /etc/sudoers.d.

Meu playbook Ansible contém a seguinte tarefa para enviar esses arquivos:

- name: copy sudoers files
  copy:
    src: "{{ item }}"
    dest: "/etc/sudoers.d/{{ item }}"
    backup: yes
    owner: root
    group: root
    mode: 0440
    validate: /usr/sbin/visudo -cf %s
  with_items:
    - admins
    - apache
    - monitor

A tarefa contém uma cláusula validate para garantir que o arquivo seja válido antes de confirmar o arquivo, e isso geralmente funcionou bem. No entanto, hoje me deparei com um problema em que uma atualização quebrou o sudo. O arquivo passou pela etapa de validação, mas continha um User_Alias com o mesmo nome de um User_Alias no arquivo principal / etc / sudoers. Qualquer tentativa de executar o sudo depois disso resultou em um erro de análise.

Minha pergunta é: como faço para testar atualizações para meus arquivos sudoers do Ansible que podem capturar erros como este? Quando o arquivo estiver no lugar, o erro pode ser detectado executando visudo -c , mas colocar isso como a etapa de validação não funciona. O Ansible requer o espaço reservado %s e, mesmo que não tenha, a validação é feita antes de copiar o arquivo para que visudo -c não o detecte.

    
por virtex 13.03.2018 / 19:57

2 respostas

0

Eu consegui trabalhar. Aqui está o que eu fiz. Primeiro, adicionei um conjunto de tarefas Ansible para criar um diretório temporário em /etc/sudoers.stage.d e copiar o conteúdo de /etc/sudoers.d para ele. Eu então carrego os arquivos para esta área de preparação e, se algum deles for alterado, execute um script personalizado para ativá-los.

É assim que a lógica no manual é agora

- name: delete staging area
  file:
    path: "/etc/sudoers.stage.d"
    state: absent
  changed_when: false

- name: copy /etc/sudoers.d to staging area
  shell: "cp -rp /etc/sudoers.d /etc/sudoers.stage.d"
  changed_when: false

- name: stage sudoers files
  copy:
    src: "{{item}}"
    dest: "/etc/sudoers.stage.d/{{item}}"
    backup: yes
    owner: root
    group: root
    mode: 0440
    validate: /usr/sbin/visudo -cf %s
  with_items:
    - admins
    - apache
    - monitor
  register: sudoers_d

- block:
  - name: push out activate script
    copy:
      src: activate_sudoers.sh
      dest: /usr/local/bin/activate_sudoers.sh
      owner: root
      group: root
      mode: 0700

  - name: activate change
    shell: /bin/sh /usr/local/bin/activate_sudoers.sh /etc/sudoers.stage.d

  when: sudoers_d.changed

e aqui está o que o script activate_sudoers.sh parece.

#!/bin/sh

function usage {
    echo "Usage: $0 <stage directory>" >&2
    exit 1
}

function abort {
    echo "*** Error detected" >&2
    [ "$#" -gt 0 ] && echo "***" $@ >&2
    exit 1
}

PATH=/usr/bin:/bin:/usr/sbin:/sbin
export PATH

test $# -eq 1 || usage
test -d "$1" || abort "Stage directory $1: missing or not a directory"
test -d /etc/sudoers.old.d && rm -rf /etc/sudoers.old.d
test -d /etc/sudoers.old.d && abort "Failed to remove /etc/sudoers.old.d"

mv /etc/sudoers.d /etc/sudoers.old.d \
  && mv "$1" /etc/sudoers.d \
  && visudo -c

if [ $? -eq 0 ]; then
    # Success - clean up
    rm -rf /etc/sudoers.old.d
    exit 0
else
    # Failure - roll back
    rm -rf /etc/sudoers.d
    mv /etc/sudoers.old.d /etc/sudoers.d
    abort "sudoers update failed"
fi

É um pouco mais longo e complexo do que eu esperava, mas faz o trabalho. Espero que isso seja útil para qualquer outra pessoa que esteja enfrentando o mesmo problema.

    
por 15.03.2018 / 21:09
1

Você já tentou isso:

- copy:
    src: '{{ item }}'
    dest: '/etc/sudoers.d/{{ item }}'
    owner: root
    group: root
    mode: 0440
    validate: 'bash -c "cat /etc/sudoers %s | visudo -cf-"'

Funciona para mim.

    
por 16.08.2018 / 21:30