Introduction

The Linux Audit Framework (auditd) tracks security-relevant events — file access, system calls, authentication, privilege escalation, and configuration changes. It's required by CIS benchmarks, STIG, PCI-DSS, and HIPAA compliance. Ansible automates auditd deployment, rule management, and log configuration across your fleet.

Install and Configure

---
- name: Configure Linux Audit Framework
  hosts: all
  become: true
  vars:
    auditd_max_log_file: 50
    auditd_max_log_file_action: rotate
    auditd_num_logs: 10
    auditd_space_left: 75
    auditd_space_left_action: email
    auditd_action_mail_acct: root
  tasks:
    - name: Install auditd
      ansible.builtin.package:
        name:
          - audit
          - audit-libs
        state: present

    - name: Configure auditd.conf
      ansible.builtin.template:
        src: auditd.conf.j2
        dest: /etc/audit/auditd.conf
        mode: '0640'
      notify: restart auditd

    - name: Deploy audit rules
      ansible.builtin.template:
        src: audit.rules.j2
        dest: /etc/audit/rules.d/ansible-managed.rules
        mode: '0640'
      notify: load audit rules

    - name: Start auditd
      ansible.builtin.service:
        name: auditd
        state: started
        enabled: true

  handlers:
    - name: restart auditd
      ansible.builtin.service:
        name: auditd
        state: restarted

    - name: load audit rules
      ansible.builtin.command: augenrules --load
      changed_when: true

auditd.conf Template

# templates/auditd.conf.j2
log_file = /var/log/audit/audit.log
log_format = ENRICHED
log_group = root
max_log_file = {{ auditd_max_log_file }}
max_log_file_action = {{ auditd_max_log_file_action }}
num_logs = {{ auditd_num_logs }}
space_left = {{ auditd_space_left }}
space_left_action = {{ auditd_space_left_action }}
action_mail_acct = {{ auditd_action_mail_acct }}
admin_space_left_action = halt
disk_full_action = halt
disk_error_action = halt
flush = incremental_async
freq = 50

Audit Rules — CIS Benchmark

# templates/audit.rules.j2
# Managed by Ansible — CIS Benchmark audit rules

# Remove all existing rules
-D

# Set buffer size
-b 8192

# Failure mode: 1=printk, 2=panic
-f 1

## Identity/Authentication
# Monitor password and group changes
-w /etc/passwd -p wa -k identity
-w /etc/shadow -p wa -k identity
-w /etc/group -p wa -k identity
-w /etc/gshadow -p wa -k identity
-w /etc/security/opasswd -p wa -k identity

## Authentication
-w /var/log/faillog -p wa -k logins
-w /var/log/lastlog -p wa -k logins
-w /var/log/tallylog -p wa -k logins
-w /var/run/utmp -p wa -k session
-w /var/log/wtmp -p wa -k logins
-w /var/log/btmp -p wa -k logins

## Privilege escalation
-w /etc/sudoers -p wa -k actions
-w /etc/sudoers.d/ -p wa -k actions
-a always,exit -F arch=b64 -S execve -C uid!=euid -F euid=0 -k setuid
-a always,exit -F arch=b32 -S execve -C uid!=euid -F euid=0 -k setuid

## System configuration
-w /etc/ssh/sshd_config -p wa -k sshd_config
-w /etc/sysctl.conf -p wa -k sysctl
-w /etc/sysctl.d/ -p wa -k sysctl
-w /etc/hosts -p wa -k network
-w /etc/hostname -p wa -k network
-w /etc/resolv.conf -p wa -k network

## Audit configuration (immutable section — must be last)
-w /etc/audit/ -p wa -k audit_config
-w /etc/libaudit.conf -p wa -k audit_config
-w /etc/audisp/ -p wa -k audit_config

## System calls
# Time changes
-a always,exit -F arch=b64 -S adjtimex -S settimeofday -k time_change
-a always,exit -F arch=b64 -S clock_settime -F a0=0x0 -k time_change
-w /etc/localtime -p wa -k time_change

# File deletion by users
-a always,exit -F arch=b64 -S unlink -S unlinkat -S rename -S renameat -F auid>=1000 -F auid!=4294967295 -k delete

# Kernel module loading
-w /sbin/insmod -p x -k modules
-w /sbin/rmmod -p x -k modules
-w /sbin/modprobe -p x -k modules
-a always,exit -F arch=b64 -S init_module -S delete_module -k modules

# Mount operations
-a always,exit -F arch=b64 -S mount -F auid>=1000 -F auid!=4294967295 -k mounts

{% if auditd_immutable | default(false) %}
# Make rules immutable (requires reboot to change)
-e 2
{% endif %}

Custom Application Rules

- name: Add application-specific audit rules
  ansible.builtin.copy:
    dest: /etc/audit/rules.d/app-rules.rules
    content: |
      # Monitor application config files
      -w /etc/myapp/ -p wa -k myapp_config
      -w /opt/myapp/conf/ -p wa -k myapp_config

      # Monitor sensitive data directories
      -w /var/lib/myapp/secrets/ -p rwa -k myapp_secrets

      # Track specific binary execution
      -w /usr/local/bin/myapp -p x -k myapp_exec

      # Monitor Docker/container events
      -w /etc/docker/ -p wa -k docker_config
      -w /var/lib/docker/ -p wa -k docker_data
      -w /usr/bin/docker -p x -k docker_commands
    mode: '0640'
  notify: load audit rules

Search and Report

- name: Search audit logs for sudo usage
  ansible.builtin.command: ausearch -k actions --format text
  register: sudo_events
  changed_when: false

- name: Generate audit report
  ansible.builtin.command: aureport --summary
  register: audit_summary
  changed_when: false

- name: Check for authentication failures
  ansible.builtin.command: aureport --auth --failed --summary
  register: auth_failures
  changed_when: false

- name: Alert on suspicious activity
  ansible.builtin.debug:
    msg: "Authentication failures detected on {{ inventory_hostname }}"
  when: "'0 authentication' not in auth_failures.stdout"

Forward Logs to Central Server

- name: Configure audisp remote logging
  ansible.builtin.template:
    src: audisp-remote.conf.j2
    dest: /etc/audit/plugins.d/au-remote.conf
    mode: '0640'
  notify: restart auditd
# templates/audisp-remote.conf.j2
active = yes
direction = out
path = /sbin/audisp-remote
type = always
format = string

Troubleshooting

Check Rule Status

- name: List active rules
  ansible.builtin.command: auditctl -l
  register: active_rules
  changed_when: false

- name: Check auditd status
  ansible.builtin.command: auditctl -s
  register: audit_status
  changed_when: false

Rules Not Loading

- name: Check for syntax errors
  ansible.builtin.command: augenrules --check
  register: rules_check
  changed_when: false

Conclusion

Ansible deploys auditd rules as code — CIS benchmark compliance, STIG requirements, and custom application monitoring all defined in templates. Use augenrules --load to apply changes without restarting, ausearch and aureport for investigation, and audisp-remote for centralized log collection. Immutable rules (-e 2) prevent tampering in high-security environments.