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 SIEM and SOC: Automate Security Operations, Incident Response, and Compliance

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

Automate SOC and SIEM operations with Ansible. Incident response playbooks, threat hunting automation, SOAR integration, compliance scanning, log collection.

Why Ansible for Security Operations?

Security Operations Centers (SOCs) face a fundamental scaling problem: alerts grow faster than headcount. The average SOC processes 10,000+ alerts per day while facing a chronic analyst shortage. Automation is not optional — it's survival.

Ansible fits SOC automation because: • Agentless — no software to install on endpoints or network devices • Human-readable — security analysts can read and write YAML playbooks without being developers • Cross-platform — orchestrate firewalls, endpoints, SIEM, ticketing, cloud, and network in a single workflow • Auditable — every action logged, every playbook version-controlled • Idempotent — safe to re-run during an incident without causing additional damage

See also: Ansible for SOC and SIEM: Automate Security Operations Complete Guide

SIEM Integration

Collect and Forward Logs

---
- name: Configure centralized logging
  hosts: all
  become: true

vars: siem_server: "siem.company.com" siem_port: 514 siem_protocol: tcp

tasks: - name: Install rsyslog ansible.builtin.package: name: rsyslog state: present

- name: Configure remote syslog forwarding ansible.builtin.template: src: rsyslog-forward.conf.j2 dest: /etc/rsyslog.d/50-siem-forward.conf mode: '0644' notify: restart rsyslog

- name: Ensure audit logging enabled ansible.builtin.package: name: auditd state: present

- name: Deploy audit rules for security monitoring ansible.builtin.copy: content: | # Monitor authentication files -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

# Monitor sudo usage -w /etc/sudoers -p wa -k sudo_changes -w /etc/sudoers.d/ -p wa -k sudo_changes

# Monitor SSH configuration -w /etc/ssh/sshd_config -p wa -k sshd_config

# Monitor cron -w /etc/crontab -p wa -k cron -w /etc/cron.d/ -p wa -k cron

# Monitor login/logout -w /var/log/lastlog -p wa -k logins -w /var/log/faillog -p wa -k logins

# Monitor privilege escalation -a always,exit -F arch=b64 -S execve -C uid!=euid -k escalation dest: /etc/audit/rules.d/security.rules mode: '0640' notify: restart auditd

handlers: - name: restart rsyslog ansible.builtin.systemd: name: rsyslog state: restarted

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

Splunk Integration

---
- name: Deploy Splunk Universal Forwarder
  hosts: all
  become: true

vars: splunk_server: "splunk-indexer.company.com" splunk_port: 9997 splunk_forwarder_url: "https://download.splunk.com/products/universalforwarder/releases/9.3.0/linux/splunkforwarder-9.3.0-linux-x86_64.tgz"

tasks: - name: Download Splunk UF ansible.builtin.get_url: url: "{{ splunk_forwarder_url }}" dest: /tmp/splunkforwarder.tgz

- name: Extract Splunk UF ansible.builtin.unarchive: src: /tmp/splunkforwarder.tgz dest: /opt remote_src: true creates: /opt/splunkforwarder

- name: Configure forwarding ansible.builtin.template: src: splunk-outputs.conf.j2 dest: /opt/splunkforwarder/etc/system/local/outputs.conf notify: restart splunk-forwarder

- name: Configure inputs ansible.builtin.copy: content: | [monitor:///var/log/auth.log] sourcetype = linux_secure index = security

[monitor:///var/log/audit/audit.log] sourcetype = linux_audit index = security

[monitor:///var/log/syslog] sourcetype = syslog index = main dest: /opt/splunkforwarder/etc/system/local/inputs.conf notify: restart splunk-forwarder

- name: Start Splunk Forwarder ansible.builtin.command: cmd: /opt/splunkforwarder/bin/splunk start --accept-license --no-prompt creates: /opt/splunkforwarder/var/run/splunk/splunkd.pid

handlers: - name: restart splunk-forwarder ansible.builtin.command: cmd: /opt/splunkforwarder/bin/splunk restart

Elastic SIEM (ELK)

---
- name: Deploy Elastic Agent for SIEM
  hosts: all
  become: true

vars: fleet_url: "https://fleet.company.com:8220" enrollment_token: "{{ vault_elastic_token }}"

tasks: - name: Download Elastic Agent ansible.builtin.get_url: url: "https://artifacts.elastic.co/downloads/beats/elastic-agent/elastic-agent-8.16.0-linux-x86_64.tar.gz" dest: /tmp/elastic-agent.tar.gz

- name: Extract agent ansible.builtin.unarchive: src: /tmp/elastic-agent.tar.gz dest: /opt remote_src: true

- name: Enroll agent with Fleet ansible.builtin.command: cmd: > /opt/elastic-agent-8.16.0-linux-x86_64/elastic-agent install --url={{ fleet_url }} --enrollment-token={{ enrollment_token }} --non-interactive creates: /opt/Elastic/Agent/elastic-agent

Incident Response Automation

Automated Host Isolation

When a compromise is detected, automatically isolate the host while preserving forensic evidence:

---
- name: Isolate compromised host
  hosts: "{{ compromised_host }}"
  become: true

vars: soc_server: "10.0.0.5" siem_server: "10.0.0.10" ticket_id: "{{ incident_ticket }}"

tasks: - name: Capture network connections before isolation ansible.builtin.shell: | ss -tunap > /root/forensics/connections_{{ ansible_date_time.iso8601 }}.txt netstat -rn > /root/forensics/routes_{{ ansible_date_time.iso8601 }}.txt ip addr show > /root/forensics/interfaces_{{ ansible_date_time.iso8601 }}.txt args: creates: /root/forensics

- name: Create forensics directory ansible.builtin.file: path: /root/forensics state: directory mode: '0700'

- name: Capture running processes ansible.builtin.shell: | ps auxww > /root/forensics/processes.txt lsof -i > /root/forensics/open_files.txt changed_when: false

- name: Capture memory-mapped files for suspicious processes ansible.builtin.shell: | for pid in $(ps aux | awk '/SUSPECT_PROCESS/ {print $2}'); do cat /proc/$pid/maps > /root/forensics/maps_${pid}.txt 2>/dev/null ls -la /proc/$pid/fd/ > /root/forensics/fd_${pid}.txt 2>/dev/null done changed_when: false ignore_errors: true

- name: Block all traffic except SOC and SIEM community.general.ufw: rule: allow from_ip: "{{ item }}" comment: "Incident {{ ticket_id }} - allowed during isolation" loop: - "{{ soc_server }}" - "{{ siem_server }}"

- name: Set default deny community.general.ufw: default: deny direction: "{{ item }}" loop: - incoming - outgoing

- name: Enable firewall community.general.ufw: state: enabled

- name: Disable cron to prevent lateral movement ansible.builtin.systemd: name: cron state: stopped enabled: false

- name: Lock all non-root user accounts ansible.builtin.shell: | for user in $(awk -F: '$3 >= 1000 && $3 != 65534 {print $1}' /etc/passwd); do usermod -L "$user" echo "Locked: $user" >> /root/forensics/locked_users.txt done changed_when: true

- name: Send isolation notification ansible.builtin.uri: url: "https://hooks.slack.com/services/{{ vault_slack_webhook }}" method: POST body_format: json body: text: "🔴 Host {{ inventory_hostname }} isolated for incident {{ ticket_id }}"

Automated Threat Hunting

---
- name: Hunt for indicators of compromise
  hosts: all
  become: true

vars: ioc_hashes: - "e99a18c428cb38d5f260853678922e03" - "d41d8cd98f00b204e9800998ecf8427e" ioc_ips: - "185.220.101.0/24" - "45.155.205.0/24" suspicious_ports: - 4444 - 5555 - 8888 - 1337

tasks: - name: Check for known malicious file hashes ansible.builtin.shell: | find / -type f -executable -newer /etc/hostname -exec md5sum {} \; 2>/dev/null | head -1000 register: file_hashes changed_when: false timeout: 120

- name: Flag IOC hash matches ansible.builtin.set_fact: ioc_matches: "{{ file_hashes.stdout_lines | select('search', item) | list }}" loop: "{{ ioc_hashes }}" register: hash_results

- name: Check for connections to known bad IPs ansible.builtin.shell: | ss -tunap | grep -E "{{ ioc_ips | join('|') }}" || true register: bad_connections changed_when: false

- name: Check for suspicious listening ports ansible.builtin.shell: | ss -tlnp | grep -E ":{{ suspicious_ports | join('|:') }}" || true register: suspicious_listeners changed_when: false

- name: Check for unauthorized SSH keys ansible.builtin.find: paths: /home patterns: "authorized_keys" recurse: true register: ssh_keys

- name: Check for suspicious cron jobs ansible.builtin.shell: | for user in $(cut -d: -f1 /etc/passwd); do crontab -l -u "$user" 2>/dev/null | grep -v "^#" | grep -v "^$" done register: cron_jobs changed_when: false

- name: Check for rootkits (basic) ansible.builtin.shell: | # Check for hidden processes diff <(ps aux | awk '{print $2}' | sort -n) <(ls /proc | grep -E '^[0-9]+$' | sort -n) || true # Check for modified system binaries rpm -Va 2>/dev/null | grep -E '^..5' || dpkg --verify 2>/dev/null | grep -v "^$" || true register: rootkit_check changed_when: false

- name: Generate hunt report ansible.builtin.template: src: hunt-report.j2 dest: "/tmp/hunt_{{ inventory_hostname }}_{{ ansible_date_time.date }}.txt" delegate_to: localhost

See also: Ansible for AI Security: Protect Models, APIs & Data Pipelines (2026 Guide)

Compliance Automation

CIS Benchmark Scanning

---
- name: CIS benchmark compliance check
  hosts: all
  become: true

tasks: - name: Check SSH configuration ansible.builtin.lineinfile: path: /etc/ssh/sshd_config regexp: "{{ item.regexp }}" line: "{{ item.line }}" state: present loop: - { regexp: '^PermitRootLogin', line: 'PermitRootLogin no' } - { regexp: '^PasswordAuthentication', line: 'PasswordAuthentication no' } - { regexp: '^X11Forwarding', line: 'X11Forwarding no' } - { regexp: '^MaxAuthTries', line: 'MaxAuthTries 4' } - { regexp: '^ClientAliveInterval', line: 'ClientAliveInterval 300' } - { regexp: '^ClientAliveCountMax', line: 'ClientAliveCountMax 0' } - { regexp: '^LoginGraceTime', line: 'LoginGraceTime 60' } - { regexp: '^Protocol', line: 'Protocol 2' } notify: restart sshd

- name: Ensure password expiration ansible.builtin.lineinfile: path: /etc/login.defs regexp: "{{ item.regexp }}" line: "{{ item.line }}" loop: - { regexp: '^PASS_MAX_DAYS', line: 'PASS_MAX_DAYS 90' } - { regexp: '^PASS_MIN_DAYS', line: 'PASS_MIN_DAYS 7' } - { regexp: '^PASS_WARN_AGE', line: 'PASS_WARN_AGE 14' }

- name: Ensure core dumps restricted ansible.builtin.lineinfile: path: /etc/security/limits.conf line: "* hard core 0" state: present

- name: Disable USB storage ansible.builtin.copy: content: "install usb-storage /bin/true" dest: /etc/modprobe.d/usb-storage.conf mode: '0644'

- name: Set file permissions on sensitive files ansible.builtin.file: path: "{{ item.path }}" mode: "{{ item.mode }}" owner: 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/gshadow, mode: '0640', group: shadow } - { path: /etc/crontab, mode: '0600' }

handlers: - name: restart sshd ansible.builtin.systemd: name: sshd state: restarted

Vulnerability Scanning and Remediation

---
- name: Vulnerability management
  hosts: all
  become: true

tasks: - name: Check for available security updates ansible.builtin.apt: update_cache: true upgrade: "no" register: apt_updates check_mode: true when: ansible_os_family == "Debian"

- name: Get list of security updates ansible.builtin.shell: | apt list --upgradable 2>/dev/null | grep -i security register: security_updates changed_when: false when: ansible_os_family == "Debian"

- name: Apply security patches (maintenance window) ansible.builtin.apt: upgrade: safe update_cache: true when: - ansible_os_family == "Debian" - maintenance_window | default(false) notify: check reboot required

- name: Scan for CVEs in installed packages ansible.builtin.shell: | if command -v grype &>/dev/null; then grype dir:/ --only-fixed -o table 2>/dev/null | head -50 else echo "grype not installed" fi register: cve_scan changed_when: false

handlers: - name: check reboot required ansible.builtin.stat: path: /var/run/reboot-required register: reboot_file

- name: notify reboot needed ansible.builtin.debug: msg: "⚠️ {{ inventory_hostname }} requires reboot after security patches" when: reboot_file.stat.exists | default(false)

Firewall Orchestration

---
- name: Block threat actor across all firewalls
  hosts: firewalls
  
  vars:
    threat_ips:
      - "185.220.101.42"
      - "45.155.205.19"
    ticket_id: "IR-2026-0142"

tasks: - name: Block on Palo Alto paloaltonetworks.panos.panos_address_object: provider: "{{ panos_provider }}" name: "block-{{ item | replace('.', '-') }}" value: "{{ item }}" description: "Blocked - {{ ticket_id }}" loop: "{{ threat_ips }}" when: "'paloalto' in group_names"

- name: Block on Linux firewalls community.general.ufw: rule: deny from_ip: "{{ item }}" comment: "Blocked - {{ ticket_id }}" loop: "{{ threat_ips }}" when: "'linux' in group_names"

- name: Block on Cisco ASA cisco.asa.asa_acls: config: - afi: ipv4 acls: - name: OUTSIDE_IN aces: - grant: deny source: address: "{{ item }}" destination: any: true state: merged loop: "{{ threat_ips }}" when: "'cisco_asa' in group_names"

See also: Ansible for Data Sovereignty & Geopatriation: Manage Sovereign Cloud Infrastructure (2026 Guide)

Integration with SOAR Platforms

Trigger Ansible from SOAR

Configure AAP webhooks to receive SOAR triggers:

# AAP job template with survey for dynamic parameters
# SOAR calls AAP API to launch jobs:

# curl -X POST "https://aap.company.com/api/controller/v2/job_templates/42/launch/" \ # -H "Authorization: Bearer $TOKEN" \ # -H "Content-Type: application/json" \ # -d '{ # "extra_vars": { # "compromised_host": "web-03.company.com", # "incident_ticket": "IR-2026-0142", # "action": "isolate" # } # }'

SOAR-Driven Response Playbook

---
- name: SOAR-triggered incident response
  hosts: "{{ compromised_host }}"
  become: true

tasks: - name: Isolate host ansible.builtin.include_role: name: incident_response tasks_from: isolate.yml when: action == "isolate"

- name: Collect forensics ansible.builtin.include_role: name: incident_response tasks_from: collect_evidence.yml when: action == "forensics"

- name: Block IOCs ansible.builtin.include_role: name: incident_response tasks_from: block_iocs.yml when: action == "block" delegate_to: "{{ item }}" loop: "{{ groups['firewalls'] }}"

- name: Restore host ansible.builtin.include_role: name: incident_response tasks_from: restore.yml when: action == "restore"

FAQ

Can Ansible replace a SOAR platform?

Ansible can handle the orchestration and automation parts of SOAR (Security Orchestration, Automation, and Response) but lacks the case management, analyst workflow, and threat intelligence platform features. Use Ansible as the execution engine behind a SOAR platform like Splunk SOAR, Palo Alto XSOAR, or IBM QRadar SOAR.

Is Ansible secure enough for SOC operations?

Yes, with proper configuration. Use AAP for centralized credential management (no passwords in playbooks), RBAC (limit who can run what), audit logging (every job tracked), and encrypted variables (Ansible Vault). AAP integrates with CyberArk, HashiCorp Vault, and other enterprise secret managers.

How does Ansible compare to dedicated security automation tools?

Ansible is general-purpose automation that excels at cross-platform orchestration. Dedicated security tools (CrowdStrike Falcon, SentinelOne) have deeper endpoint visibility. The best approach: use Ansible to orchestrate responses across your full stack while dedicated tools handle detection and endpoint telemetry.

Conclusion

Ansible bridges the gap between security detection and response. Deploy SIEM agents across thousands of endpoints, automate incident response with host isolation playbooks, run compliance scans against CIS benchmarks, orchestrate firewall blocks across multi-vendor environments, and integrate with SOAR platforms — all with human-readable YAML that security analysts can understand and modify. Combined with AAP's RBAC, scheduling, and audit capabilities, Ansible becomes the execution layer for enterprise security operations.

Related Articles

Ansible Hardening: CIS Security Benchmark AutomationAAP 2.6 RBAC Best PracticesAAP 2.6 Notifications and WebhooksAAP 2.6 Event-Driven Ansible (EDA)UFW Allow Port with Ansible

Category: installation

Browse all Ansible tutorials · AnsiblePilot Home