Configure audit compliance automation with Ansible for security monitoring and reporting

Advanced 45 min May 21, 2026 445 views
Ubuntu 24.04 Debian 12 AlmaLinux 9 Rocky Linux 9

Build comprehensive security audit compliance automation using Ansible playbooks to enforce security policies, monitor system configurations, and generate compliance reports across your Linux infrastructure fleet.

Prerequisites

  • Ansible control node with SSH access
  • Root or sudo privileges on target systems
  • Basic understanding of security frameworks
  • Familiarity with Ansible playbooks

What this solves

Security compliance requires continuous monitoring, policy enforcement, and regular reporting across your infrastructure. Manual compliance checks are time-consuming, error-prone, and don't scale with growing infrastructure. This tutorial shows you how to build a complete audit compliance automation system using Ansible that enforces security policies, monitors system configurations, and generates detailed compliance reports automatically.

Prerequisites

  • Ansible control node with SSH access to target hosts
  • Root or sudo privileges on all target systems
  • Basic understanding of security frameworks (CIS, NIST, SOC2)
  • Familiarity with Ansible playbooks and inventory management

Step-by-step configuration

Install and configure Linux audit framework

Start by installing the audit daemon and related tools on your target systems. The audit framework provides kernel-level monitoring of system calls, file access, and security events.

sudo apt update
sudo apt install -y auditd audispd-plugins aide rkhunter chkrootkit
sudo dnf install -y audit audit-libs aide rkhunter chkrootkit

Create Ansible directory structure

Set up a proper directory structure for your audit compliance automation project with organized roles, playbooks, and configuration files.

mkdir -p /opt/audit-compliance/{playbooks,roles,inventory,reports,templates}
cd /opt/audit-compliance

# Create role directories
mkdir -p roles/{audit-setup,compliance-check,security-hardening,reporting}/tasks
mkdir -p roles/{audit-setup,compliance-check,security-hardening,reporting}/templates
mkdir -p roles/{audit-setup,compliance-check,security-hardening,reporting}/handlers
mkdir -p roles/{audit-setup,compliance-check,security-hardening,reporting}/vars

Configure audit daemon baseline

Create an Ansible role to configure auditd with comprehensive rules for security monitoring. This establishes the foundation for compliance tracking.

---
- name: Install audit packages
  package:
    name:
      - auditd
      - audispd-plugins
      - aide
    state: present

- name: Configure auditd main configuration
  template:
    src: auditd.conf.j2
    dest: /etc/audit/auditd.conf
    backup: yes
  notify: restart auditd

- name: Deploy comprehensive audit rules
  template:
    src: audit.rules.j2
    dest: /etc/audit/rules.d/audit.rules
    backup: yes
  notify: restart auditd

- name: Initialize AIDE database
  command: aide --init
  args:
    creates: /var/lib/aide/aide.db.new.gz

- name: Move AIDE database to production location
  command: mv /var/lib/aide/aide.db.new.gz /var/lib/aide/aide.db.gz
  args:
    creates: /var/lib/aide/aide.db.gz

- name: Enable and start auditd service
  systemd:
    name: auditd
    enabled: yes
    state: started

Create comprehensive audit rules template

Define audit rules that cover critical security events including file access, privilege escalation, network connections, and system configuration changes.

# Delete all existing rules
-D

# Buffer size for audit events
-b 8192

# Failure mode (0=silent, 1=printk, 2=panic)
-f 1

# Monitor file access and modifications
-w /etc/passwd -p wa -k identity
-w /etc/group -p wa -k identity
-w /etc/shadow -p wa -k identity
-w /etc/sudoers -p wa -k privilege-escalation
-w /etc/sudoers.d/ -p wa -k privilege-escalation

# Monitor authentication and authorization
-w /var/log/auth.log -p wa -k authentication
-w /var/log/secure -p wa -k authentication
-w /etc/ssh/sshd_config -p wa -k ssh-config

# Monitor system configuration changes
-w /etc/hosts -p wa -k network-config
-w /etc/hostname -p wa -k network-config
-w /etc/resolv.conf -p wa -k network-config
-w /etc/crontab -p wa -k scheduled-tasks
-w /etc/cron.d/ -p wa -k scheduled-tasks

# Monitor critical system calls
-a always,exit -F arch=b64 -S adjtimex -S settimeofday -k time-change
-a always,exit -F arch=b32 -S adjtimex -S settimeofday -S stime -k time-change
-a always,exit -F arch=b64 -S clock_settime -k time-change
-a always,exit -F arch=b32 -S clock_settime -k time-change

# Monitor network connections
-a always,exit -F arch=b64 -S socket -F a0=10 -k network-socket
-a always,exit -F arch=b64 -S socket -F a0=2 -k network-socket

# Monitor file permission changes
-a always,exit -F arch=b64 -S chmod -S fchmod -S fchmodat -k file-permissions
-a always,exit -F arch=b64 -S chown -S fchown -S fchownat -S lchown -k file-ownership

# Monitor privilege escalation
-a always,exit -F arch=b64 -S setuid -S setgid -S setreuid -S setregid -k privilege-escalation

# Monitor kernel module loading
-w /sbin/insmod -p x -k kernel-modules
-w /sbin/rmmod -p x -k kernel-modules
-w /sbin/modprobe -p x -k kernel-modules

# Make rules immutable
-e 2

Create compliance checking role

Build an Ansible role that performs automated compliance checks against security frameworks like CIS benchmarks and generates structured results.

---
- name: Create compliance report directory
  file:
    path: /var/log/compliance
    state: directory
    mode: '0750'
    owner: root
    group: root

- name: Check SSH configuration compliance
  block:
    - name: Verify SSH protocol version
      lineinfile:
        path: /etc/ssh/sshd_config
        regexp: '^Protocol'
        line: 'Protocol 2'
        state: present
      check_mode: yes
      register: ssh_protocol_check
      failed_when: false

    - name: Check SSH root login disabled
      lineinfile:
        path: /etc/ssh/sshd_config
        regexp: '^PermitRootLogin'
        line: 'PermitRootLogin no'
        state: present
      check_mode: yes
      register: ssh_root_check
      failed_when: false

    - name: Verify SSH key authentication
      lineinfile:
        path: /etc/ssh/sshd_config
        regexp: '^PubkeyAuthentication'
        line: 'PubkeyAuthentication yes'
        state: present
      check_mode: yes
      register: ssh_pubkey_check
      failed_when: false

- name: Check file permission compliance
  stat:
    path: "{{ item.path }}"
  register: file_permissions
  loop:
    - { path: '/etc/passwd', expected: '0644' }
    - { path: '/etc/shadow', expected: '0640' }
    - { path: '/etc/group', expected: '0644' }
    - { path: '/etc/sudoers', expected: '0440' }

- name: Run AIDE file integrity check
  command: aide --check
  register: aide_check
  failed_when: false
  changed_when: false

- name: Check for rootkits with rkhunter
  command: rkhunter --check --skip-keypress --report-warnings-only
  register: rkhunter_check
  failed_when: false
  changed_when: false

- name: Generate compliance report
  template:
    src: compliance-report.j2
    dest: "/var/log/compliance/compliance-{{ ansible_date_time.date }}.json"
    mode: '0644'
  vars:
    compliance_results:
      ssh_protocol: "{{ ssh_protocol_check }}"
      ssh_root_login: "{{ ssh_root_check }}"
      ssh_pubkey_auth: "{{ ssh_pubkey_check }}"
      file_permissions: "{{ file_permissions }}"
      aide_check: "{{ aide_check }}"
      rkhunter_results: "{{ rkhunter_check }}"
      timestamp: "{{ ansible_date_time.iso8601 }}"
      hostname: "{{ ansible_hostname }}"
      ip_address: "{{ ansible_default_ipv4.address }}"

Create security hardening role

Implement automated security hardening based on industry standards. This role enforces security policies and configurations across your infrastructure.

---
- name: Configure password policies
  block:
    - name: Set password minimum length
      lineinfile:
        path: /etc/login.defs
        regexp: '^PASS_MIN_LEN'
        line: 'PASS_MIN_LEN 12'
        backup: yes

    - name: Set password maximum age
      lineinfile:
        path: /etc/login.defs
        regexp: '^PASS_MAX_DAYS'
        line: 'PASS_MAX_DAYS 90'
        backup: yes

    - name: Set password minimum age
      lineinfile:
        path: /etc/login.defs
        regexp: '^PASS_MIN_DAYS'
        line: 'PASS_MIN_DAYS 1'
        backup: yes

- name: Configure kernel parameters for security
  sysctl:
    name: "{{ item.name }}"
    value: "{{ item.value }}"
    state: present
    reload: yes
  loop:
    - { name: 'net.ipv4.ip_forward', value: '0' }
    - { name: 'net.ipv4.conf.all.send_redirects', value: '0' }
    - { name: 'net.ipv4.conf.default.send_redirects', value: '0' }
    - { name: 'net.ipv4.conf.all.accept_source_route', value: '0' }
    - { name: 'net.ipv4.conf.default.accept_source_route', value: '0' }
    - { name: 'net.ipv4.conf.all.accept_redirects', value: '0' }
    - { name: 'net.ipv4.conf.default.accept_redirects', value: '0' }
    - { name: 'net.ipv4.conf.all.log_martians', value: '1' }
    - { name: 'net.ipv4.conf.default.log_martians', value: '1' }
    - { name: 'kernel.randomize_va_space', value: '2' }

- name: Disable unnecessary services
  systemd:
    name: "{{ item }}"
    enabled: no
    state: stopped
  loop:
    - avahi-daemon
    - cups
    - bluetooth
  failed_when: false

- name: Configure file permissions for critical files
  file:
    path: "{{ item.path }}"
    mode: "{{ item.mode }}"
    owner: "{{ item.owner | default('root') }}"
    group: "{{ item.group | default('root') }}"
  loop:
    - { path: '/etc/passwd', mode: '0644' }
    - { path: '/etc/shadow', mode: '0640', group: 'shadow' }
    - { path: '/etc/group', mode: '0644' }
    - { path: '/etc/sudoers', mode: '0440' }
    - { path: '/boot/grub/grub.cfg', mode: '0600' }

- name: Configure fail2ban for SSH protection
  block:
    - name: Install fail2ban
      package:
        name: fail2ban
        state: present

    - name: Configure fail2ban SSH jail
      template:
        src: jail.local.j2
        dest: /etc/fail2ban/jail.local
        backup: yes
      notify: restart fail2ban

    - name: Enable and start fail2ban
      systemd:
        name: fail2ban
        enabled: yes
        state: started

Create automated reporting role

Build comprehensive reporting capabilities that aggregate compliance data, generate dashboards, and send alerts for security violations.

---
- name: Create reporting directories
  file:
    path: "{{ item }}"
    state: directory
    mode: '0755'
    owner: root
    group: root
  loop:
    - /var/log/compliance/reports
    - /var/log/compliance/alerts
    - /opt/compliance-dashboard

- name: Generate HTML compliance dashboard
  template:
    src: dashboard.html.j2
    dest: "/var/log/compliance/reports/compliance-dashboard-{{ ansible_date_time.date }}.html"
    mode: '0644'
  vars:
    report_date: "{{ ansible_date_time.date }}"
    total_hosts: "{{ groups['all'] | length }}"

- name: Create compliance summary report
  template:
    src: summary-report.j2
    dest: "/var/log/compliance/reports/summary-{{ ansible_date_time.date }}.json"
    mode: '0644'
  vars:
    compliance_summary:
      report_date: "{{ ansible_date_time.iso8601 }}"
      total_checks: 15
      passed_checks: "{{ compliance_passed | default(0) }}"
      failed_checks: "{{ compliance_failed | default(0) }}"
      hostname: "{{ ansible_hostname }}"
      ip_address: "{{ ansible_default_ipv4.address }}"

- name: Check for critical compliance failures
  set_fact:
    critical_failures: true
  when: >
    (ssh_root_check.changed | default(false)) or
    (aide_check.rc | default(0) != 0) or
    (rkhunter_check.rc | default(0) != 0)

- name: Send alert for critical failures
  mail:
    to: "{{ compliance_email | default('admin@example.com') }}"
    subject: "CRITICAL: Compliance failure on {{ ansible_hostname }}"
    body: |
      Critical compliance failures detected on {{ ansible_hostname }} ({{ ansible_default_ipv4.address }})
      
      Time: {{ ansible_date_time.iso8601 }}
      
      Failures detected:
      {% if ssh_root_check.changed | default(false) %}
      - SSH root login not properly disabled
      {% endif %}
      {% if aide_check.rc | default(0) != 0 %}
      - AIDE file integrity check failed
      {% endif %}
      {% if rkhunter_check.rc | default(0) != 0 %}
      - Rootkit scanner detected issues
      {% endif %}
      
      Please investigate immediately.
  when: critical_failures | default(false)
  ignore_errors: yes

- name: Generate audit log analysis
  shell: |
    ausearch -ts today | aureport -au > /var/log/compliance/reports/audit-summary-{{ ansible_date_time.date }}.txt
    ausearch -ts today | aureport -f >> /var/log/compliance/reports/audit-summary-{{ ansible_date_time.date }}.txt
  ignore_errors: yes

- name: Collect system security metrics
  shell: |
    echo "Security Metrics Report - {{ ansible_date_time.iso8601 }}" > /var/log/compliance/reports/security-metrics-{{ ansible_date_time.date }}.txt
    echo "========================================" >> /var/log/compliance/reports/security-metrics-{{ ansible_date_time.date }}.txt
    echo "Failed login attempts:" >> /var/log/compliance/reports/security-metrics-{{ ansible_date_time.date }}.txt
    grep "Failed password" /var/log/auth.log | wc -l >> /var/log/compliance/reports/security-metrics-{{ ansible_date_time.date }}.txt
    echo "Successful sudo commands:" >> /var/log/compliance/reports/security-metrics-{{ ansible_date_time.date }}.txt
    grep "sudo:" /var/log/auth.log | grep "COMMAND" | wc -l >> /var/log/compliance/reports/security-metrics-{{ ansible_date_time.date }}.txt
  ignore_errors: yes

Create main compliance playbook

Combine all roles into a comprehensive playbook that orchestrates the entire compliance automation workflow across your infrastructure.

---
- name: Automated Security Audit and Compliance
  hosts: all
  become: yes
  gather_facts: yes
  
  vars:
    compliance_email: "security@example.com"
    compliance_schedule: "daily"
    retention_days: 30
    
  pre_tasks:
    - name: Create timestamp for this run
      set_fact:
        compliance_run_id: "{{ ansible_date_time.epoch }}"
        
  roles:
    - role: audit-setup
      tags: ['setup', 'audit']
      
    - role: security-hardening
      tags: ['hardening', 'security']
      
    - role: compliance-check
      tags: ['compliance', 'check']
      
    - role: reporting
      tags: ['reporting', 'alerts']
      
  post_tasks:
    - name: Cleanup old compliance reports
      find:
        paths: /var/log/compliance/reports
        age: "{{ retention_days }}d"
        file_type: file
      register: old_reports
      
    - name: Remove old reports
      file:
        path: "{{ item.path }}"
        state: absent
      loop: "{{ old_reports.files }}"
      
    - name: Log compliance run completion
      lineinfile:
        path: /var/log/compliance/compliance.log
        line: "{{ ansible_date_time.iso8601 }} - Compliance run {{ compliance_run_id }} completed on {{ ansible_hostname }}"
        create: yes
        mode: '0644'

- name: Generate consolidated compliance report
  hosts: localhost
  gather_facts: no
  
  tasks:
    - name: Create consolidated report directory
      file:
        path: /opt/compliance-reports
        state: directory
        mode: '0755'
        
    - name: Generate infrastructure-wide compliance summary
      template:
        src: templates/infrastructure-summary.j2
        dest: "/opt/compliance-reports/infrastructure-compliance-{{ ansible_date_time.date }}.html"
        mode: '0644'
      vars:
        total_servers: "{{ groups['all'] | length }}"
        report_timestamp: "{{ ansible_date_time.iso8601 }}"
        
  tags: ['reporting', 'summary']

Create inventory and configuration

Set up your Ansible inventory with proper grouping and configure automation scheduling for regular compliance checks.

all:
  children:
    production:
      hosts:
        web-01:
          ansible_host: 203.0.113.10
          compliance_level: high
        web-02:
          ansible_host: 203.0.113.11
          compliance_level: high
        db-01:
          ansible_host: 203.0.113.20
          compliance_level: critical
          
    staging:
      hosts:
        staging-01:
          ansible_host: 203.0.113.50
          compliance_level: medium
          
    development:
      hosts:
        dev-01:
          ansible_host: 203.0.113.60
          compliance_level: low
          
  vars:
    ansible_user: ubuntu
    ansible_ssh_private_key_file: ~/.ssh/compliance-key
    compliance_email: security-team@example.com
    report_retention_days: 90

Configure automated scheduling

Set up cron jobs and systemd timers to run compliance checks automatically and ensure continuous monitoring of your infrastructure.

# Create systemd service for compliance checks
sudo tee /etc/systemd/system/audit-compliance.service > /dev/null << 'EOF'
[Unit]
Description=Automated Security Audit and Compliance Check
After=network.target

[Service]
Type=oneshot
User=root
WorkingDirectory=/opt/audit-compliance
ExecStart=/usr/bin/ansible-playbook -i inventory/hosts.yml playbooks/audit-compliance.yml
StandardOutput=journal
StandardError=journal
EOF

# Create systemd timer for daily execution
sudo tee /etc/systemd/system/audit-compliance.timer > /dev/null << 'EOF'
[Unit]
Description=Run audit compliance check daily
Requires=audit-compliance.service

[Timer]
OnCalendar=daily
Persistent=true
R

Automated install script

Run this to automate the entire setup

Don't want to manage this yourself?

We handle infrastructure for businesses that depend on uptime. Fully managed, with one fixed contact who knows your setup.

You get one fixed contact who knows your setup

Rotterdam 07:19 · reachable in a message, no ticket form