AnsiblePilot — Master Ansible Automation

AnsiblePilot is the leading resource for learning Ansible automation, DevOps, and infrastructure as code. Browse over 1,400 tutorials covering Ansible modules, playbooks, roles, collections, and real-world examples. Whether you are a beginner or an experienced engineer, our step-by-step guides help you automate Linux, Windows, cloud, containers, and network infrastructure.

Popular Topics

About Luca Berton

Luca Berton is an Ansible automation expert, author of 8 Ansible books published by Apress and Leanpub including "Ansible for VMware by Examples" and "Ansible for Kubernetes by Example", and creator of the Ansible Pilot YouTube channel. He shares practical automation knowledge through tutorials, books, and video courses to help IT professionals and DevOps engineers master infrastructure automation.

Ansible for Compliance Automation: CIS Benchmarks, STIG, and PCI DSS

By Luca Berton · Published 2024-01-01 · Category: installation

Automate security compliance with Ansible. Implement CIS Benchmarks, DISA STIG, PCI DSS, and SOC 2 hardening across enterprise infrastructure at scale.

Introduction

Security compliance is not optional — regulations like PCI DSS, SOC 2, HIPAA, and government standards like CIS Benchmarks and DISA STIGs require organizations to maintain hardened configurations across their entire infrastructure. Doing this manually is impossible at scale. Ansible transforms compliance from a periodic audit nightmare into continuous, automated enforcement.

See also: AAP 2.6 Compliance and Audit: CIS Benchmarks, STIG, and Regulatory Automation

Compliance Frameworks

| Framework | Scope | Who Needs It | |-----------|-------|-------------| | CIS Benchmarks | OS/app hardening | Everyone (best practice) | | DISA STIG | Government security | US DoD, federal agencies | | PCI DSS | Payment card data | Anyone handling credit cards | | SOC 2 | Service security | SaaS providers, cloud services | | HIPAA | Health data | Healthcare organizations | | NIST 800-53 | Security controls | US federal information systems |

Compliance as Code

The key principle: define compliance rules as Ansible playbooks, then enforce them continuously.

# compliance-baseline.yml
---
- name: Apply CIS Level 1 baseline
  hosts: all
  become: true
  roles:
    - cis_level1_filesystem
    - cis_level1_services
    - cis_level1_network
    - cis_level1_logging
    - cis_level1_access

See also: Ansible for Financial Services: Compliance, Trading Systems, and Regulatory Automation

CIS Benchmark Implementation

Filesystem Hardening

# CIS 1.1.1 — Disable unused filesystems
- name: "CIS 1.1.1.1 | Disable cramfs"
  ansible.builtin.copy:
    content: "install cramfs /bin/true\nblacklist cramfs\n"
    dest: /etc/modprobe.d/cramfs.conf
    mode: '0644'

- name: "CIS 1.1.1.2 | Disable freevxfs" ansible.builtin.copy: content: "install freevxfs /bin/true\nblacklist freevxfs\n" dest: /etc/modprobe.d/freevxfs.conf

# CIS 1.1.2 — /tmp on separate partition with noexec - name: "CIS 1.1.2 | Ensure /tmp has noexec" ansible.posix.mount: name: /tmp src: "{{ tmp_device }}" fstype: tmpfs opts: defaults,noexec,nosuid,nodev state: mounted

Service Hardening

# CIS 2.1 — Disable unnecessary services
- name: "CIS 2.1 | Disable unneeded services"
  ansible.builtin.systemd:
    name: "{{ item }}"
    state: stopped
    enabled: false
    masked: true
  loop:
    - avahi-daemon
    - cups
    - rpcbind
    - nfs-server
    - vsftpd
    - xinetd
  ignore_errors: true  # Service may not be installed

# CIS 2.2 — Ensure time synchronization - name: "CIS 2.2.1 | Ensure chrony is configured" ansible.builtin.template: src: chrony.conf.j2 dest: /etc/chrony.conf notify: restart chronyd

SSH Hardening

# CIS 5.2 — SSH Server Configuration
- name: "CIS 5.2 | Harden SSH configuration"
  ansible.builtin.lineinfile:
    path: /etc/ssh/sshd_config
    regexp: "{{ item.regexp }}"
    line: "{{ item.line }}"
  loop:
    - { regexp: '^#?PermitRootLogin', line: 'PermitRootLogin no' }
    - { regexp: '^#?PasswordAuthentication', line: 'PasswordAuthentication no' }
    - { regexp: '^#?MaxAuthTries', line: 'MaxAuthTries 4' }
    - { regexp: '^#?ClientAliveInterval', line: 'ClientAliveInterval 300' }
    - { regexp: '^#?ClientAliveCountMax', line: 'ClientAliveCountMax 3' }
    - { regexp: '^#?LoginGraceTime', line: 'LoginGraceTime 60' }
    - { regexp: '^#?X11Forwarding', line: 'X11Forwarding no' }
    - { regexp: '^#?AllowTcpForwarding', line: 'AllowTcpForwarding no' }
    - { regexp: '^#?Protocol', line: 'Protocol 2' }
  notify: restart sshd

Audit Logging

# CIS 4.1 — Configure auditd
- name: "CIS 4.1.1 | Ensure auditd is installed"
  ansible.builtin.package:
    name:
      - audit
      - audit-libs
    state: present

- name: "CIS 4.1.2 | Configure audit rules" ansible.builtin.template: src: audit.rules.j2 dest: /etc/audit/rules.d/cis.rules notify: restart auditd

DISA STIG Automation

# Use the RHEL STIG role from Ansible Galaxy
# ansible-galaxy install redhatofficial.rhel9_stig

- name: Apply DISA STIG to RHEL 9 hosts: government_servers become: true vars: # Override specific controls rhel9stig_ssh_required: true rhel9stig_fips_required: true rhel9stig_aide_required: true roles: - redhatofficial.rhel9_stig

See also: Ansible Automation Platform RBAC: Role-Based Access Control for Enterprise Teams

PCI DSS Requirements

# PCI DSS Requirement 2 — Change default passwords
- name: "PCI 2.1 | Ensure no default passwords"
  ansible.builtin.user:
    name: "{{ item }}"
    password_lock: true
  loop: "{{ default_accounts }}"

# PCI DSS Requirement 8 — Password policy - name: "PCI 8.2 | Set password complexity" ansible.builtin.lineinfile: path: /etc/security/pwquality.conf regexp: "{{ item.regexp }}" line: "{{ item.line }}" loop: - { regexp: '^minlen', line: 'minlen = 12' } - { regexp: '^dcredit', line: 'dcredit = -1' } - { regexp: '^ucredit', line: 'ucredit = -1' } - { regexp: '^lcredit', line: 'lcredit = -1' } - { regexp: '^ocredit', line: 'ocredit = -1' }

# PCI DSS Requirement 10 — Logging - name: "PCI 10.2 | Ensure audit logging" ansible.builtin.service: name: auditd state: started enabled: true

Compliance Scanning (Audit Mode)

Run playbooks in check mode to audit without changing anything:

# Dry-run compliance check
ansible-playbook compliance-baseline.yml --check --diff

# Generate compliance report ansible-playbook compliance-audit.yml -e "report_output=/tmp/compliance-report.html"

Audit Playbook Pattern

- name: Compliance audit
  hosts: all
  become: true
  tasks:
    - name: "Check SSH PermitRootLogin"
      ansible.builtin.command: grep "^PermitRootLogin no" /etc/ssh/sshd_config
      register: ssh_root
      changed_when: false
      failed_when: false

- name: Record compliance status ansible.builtin.set_fact: compliance_results: "{{ compliance_results | default([]) + [ {'control': 'SSH-001', 'name': 'PermitRootLogin', 'status': 'PASS' if ssh_root.rc == 0 else 'FAIL'} ] }}"

- name: Generate report ansible.builtin.template: src: compliance-report.j2 dest: "/tmp/compliance-{{ inventory_hostname }}.json" delegate_to: localhost

Continuous Compliance with AAP

# Schedule compliance checks in AAP:
# 1. Daily audit scan (check mode) → generates report
# 2. Weekly remediation run → enforces baseline
# 3. Alert on drift → notify security team

# Workflow Template: # [Audit Scan] → [Diff Report] → [Approval Gate] → [Remediate]

Community Roles

# CIS Benchmark roles
ansible-galaxy install alivx.cis_ubuntu_22
ansible-galaxy install MindPointGroup.RHEL9-CIS

# STIG roles ansible-galaxy install redhatofficial.rhel9_stig

# Hardening ansible-galaxy install dev-sec.os-hardening ansible-galaxy install dev-sec.ssh-hardening

Best Practices

Start with check mode — Audit before enforcing to understand the gap Tag controls individually — Run specific controls: --tags "cis_5.2,cis_4.1" Environment-specific exceptions — Some controls may not apply to all systems Version your compliance code — Git-managed playbooks with change history Automate reporting — Generate machine-readable compliance reports (JSON/CSV) Schedule regular scans — Daily audits, weekly remediation in AAP Test in staging first — Compliance hardening can break applications Document exceptions — Track why specific controls are skipped

FAQ

Can Ansible replace a compliance scanner?

Ansible can enforce and audit configurations but may not replace dedicated scanners like OpenSCAP or Qualys for vulnerability assessment. They complement each other — Ansible remediates what scanners find.

How to handle exceptions?

Use variables to skip controls: cis_5_2_enabled: false. Document why in your compliance repository.

CIS Level 1 vs Level 2?

Level 1 is practical for most environments. Level 2 adds stricter controls that may impact usability (e.g., USB storage disabled, specific kernel parameters). Start with Level 1.

Conclusion

Ansible transforms compliance from a manual audit exercise into continuous automated enforcement. By codifying CIS Benchmarks, STIG, and PCI DSS requirements as playbooks, organizations can maintain compliance at scale while reducing the cost and effort of security audits.

Related Articles

Ansible Roles Complete GuideAnsible Check Mode Dry Run GuideAnsible Automation Platform 2.6

Category: installation

Browse all Ansible tutorials · AnsiblePilot Home