New to Ansible and have several machines which make use of the pam_access
module which is configured in /etc/security/access.conf
. Multiple lines specifying ALLOW/DENY (+/-) and then either users or groups along with src IP addresses to match.
What's a cleaner way to manage this file in Ansible?
The file /etc/security/access.conf
looks something like this:
+ : 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
Most machines will employ this base ACL and then other groups or users may be added as need be. Web devs login over SFTP on two of the web servers so an ACL would be inserted for that group (before the - : ALL : ALL
line) like so:
+ : webdev : 10.137.198.0/24
- : ALL : ALL
Some web servers also run passenger
. The developers for these systems push out code as the passenger
user, so this user is allowed from the dev LAN, but this is not on all web servers.
+ : passenger: 10.137.197.0/24
- : ALL : ALL
The rules become quite specific for each machine and I don't see an easy way of managing this file. I started with the playbook and group_vars below which sort of works but having multiple definitions for the same machine needs help. Probably an array definition for line:
in the playbook is needed and looking into that.
Also, this model would require re-writing the file every time since removing a host from group_vars
doesn't remove the entry from access.conf
. The only states for lineinfile
are absent
or present
. I need a state called add_line_if_missing_remove_if_absent_from_vars
. Is there a better way?
- 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 – got to be a better way:
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'
Best Answer
This is what I ended up using. Maybe it will be useful to someone else. The playbook will apply a base ACL to every host and then look for an additional ACL under the directory
{{ acl_dir }}
with the name of the current host being provisioned. If this exists, it gets applied. Finally, the default deny rule is appended last.I thought a comment at the beginning of the file would be nice to have noting when the file was last updated.
gather_facts
adds a lot of execution time so opted for theshell:
command to get the date instead.base ACL:
additional host ACL named
websrv01.mydom.com
: