Ayadi Tahar | Windows management with Ansible

Windows management with Ansible

Publish Date: 2024-02-01


Ansible is known for its ability to automate many IT processes, which are usually performed manually, including provisioning, system configuration, and software deployment in a flexible, secure way.

while this is mostly true and widely implemented in Linux-based environments, it becomes challenging at first to manage a Windows environment, which we will address in our article today.

1. Terminology and Requirements

In order to run ansible over windows hosts we must have a contoler and a host, a controler is where ansible is installed and it should be linux, and a host where ansible will execute over and it could be both linux and windows, but in our case it is windows.

For Ansible controler to communicate with a Windows host and use Windows modules, the Windows host must meet these base requirements for connectivity:

  • Windows versions under the current and extended support from Microsoft, including Windows 10 and 11, and server OSs including Windows Server 2016, 2019, and 2022.
  • PowerShell 5.1 or newer is installed and at least .NET 4.0 on the Windows host.
  • A WinRM listener need to be created and activated.
  • A dedicated user which has administrative privileges in order to execute some Ansible code and modules.

2. Verify the requirements

As we said, The control machine should be a linux machine, and in our case it is an Ubuntu machine running ansible version 2.16:


ansible --version 
ansible [core 2.16.6]
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/home/ahmed/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3/dist-packages/ansible
  ansible collection location = /home/ahmed/.ansible/collections:/usr/share/ansible/collections
  executable location = /usr/bin/ansible
  python version = 3.10.12 (main, Nov 20 2023, 15:14:05) [GCC 11.4.0] (/usr/bin/python3)
  jinja version = 3.0.3
  libyaml = True
the istallation and configuration of ansible is not addressed here, but you can install it quickly by running the following commands in your shell, if you have an ubuntu machine:

#include the official project’s PPA (personal package archive) in your system’s list of sources:
sudo apt-add-repository ppa:ansible/ansible
#refresh your system’s package index so that it is aware of the packages available in the newly included PPA:
sudo apt update
#install the Ansible software with:
sudo apt install ansible

Next we need to verify that PowerShell and .NET versions, already meet the requirements in the windows target host. and the most important part is to set up the WinRM.

1. Verify PowerShell and .NET


Get-Host | Select-Object Version
Version
-------
5.1.19041.4291

2. verify .NET version


Get-ChildItem 'HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP' -Recurse | Get-ItemProperty -Name version -EA 0 | Where { $_.PSChildName -Match '^(?!S)\p{L}'} | Select PSChildName, version
PSChildName Version
----------- -------
Client      4.8.09037
Full        4.8.09037
Client      4.0.0.0

3. Verify WinRM if not-configured


winrm get winrm/config/Service
WSManFault
Message = The client cannot connect to the destination specified in the request. Verify that the service on the destination is running and is accepting requests. Consult the logs and documentation for the WS-Management service running on the destination, most commonly IIS or WinRM. If the destination is the WinRM service, run the following command on the destination to analyze and configure the WinRM service: "winrm quickconfig".
Error number:  -2144108526 0x80338012
The client cannot connect to the destination specified in the request. Verify that the service on the destination is running and is accepting requests. Consult the logs and documentation for the WS-Management service running on the destination, most commonly IIS or WinRM. If the destination is the WinRM service, run the following command on the destination to analyze and configure the WinRM service: "winrm quickconfig".

winrm get winrm/config/Winrs
WSManFault
Message = The client cannot connect to the destination specified in the request. Verify that the service on the destination is running and is accepting requests. Consult the logs and documentation for the WS-Management service running on the destination, most commonly IIS or WinRM. If the destination is the WinRM service, run the following command on the destination to analyze and configure the WinRM service: "winrm quickconfig".
Error number:  -2144108526 0x80338012
The client cannot connect to the destination specified in the request. Verify that the service on the destination is running and is accepting requests. Consult the logs and documentation for the WS-Management service running on the destination, most commonly IIS or WinRM. If the destination is the WinRM service, run the following command on the destination to analyze and configure the WinRM service: "winrm quickconfig".

winrm enumerate winrm/config/Listener
WSManFault
Message = The client cannot connect to the destination specified in the request. Verify that the service on the destination is running and is accepting requests. Consult the logs and documentation for the WS-Management service running on the destination, most commonly IIS or WinRM. If the destination is the WinRM service, run the following command on the destination to analyze and configure the WinRM service: "winrm quickconfig".
Error number:  -2144108526 0x80338012
The client cannot connect to the destination specified in the request. Verify that the service on the destination is running and is accepting requests. Consult the logs and documentation for the WS-Management service running on the destination, most commonly IIS or WinRM. If the destination is the WinRM service, run the following command on the destination to analyze and configure the WinRM service: "winrm quickconfig".

3. Setup WinRM

There is a great PowerShell script that sets up both HTTP and HTTPS listeners with a self-signed certificate and enables the Basic authentication option on the service.

Execute the following lines to download and setup WinRM in your windows host:

[Net.ServicePointManager]::SecurityProtocol =  [Net.SecurityProtocolType]::Tls12
$url = "https://raw.githubusercontent.com/ansible/ansible-documentation/ae8772176a5c645655c91328e93196bcf741732d/examples/scripts/ConfigureRemotingForAnsible.ps1"

$file = "$env:temp\ConfigureRemotingForAnsible.ps1"

(New-Object -TypeName System.Net.WebClient).DownloadFile($url, $file)

powershell.exe -ExecutionPolicy ByPass -File $file

4. Verify WinRM configured

Execute the following commands to verify that winrm is configured correctly:


winrm get winrm/config/Service
Service
    RootSDDL = O:NSG:BAD:P(A;;GA;;;BA)(A;;GR;;;IU)S:P(AU;FA;GA;;;WD)(AU;SA;GXGW;;;WD)
    MaxConcurrentOperations = 4294967295
    MaxConcurrentOperationsPerUser = 1500
    EnumerationTimeoutms = 240000
    MaxConnections = 300
    MaxPacketRetrievalTimeSeconds = 120
    AllowUnencrypted = false
    Auth
        Basic = true
        Kerberos = true
        Negotiate = true
        Certificate = false
        CredSSP = false
        CbtHardeningLevel = Relaxed
    DefaultPorts
        HTTP = 5985
        HTTPS = 5986
    IPv4Filter = *
    IPv6Filter = *
    EnableCompatibilityHttpListener = false
    EnableCompatibilityHttpsListener = false
    CertificateThumbprint
    AllowRemoteAccess = true

winrm get winrm/config/Winrs
Winrs
    AllowRemoteShellAccess = true
    IdleTimeout = 7200000
    MaxConcurrentUsers = 2147483647
    MaxShellRunTime = 2147483647
    MaxProcessesPerShell = 2147483647
    MaxMemoryPerShellMB = 2147483647
    MaxShellsPerUser = 2147483647

winrm enumerate winrm/config/Listener
Listener
    Address = *
    Transport = HTTP
    Port = 5985
    Hostname
    Enabled = true
    URLPrefix = wsman
    CertificateThumbprint
    ListeningOn = 127.0.0.1, 169.254.56.62, 169.254.135.141, 169.254.253.85, ::1, fe80::a420:4700:6eb1:e196%10, fe80::c882:ffff:2305:2873%17, fe80::d170:c58:8715:f9d7%15

Listener
    Address = *
    Transport = HTTPS
    Port = 5986
    Hostname = DESKTOP-5HBDSM6
    Enabled = true
    URLPrefix = wsman
    CertificateThumbprint = 2E523C615D570911D3131A747C1E1F649AE46893
    ListeningOn = 127.0.0.1, 169.254.56.62, 169.254.135.141, 169.254.253.85, ::1, fe80::a420:4700:6eb1:e196%10, fe80::c882:ffff:2305:2873%17, fe80::d170:c58:8715:f9d7%15

from the above output, we confirm that winrm is configured correctly .

next let's configure our control machine to execute a simple playbook.

Test our demo

This is the structure of our configuration files


windows
├── hosts
├── host_vars
│   └── windows10.yml
└── test-win.yml

add the entry of windows target hosts under the inventory file(hosts) :

  
cat hosts
[windows]
windows10 

under hosts_vars/windows10.yml file, add the following content:


cat host_vars/windows10.yml
ansible_user: ahmed
ansible_password: Pa$$w0rd
ansible_port: 5986
ansible_connection: winrm
ansible_winrm_transport: basic
ansible_winrm_server_cert_validation: ignore

let's first create a simple playbook to run against our windows 10 machine. the playbook test basic connectivity and ensure thar 7zip is installed :


---
- name: win_ping module demo
  hosts: windows
  become: false
  gather_facts: false
  tasks:
    - name: test connection
      ansible.windows.win_ping:
    - name: Ensure 7-Zip is installed through Chocolatey
      win_chocolatey:
        name: 7zip
        state: present

now, let's execute our playbook:


ansible-playbook -i windows/inventory windows/test_win.yml


PLAY [win_ping module demo] **************************************************************************************************************

TASK [test connection] *******************************************************************************************************************
ok: [windows10]

TASK [Ensure 7-Zip is installed through Chocolatey] **************************************************************************************
ok: [windows10]

PLAY RECAP *******************************************************************************************************************************
windows10                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

Conclusion

Today we saw how configure a windows host to for ansible and a basic demo for running a playbook .