Configure audit compliance automation with Ansible for security monitoring and reporting

Advanced 45 min May 21, 2026 27 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 RandomizedDelaySec=300 [Install] WantedBy=timers.target EOF

Enable and start the timer

sudo systemctl daemon-reload sudo systemctl enable audit-compliance.timer sudo systemctl start audit-compliance.timer

Configure compliance templates

Create the reporting templates that generate readable compliance reports and dashboards for management and audit teams.




    
    
    Security Compliance Dashboard
    


    

Security Compliance Dashboard

Generated: {{ ansible_date_time.iso8601 }} | Infrastructure: {{ total_hosts }} servers

Overall Compliance

{{ ((compliance_passed | default(12)) / 15 * 100) | round(1) }}%

Critical Issues

{{ compliance_failed | default(3) }}

Last Scan

{{ ansible_date_time.date }}

AIDE Status

{% if aide_check.rc == 0 %}PASS{% else %}FAIL{% endif %}

Compliance Check Results

Check Status Description Risk Level
SSH Root Login {% if not ssh_root_check.changed %}PASS{% else %}FAIL{% endif %} Root login via SSH disabled HIGH
File Integrity {% if aide_check.rc == 0 %}PASS{% else %}FAIL{% endif %} AIDE file integrity verification CRITICAL
Rootkit Detection {% if rkhunter_check.rc == 0 %}PASS{% else %}WARNING{% endif %} RKHunter rootkit scan HIGH

Advanced compliance automation

Integrate with external SIEM

Configure integration with external monitoring systems for centralized compliance tracking. This extends your automation to work with existing security infrastructure.

---
  • name: Send compliance data to Splunk
uri: url: "https://splunk.example.com:8088/services/collector" method: POST headers: Authorization: "Splunk {{ splunk_hec_token }}" Content-Type: "application/json" body_format: json body: time: "{{ ansible_date_time.epoch }}" host: "{{ ansible_hostname }}" source: "ansible-compliance" sourcetype: "compliance:audit" event: compliance_score: "{{ compliance_score | default(80) }}" critical_failures: "{{ critical_failures | default(false) }}" checks_passed: "{{ compliance_passed | default(12) }}" checks_failed: "{{ compliance_failed | default(3) }}" server_ip: "{{ ansible_default_ipv4.address }}" environment: "{{ group_names[0] }}" when: splunk_hec_token is defined ignore_errors: yes
  • name: Send alerts to security team Slack
uri: url: "{{ slack_webhook_url }}" method: POST body_format: json body: text: "Security compliance alert for {{ ansible_hostname }}" attachments: - color: "{% if critical_failures | default(false) %}danger{% else %}good{% endif %}" fields: - title: "Hostname" value: "{{ ansible_hostname }}" short: true - title: "IP Address" value: "{{ ansible_default_ipv4.address }}" short: true - title: "Compliance Score" value: "{{ ((compliance_passed | default(12)) / 15 * 100) | round(1) }}%" short: true - title: "Critical Issues" value: "{{ compliance_failed | default(0) }}" short: true when: slack_webhook_url is defined and critical_failures | default(false) ignore_errors: yes

Create custom compliance policies

Define organization-specific compliance policies that extend beyond standard frameworks to meet your unique security requirements.

---
custom_compliance_checks:
  - name: "database_encryption"
    description: "Verify database encryption at rest"
    commands:
      - "grep -i 'encrypt' /etc/mysql/mysql.conf.d/mysqld.cnf || echo 'not_found'"
    expected_result: "encrypt"
    risk_level: "critical"
    
  - name: "backup_encryption"
    description: "Verify backup encryption configuration"
    commands:
      - "gpg --list-keys | grep backup || echo 'no_backup_key'"
    expected_result: "backup"
    risk_level: "high"
    
  - name: "network_segmentation"
    description: "Check network segmentation rules"
    commands:
      - "iptables -L | grep -c 'REJECT\|DROP' || echo '0'"
    expected_result: ">5"
    risk_level: "medium"
    
  - name: "container_security"
    description: "Verify container runtime security"
    commands:
      - "docker info | grep 'Security Options' || echo 'not_configured'"
    expected_result: "apparmor"
    risk_level: "high"
    
organization_policies:
  password_complexity:
    min_length: 12
    require_special: true
    require_numbers: true
    max_age_days: 90
    
  access_controls:
    sudo_timeout: 15
    session_timeout: 900
    max_login_attempts: 3
    
  monitoring_requirements:
    log_retention_days: 365
    real_time_alerts: true
    integrity_checks: "daily"

Verify your setup

Test your audit compliance automation to ensure it works correctly and generates proper reports across your infrastructure.

# Run compliance check on a single host
ansible-playbook -i inventory/hosts.yml playbooks/audit-compliance.yml --limit web-01 --tags compliance

Check systemd timer status

sudo systemctl status audit-compliance.timer sudo systemctl list-timers audit-compliance.timer

Verify audit rules are loaded

sudo auditctl -l

Test compliance report generation

ansible-playbook -i inventory/hosts.yml playbooks/audit-compliance.yml --tags reporting --check

View recent compliance logs

sudo tail -f /var/log/compliance/compliance.log

Check AIDE database status

sudo aide --check | head -20

You can also integrate this with your existing monitoring infrastructure. For example, you might want to configure auditd with Elasticsearch and Kibana for compliance reporting to visualize your audit data, or set up audit log analysis dashboard with Grafana for real-time monitoring.

Common issues

SymptomCauseFix
Auditd service fails to start Invalid audit rules syntax auditctl -D && auditctl -R /etc/audit/rules.d/audit.rules
AIDE check takes too long Database includes too many files Configure /etc/aide/aide.conf to exclude temporary directories
Ansible playbook fails with permission errors SSH user lacks sudo privileges Add user to sudoers: usermod -aG sudo username
Compliance reports not generated Template directory missing Create directory: mkdir -p /var/log/compliance/reports
Email alerts not sent Mail system not configured Install and configure postfix: apt install postfix mailutils
Systemd timer not executing Timer not enabled or started systemctl enable --now audit-compliance.timer
Security consideration: Always test compliance playbooks in a development environment first. Some hardening measures can lock you out of systems if not properly configured. Keep backup access methods available during initial deployment.

Next steps

Running this in production?

Want this handled for you? Running compliance automation at scale adds complexity: multi-framework support, custom policy engines, integration with existing SIEM tools, and 24/7 incident response. Our managed platform covers automated compliance monitoring, audit reporting, and security incident response for European SaaS teams.

Automated install script

Run this to automate the entire setup

Need help?

Don't want to manage this yourself?

We handle infrastructure security hardening for businesses that depend on uptime. From initial setup to ongoing operations.