AAP 2.6 Windows Automation: WinRM, PowerShell, and Active Directory Management
By Luca Berton · Published 2024-01-01 · Category: installation
Automate Windows infrastructure with AAP 2.6. Configure WinRM connectivity, run PowerShell scripts, manage Active Directory, deploy IIS, handle Windows.
Windows Automation in AAP 2.6
AAP 2.6 provides full Windows automation support through WinRM (Windows Remote Management) and SSH. You can manage Windows servers, workstations, and Active Directory environments using the same platform that handles Linux infrastructure.
See also: Ansible for Windows Server Enterprise Management: Active Directory, IIS, and Group Policy
Prerequisites
Windows Host Requirements
| Requirement | Details | |-------------|---------| | PowerShell | 5.1 or later | | .NET Framework | 4.6 or later | | WinRM | Enabled and configured | | OS | Windows Server 2016+ or Windows 10/11 |
Enable WinRM on Windows Hosts
Run this PowerShell script on target Windows hosts:
# Enable WinRM with HTTPS
$cert = New-SelfSignedCertificate -DnsName $env:COMPUTERNAME -CertStoreLocation Cert:\LocalMachine\My
$thumbprint = $cert.Thumbprint
winrm quickconfig -quiet
winrm set winrm/config/service/auth '@{Basic="true"}'
winrm set winrm/config/service '@{AllowUnencrypted="false"}'
# Create HTTPS listener
winrm create winrm/config/Listener?Address=*+Transport=HTTPS "@{Hostname=`"$env:COMPUTERNAME`";CertificateThumbprint=`"$thumbprint`"}"
# Firewall rule
New-NetFirewallRule -Name "WinRM-HTTPS" -DisplayName "WinRM HTTPS" -Enabled True -Direction Inbound -Protocol TCP -LocalPort 5986 -Action Allow
Or use the Ansible-provided ConfigureRemotingForAnsible.ps1 script:
Invoke-WebRequest -Uri https://raw.githubusercontent.com/ansible/ansible/devel/examples/scripts/ConfigureRemotingForAnsible.ps1 -OutFile ConfigureRemotingForAnsible.ps1
.\ConfigureRemotingForAnsible.ps1 -EnableCredSSP -ForceNewSSLCert
Credential Configuration
Machine Credential for Windows
- name: Create Windows machine credential
ansible.platform.credential:
controller_host: "{{ gateway_url }}"
controller_username: "{{ controller_user }}"
controller_password: "{{ controller_pass }}"
name: "Windows Domain Admin"
organization: "Operations"
credential_type: "Machine"
inputs:
username: "DOMAIN\\ansible_svc"
password: "{{ vault_windows_password }}"
state: present
Inventory Variables for WinRM
# Group variables for Windows hosts
- name: Create Windows group
ansible.platform.group:
controller_host: "{{ gateway_url }}"
controller_username: "{{ controller_user }}"
controller_password: "{{ controller_pass }}"
name: "windows"
inventory: "Production Windows"
variables:
ansible_connection: winrm
ansible_winrm_transport: ntlm
ansible_winrm_server_cert_validation: ignore
ansible_port: 5986
ansible_winrm_scheme: https
state: present
Connection Methods
| Transport | Auth Method | Use Case |
|-----------|-------------|----------|
| ntlm | NTLM | Domain and local accounts |
| kerberos | Kerberos | Domain environments (most secure) |
| credssp | CredSSP | Double-hop scenarios |
| basic | Basic auth | Local accounts over HTTPS |
| certificate | Client cert | Certificate-based auth |
Kerberos Configuration
For domain environments, Kerberos is recommended:
# Execution Environment with Kerberos support
---
version: 3
images:
base_image:
name: registry.redhat.io/ansible-automation-platform-26/ee-supported-rhel9:latest
dependencies:
python:
- pywinrm>=0.4.0
- requests-kerberos>=0.14
- pykerberos>=1.2
system:
- krb5-workstation [platform:rpm]
- krb5-libs [platform:rpm]
- krb5-devel [platform:rpm]
additional_build_steps:
append_final:
- COPY krb5.conf /etc/krb5.conf
# krb5.conf for the EE
[libdefaults]
default_realm = EXAMPLE.COM
dns_lookup_realm = false
dns_lookup_kdc = true
[realms]
EXAMPLE.COM = {
kdc = dc01.example.com
admin_server = dc01.example.com
}
[domain_realm]
.example.com = EXAMPLE.COM
example.com = EXAMPLE.COM
See also: Ansible WinRM: Configure Windows Remote Management Connection (Complete Guide)
Common Windows Automation Tasks
Install Windows Features and Roles
- name: Install IIS web server
hosts: windows_webservers
tasks:
- name: Install IIS with management tools
ansible.windows.win_feature:
name:
- Web-Server
- Web-Mgmt-Tools
- Web-Asp-Net45
- Web-Net-Ext45
state: present
include_management_tools: true
register: iis_install
- name: Reboot if required
ansible.windows.win_reboot:
when: iis_install.reboot_required
Manage Windows Services
- name: Manage Windows services
hosts: windows
tasks:
- name: Ensure critical services are running
ansible.windows.win_service:
name: "{{ item }}"
start_mode: auto
state: started
loop:
- W32Time
- WinRM
- Winmgmt
- EventLog
- name: Disable unnecessary services
ansible.windows.win_service:
name: "{{ item }}"
start_mode: disabled
state: stopped
loop:
- RemoteRegistry
- TlntSvr
Windows Updates
- name: Apply Windows updates
hosts: windows
tasks:
- name: Install all critical and security updates
ansible.windows.win_updates:
category_names:
- CriticalUpdates
- SecurityUpdates
state: installed
reboot: true
reboot_timeout: 3600
register: update_result
- name: Report update status
ansible.builtin.debug:
msg: |
Updates installed: {{ update_result.installed_update_count }}
Reboot required: {{ update_result.reboot_required }}
Updates: {{ update_result.updates | map(attribute='title') | list }}
Active Directory Management
- name: Manage Active Directory
hosts: domain_controllers
tasks:
- name: Create organizational unit
microsoft.ad.ou:
name: "Automation Managed"
path: "DC=example,DC=com"
state: present
- name: Create service account
microsoft.ad.user:
name: "svc_ansible"
firstname: "Ansible"
surname: "Service Account"
password: "{{ vault_svc_password }}"
path: "OU=Service Accounts,DC=example,DC=com"
password_never_expires: true
user_cannot_change_password: true
state: present
- name: Create security group
microsoft.ad.group:
name: "Ansible Managed Servers"
path: "OU=Security Groups,DC=example,DC=com"
scope: global
category: security
members:
add:
- "svc_ansible"
state: present
- name: Add computer to group
microsoft.ad.group:
name: "Ansible Managed Servers"
members:
add:
- "WEB01$"
- "WEB02$"
- "APP01$"
Group Policy Management
- name: Configure Group Policy settings via registry
hosts: windows
tasks:
- name: Set audit policy
ansible.windows.win_regedit:
path: HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\Audit
name: ProcessCreationIncludeCmdLine_Enabled
data: 1
type: dword
- name: Configure Windows Firewall
community.windows.win_firewall:
state: enabled
profiles:
- Domain
- Private
- Public
Deploy IIS Website
- name: Deploy IIS website
hosts: windows_webservers
tasks:
- name: Create website directory
ansible.windows.win_file:
path: C:\inetpub\myapp
state: directory
- name: Deploy application files
ansible.windows.win_copy:
src: files/myapp/
dest: C:\inetpub\myapp\
- name: Create IIS application pool
community.windows.win_iis_webapppool:
name: MyAppPool
state: started
attributes:
managedRuntimeVersion: v4.0
autoStart: true
startMode: AlwaysRunning
- name: Create IIS website
community.windows.win_iis_website:
name: MyApp
state: started
port: 443
ssl: true
physical_path: C:\inetpub\myapp
application_pool: MyAppPool
parameters: "logFile.directory:C:\\Logs\\MyApp"
PowerShell Script Execution
- name: Run PowerShell scripts
hosts: windows
tasks:
- name: Execute inline PowerShell
ansible.windows.win_powershell:
script: |
$services = Get-Service | Where-Object { $_.Status -eq 'Stopped' -and $_.StartType -eq 'Automatic' }
$services | ForEach-Object {
Write-Output "Starting $($_.Name)..."
Start-Service $_.Name -ErrorAction SilentlyContinue
}
$Ansible.Result = @{
started = ($services | Measure-Object).Count
}
register: ps_result
- name: Show result
ansible.builtin.debug:
msg: "Started {{ ps_result.result.started }} services"
- name: Run script file
ansible.windows.win_powershell:
script: "{{ lookup('file', 'scripts/health-check.ps1') }}"
parameters:
Verbose: true
OutputPath: C:\Reports\health-check.html
Windows Certificate Management
- name: Manage certificates
hosts: windows
tasks:
- name: Import PFX certificate
ansible.windows.win_certificate_store:
path: C:\certs\webapp.pfx
password: "{{ cert_password }}"
store_location: LocalMachine
store_name: My
state: present
- name: Find expiring certificates
ansible.windows.win_powershell:
script: |
$threshold = (Get-Date).AddDays(30)
$expiring = Get-ChildItem Cert:\LocalMachine\My |
Where-Object { $_.NotAfter -lt $threshold }
$Ansible.Result = $expiring | Select-Object Subject, NotAfter, Thumbprint
register: expiring_certs
- name: Alert on expiring certs
ansible.builtin.debug:
msg: "WARNING: {{ item.Subject }} expires {{ item.NotAfter }}"
loop: "{{ expiring_certs.result }}"
when: expiring_certs.result | length > 0
Execution Environment for Windows
Build a dedicated EE with Windows dependencies:
---
version: 3
images:
base_image:
name: registry.redhat.io/ansible-automation-platform-26/ee-minimal-rhel9:latest
dependencies:
galaxy:
collections:
- name: ansible.windows
version: ">=2.5.0"
- name: community.windows
version: ">=2.3.0"
- name: microsoft.ad
version: ">=1.7.0"
- name: chocolatey.chocolatey
version: ">=1.5.0"
python:
- pywinrm>=0.4.0
- requests-ntlm>=1.2
- requests-kerberos>=0.14
- pykerberos>=1.2
system:
- krb5-workstation [platform:rpm]
- krb5-libs [platform:rpm]
See also: Ansible Windows Server 2025 Automation: WinRM, PSRP, Active Directory, IIS, Hyper-V Complete Guide
FAQ
Should I use WinRM or SSH for Windows?
WinRM is the standard and best-supported method. Windows OpenSSH works but has limitations: no become, no win_* modules (only shell/raw). Use WinRM for production Windows automation.
How do I handle the double-hop problem?
When connecting to a Windows host and needing to access a network resource (like a file share), you hit the double-hop problem. Use CredSSP transport (ansible_winrm_transport: credssp) or Kerberos delegation to resolve this.
Can I manage Windows hosts from Linux execution nodes?
Yes. The EE runs on Linux and connects to Windows hosts via WinRM over the network. No Windows software is needed on the execution node — just the Python pywinrm library (included in the EE).
How do I run domain join operations?
Use the microsoft.ad.membership module. The credential must have domain join permissions, and the WinRM connection must use Kerberos or NTLM with a domain account.
What about Windows Nano Server or Server Core?
Both are supported via WinRM. Server Core works identically to full installations. Nano Server has limited PowerShell support, so test modules before deploying.
Conclusion
AAP 2.6 treats Windows as a first-class automation target. From Active Directory management to IIS deployments, Windows Updates to PowerShell scripting, the platform provides comprehensive Windows automation capabilities alongside Linux. Build a dedicated Windows EE, configure WinRM with Kerberos for enterprise environments, and automate your entire Windows estate through the same platform.
Related Articles
• AAP 2.6 Architecture and Components: Complete Guide • AAP 2.6 Execution Environments: Build, Manage, and Deploy Custom EEs • AAP 2.6 Credential Management: Vaults, External Secrets, and Machine Credentials • AAP 2.6 Job Templates and Inventories: Complete Configuration Guide • AAP 2.6 Automation Mesh: Distributed Execution Across Sites and NetworksCategory: installation