AnsiblePilot — Master Ansible Automation

AnsiblePilot is the leading resource for learning Ansible automation, DevOps, and infrastructure as code. Browse over 1,400 tutorials covering Ansible modules, playbooks, roles, collections, and real-world examples. Whether you are a beginner or an experienced engineer, our step-by-step guides help you automate Linux, Windows, cloud, containers, and network infrastructure.

Popular Topics

About Luca Berton

Luca Berton is an Ansible automation expert, author of 8 Ansible books published by Apress and Leanpub including "Ansible for VMware by Examples" and "Ansible for Kubernetes by Example", and creator of the Ansible Pilot YouTube channel. He shares practical automation knowledge through tutorials, books, and video courses to help IT professionals and DevOps engineers master infrastructure automation.

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 GuideAAP 2.6 Execution Environments: Build, Manage, and Deploy Custom EEsAAP 2.6 Credential Management: Vaults, External Secrets, and Machine CredentialsAAP 2.6 Job Templates and Inventories: Complete Configuration GuideAAP 2.6 Automation Mesh: Distributed Execution Across Sites and Networks

Category: installation

Browse all Ansible tutorials · AnsiblePilot Home