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.
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:
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.
Get-Host | Select-Object Version
Version
-------
5.1.19041.4291
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
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".
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
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.
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
Today we saw how configure a windows host to for ansible and a basic demo for running a playbook .