Gerenciando /etc/security/access.conf com ansible

2

Novo no Ansible e tenha várias máquinas que fazem uso do módulo pam_access que é configurado em /etc/security/access.conf . Várias linhas especificando ALLOW / DENY (+/-) e, em seguida, usuários ou grupos, juntamente com endereços IP src para corresponder.

O que é uma maneira mais limpa de gerenciar este arquivo no Ansible?

O arquivo /etc/security/access.conf é parecido com isto:

+ : root     : cron crond :0 ttyS0 tty1 tty2 tty3 tty4 tty5 tty6
+ : root     : 10.137.198.176
+ : inventory: 10.137.198.25
+ : sysadmin : 10.137.198.202
- : ALL : ALL

A maioria das máquinas empregará essa ACL base e outros grupos ou usuários poderão ser adicionados conforme necessário. Web devs faz o login através do SFTP em dois dos servidores web, então uma ACL seria inserida para aquele grupo (antes da - : ALL : ALL line) assim:

+ : webdev   : 10.137.198.0/24
- : ALL : ALL

Alguns servidores da web também executam passenger . Os desenvolvedores desses sistemas enviam código como passenger user, portanto, esse usuário é permitido na LAN dev, mas isso não está em todos os servidores da web.

+ : passenger: 10.137.197.0/24
- : ALL : ALL

As regras se tornam bastante específicas para cada máquina e não vejo uma maneira fácil de gerenciar esse arquivo. Eu comecei com o playbook e group_vars abaixo que tipo de trabalho, mas ter várias definições para a mesma máquina precisa de ajuda. Provavelmente uma definição de array para line: no playbook é necessária e olhando para isso.

Além disso, esse modelo exigiria a reescrita do arquivo toda vez que a remoção de um host de group_vars não remove a entrada de access.conf . Os únicos estados para lineinfile são absent ou present . Eu preciso de um estado chamado add_line_if_missing_remove_if_absent_from_vars . Existe uma maneira melhor?

- hosts: all
  vars_files:
    - ../group_vars/test-etc-security-access-conf.yml
  gather_facts: false

  tasks:
    - name: "Set up /etc/security/access.conf for {{ inventory_hostname }}"
      when: inventory_hostname is match (item.name)
      lineinfile:
        dest  : /tmp/access.conf
        regexp: '{{ item.regexp }}'
        line: '{{ item.line }}'
      with_items: "{{ access_rules }}"

group_vars - chegou a ser uma maneira melhor:

access_rules:
  - name: 10.137.1.66
    regexp: '.*passenger.*'
    line: '+ : passenger : 10.137.10.0/24'

  - name: 10.137.1.66
    regexp: '.*webdev.*'
    line: '+ : webdev : 10.137.198.0/24'
    
por Server Fault 25.05.2018 / 16:04

1 resposta

0

Isso é o que acabei usando. Talvez seja útil para outra pessoa. O manual aplicará uma ACL base a cada host e, em seguida, procurará uma ACL adicional no diretório {{ acl_dir }} com o nome do host atual que está sendo provisionado. Se isso existir, será aplicado. Por fim, a regra de negação padrão é anexada por último.

Eu pensei que um comentário no início do arquivo seria bom ter anotado quando o arquivo foi atualizado pela última vez. gather_facts adiciona muito tempo de execução, então optou pelo comando shell: para obter a data.

---
- hosts: all
  vars:
    dest_file: /etc/security/access.conf
    base_acl : base
    acl_dir  : ../group_vars/pam_access
  gather_facts: false

  tasks:
    - name: "Empty existing ACL and replace with base ACL"
      copy:
        content: ""
        dest   : "{{ dest_file }}"
        owner  : root
        group  : root
        mode   : 0644

    - name: "Get current date from shell rather than wait for gather_facts"
      shell: date '+%Y-%m-%d'
      register: date_now

    - name: "Add ansible header with modified date to beginning of file"
      copy:
        content: "# updated via ansible on {{ date_now.stdout }} by {{ lookup ('env', 'LOGNAME') }}"
        dest: "{{ dest_file }}"
        owner  : root
        group  : root
        mode   : 0644

    - name: "Add base ACL {{ acl_dir }}/base to {{ inventory_hostname }}"
      lineinfile:
        dest: "{{ dest_file }}"
        line: "{{ lookup ('file', '{{ acl_dir }}/{{ base_acl }}') }}"

    - name: "Check for additional ACL {{ acl_dir }}/{{ inventory_hostname }}..."
      stat:
        path  : "{{ acl_dir }}/{{ inventory_hostname }}"
      register: host_acl

    - name: "Add host specific ACL from {{ acl_dir }}/{{ inventory_hostname }}"
      when: host_acl.stat.exists
      lineinfile:
        dest: "{{ dest_file }}"
        line: "{{ lookup ('file', '{{ acl_dir }}/{{ inventory_hostname }}') }}"

    - name: "Add default DENY as last ACL as a security precaution"
      lineinfile:
        dest: "{{ dest_file }}"
        line: "- : ALL : ALL"

base ACL:

+ : root     : cron crond :0 ttyS0 tty1 tty2 tty3 tty4 tty5 tty6
+ : root     : 10.137.198.176
+ : inventory: 10.137.198.25
+ : sysadmin : 10.137.198.202

host ACL adicional chamado websrv01.mydom.com :

+ : webdev   : 10.137.198.0/24
+ : passenger: 10.137.197.0/24
    
por 25.05.2018 / 20:34