WinRM is a management protocol used by Windows to remotely communicate with
another server. It is a SOAP-based protocol that communicates over HTTP/HTTPS, and is
included in all recent Windows operating systems. Since Windows
Server 2012, WinRM has been enabled by default, but in most cases extra
configuration is required to use WinRM with Ansible.

Ansible uses the pywinrm package to
communicate with Windows servers over WinRM. It is not installed by default
with the Ansible package, but can be installed by running the following:

pip install "pywinrm>=0.3.0"

Note

on distributions with multiple python versions, use pip2 or pip2.x,
where x matches the python minor version Ansible is running under.

When connecting to a Windows host, there are several different options that can be used
when authenticating with an account. The authentication type may be set on inventory
hosts or groups with the ansible_winrm_transport variable.

Basic authentication is one of the simplest authentication options to use, but is
also the most insecure. This is because the username and password are simply
base64 encoded, and if a secure channel is not in use (eg, HTTPS) then it can be
decoded by anyone. Basic authentication can only be used for local accounts (not domain accounts).

The following example shows host vars configured for basic authentication:

Using the PowerShell cmdlet New-SelfSignedCertificate to generate
a certificate for authentication only works when being generated from a
Windows 10 or Windows Server 2012 R2 host or later. OpenSSL is still required to
extract the private key from the PFX certificate to a PEM file for Ansible
to use.

Once a certificate has been generated, the issuing certificate needs to be
imported into the TrustedRootCertificateAuthorities of the
LocalMachine store, and the client certificate public key must be present
in the TrustedPeople folder of the LocalMachine store. For this example,
both the issuing certificate and public key are the same.

Kerberos is the recommended authentication option to use when running in a
domain environment. Kerberos supports features like credential delegation and
message encryption over HTTP and is one of the more secure options that
is available through WinRM.

Kerberos requires some additional setup work on the Ansible host before it can be
used properly.

The following example shows host vars configured for Kerberos authentication:

As of Ansible version 2.3, the Kerberos ticket will be created based on
ansible_user and ansible_password. If running on an older version of
Ansible or when ansible_winrm_kinit_mode is manual, a Kerberos
ticket must already be obtained. See below for more details.

There are some extra host variables that can be set:

ansible_winrm_kinit_mode:managed/manual (manual means Ansible will not obtain a ticket)ansible_winrm_kinit_cmd:the kinit binary to use to obtain a Kerberos ticket (default to kinit)ansible_winrm_service:overrides the SPN prefix that is used, the default is ``HTTP`` and should rarely ever need changingansible_winrm_kerberos_delegation:allows the credentials to traverse multiple hopsansible_winrm_kerberos_hostname_override:the hostname to be used for the kerberos exchange

Once the dependencies have been installed, Kerberos needs to be configured so
that it can communicate with a domain. This configuration is done through the
/etc/krb5.conf file, which is installed with the packages in the script above.

To configure Kerberos, in the section that starts with:

[realms]

Add the full domain name and the fully qualified domain names of the primary
and secondary Active Directory domain controllers. It should look something
like this:

Ansible version 2.3 and later defaults to automatically managing Kerberos tickets
when both ansible_user and ansible_password are specified for a host. In
this process, a new ticket is created in a temporary credential cache for each
host. This is done before each task executes to minimize the chance of ticket
expiration. The temporary credential caches are deleted after each task
completes and will not interfere with the default credential cache.

To disable automatic ticket management, set ansible_winrm_kinit_mode=manual
via the inventory.

Automatic ticket management requires a standard kinit binary on the control
host system path. To specify a different location or binary name, set the
ansible_winrm_kinit_cmd hostvar to the fully qualified path to a MIT krbv5
kinit-compatible binary.

Kerberos is reliant on a properly-configured environment to
work. To troubleshoot Kerberos issues, ensure that:

The hostname set for the Windows host is the FQDN and not an IP address.

The forward and reverse DNS lookups are working properly in the domain. To
test this, ping the windows host by name and then use the ip address returned
with nslookup. The same name should be returned when using nslookup
on the IP address.

The Ansible host’s clock is synchronized with the domain controller. Kerberos
is time sensitive, and a little clock drift can cause the ticket generation
process to fail.

Ensure that the fully qualified domain name for the domain is configured in
the krb5.conf file. To check this, run:

If the domain name returned by klist is different from the one requested,
an alias is being used. The krb5.conf file needs to be updated so that
the fully qualified domain name is used and not an alias.

CredSSP authentication is a newer authentication protocol that allows
credential delegation. This is achieved by encrypting the username and password
after authentication has succeeded and sending that to the server using the
CredSSP protocol.

Because the username and password are sent to the server to be used for double
hop authentication, ensure that the hosts that the Windows host communicates with are
not compromised and are trusted.

CredSSP can be used for both local and domain accounts and also supports
message encryption over HTTP.

By default the requests-credssp library is configured to authenticate over
the TLS 1.2 protocol. TLS 1.2 is installed and enabled by default for Windows Server 2012
and Windows 8 and more recent releases.

There are two ways that older hosts can be used with CredSSP:

Install and enable a hotfix to enable TLS 1.2 support (recommended
for Server 2008 R2 and Windows 7).

Set ansible_winrm_credssp_disable_tlsv1_2=True in the inventory to run
over TLS 1.0. This is the only option when connecting to Windows Server 2008, which
has no way of supporting TLS 1.2

To enable TLS 1.2 support on Server 2008 R2 and Windows 7, the optional update
KRB3080079
needs to be installed.

Once the update has been applied and the Windows host rebooted, run the following
PowerShell commands to enable TLS 1.2:

CredSSP works by encrypting the credentials through the TLS protocol and uses a self-signed certificate by default. The CertificateThumbprint option under the WinRM service configuration can be used to specify the thumbprint of
another certificate.

Note

This certificate configuration is independent of the WinRM listener
certificate. With CredSSP, message transport still occurs over the WinRM listener,
but the TLS-encrypted messages inside the channel use the service-level certificate.

To explicitly set the certificate to use for CredSSP:

# note the value $certificate_thumbprint will be different in each
# situation, this needs to be set based on the cert that is used.
$certificate_thumbprint = "7C8DCBD5427AFEE6560F4AF524E325915F51172C"
# set the thumbprint value
Set-Item -Path WSMan:\localhost\Service\CertificateThumbprint -Value $certificate_thumbprint

By default WinRM will fail to work when running over an unencrypted channel.
The WinRM protocol considers the channel to be encrypted if using TLS over HTTP
(HTTPS) or using message level encryption. Using WinRM with TLS is the
recommended option as it works with all authentication options, but requires
a certificate to be created and used on the WinRM listener.

The ConfigureRemotingForAnsible.ps1 creates a self-signed certificate and
creates the listener with that certificate. If in a domain environment, ADCS
can also create a certificate for the host that is issued by the domain itself.

If using HTTPS is not an option, then HTTP can be used when the authentication
option is NTLM, Kerberos or CredSSP. These protocols will encrypt
the WinRM payload with their own encryption method before sending it to the
server. The message-level encryption is not used when running over HTTPS because the
encryption uses the more secure TLS protocol instead. If both transport and
message encryption is required, set ansible_winrm_message_encryption=always
in the host vars.

A last resort is to disable the encryption requirement on the Windows host. This
should only be used for development and debugging purposes, as anything sent
from Ansible can viewed by anyone on the network. To disable the encryption
requirement, run the following from PowerShell on the target host:

Set-Item -Path WSMan:\localhost\Service\AllowUnencrypted -Value $true

Note

Do not disable the encryption check unless it is
absolutely required. Doing so could allow sensitive information like
credentials and files to be intercepted by others on the network.

Ansible’s Windows support relies on a few standard variables to indicate the
username, password, and connection type of the remote hosts. These variables
are most easily set up in the inventory, but can be set on the host_vars/
group_vars level.

When setting up the inventory, the following variables are required:

# it is suggested that these be encrypted with ansible-vault:# ansible-vault edit group_vars/windows.ymlansible_connection:winrm# may also be passed on the command-line via --useransible_user:Administrator# may also be supplied at runtime with --ask-passansible_password:SecretPasswordGoesHere

Using the variables above, Ansible will connect to the Windows host with Basic
authentication through HTTPS. If ansible_user has a UPN value like
username@MY.DOMAIN.COM then the authentication option will automatically attempt
to use Kerberos unless ansible_winrm_transport has been set to something other than
kerberos.

The following custom inventory variables are also supported
for additional configuration of WinRM connections:

ansible_port: The port WinRM will run over, HTTPS is 5986 which is
the default while HTTP is 5985

ansible_winrm_scheme: Specify the connection scheme (http or
https) to use for the WinRM connection. Ansible uses https by default
unless ansible_port is 5985

ansible_winrm_realm: Specify the realm to use for Kerberos
authentication. If ansible_user contains @, Ansible will use the part
of the username after @ by default

ansible_winrm_transport: Specify one or more authentication transport
options as a comma-separated list. By default, Ansible will use kerberos,basic if the kerberos module is installed and a realm is defined,
otherwise it will be plaintext

ansible_winrm_server_cert_validation: Specify the server certificate
validation mode (ignore or validate). Ansible defaults to
validate on Python 2.7.9 and higher, which will result in certificate
validation errors against the Windows self-signed certificates. Unless
verifiable certificates have been configured on the WinRM listeners, this
should be set to ignore

ansible_winrm_message_encryption: Specify the message encryption
operation (auto, always, never) to use, Ansible uses auto by
default. auto means message encryption is only used when
ansible_winrm_scheme is http and ansible_winrm_transport supports
message encryption. always means message encryption will always be used
and never means message encryption will never be used

ansible_winrm_ca_trust_path: Used to specify a different cacert container
than the one used in the certifi module. See the HTTPS Certificate
Validation section for more details.

ansible_winrm_send_cbt: When using ntlm or kerberos over HTTPS,
the authentication library will try to send channel binding tokens to
mitigate against man in the middle attacks. This flag controls whether these
bindings will be sent or not (default: True).

ansible_winrm_*: Any additional keyword arguments supported by
winrm.Protocol may be provided in place of *

In addition, there are also specific variables that need to be set
for each authentication option. See the section on authentication above for more information.

Note

Ansible 2.0 has deprecated the “ssh” from ansible_ssh_user,
ansible_ssh_pass, ansible_ssh_host, and ansible_ssh_port to
become ansible_user, ansible_password, ansible_host, and
ansible_port. If using a version of Ansible prior to 2.0, the older
style (ansible_ssh_*) should be used instead. The shorter variables
are ignored, without warning, in older versions of Ansible.

Note

ansible_winrm_message_encryption is different from transport
encryption done over TLS. The WinRM payload is still encrypted with TLS
when run over HTTPS, even if ansible_winrm_message_encryption=never.

IPv6 addresses can be used instead of IPv4 addresses or hostnames. This option
is normally set in an inventory. Ansible will attempt to parse the address
using the ipaddress
package and pass to pywinrm correctly.

When defining a host using an IPv6 address, just add the IPv6 address as you
would an IPv4 address or hostname:

As part of the TLS protocol, the certificate is validated to ensure the host
matches the subject and the client trusts the issuer of the server certificate.
When using a self-signed certificate or setting
ansible_winrm_server_cert_validation:ignore these security mechanisms are
bypassed. While self signed certificates will always need the ignore flag,
certificates that have been issued from a certificate authority can still be
validated.

One of the more common ways of setting up a HTTPS listener in a domain
environment is to use Active Directory Certificate Service (AD CS). AD CS is
used to generate signed certificates from a Certificate Signing Request (CSR).
If the WinRM HTTPS listener is using a certificate that has been signed by
another authority, like AD CS, then Ansible can be set up to trust that
issuer as part of the TLS handshake.

To get Ansible to trust a Certificate Authority (CA) like AD CS, the issuer
certificate of the CA can be exported as a PEM encoded certificate. This
certificate can then be copied locally to the Ansible controller and used as a
source of certificate validation, otherwise known as a CA chain.

The CA chain can contain a single or multiple issuer certificates and each
entry is contained on a new line. To then use the custom CA chain as part of
the validation process, set ansible_winrm_ca_trust_path to the path of the
file. If this variable is not set, the default CA chain is used instead which
is located in the install path of the Python package
certifi.

Note

Each HTTP call is done by the Python requests library which does not
use the systems built-in certificate store as a trust authority.
Certificate validation will fail if the server’s certificate issuer is
only added to the system’s truststore.

Due to the design of the WinRM protocol , there are a few limitations
when using WinRM that can cause issues when creating playbooks for Ansible.
These include:

Credentials are not delegated for most authentication types, which causes
authentication errors when accessing network resources or installing certain
programs.

Many calls to the Windows Update API are blocked when running over WinRM.

Some programs fail to install with WinRM due to no credential delegation or
because they access forbidden Windows API like WUA over WinRM.

Commands under WinRM are done under a non-interactive session, which can prevent
certain commands or executables from running.

You cannot run a process that interacts with DPAPI, which is used by some
installers (like Microsoft SQL Server).

Some of these limitations can be mitigated by doing one of the following:

Set ansible_winrm_transport to credssp or kerberos (with
ansible_winrm_kerberos_delegation=true) to bypass the double hop issue
and access network resources

Use become to bypass all WinRM restrictions and run a command as it would
locally. Unlike using an authentication transport like credssp, this will
also remove the non-interactive restriction and API restrictions like WUA and
DPAPI

Use a scheduled task to run a command which can be created with the
win_scheduled_task module. Like become, this bypasses all WinRM
restrictions but can only run a command and not modules.