Automate Patch Management with Ansible

Maintaining system security and stability through effective patch management has become more critical than ever. As we navigate through 2025, Ansible continues to stand out as a powerful and versatile tool for automating patch management across diverse environments, including both Linux and Windows systems. This comprehensive guide delves into the latest advancements, best practices, and detailed examples for automating patch management with Ansible, ensuring your systems remain secure, compliant, and up-to-date.
The Critical Importance of Patch Management
Patch management is a cornerstone of IT security, addressing vulnerabilities that could be exploited by malicious actors. With cyber threats growing in sophistication and frequency, the timely application of patches is essential to protect sensitive data, maintain system integrity, and ensure business continuity. Manual patching processes are not only time-consuming and labor-intensive but also prone to human error, making automation an indispensable solution. Ansible, with its robust automation capabilities, agentless architecture, and idempotent nature, provides a streamlined and efficient approach to patch management, reducing the risk of errors and ensuring consistency across your IT environment.
Latest Advancements in Ansible for Patch Management in 2025
As of 2025, Ansible Automation Platform has introduced significant enhancements and new features that make patch management more efficient, secure, and user-friendly. Some of the latest advancements include:
- Improved Collections and Modules: The
[ansible](https://en.wikipedia.org/wiki/Ansible).platform
collection has been enhanced with new modules and improved functionality for managing patches on various operating systems, including RHEL, Ubuntu, Windows, and more. - Enhanced Security: Recent updates have focused on addressing security issues, such as request smuggling vulnerabilities (CVE-2025-22871) in the automation gateway, ensuring a more secure patch management process.
- Simplified Workflows: The new web-based interface and improved job templates make it easier to create, manage, and monitor patch management workflows.
- Better Integration: Ansible Automation Platform now offers better integration with other Red Hat products, such as Red Hat Satellite and Red Hat Insights, providing a more comprehensive and unified patch management solution.
- Event-Driven Automation: The introduction of event-driven automation allows you to trigger patching workflows in response to specific events, such as the detection of new vulnerabilities or compliance issues, enhancing the responsiveness and agility of your patch management processes.
Key Steps to Automate Patch Management with Ansible
1. Building a Centralized and Detailed Inventory of Systems
The foundation of effective patch management is a centralized and detailed inventory of all systems within your IT environment. Ansible allows you to create a comprehensive inventory that includes detailed information about each system, such as:
- Hostname or IP address
- Operating system and version
- Installed software and versions
- Current patch levels
- System roles and purposes
- Network locations and environments (e.g., development, staging, production)
- Contact information for system owners or administrators
This centralized inventory serves as a single source of truth, enabling you to track and manage patches across your entire infrastructure effectively.
Example of a Detailed Inventory File (inventory.ini):
[all:vars]
ansible_user=admin
ansible_ssh_private_key_file=/path/to/private/key
ansible_python_interpreter=/usr/bin/python3
[web_servers]
webserver1 ansible_host=192.168.1.10 os=RHEL os_version=8.4 environment=production role=web_server [email protected]
webserver2 ansible_host=192.168.1.11 os=Ubuntu os_version=20.04 environment=staging role=web_server [email protected]
[database_servers]
dbserver1 ansible_host=192.168.1.20 os=RHEL os_version=8.4 environment=production role=database_server [email protected]
dbserver2 ansible_host=192.168.1.21 os=Ubuntu os_version=20.04 environment=staging role=database_server [email protected]
[windows_servers]
windows_server1 ansible_host=192.168.1.30 os=Windows os_version=Server 2019 environment=production role=file_server [email protected]
windows_server2 ansible_host=192.168.1.31 os=Windows os_version=Server 2019 environment=staging role=application_server [email protected]
[all:children]
servers:
web_servers
database_servers
windows_servers
2. Creating Detailed and Customizable Job Templates for Patch Deployment
Ansible Automation Platform enables the creation of detailed and customizable job templates that standardize the patch deployment process. These templates define the specific tasks, workflows, and parameters required to apply patches, ensuring consistency, reducing the likelihood of errors, and allowing for easy customization based on system roles, environments, or other factors.
Job templates can include various components, such as:
- Inventory selection
- Project selection
- Playbook selection
- Credentials and privilege escalation methods
- Extra variables and custom facts
- Schedules and time zones
- Notifications and callbacks
- Workflow approvals and delegations
- Job slicing and parallelism
- Job environment and isolation
By using job templates, you can automate the entire patch management lifecycle, from identifying missing patches to deploying, verifying, and reporting on their installation.
Example of a Detailed Job Template for Patch Management:
---
- name: Apply security patches to systems
hosts: all
gather_facts: true
vars:
patch_level: latest
reboot: false
notification_email: [email protected]
smtp_server: smtp.company.com
smtp_port: 587
smtp_username: [ansible](https://en.wikipedia.org/wiki/Ansible)@company.com
smtp_password: "{{ vault_smtp_password }}"
smtp_from: [ansible](https://en.wikipedia.org/wiki/Ansible)@company.com
smtp_to: "{{ notification_email }}"
smtp_subject: "[Patch Management](https://en.wikipedia.org/wiki/Patch_management) Notification"
smtp_body: "[Patch management](https://en.wikipedia.org/wiki/Patch_management) workflow has completed with status: {{ job_status }}"
tasks:
- name: Check for available security updates
block:
- name: Update package index (Debian/Ubuntu)
apt:
update_cache: yes
when: ansible_os_family == 'Debian'
register: update_cache_result
until: update_cache_result is success
retries: 3
delay: 10
- name: List security updates (Debian/Ubuntu)
apt:
list: security
security: yes
when: ansible_os_family == 'Debian'
register: security_updates
until: security_updates is success
retries: 3
delay: 10
- name: Update package index (RHEL/CentOS)
yum:
update_cache: yes
when: ansible_os_family == 'RedHat'
register: update_cache_result
until: update_cache_result is success
retries: 3
delay: 10
- name: List security updates (RHEL/CentOS)
yum:
list: security
security: yes
when: ansible_os_family == 'RedHat'
register: security_updates
until: security_updates is success
retries: 3
delay: 10
- name: List installed updates (Windows)
win_updates:
state: searched
when: ansible_os_name == 'Windows'
register: security_updates
until: security_updates is success
retries: 3
delay: 10
rescue:
- name: Send notification email on failure
community.general.mail:
host: "{{ smtp_server }}"
port: "{{ smtp_port }}"
username: "{{ smtp_username }}"
password: "{{ smtp_password }}"
to: "{{ smtp_to }}"
from: "{{ smtp_from }}"
subject: "{{ smtp_subject }} (FAILED)"
body: "[Patch management](https://en.wikipedia.org/wiki/Patch_management) workflow has failed on {{ inventory_hostname }} with error: {{ ansible_failed_result }}"
delegate_to: localhost
run_once: true
- name: Install security updates
block:
- name: Install security updates (Debian/Ubuntu)
apt:
upgrade: dist
autoremove: yes
when: ansible_os_family == 'Debian' and security_updates.results | length > 0
register: update_result
until: update_result is success
retries: 3
delay: 10
- name: Install security updates (RHEL/CentOS)
yum:
name: '*'
state: latest
security: yes
when: ansible_os_family == 'RedHat' and security_updates.results | length > 0
register: update_result
until: update_result is success
retries: 3
delay: 10
- name: Install security updates (Windows)
win_updates:
category_names:
- CriticalUpdates
- SecurityUpdates
state: installed
when: ansible_os_name == 'Windows' and security_updates.updates | length > 0
register: update_result
until: update_result is success
retries: 3
delay: 10
rescue:
- name: Send notification email on failure
community.general.mail:
host: "{{ smtp_server }}"
port: "{{ smtp_port }}"
username: "{{ smtp_username }}"
password: "{{ smtp_password }}"
to: "{{ smtp_to }}"
from: "{{ smtp_from }}"
subject: "{{ smtp_subject }} (FAILED)"
body: "[Patch management](https://en.wikipedia.org/wiki/Patch_management) workflow has failed on {{ inventory_hostname }} with error: {{ ansible_failed_result }}"
delegate_to: localhost
run_once: true
- name: Verify update installation
block:
- name: Verify update installation (Debian/Ubuntu)
apt:
list: installed
when: ansible_os_family == 'Debian'
register: installed_updates
until: installed_updates is success
retries: 3
delay: 10
- name: Verify update installation (RHEL/CentOS)
yum:
list: installed
when: ansible_os_family == 'RedHat'
register: installed_updates
until: installed_updates is success
retries: 3
delay: 10
- name: Verify update installation (Windows)
win_updates:
state: searched
when: ansible_os_name == 'Windows'
register: installed_updates
until: installed_updates is success
retries: 3
delay: 10
rescue:
- name: Send notification email on failure
community.general.mail:
host: "{{ smtp_server }}"
port: "{{ smtp_port }}"
username: "{{ smtp_username }}"
password: "{{ smtp_password }}"
to: "{{ smtp_to }}"
from: "{{ smtp_from }}"
subject: "{{ smtp_subject }} (FAILED)"
body: "[Patch management](https://en.wikipedia.org/wiki/Patch_management) workflow has failed on {{ inventory_hostname }} with error: {{ ansible_failed_result }}"
delegate_to: localhost
run_once: true
- name: Reboot if necessary
block:
- name: Check if reboot is required (Debian/Ubuntu)
stat:
path: /var/run/reboot-required
when: ansible_os_family == 'Debian'
register: reboot_required
- name: Reboot system (Debian/Ubuntu)
reboot:
msg: "Reboot initiated by [Ansible](https://en.wikipedia.org/wiki/Ansible) for applying security patches"
connect_timeout: 5
reboot_timeout: 600
pre_reboot_delay: 0
post_reboot_delay: 30
when: ansible_os_family == 'Debian' and reboot_required.stat.exists
- name: Check if reboot is required (RHEL/CentOS)
command: needs-restarting -r
when: ansible_os_family == 'RedHat'
register: reboot_required
ignore_errors: yes
changed_when: false
- name: Reboot system (RHEL/CentOS)
reboot:
msg: "Reboot initiated by [Ansible](https://en.wikipedia.org/wiki/Ansible) for applying security patches"
connect_timeout: 5
reboot_timeout: 600
pre_reboot_delay: 0
post_reboot_delay: 30
when: ansible_os_family == 'RedHat' and reboot_required.stdout == "reboot"
- name: Reboot system (Windows)
win_reboot:
when: ansible_os_name == 'Windows' and update_result.reboot_required
rescue:
- name: Send notification email on failure
community.general.mail:
host: "{{ smtp_server }}"
port: "{{ smtp_port }}"
username: "{{ smtp_username }}"
password: "{{ smtp_password }}"
to: "{{ smtp_to }}"
from: "{{ smtp_from }}"
subject: "{{ smtp_subject }} (FAILED)"
body: "[Patch management](https://en.wikipedia.org/wiki/Patch_management) workflow has failed on {{ inventory_hostname }} with error: {{ ansible_failed_result }}"
delegate_to: localhost
run_once: true
- name: Generate compliance report
block:
- name: Generate compliance report
template:
src: compliance_report.j2
dest: "/var/lib/awx/compliance_reports/{{ ansible_date_time.iso8601 }}.html"
vars:
missing_patches: "{{ security_updates.results | difference(installed_updates.results) | list }}"
delegate_to: localhost
run_once: true
- name: Send notification email on success
community.general.mail:
host: "{{ smtp_server }}"
port: "{{ smtp_port }}"
username: "{{ smtp_username }}"
password: "{{ smtp_password }}"
to: "{{ smtp_to }}"
from: "{{ smtp_from }}"
subject: "{{ smtp_subject }} (SUCCESS)"
body: "[Patch management](https://en.wikipedia.org/wiki/Patch_management) workflow has completed successfully on {{ inventory_hostname }}. Compliance report is attached."
attach: "/var/lib/awx/compliance_reports/{{ ansible_date_time.iso8601 }}.html"
delegate_to: localhost
run_once: true
rescue:
- name: Send notification email on failure
community.general.mail:
host: "{{ smtp_server }}"
port: "{{ smtp_port }}"
username: "{{ smtp_username }}"
password: "{{ smtp_password }}"
to: "{{ smtp_to }}"
from: "{{ smtp_from }}"
subject: "{{ smtp_subject }} (FAILED)"
body: "[Patch management](https://en.wikipedia.org/wiki/Patch_management) workflow has failed on {{ inventory_hostname }} with error: {{ ansible_failed_result }}"
delegate_to: localhost
run_once: true
3. Applying Patches Consistently on Red Hat Enterprise Linux (RHEL), Ubuntu, and Windows
One of the key advantages of Ansible is its ability to manage patches across different operating systems, including RHEL, Ubuntu, and Windows. For RHEL and Ubuntu, Ansible playbooks can be used to automate the patching process, ensuring that all systems are updated with the latest security patches. Similarly, for Windows environments, Ansible can coordinate advanced orchestration tasks, such as cluster failovers, and integrate validation and notification steps to minimize downtime and ensure patch correctness.
Example for RHEL and Ubuntu:
---
- name: Apply security patches to RHEL and Ubuntu systems
hosts: all
gather_facts: true
vars:
patch_level: latest
reboot: false
notification_email: [email protected]
smtp_server: smtp.company.com
smtp_port: 587
smtp_username: [ansible](https://en.wikipedia.org/wiki/Ansible)@company.com
smtp_password: "{{ vault_smtp_password }}"
smtp_from: [ansible](https://en.wikipedia.org/wiki/Ansible)@company.com
smtp_to: "{{ notification_email }}"
smtp_subject: "[Patch Management](https://en.wikipedia.org/wiki/Patch_management) Notification"
smtp_body: "[Patch management](https://en.wikipedia.org/wiki/Patch_management) workflow has completed with status: {{ job_status }}"
tasks:
- name: Check for available security updates
block:
- name: Update package index (Debian/Ubuntu)
apt:
update_cache: yes
when: ansible_os_family == 'Debian'
register: update_cache_result
until: update_cache_result is success
retries: 3
delay: 10
- name: List security updates (Debian/Ubuntu)
apt:
list: security
security: yes
when: ansible_os_family == 'Debian'
register: security_updates
until: security_updates is success
retries: 3
delay: 10
- name: Update package index (RHEL/CentOS)
yum:
update_cache: yes
when: ansible_os_family == 'RedHat'
register: update_cache_result
until: update_cache_result is success
retries: 3
delay: 10
- name: List security updates (RHEL/CentOS)
yum:
list: security
security: yes
when: ansible_os_family == 'RedHat'
register: security_updates
until: security_updates is success
retries: 3
delay: 10
rescue:
- name: Send notification email on failure
community.general.mail:
host: "{{ smtp_server }}"
port: "{{ smtp_port }}"
username: "{{ smtp_username }}"
password: "{{ smtp_password }}"
to: "{{ smtp_to }}"
from: "{{ smtp_from }}"
subject: "{{ smtp_subject }} (FAILED)"
body: "[Patch management](https://en.wikipedia.org/wiki/Patch_management) workflow has failed on {{ inventory_hostname }} with error: {{ ansible_failed_result }}"
delegate_to: localhost
run_once: true
- name: Install security updates
block:
- name: Install security updates (Debian/Ubuntu)
apt:
upgrade: dist
autoremove: yes
when: ansible_os_family == 'Debian' and security_updates.results | length > 0
register: update_result
until: update_result is success
retries: 3
delay: 10
- name: Install security updates (RHEL/CentOS)
yum:
name: '*'
state: latest
security: yes
when: ansible_os_family == 'RedHat' and security_updates.results | length > 0
register: update_result
until: update_result is success
retries: 3
delay: 10
rescue:
- name: Send notification email on failure
community.general.mail:
host: "{{ smtp_server }}"
port: "{{ smtp_port }}"
username: "{{ smtp_username }}"
password: "{{ smtp_password }}"
to: "{{ smtp_to }}"
from: "{{ smtp_from }}"
subject: "{{ smtp_subject }} (FAILED)"
body: "[Patch management](https://en.wikipedia.org/wiki/Patch_management) workflow has failed on {{ inventory_hostname }} with error: {{ ansible_failed_result }}"
delegate_to: localhost
run_once: true
- name: Verify update installation
block:
- name: Verify update installation (Debian/Ubuntu)
apt:
list: installed
when: ansible_os_family == 'Debian'
register: installed_updates
until: installed_updates is success
retries: 3
delay: 10
- name: Verify update installation (RHEL/CentOS)
yum:
list: installed
when: ansible_os_family == 'RedHat'
register: installed_updates
until: installed_updates is success
retries: 3
delay: 10
rescue:
- name: Send notification email on failure
community.general.mail:
host: "{{ smtp_server }}"
port: "{{ smtp_port }}"
username: "{{ smtp_username }}"
password: "{{ smtp_password }}"
to: "{{ smtp_to }}"
from: "{{ smtp_from }}"
subject: "{{ smtp_subject }} (FAILED)"
body: "[Patch management](https://en.wikipedia.org/wiki/Patch_management) workflow has failed on {{ inventory_hostname }} with error: {{ ansible_failed_result }}"
delegate_to: localhost
run_once: true
- name: Reboot if necessary
block:
- name: Check if reboot is required (Debian/Ubuntu)
stat:
path: /var/run/reboot-required
when: ansible_os_family == 'Debian'
register: reboot_required
- name: Reboot system (Debian/Ubuntu)
reboot:
msg: "Reboot initiated by [Ansible](https://en.wikipedia.org/wiki/Ansible) for applying security patches"
connect_timeout: 5
reboot_timeout: 600
pre_reboot_delay: 0
post_reboot_delay: 30
when: ansible_os_family == 'Debian' and reboot_required.stat.exists
- name: Check if reboot is required (RHEL/CentOS)
command: needs-restarting -r
when: ansible_os_family == 'RedHat'
register: reboot_required
ignore_errors: yes
changed_when: false
- name: Reboot system (RHEL/CentOS)
reboot:
msg: "Reboot initiated by [Ansible](https://en.wikipedia.org/wiki/Ansible) for applying security patches"
connect_timeout: 5
reboot_timeout: 600
pre_reboot_delay: 0
post_reboot_delay: 30
when: ansible_os_family == 'RedHat' and reboot_required.stdout == "reboot"
rescue:
- name: Send notification email on failure
community.general.mail:
host: "{{ smtp_server }}"
port: "{{ smtp_port }}"
username: "{{ smtp_username }}"
password: "{{ smtp_password }}"
to: "{{ smtp_to }}"
from: "{{ smtp_from }}"
subject: "{{ smtp_subject }} (FAILED)"
body: "[Patch management](https://en.wikipedia.org/wiki/Patch_management) workflow has failed on {{ inventory_hostname }} with error: {{ ansible_failed_result }}"
delegate_to: localhost
run_once: true
- name: Generate compliance report
block:
- name: Generate compliance report
template:
src: compliance_report.j2
dest: "/var/lib/awx/compliance_reports/{{ ansible_date_time.iso8601 }}.html"
vars:
missing_patches: "{{ security_updates.results | difference(installed_updates.results) | list }}"
delegate_to: localhost
run_once: true
- name: Send notification email on success
community.general.mail:
host: "{{ smtp_server }}"
port: "{{ smtp_port }}"
username: "{{ smtp_username }}"
password: "{{ smtp_password }}"
to: "{{ smtp_to }}"
from: "{{ smtp_from }}"
subject: "{{ smtp_subject }} (SUCCESS)"
body: "[Patch management](https://en.wikipedia.org/wiki/Patch_management) workflow has completed successfully on {{ inventory_hostname }}. Compliance report is attached."
attach: "/var/lib/awx/compliance_reports/{{ ansible_date_time.iso8601 }}.html"
delegate_to: localhost
run_once: true
rescue:
- name: Send notification email on failure
community.general.mail:
host: "{{ smtp_server }}"
port: "{{ smtp_port }}"
username: "{{ smtp_username }}"
password: "{{ smtp_password }}"
to: "{{ smtp_to }}"
from: "{{ smtp_from }}"
subject: "{{ smtp_subject }} (FAILED)"
body: "[Patch management](https://en.wikipedia.org/wiki/Patch_management) workflow has failed on {{ inventory_hostname }} with error: {{ ansible_failed_result }}"
delegate_to: localhost
run_once: true
Example for Windows:
---
- name: Apply security patches to [Windows systems](https://en.wikipedia.org/wiki/Windows_System_Assessment_Tool)
hosts: windows_servers
gather_facts: true
vars:
patch_level: latest
reboot: false
notification_email: [email protected]
smtp_server: smtp.company.com
smtp_port: 587
smtp_username: [ansible](https://en.wikipedia.org/wiki/Ansible)@company.com
smtp_password: "{{ vault_smtp_password }}"
smtp_from: [ansible](https://en.wikipedia.org/wiki/Ansible)@company.com
smtp_to: "{{ notification_email }}"
smtp_subject: "[Patch Management](https://en.wikipedia.org/wiki/Patch_management) Notification"
smtp_body: "[Patch management](https://en.wikipedia.org/wiki/Patch_management) workflow has completed with status: {{ job_status }}"
tasks:
- name: Check for available security updates
block:
- name: List installed updates (Windows)
win_updates:
state: searched
register: security_updates
until: security_updates is success
retries: 3
delay: 10
rescue:
- name: Send notification email on failure
community.general.mail:
host: "{{ smtp_server }}"
port: "{{ smtp_port }}"
username: "{{ smtp_username }}"
password: "{{ smtp_password }}"
to: "{{ smtp_to }}"
from: "{{ smtp_from }}"
subject: "{{ smtp_subject }} (FAILED)"
body: "[Patch management](https://en.wikipedia.org/wiki/Patch_management) workflow has failed on {{ inventory_hostname }} with error: {{ ansible_failed_result }}"
delegate_to: localhost
run_once: true
- name: Install security updates
block:
- name: Install security updates (Windows)
win_updates:
category_names:
- CriticalUpdates
- SecurityUpdates
state: installed
when: security_updates.updates | length > 0
register: update_result
until: update_result is success
retries: 3
delay: 10
rescue:
- name: Send notification email on failure
community.general.mail:
host: "{{ smtp_server }}"
port: "{{ smtp_port }}"
username: "{{ smtp_username }}"
password: "{{ smtp_password }}"
to: "{{ smtp_to }}"
from: "{{ smtp_from }}"
subject: "{{ smtp_subject }} (FAILED)"
body: "[Patch management](https://en.wikipedia.org/wiki/Patch_management) workflow has failed on {{ inventory_hostname }} with error: {{ ansible_failed_result }}"
delegate_to: localhost
run_once: true
- name: Verify update installation
block:
- name: Verify update installation (Windows)
win_updates:
state: searched
register: installed_updates
until: installed_updates is success
retries: 3
delay: 10
rescue:
- name: Send notification email on failure
community.general.mail:
host: "{{ smtp_server }}"
port: "{{ smtp_port }}"
username: "{{ smtp_username }}"
password: "{{ smtp_password }}"
to: "{{ smtp_to }}"
from: "{{ smtp_from }}"
subject: "{{ smtp_subject }} (FAILED)"
body: "[Patch management](https://en.wikipedia.org/wiki/Patch_management) workflow has failed on {{ inventory_hostname }} with error: {{ ansible_failed_result }}"
delegate_to: localhost
run_once: true
- name: Reboot if necessary
block:
- name: Reboot system (Windows)
win_reboot:
when: update_result.reboot_required
rescue:
- name: Send notification email on failure
community.general.mail:
host: "{{ smtp_server }}"
port: "{{ smtp_port }}"
username: "{{ smtp_username }}"
password: "{{ smtp_password }}"
to: "{{ smtp_to }}"
from: "{{ smtp_from }}"
subject: "{{ smtp_subject }} (FAILED)"
body: "[Patch management](https://en.wikipedia.org/wiki/Patch_management) workflow has failed on {{ inventory_hostname }} with error: {{ ansible_failed_result }}"
delegate_to: localhost
run_once: true
- name: Generate compliance report
block:
- name: Generate compliance report
template:
src: compliance_report.j2
dest: "C:\\compliance_reports\\{{ ansible_date_time.iso8601 }}.html"
vars:
missing_patches: "{{ security_updates.updates | difference(installed_updates.updates) | list }}"
delegate_to: localhost
run_once: true
- name: Send notification email on success
community.general.mail:
host: "{{ smtp_server }}"
port: "{{ smtp_port }}"
username: "{{ smtp_username }}"
password: "{{ smtp_password }}"
to: "{{ smtp_to }}"
from: "{{ smtp_from }}"
subject: "{{ smtp_subject }} (SUCCESS)"
body: "[Patch management](https://en.wikipedia.org/wiki/Patch_management) workflow has completed successfully on {{ inventory_hostname }}. Compliance report is attached."
attach: "C:\\compliance_reports\\{{ ansible_date_time.iso8601 }}.html"
delegate_to: localhost
run_once: true
rescue:
- name: Send notification email on failure
community.general.mail:
host: "{{ smtp_server }}"
port: "{{ smtp_port }}"
username: "{{ smtp_username }}"
password: "{{ smtp_password }}"
to: "{{ smtp_to }}"
from: "{{ smtp_from }}"
subject: "{{ smtp_subject }} (FAILED)"
body: "[Patch management](https://en.wikipedia.org/wiki/Patch_management) workflow has failed on {{ inventory_hostname }} with error: {{ ansible_failed_result }}"
delegate_to: localhost
run_once: true
4. Validating Patch Success with Automated Compliance Reports
After deploying patches, it is crucial to validate their success and ensure compliance with organizational policies and industry standards. Ansible Automation Platform provides automated compliance reporting capabilities, allowing you to generate detailed reports on the status of patch deployments. These reports help you verify that patches have been applied correctly and that systems are compliant with security requirements.
Example of a Compliance Report Template (compliance_report.j2):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>[Patch Management](https://en.wikipedia.org/wiki/Patch_management) Compliance Report</title>
<style>
body {
font-family: Arial, sans-serif;
line-height: 1.6;
margin: 0;
padding: 20px;
color: #333;
}
h1 {
color: #2c3e50;
text-align: center;
}
h2 {
color: #3498db;
border-bottom: 2px solid #3498db;
padding-bottom: 5px;
}
table {
width: 100%;
border-collapse: collapse;
margin: 20px 0;
}
th, td {
border: 1px solid #ddd;
padding: 8px;
text-align: left;
}
th {
background-color: #f2f2f2;
}
tr:nth-child(even) {
background-color: #f9f9f9;
}
.success {
color: #27ae60;
}
.failure {
color: #e74c3c;
}
.warning {
color: #f39c12;
}
.compliance-status {
font-weight: bold;
font-size: 1.2em;
margin: 20px 0;
}
</style>
</head>
<body>
<h1>[Patch Management](https://en.wikipedia.org/wiki/Patch_management) Compliance Report</h1>
<p><strong>Generated on:</strong> {{ ansible_date_time.iso8601 }}</p>
<p><strong>Generated by:</strong> [Ansible](https://en.wikipedia.org/wiki/Ansible) Automation Platform</p>
<h2>Compliance Status</h2>
{% if missing_patches | length == 0 %}
<p class="compliance-status success">All systems are compliant with the latest security patches.</p>
{% else %}
<p class="compliance-status failure">Some systems are not compliant with the latest security patches.</p>
{% endif %}
<h2>Systems and Patches</h2>
<table>
<thead>
<tr>
<th>System</th>
<th>Operating System</th>
<th>Environment</th>
<th>Missing Patches</th>
<th>Status</th>
</tr>
</thead>
<tbody>
{% for host in groups['all'] %}
{% set host_facts = hostvars[host] %}
{% set host_missing_patches = missing_patches | select('match', host) | list %}
{% if host_missing_patches | length > 0 %}
<tr>
<td>{{ host }}</td>
<td>{{ host_facts.ansible_facts.distribution }} {{ host_facts.ansible_facts.distribution_version }}</td>
<td>{{ host_facts.environment }}</td>
<td>
<ul>
{% for patch in host_missing_patches %}
<li>{{ patch }}</li>
{% endfor %}
</ul>
</td>
<td class="failure">Non-compliant</td>
</tr>
{% else %}
<tr>
<td>{{ host }}</td>
<td>{{ host_facts.ansible_facts.distribution }} {{ host_facts.ansible_facts.distribution_version }}</td>
<td>{{ host_facts.environment }}</td>
<td>None</td>
<td class="success">Compliant</td>
</tr>
{% endif %}
{% endfor %}
</tbody>
</table>
<h2>Summary</h2>
<p><strong>Total systems:</strong> {{ groups['all'] | length }}</p>
<p><strong>Compliant systems:</strong> {{ groups['all'] | select('search', 'missing_patches') | length }}</p>
<p><strong>Non-compliant systems:</strong> {{ groups['all'] | reject('search', 'missing_patches') | length }}</p>
<p><strong>Total missing patches:</strong> {{ missing_patches | length }}</p>
<h2>Recommendations</h2>
<p>To ensure the security and compliance of your [IT infrastructure](https://en.wikipedia.org/wiki/IT_infrastructure), it is recommended to:</p>
<ul>
<li>Apply the missing patches to the non-compliant systems as soon as possible.</li>
<li>Schedule regular [patch management](https://en.wikipedia.org/wiki/Patch_management) workflows to keep all systems up-to-date with the latest security patches.</li>
<li>Monitor the compliance status of your systems continuously and take appropriate actions when non-compliant systems are detected.</li>
<li>Review and update your [patch management](https://en.wikipedia.org/wiki/Patch_management) policies and procedures regularly to adapt to the evolving threat landscape.</li>
</ul>
</body>
</html>
5. Event-Driven Automation for Responsive Patch Management
In addition to scheduled patch management, event-driven automation allows you to trigger patching workflows in response to specific events, such as the detection of new vulnerabilities or compliance issues. This proactive approach ensures that patches are applied promptly, reducing the window of exposure to potential threats. By leveraging event-driven automation, you can enhance the responsiveness and agility of your patch management processes.
Example of Event-Driven Automation for Patch Management:
---
- name: Trigger [patch management](https://en.wikipedia.org/wiki/Patch_management) workflow on vulnerability detection
hosts: all
gather_facts: false
vars:
vulnerability_api_url: "https://example.com/api/vulnerabilities"
vulnerability_api_key: "{{ vault_vulnerability_api_key }}"
notification_email: [email protected]
smtp_server: smtp.company.com
smtp_port: 587
smtp_username: [ansible](https://en.wikipedia.org/wiki/Ansible)@company.com
smtp_password: "{{ vault_smtp_password }}"
smtp_from: [ansible](https://en.wikipedia.org/wiki/Ansible)@company.com
smtp_to: "{{ notification_email }}"
smtp_subject: "[Patch Management](https://en.wikipedia.org/wiki/Patch_management) Notification"
smtp_body: "[Patch management](https://en.wikipedia.org/wiki/Patch_management) workflow has been triggered by vulnerability detection with status: {{ job_status }}"
tasks:
- name: Check for new vulnerabilities
uri:
url: "{{ vulnerability_api_url }}"
method: GET
headers:
Authorization: "Bearer {{ vulnerability_api_key }}"
return_content: yes
register: vulnerabilities
until: vulnerabilities is success
retries: 3
delay: 10
- name: Trigger [patch management](https://en.wikipedia.org/wiki/Patch_management) workflow if vulnerabilities are detected
include_tasks: apply_patches.yml
when: vulnerabilities.json | length > 0
vars:
triggered_by: "vulnerability_detection"
vulnerability_details: "{{ vulnerabilities.json }}"
- name: Send notification email on success
community.general.mail:
host: "{{ smtp_server }}"
port: "{{ smtp_port }}"
username: "{{ smtp_username }}"
password: "{{ smtp_password }}"
to: "{{ smtp_to }}"
from: "{{ smtp_from }}"
subject: "{{ smtp_subject }} (SUCCESS)"
body: "[Patch management](https://en.wikipedia.org/wiki/Patch_management) workflow has been triggered by vulnerability detection and completed successfully."
delegate_to: localhost
run_once: true
when: vulnerabilities.json | length > 0
- name: Send notification email on no vulnerabilities
community.general.mail:
host: "{{ smtp_server }}"
port: "{{ smtp_port }}"
username: "{{ smtp_username }}"
password: "{{ smtp_password }}"
to: "{{ smtp_to }}"
from: "{{ smtp_from }}"
subject: "{{ smtp_subject }} (NO VULNERABILITIES)"
body: "No new vulnerabilities were detected, so no [patch management](https://en.wikipedia.org/wiki/Patch_management) workflow was triggered."
delegate_to: localhost
run_once: true
when: vulnerabilities.json | length == 0
Example of a Playbook for Applying Patches (apply_patches.yml):
---
- name: Apply security patches to systems
hosts: all
gather_facts: true
vars:
patch_level: latest
reboot: false
notification_email: [email protected]
smtp_server: smtp.company.com
smtp_port: 587
smtp_username: [ansible](https://en.wikipedia.org/wiki/Ansible)@company.com
smtp_password: "{{ vault_smtp_password }}"
smtp_from: [ansible](https://en.wikipedia.org/wiki/Ansible)@company.com
smtp_to: "{{ notification_email }}"
smtp_subject: "[Patch Management](https://en.wikipedia.org/wiki/Patch_management) Notification"
smtp_body: "[Patch management](https://en.wikipedia.org/wiki/Patch_management) workflow has completed with status: {{ job_status }}"
tasks:
- name: Check for available security updates
block:
- name: Update package index (Debian/Ubuntu)
apt:
update_cache: yes
when: ansible_os_family == 'Debian'
register: update_cache_result
until: update_cache_result is success
retries: 3
delay: 10
- name: List security updates (Debian/Ubuntu)
apt:
list: security
security: yes
when: ansible_os_family == 'Debian'
register: security_updates
until: security_updates is success
retries: 3
delay: 10
- name: Update package index (RHEL/CentOS)
yum:
update_cache: yes
when: ansible_os_family == 'RedHat'
register: update_cache_result
until: update_cache_result is success
retries: 3
delay: 10
- name: List security updates (RHEL/CentOS)
yum:
list: security
security: yes
when: ansible_os_family == 'RedHat'
register: security_updates
until: security_updates is success
retries: 3
delay: 10
- name: List installed updates (Windows)
win_updates:
state: searched
when: ansible_os_name == 'Windows'
register: security_updates
until: security_updates is success
retries: 3
delay: 10
rescue:
- name: Send notification email on failure
community.general.mail:
host: "{{ smtp_server }}"
port: "{{ smtp_port }}"
username: "{{ smtp_username }}"
password: "{{ smtp_password }}"
to: "{{ smtp_to }}"
from: "{{ smtp_from }}"
subject: "{{ smtp_subject }} (FAILED)"
body: "[Patch management](https://en.wikipedia.org/wiki/Patch_management) workflow has failed on {{ inventory_hostname }} with error: {{ ansible_failed_result }}"
delegate_to: localhost
run_once: true
- name: Install security updates
block:
- name: Install security updates (Debian/Ubuntu)
apt:
upgrade: dist
autoremove: yes
when: ansible_os_family == 'Debian' and security_updates.results | length > 0
register: update_result
until: update_result is success
retries: 3
delay: 10
- name: Install security updates (RHEL/CentOS)
yum:
name: '*'
state: latest
security: yes
when: ansible_os_family == 'RedHat' and security_updates.results | length > 0
register: update_result
until: update_result is success
retries: 3
delay: 10
- name: Install security updates (Windows)
win_updates:
category_names:
- CriticalUpdates
- SecurityUpdates
state: installed
when: ansible_os_name == 'Windows' and security_updates.updates | length > 0
register: update_result
until: update_result is success
retries: 3
delay: 10
rescue:
- name: Send notification email on failure
community.general.mail:
host: "{{ smtp_server }}"
port: "{{ smtp_port }}"
username: "{{ smtp_username }}"
password: "{{ smtp_password }}"
to: "{{ smtp_to }}"
from: "{{ smtp_from }}"
subject: "{{ smtp_subject }} (FAILED)"
body: "[Patch management](https://en.wikipedia.org/wiki/Patch_management) workflow has failed on {{ inventory_hostname }} with error: {{ ansible_failed_result }}"
delegate_to: localhost
run_once: true
- name: Verify update installation
block:
- name: Verify update installation (Debian/Ubuntu)
apt:
list: installed
when: ansible_os_family == 'Debian'
register: installed_updates
until: installed_updates is success
retries: 3
delay: 10
- name: Verify update installation (RHEL/CentOS)
yum:
list: installed
when: ansible_os_family == 'RedHat'
register: installed_updates
until: installed_updates is success
retries: 3
delay: 10
- name: Verify update installation (Windows)
win_updates:
state: searched
when: ansible_os_name == 'Windows'
register: installed_updates
until: installed_updates is success
retries: 3
delay: 10
rescue:
- name: Send notification email on failure
community.general.mail:
host: "{{ smtp_server }}"
port: "{{ smtp_port }}"
username: "{{ smtp_username }}"
password: "{{ smtp_password }}"
to: "{{ smtp_to }}"
from: "{{ smtp_from }}"
subject: "{{ smtp_subject }} (FAILED)"
body: "[Patch management](https://en.wikipedia.org/wiki/Patch_management) workflow has failed on {{ inventory_hostname }} with error: {{ ansible_failed_result }}"
delegate_to: localhost
run_once: true
- name: Reboot if necessary
block:
- name: Check if reboot is required (Debian/Ubuntu)
stat:
path: /var/run/reboot-required
when: ansible_os_family == 'Debian'
register: reboot_required
- name: Reboot system (Debian/Ubuntu)
reboot:
msg: "Reboot initiated by [Ansible](https://en.wikipedia.org/wiki/Ansible) for applying security patches"
connect_timeout: 5
reboot_timeout: 600
pre_reboot_delay: 0
post_reboot_delay: 30
when: ansible_os_family == 'Debian' and reboot_required.stat.exists
- name: Check if reboot is required (RHEL/CentOS)
command: needs-restarting -r
when: ansible_os_family == 'RedHat'
register: reboot_required
ignore_errors: yes
changed_when: false
- name: Reboot system (RHEL/CentOS)
reboot:
msg: "Reboot initiated by [Ansible](https://en.wikipedia.org/wiki/Ansible) for applying security patches"
connect_timeout: 5
reboot_timeout: 600
pre_reboot_delay: 0
post_reboot_delay: 30
when: ansible_os_family == 'RedHat' and reboot_required.stdout == "reboot"
- name: Reboot system (Windows)
win_reboot:
when: ansible_os_name == 'Windows' and update_result.reboot_required
rescue:
- name: Send notification email on failure
community.general.mail:
host: "{{ smtp_server }}"
port: "{{ smtp_port }}"
username: "{{ smtp_username }}"
password: "{{ smtp_password }}"
to: "{{ smtp_to }}"
from: "{{ smtp_from }}"
subject: "{{ smtp_subject }} (FAILED)"
body: "[Patch management](https://en.wikipedia.org/wiki/Patch_management) workflow has failed on {{ inventory_hostname }} with error: {{ ansible_failed_result }}"
delegate_to: localhost
run_once: true
- name: Generate compliance report
block:
- name: Generate compliance report
template:
src: compliance_report.j2
dest: "/var/lib/awx/compliance_reports/{{ ansible_date_time.iso8601 }}.html"
vars:
missing_patches: "{{ security_updates.results | difference(installed_updates.results) | list }}"
delegate_to: localhost
run_once: true
- name: Send notification email on success
community.general.mail:
host: "{{ smtp_server }}"
port: "{{ smtp_port }}"
username: "{{ smtp_username }}"
password: "{{ smtp_password }}"
to: "{{ smtp_to }}"
from: "{{ smtp_from }}"
subject: "{{ smtp_subject }} (SUCCESS)"
body: "[Patch management](https://en.wikipedia.org/wiki/Patch_management) workflow has completed successfully on {{ inventory_hostname }}. Compliance report is attached."
attach: "/var/lib/awx/compliance_reports/{{ ansible_date_time.iso8601 }}.html"
delegate_to: localhost
run_once: true
rescue:
- name: Send notification email on failure
community.general.mail:
host: "{{ smtp_server }}"
port: "{{ smtp_port }}"
username: "{{ smtp_username }}"
password: "{{ smtp_password }}"
to: "{{ smtp_to }}"
from: "{{ smtp_from }}"
subject: "{{ smtp_subject }} (FAILED)"
body: "[Patch management](https://en.wikipedia.org/wiki/Patch_management) workflow has failed on {{ inventory_hostname }} with error: {{ ansible_failed_result }}"
delegate_to: localhost
run_once: true
Practical Guides and Workshops for Mastering Patch Management with Ansible
To help IT professionals master the art of automated patch management, numerous guides and workshops are available. For instance, comprehensive guides on automating Linux patching and updates with Ansible provide step-by-step instructions on creating and running Ansible playbooks for various Linux distributions, including Debian, Ubuntu, RHEL, and Alpine. These resources are invaluable for IT teams looking to implement efficient and automated patch management solutions.
Example of a Step-by-Step Guide for Automating Linux Patching with Ansible:
-
Install Ansible: Install Ansible on your control node using the appropriate package manager for your operating system.
- For Debian/Ubuntu:
sudo apt-get install [ansible](https://en.wikipedia.org/wiki/Ansible)
- For RHEL/CentOS:
sudo yum install [ansible](https://en.wikipedia.org/wiki/Ansible)
- For Debian/Ubuntu:
-
Set Up Inventory: Create an inventory file that lists all the systems you want to manage. Include relevant variables for each system, such as the operating system, environment, and owner.
- Example inventory file:
inventory.ini
- Example inventory file:
-
Create a Playbook: Create a playbook that defines the tasks required to apply patches to your systems. Include tasks for updating the package index, listing available security updates, installing the updates, verifying the installation, and rebooting if necessary.
- Example playbook:
apply_patches.yml
- Example playbook:
-
Test the Playbook: Test the playbook on a small subset of systems to ensure it works as expected. Use the
--limit
option to limit the execution to specific systems.- Example command:
[ansible](https://en.wikipedia.org/wiki/Ansible)-playbook -i inventory.ini apply_patches.yml --limit web_servers
- Example command:
-
Schedule the Playbook: Schedule the playbook to run regularly using a cron job, systemd timer, or Ansible Automation Platform's built-in scheduling capabilities.
- Example cron job:
0 2 * * 0 [ansible](https://en.wikipedia.org/wiki/Ansible)-playbook -i /path/to/inventory.ini /path/to/apply_patches.yml
- Example cron job:
-
Monitor and Maintain: Monitor the execution of the playbook and maintain it as needed. Update the playbook to address any issues or changes in your environment.
Workshops and labs using the Ansible Automation Platform illustrate the process of building complex patch management workflows, including content view publishing and environment promotion. These hands-on sessions offer practical experience in enforcing reliable patch orchestration, ensuring that IT professionals are well-equipped to handle real-world patch management challenges.
Example of a Workshop for Building Complex Patch Management Workflows:
-
Introduction to Ansible Automation Platform: Learn about the features and capabilities of the Ansible Automation Platform, including job templates, workflows, and event-driven automation.
-
Creating Job Templates: Create job templates for applying patches to different types of systems, such as RHEL, Ubuntu, and Windows. Include relevant variables, credentials, and notifications.
-
Building Workflows: Build workflows that combine multiple job templates into a single, end-to-end patch management process. Include approvals, delegations, and error handling.
-
Event-Driven Automation: Set up event-driven automation to trigger patch management workflows in response to specific events, such as the detection of new vulnerabilities or compliance issues.
-
Content View Publishing and Environment Promotion: Learn how to use content view publishing and environment promotion to manage the deployment of patches across different environments, such as development, staging, and production.
-
Monitoring and Reporting: Set up monitoring and reporting to track the execution of patch management workflows and generate compliance reports.
Cross-Platform Capabilities of Ansible for Patch Management
Ansible's cross-platform capabilities are a significant advantage for organizations with mixed IT environments. Whether you are managing Linux servers, Windows workstations, or a combination of both, Ansible provides a unified framework for patch management. This cross-platform support simplifies the patch management process, allowing you to use the same tools and workflows across different operating systems.
Example of Cross-Platform Patch Management with Ansible:
---
- name: Apply security patches to cross-platform systems
hosts: all
gather_facts: true
vars:
patch_level: latest
reboot: false
notification_email: [email protected]
smtp_server: smtp.company.com
smtp_port: 587
smtp_username: [ansible](https://en.wikipedia.org/wiki/Ansible)@company.com
smtp_password: "{{ vault_smtp_password }}"
smtp_from: [ansible](https://en.wikipedia.org/wiki/Ansible)@company.com
smtp_to: "{{ notification_email }}"
smtp_subject: "[Patch Management](https://en.wikipedia.org/wiki/Patch_management) Notification"
smtp_body: "[Patch management](https://en.wikipedia.org/wiki/Patch_management) workflow has completed with status: {{ job_status }}"
tasks:
- name: Check for available security updates
block:
- name: Update package index (Debian/Ubuntu)
apt:
update_cache: yes
when: ansible_os_family == 'Debian'
register: update_cache_result
until: update_cache_result is success
retries: 3
delay: 10
- name: List security updates (Debian/Ubuntu)
apt:
list: security
security: yes
when: ansible_os_family == 'Debian'
register: security_updates
until: security_updates is success
retries: 3
delay: 10
- name: Update package index (RHEL/CentOS)
yum:
update_cache: yes
when: ansible_os_family == 'RedHat'
register: update_cache_result
until: update_cache_result is success
retries: 3
delay: 10
- name: List security updates (RHEL/CentOS)
yum:
list: security
security: yes
when: ansible_os_family == 'RedHat'
register: security_updates
until: security_updates is success
retries: 3
delay: 10
- name: List installed updates (Windows)
win_updates:
state: searched
when: ansible_os_name == 'Windows'
register: security_updates
until: security_updates is success
retries: 3
delay: 10
rescue:
- name: Send notification email on failure
community.general.mail:
host: "{{ smtp_server }}"
port: "{{ smtp_port }}"
username: "{{ smtp_username }}"
password: "{{ smtp_password }}"
to: "{{ smtp_to }}"
from: "{{ smtp_from }}"
subject: "{{ smtp_subject }} (FAILED)"
body: "[Patch management](https://en.wikipedia.org/wiki/Patch_management) workflow has failed on {{ inventory_hostname }} with error: {{ ansible_failed_result }}"
delegate_to: localhost
run_once: true
- name: Install security updates
block:
- name: Install security updates (Debian/Ubuntu)
apt:
upgrade: dist
autoremove: yes
when: ansible_os_family == 'Debian' and security_updates.results | length > 0
register: update_result
until: update_result is success
retries: 3
delay: 10
- name: Install security updates (RHEL/CentOS)
yum:
name: '*'
state: latest
security: yes
when: ansible_os_family == 'RedHat' and security_updates.results | length > 0
register: update_result
until: update_result is success
retries: 3
delay: 10
- name: Install security updates (Windows)
win_updates:
category_names:
- CriticalUpdates
- SecurityUpdates
state: installed
when: ansible_os_name == 'Windows' and security_updates.updates | length > 0
register: update_result
until: update_result is success
retries: 3
delay: 10
rescue:
- name: Send notification email on failure
community.general.mail:
host: "{{ smtp_server }}"
port: "{{ smtp_port }}"
username: "{{ smtp_username }}"
password: "{{ smtp_password }}"
to: "{{ smtp_to }}"
from: "{{ smtp_from }}"
subject: "{{ smtp_subject }} (FAILED)"
body: "[Patch management](https://en.wikipedia.org/wiki/Patch_management) workflow has failed on {{ inventory_hostname }} with error: {{ ansible_failed_result }}"
delegate_to: localhost
run_once: true
- name: Verify update installation
block:
- name: Verify update installation (Debian/Ubuntu)
apt:
list: installed
when: ansible_os_family == 'Debian'
register: installed_updates
until: installed_updates is success
retries: 3
delay: 10
- name: Verify update installation (RHEL/CentOS)
yum:
list: installed
when: ansible_os_family == 'RedHat'
register: installed_updates
until: installed_updates is success
retries: 3
delay: 10
- name: Verify update installation (Windows)
win_updates:
state: searched
when: ansible_os_name == 'Windows'
register: installed_updates
until: installed_updates is success
retries: 3
delay: 10
rescue:
- name: Send notification email on failure
community.general.mail:
host: "{{ smtp_server }}"
port: "{{ smtp_port }}"
username: "{{ smtp_username }}"
password: "{{ smtp_password }}"
to: "{{ smtp_to }}"
from: "{{ smtp_from }}"
subject: "{{ smtp_subject }} (FAILED)"
body: "[Patch management](https://en.wikipedia.org/wiki/Patch_management) workflow has failed on {{ inventory_hostname }} with error: {{ ansible_failed_result }}"
delegate_to: localhost
run_once: true
- name: Reboot if necessary
block:
- name: Check if reboot is required (Debian/Ubuntu)
stat:
path: /var/run/reboot-required
when: ansible_os_family == 'Debian'
register: reboot_required
- name: Reboot system (Debian/Ubuntu)
reboot:
msg: "Reboot initiated by [Ansible](https://en.wikipedia.org/wiki/Ansible) for applying security patches"
connect_timeout: 5
reboot_timeout: 600
pre_reboot_delay: 0
post_reboot_delay: 30
when: ansible_os_family == 'Debian' and reboot_required.stat.exists
- name: Check if reboot is required (RHEL/CentOS)
command: needs-restarting -r
when: ansible_os_family == 'RedHat'
register: reboot_required
ignore_errors: yes
changed_when: false
- name: Reboot system (RHEL/CentOS)
reboot:
msg: "Reboot initiated by [Ansible](https://en.wikipedia.org/wiki/Ansible) for applying security patches"
connect_timeout: 5
reboot_timeout: 600
pre_reboot_delay: 0
post_reboot_delay: 30
when: ansible_os_family == 'RedHat' and reboot_required.stdout == "reboot"
- name: Reboot system (Windows)
win_reboot:
when: ansible_os_name == 'Windows' and update_result.reboot_required
rescue:
- name: Send notification email on failure
community.general.mail:
host: "{{ smtp_server }}"
port: "{{ smtp_port }}"
username: "{{ smtp_username }}"
password: "{{ smtp_password }}"
to: "{{ smtp_to }}"
from: "{{ smtp_from }}"
subject: "{{ smtp_subject }} (FAILED)"
body: "[Patch management](https://en.wikipedia.org/wiki/Patch_management) workflow has failed on {{ inventory_hostname }} with error: {{ ansible_failed_result }}"
delegate_to: localhost
run_once: true
- name: Generate compliance report
block:
- name: Generate compliance report
template:
src: compliance_report.j2
dest: "/var/lib/awx/compliance_reports/{{ ansible_date_time.iso8601 }}.html"
vars:
missing_patches: "{{ security_updates.results | difference(installed_updates.results) | list }}"
delegate_to: localhost
run_once: true
- name: Send notification email on success
community.general.mail:
host: "{{ smtp_server }}"
port: "{{ smtp_port }}"
username: "{{ smtp_username }}"
password: "{{ smtp_password }}"
to: "{{ smtp_to }}"
from: "{{ smtp_from }}"
subject: "{{ smtp_subject }} (SUCCESS)"
body: "[Patch management](https://en.wikipedia.org/wiki/Patch_management) workflow has completed successfully on {{ inventory_hostname }}. Compliance report is attached."
attach: "/var/lib/awx/compliance_reports/{{ ansible_date_time.iso8601 }}.html"
delegate_to: localhost
run_once: true
rescue:
- name: Send notification email on failure
community.general.mail:
host: "{{ smtp_server }}"
port: "{{ smtp_port }}"
username: "{{ smtp_username }}"
password: "{{ smtp_password }}"
to: "{{ smtp_to }}"
from: "{{ smtp_from }}"
subject: "{{ smtp_subject }} (FAILED)"
body: "[Patch management](https://en.wikipedia.org/wiki/Patch_management) workflow has failed on {{ inventory_hostname }} with error: {{ ansible_failed_result }}"
delegate_to: localhost
run_once: true
As we move through 2025, automating patch management with Ansible has become an essential practice for maintaining the security and stability of IT infrastructures. By leveraging the latest advancements in Ansible Automation Platform, IT professionals can streamline patch management processes, reduce the risk of human error, and ensure compliance with security standards. From building centralized inventories and creating job templates to applying patches consistently and validating their success, Ansible provides a comprehensive solution for automated patch management. Embracing these best practices and utilizing the available guides and workshops will empower IT teams to master patch management and safeguard their systems against evolving cyber threats.
By adopting a proactive and automated approach to patch management, organizations can minimize the risk of security breaches, reduce downtime, and ensure the smooth operation of their IT environments. As the threat landscape continues to evolve, the importance of effective patch management cannot be overstated. With Ansible as your trusted automation partner, you can stay ahead of the curve and protect your systems from potential vulnerabilities and exploits.
Also read: