872 words
4 minutes
Automating Windows Patch Management with Chocolatey and Ansible

Introduction#

Windows patch management is a critical task for maintaining system security and stability. However, manually patching Windows systems can be time-consuming, error-prone, and difficult to scale. This article explores how to automate Windows patch management using Chocolatey, a popular package manager for Windows, and Ansible, a powerful automation engine. By combining these tools, you can streamline the patching process, ensure consistent configurations, and reduce the administrative burden associated with keeping your Windows systems up-to-date.

Understanding the Tools#

Before diving into the automation process, let’s briefly introduce Chocolatey and Ansible:

  • Chocolatey: Chocolatey is a package manager for Windows, similar to apt for Debian/Ubuntu or yum for CentOS/RHEL. It allows you to install, upgrade, and uninstall software packages from a central repository. Chocolatey packages are community-maintained and cover a wide range of applications and tools.

  • Ansible: Ansible is an open-source automation engine that simplifies configuration management, application deployment, and task automation. It uses a declarative language based on YAML to define desired system states. Ansible connects to target systems over SSH or WinRM (Windows Remote Management) and executes tasks to achieve the desired state.

Prerequisites#

To follow this guide, you’ll need the following prerequisites:

  • Ansible Control Node: A Linux machine with Ansible installed. This machine will orchestrate the patching process.
  • Windows Target Machines: Windows servers or workstations that you want to manage. WinRM must be configured on these machines to allow Ansible to connect.
  • Chocolatey Installed: Chocolatey must be installed on each Windows target machine.
  • Ansible WinRM Configuration: Ansible must be configured to connect to Windows machines using WinRM.

Setting up WinRM on Windows Target Machines#

Ansible uses WinRM to communicate with Windows machines. To configure WinRM, you can use the Configure-WinRM.ps1 script provided by Ansible.

  1. Download the script: Download the Configure-WinRM.ps1 script from the Ansible documentation or GitHub repository.

  2. Run the script: Open PowerShell as an administrator and run the script:

    .\Configure-WinRM.ps1
    

    This script will configure WinRM with the necessary settings for Ansible to connect.

Installing Chocolatey on Windows Target Machines#

If Chocolatey is not already installed on your Windows target machines, you can install it using PowerShell:

Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))

This command downloads and executes the Chocolatey installation script.

Creating an Ansible Inventory File#

Ansible uses an inventory file to define the target machines it will manage. Create an inventory file (e.g., hosts) with the following content:

[windows]
winserver1 ansible_host=192.168.1.101 ansible_user=administrator ansible_password=YourPassword
winserver2 ansible_host=192.168.1.102 ansible_user=administrator ansible_password=YourPassword

[windows:vars]
ansible_connection=winrm
ansible_winrm_server_cert_validation=ignore

Replace 192.168.1.101 and 192.168.1.102 with the IP addresses of your Windows target machines. Replace administrator and YourPassword with the appropriate credentials. The ansible_winrm_server_cert_validation=ignore setting is used for testing purposes and should be replaced with proper certificate validation in a production environment.

Creating an Ansible Playbook for Patch Management#

Now, let’s create an Ansible playbook to automate the patch management process. Create a file named patch_windows.yml with the following content:

---
- name: Update Windows Packages with Chocolatey
  hosts: windows
  gather_facts: false
  tasks:
    - name: Refresh Chocolatey Package Cache
      win_shell: choco outdated
      register: choco_outdated
      changed_when: "'0 packages outdated' not in choco_outdated.stdout"

    - name: Upgrade Outdated Packages
      win_chocolatey:
        name: "{{ item.name }}"
        state: latest
      loop: "{{ choco_outdated.stdout_lines | select('match', '^[a-zA-Z0-9]') | map('regex_search', '^([a-zA-Z0-9\.\-]+)') | list | zip(choco_outdated.stdout_lines | select('match', '^[a-zA-Z0-9]') | map('regex_search', '\|([a-zA-Z0-9\.\-]+)$') | list) | map('flatten') | list  | list | chunk(2) | map('list') | list | map('combine', [{'name': ''}, {'current_version': ''}]) | list }}"
      when: "'0 packages outdated' not in choco_outdated.stdout"
      register: choco_upgrade

    - name: Reboot Windows Server if Required
      win_reboot:
      when: choco_upgrade.changed

This playbook performs the following actions:

  1. Refreshes Chocolatey Package Cache: It uses choco outdated to determine which packages are outdated. It registers the output to choco_outdated. The changed_when condition ensures that the task is considered “changed” only if there are outdated packages.
  2. Upgrades Outdated Packages: It iterates through the list of outdated packages and upgrades them using the win_chocolatey module. The loop parameter uses a complex Jinja2 expression to parse the output of choco outdated and extract the package names. The when condition ensures that this task is only executed if there are outdated packages. The output of the upgrade is registered in choco_upgrade.
  3. Reboots Windows Server (if required): If any packages were upgraded, it reboots the Windows server using the win_reboot module. The when condition ensures that the server is only rebooted if the choco_upgrade task changed any packages.

Running the Ansible Playbook#

To run the playbook, use the following command:

ansible-playbook -i hosts patch_windows.yml

This command will connect to the Windows target machines defined in the hosts file and execute the tasks defined in the patch_windows.yml playbook.

Scheduling the Playbook#

To automate the patch management process on a regular basis, you can schedule the Ansible playbook using a cron job or a similar scheduling mechanism.

For example, to run the playbook every Sunday at 2:00 AM, you can add the following line to your crontab:

0 2 * * 0 ansible-playbook -i /path/to/hosts /path/to/patch_windows.yml

Replace /path/to/hosts and /path/to/patch_windows.yml with the actual paths to your inventory file and playbook.

Conclusion#

Automating Windows patch management with Chocolatey and Ansible can significantly improve system security, reduce administrative overhead, and ensure consistent configurations. By leveraging the power of these tools, you can streamline the patching process and keep your Windows systems up-to-date with minimal effort. This approach not only saves time but also reduces the risk of human error, leading to a more secure and reliable IT infrastructure. Remember to test your playbooks thoroughly in a non-production environment before deploying them to production systems.

Automating Windows Patch Management with Chocolatey and Ansible
https://en.dymripper.com/posts/2025-05-22-automating-windows-patch-management-with-chocolatey-and-ansible/
Author
DYMripper
Published at
2025-05-22