The process of applying Windows updates can be arduous from an administrative perspective. By using Ansible, administrators have a powerful automated way to apply Windows updates.

Brandon Lee

Brandon Lee has been in the IT industry 15+ years and focuses on networking and virtualization. He contributes to the community through various blog posts and technical documentation primarily at Virtualizationhowto.com.

As Windows administrators, let's face it, one of the most arduous chores we have to accomplish when provisioning a new Windows Server is installing Windows updates. Windows updates are critical to routine Windows Server administration. Security is on the forefront of everyone's focus. Thus, keeping patches applied is crucial to ensure patching vulnerabilities and other exploits before there's a chance to expose the server to an attack vector due to the unpatched security vulnerability.

However, controlling Windows updates is a pain for administrators. Microsoft hasn't updated or modernized their Windows Server Update Services (WSUS) since legacy versions of the Windows Server operating system. It can be difficult to manage and even unreliable at times. Let's take a look at how to automate Windows updates with Ansible and see how we can successfully patch Windows Servers quickly and relatively easily using the power of Ansible automation.

Configure Ansible for Windows Server update patching ^

Configuring Ansible for patching Windows Server updates is fairly straightforward. It involves the following steps:

  1. Setting up an Ansible server:

Loading a supported distribution of Linux with the prerequisites and requirements for both Ansible and supporting modules (Kerberos, etc.)

  1. Configuring Ansible authentication to communicate with Windows Servers:

Configuring Windows Remote Management (WinRM) and setting up authentication to be able to connect to servers listed in the inventory file

  1. Creating playbooks containing Windows Server updates directives

Creating the actual playbook with the code snippets to perform Windows updates

Setting up Ansible Server ^

Configuring an Ansible Server is as simple as installing a supported distribution of Linux such as Ubuntu Server (we will use this as the reference Linux operating system throughout the post) and then installing both the ansible package as well as pywinrm. The pywinrm package is what allows Ansible to communicate to Windows Servers via WinRM instead of Secure Shell (SSH).

Make sure to update your Ubuntu Linux distribution:

Also, to make Python package installation easier and more robust, let's install pip. What is pip? It's a package management system used to install and manage software packages written in Python. To install pip, run the following in Ubuntu:

Now we can use pip to install both the pywinrm package as well as Ansible itself using the two following commands:

We can verify this successfully installed Ansible by querying the Ansible version using the following:

Checking the Ansible version after installation

Checking the Ansible version after installation

Configuring Ansible authentication ^

An extremely important part of Ansible configuration is configuring its authentication to communicate properly with the target Windows Servers. Many may choose to use local authentication between the Ansible server and the target Windows Servers they're managing. Also, domain-based permissions can  use Kerberos authentication supported with Microsoft Active Directory Services. With larger and more complex environments, domain authentication tends to be the more robust authentication mechanism. It allows a greater level of trust for the WinRM connections as well as a centralized repository for credentials.

Configuring the WinRM connections required to connect Ansible to the Windows Servers involves a few tweaks to the WinRM configuration settings on the target servers. A great way for easily making the changes necessary for WinRM communication is simply running the ConfigureRemotingForAnsible.ps1 script. This community-driven script enables WinRM properly to communicate with the Ansible server. The script also enables the required Windows Firewall rules as well as PowerShell remoting and is an easy way to make all the necessary changes for Ansible communication at once.

But how do you bootstrap a Windows Server you don't have remote access to via WinRM or PowerShell remoting? You can either bake the needed changes into the image used for provisioning, or for existing machines with an internet or network connection, you can use psexec to pull the script down and run it on the target Windows Server using a command like the following:

You can download the latest version of the script from GitHub.

After running the script, you can test communication with the target Windows Server by running the win_ping Ansible command, which tests connectivity from Ansible to the Windows Server via WinRM. Below we can see both an unsuccessful WinRM test and a successful WinRM test from Ansible.

Unsuccessful WinRM test from Ansible due to expired Kerberos credentials

Unsuccessful WinRM test from Ansible due to expired Kerberos credentials

Successful test from the Ansible server to the Windows Server via WinRM

Successful test from the Ansible server to the Windows Server via WinRM

Automate Windows updates with Ansible ^

Now that we have gone over the basics of setting up an Ansible server for Windows communication and seen how to ensure successful WinRM communication, let's look at how we can use this connection to automate Windows updates with Ansible.

Ansible includes powerful modules "out of the box" that provide the mechanisms to install Windows updates on your Windows Servers. The Ansible modules allow administrators to control downloading and installing Windows updates on their Windows Servers. They download Windows updates from the configured location on the server (either from Microsoft or WSUS) and then install them as directed by Ansible. The win_updates module allows automating various aspects of installing Windows updates. Let's look at a few examples.

If you want to install Windows updates by the category of the Windows updates, you can specify the category in the Ansible playbook directive of the win_updates module. Notice below that the category_names directive allows specifying the type of updates to download and apply. Adding or omitting the category either adds or leaves it out of the Windows update pull for the server.

If you want to install only specific updates based on the KB numbers for a specific category, you can specify those updates via the whitelist directive in the YML code.

If you simply want to check for missing updates, you can run the following:

What if you want to install the updates and reboot if the result records a reboot is necessary?

Running an Ansible playbook is as simple as telling Ansible which inventory section you want to run the playbook against as well as which playbook you want to run.

An example inventory file will look like the following:

A sample windowsupdates.yml playbook might look like the following, which directs the installation of security, critical, and update rollups:

You could do something like the following: Configure the domain controllers (DCs) in this case with the settings in the windowsupdates.yml file.

If a target machine is offline, Ansible will simply display the error connecting to the target machine and move on to the next server in the list to update.

In the example below, we are searching for all available updates and piping these out to c:\ansible_wu.txt. We can do this with the following code:

Running an Ansible playbook to search for available Windows updates

Running an Ansible playbook to search for available Windows updates

The snippet below shows the contents of the c:\ansible_wu.txt file with the available Windows updates pulled from running the Ansible playbook.

Log file containing the missing Windows updates Ansible found

Log file containing the missing Windows updates Ansible found

Results after installing Windows updates and rebooting with Ansible

Results after installing Windows updates and rebooting with Ansible

Here we have a snippet of the Windowsupdate.log file showing Ansible indeed installed the updates.

Log file confirming Windows update installation

Log file confirming Windows update installation

Takeaways ^

Ansible provides a powerful mechanism to apply Windows updates. You can control the type of updates, query updates to install, specify KB-related passwords and many other options. Additionally, you can control when and how to integrate reboots with the Windows updates when applying them to the Windows Server. Especially if you are provisioning a greenfield server installation, you can simply add the win_update directive to your normal Ansible playbook. You can then incorporate installation of Windows updates for provisioning software and other customizations needed for the Windows Server installation.

A downside of using Ansible for deploying updates is that you can only target computers currently online. Thus, this solution works well for Windows Servers but not for workstations that could be offline when you initiate the update process. Automation in general is required in today's fast-paced world of DevOps. Being able to provision virtual machine software quickly, including Windows updates, allows administrators to be efficient, effective, and consistent in provisioning Windows Servers in the enterprise datacenter.

Win the monthly 4sysops member prize for IT pros

8+

Users who have LIKED this post:

  • avatar
  • avatar
Share
12 Comments
  1. Phani 1 year ago

    Hi,

    Is there any best way to do this with the help of PowerShell or PowerShell DSC using Azure Automation for Azure VM's

    2+

  2. Ruben Zimmermann 1 year ago

    Great article.

    If you know SCCM and its patch-lists and collections how would you compare the manageability?
    Consider you need to patch a few hundred machines with different maintenance windows (unpleasant situation where there are single resources and no clusters)

    Thanks ^_^

    2+

    • Fred 10 months ago

      I would create groups machines per update window and put that in a cron job to run the updates on the right group of machines to update at that time basically.

      0

  3. Ben Roc 12 months ago

    What would be the registry config on the Windows server? in the WindowsUpdate and AU section.

    Thanks!

    1+

  4. Raju Balami 7 months ago

    Hi,

    I tried ansible for automatic windows update, its working completely fine.

    But while trying to update windows through KB number, but its showing some syntax error.

    commands looks like

    vi ism1.yml

    ---
    - hosts: icc1
    remote_user: itsupport@DC.DMN

    - name: Install specific updates based on the KBs for those updates
    win_updates:
    category_name:
    - SecurityUpdates
    whitelist:
    - KB4489891

    where icc1 is my group name and i have assigned one windows machine on it. i:e ism1

    while the error is:

    [root@ansible ansible]# ansible-playbook -l icc1 ism1.yml
    ERROR! 'win_updates' is not a valid attribute for a Play

    The error appears to have been in '/etc/ansible/ism1.yml': line 5, column 3, but may
    be elsewhere in the file depending on the exact syntax problem.

    The offending line appears to be:

    - name: Install specific updates based on the KBs for those updates
    ^ here

    Can you please help?

    0

  5. Arkady 6 months ago

    Hi,

    I am running following playbook to search for available Windows update:

    Log file saved on target Windows machines. I am looking for some way to save it in some central network share, even on Linux host running Ansible. Already spent few hours without success.

    Any ideas or tips?

    Thank you in advance!

    Arkady.

    2+

    • RR 2 months ago

      Hi Arkady,

      use, for example, win_robocopy module to put log to some network share.

      RR.

      0

  6. Mike 2 months ago

    Hello All,

    Please your Your guide would be very appreciated , I am running ansible (ansible 2.8.4 ) and try to install security update . there is multiple update but it could not install any of the upgrade ? could you please help me ?

    Here is my task.yml

    ---
      - name: Search Windows update
        win_updates:
          category_names: "- SecurityUpdates - CriticalUpdates - UpdateRollups - Updates"
          state: searched
          log_path: C:ansible_wu.txt

      - name: Install SecurityUpdates and CriticalUpdates
        win_updates:
          category_names: "- SecurityUpdates - CriticalUpdates"
         #state: installed
          reboot: yes
          log_path: C:ansible_installedpatch.txt
      
     

    In the target host , How to set up windows update settings: "Download update but let me choose whether to install them " ; "Check for update but let me choose whether to download and install " or " never check for update ".

     

    Here is the log 

    2019-08-28 13:07:06Z Skipping update 03eb6475-ce34-4e09-a0ac-feac7689c7d0 - 2019-07 Servicing Stack Update for Windows Server 2012 R2 for x64-based Systems (KB4504418) as it was not found in the category names filter
    2019-08-28 13:07:06Z Skipping update d0bf3ffb-d01a-4877-b5df-be5d48ff898c - Windows Malicious Software Removal Tool x64 - August 2019 (KB890830) as it was not found in the category names filter
    2019-08-28 13:07:06Z Skipping update 5aa5521c-0343-48a0-bba4-d2a5b9357e81 - Microsoft .NET Framework 4.8 for Windows Server 2012 R2 for x64 (KB4486105) as it was not found in the category names filter
    2019-08-28 13:07:06Z Skipping update 63db54d7-70d7-42d9-950a-8df77e645b29 - 2019-08 Security Monthly Quality Rollup for Windows Server 2012 R2 for x64-based Systems (KB4512488) as it was not found in the category names filter
    2019-08-28 13:07:06Z Skipping update e1dcbde9-3dec-45d9-9b5b-426b457a5679 - 2019-08 Preview of Monthly Quality Rollup for Windows Server 2012 R2 for x64-based Systems (KB4512478) as it was not found in the category names filter
    2019-08-28 13:07:06Z Calculating pre-install reboot requirement...
    2019-08-28 13:07:06Z Native job completed with output: 
    Name                           Value                                                                                                                                                                                                                                                                        
    ----                           -----                                                                                                                                                                                                                                                                        
    updates                        {}                                                                                                                                                                                                                                                                           
    found_update_count             0                                                                                                                                                                                                                                                                            
    changed                        False                                                                                                                                                                                                                                                                        
    reboot_required                False                                                                                                                                                                                                                                                                        
    installed_update_count         0                                                                                                                                                                                                                                                                            
    filtered_updates               {d928f50f-191e-4858-b546-acda983da182, 06eae584-188d-4a35-805a-ef98beddcd3d, 04f04253-f803-43b8-8b37-6841c614dd9f, 7c5f1dad-2f35-4120-b4ad-c5947edf0567...}                                                                                                                  

    0

  7. pramod 4 weeks ago

    able to ping the machine, but playbook fails at win_update module....

    1+

    • nariman 4 weeks ago

      can you also post your playbook?

      0

  8. Mike 4 weeks ago

    My question : How you set up if the windows Machine is part of a Domain and how you set it up for Non Domain computer. ?  Please provide the script for each case ? How to make sure that these windows computers are allowed to receive commands only from the ansible host. is there a way to set up the control node IP address on every remote host for security purpose?

     

    Regards,

    0

  9. Mathias 2 weeks ago

    is there actually a list of all possible values for the categories somewhere?

    0

Leave a reply

Your email address will not be published. Required fields are marked *

*

© 4sysops 2006 - 2019

CONTACT US

Please ask IT administration questions in the forums. Any other messages are welcome.

Sending

Log in with your credentials

or    

Forgot your details?

Create Account