No additional software needs to be installed on the remote machines for Ansible to manage them, it still maintains the agentless properties that make it popular on Linux/Unix.
Note that it is expected you have a basic understanding of Ansible prior to jumping into this section, so if you haven't written a Linux playbook first, it might be worthwhile to dig in there first.
A Linux control machine is required to manage Windows hosts. This Linux control machine can be a Windows Subsystem for Linux (WSL) bash shell.
..Note:: Running Ansible from a Windows control machine directly is not a goal of the project. Refrain from asking for this feature, as it limits what technologies, features, and code we can use in the main project in the future.
..Note:: The Windows Subsystem for Linux (Beta) is not supported by Microsoft or Ansible and should not be used for production systems.
If you would like to experiment with the Windows Subsystem for Linux (WSL), first enable the Windows Subsystem for Linux using
Once WSL is enabled, you can open the Bash terminal. The first time you so this, a few questions need to be answered.
At the prompt you can quickly start using the Ansible devel branch by running the following commands::
sudo apt-get install python-pip
pip install pywinrm
git clone https://github.com/ansible/ansible.git
source ansible/hacking/env-setup
After you've successfully run these commands, you can start to create your inventory, write example playbooks and start targetting systems using the plethora of available Windows modules.
..Note:: Ansible is also reported to work on Cygwin, but this is more cumbersome and doesn't scale as well as WSL.
You can specify which authentication option you wish to use by setting it to the ``ansible_winrm_transport`` variable.
Certificate
+++++++++++
Certificate authentication is similar to SSH where a certificate is assigned to a local user and instead of using a password to authenticate a certificate is used instead.
Kerberos
++++++++
Kerberos is the preferred option compared to NTLM to use when using an Active Directory account but it requires a few extra steps to set up on the Ansible control host. You will need to install the "python-kerberos" module on the Ansible control host (and the MIT krb5 libraries it depends on). The Ansible control host also requires a properly configured computer account in Active Directory.
Kerberos is installed and configured by default on OS X and many Linux distributions. If your control machine has not already done this for you, you will need to.
Edit your /etc/krb5.conf (which should be installed as a result of installing packages above) and add the following information for each domain you need to connect to:
add the full domain name and the fully qualified domain names of your primary and secondary Active Directory domain controllers. It should look something like this:
You may wish to configure other settings here, such as the default domain.
Testing a kerberos connection
-----------------------------
If you have installed krb5-workstation (yum) or krb5-user (apt-get) you can use the following command to test that you can be authorised by your domain controller.
..code-block:: bash
kinit user@MY.DOMAIN.COM
Note that the domain part has to be fully qualified and must be in upper case.
To see what tickets if any you have acquired, use the command klist
Ansible defaults to automatically managing kerberos tickets (as of Ansible 2.3) when both username and password are specified for a host that's configured for kerberos. A new ticket is created in a temporary credential cache for each host, before each task executes (to minimize the chance of ticket expiration). The temporary credential caches are deleted after each task, and will not interfere with the default credential cache.
To disable automatic ticket management (e.g., to use an existing SSO ticket or call ``kinit`` manually to populate the default credential cache), set ``ansible_winrm_kinit_mode=manual`` via 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`` inventory var to the fully-qualified path to an MIT krbv5 ``kinit``-compatible binary.
If you unable to connect using kerberos, check the following:
Ensure that forward and reverse DNS lookups are working properly on your domain.
To test this, ping the windows host you want to control by name then use the ip address returned with nslookup. You should get the same name back from DNS when you use nslookup on the ip address.
If you get different hostnames back than the name you originally pinged, speak to your active directory administrator and get them to check that DNS Scavenging is enabled and that DNS and DHCP are updating each other.
Ensure that the Ansible controller has a properly configured computer account in the domain.
Check your Ansible controller's clock is synchronised with your domain controller. Kerberos is time sensitive and a little clock drift can cause tickets not be granted.
Check you are using the real fully qualified domain name for the domain. Sometimes domains are commonly known to users by aliases. To check this run:
..code-block:: bash
kinit -C user@MY.DOMAIN.COM
klist
If the domain name returned by klist is different from the domain name you requested, you are requesting using an alias, and you need to update your krb5.conf so you are using the fully qualified domain name, not its alias.
CredSSP authentication can be used to authenticate with both domain and local accounts. It allows credential delegation to do second hop authentication on a remote host by sending an encrypted form of the credentials to the remote host using the CredSSP protocol.
Installing requests-credssp
---------------------------
To install credssp you can use pip to install the requests-credssp library:
..code-block:: bash
pip install pywinrm[credssp]
CredSSP and TLS 1.2
-------------------
CredSSP requires the remote host to have TLS 1.2 configured or else the connection will fail. TLS 1.2 is installed by default from Server 2012 and Windows 8 onwards. For Server 2008, 2008 R2 and Windows 7 you can add TLS 1.2 support by:
* Installing the `TLS 1.2 update from Microsoft <https://support.microsoft.com/en-us/help/3080079/update-to-add-rds-support-for-tls-1.1-and-tls-1.2-in-windows-7-or-windows-server-2008-r2>`_
* Adding the TLS 1.2 registry keys as shown on this `page <https://technet.microsoft.com/en-us/library/dn786418.aspx#BKMK_SchannelTR_TLS12>`_
Credential Delegation
+++++++++++++++++++++
If you need to interact with a remote resource or run a process that requires the credentials to be stored in the current session like a certreq.exe then an authentication protocol that supports credential delegation needs to be used.
Ansible's windows support relies on a few standard variables to indicate the username, password, and connection type (windows) of the remote hosts. These variables are most easily set up in inventory. This is used instead of SSH-keys or passwords as normally fed into Ansible::
# The following is necessary for Python 2.7.9+ (or any older Python that has backported SSLContext, eg, Python 2.7.5 on RHEL7) when using default WinRM self-signed certificates:
Although Ansible is mostly an SSH-oriented system, Windows management will not happen over SSH (`yet <http://blogs.msdn.com/b/powershell/archive/2015/06/03/looking-forward-microsoft-support-for-secure-shell-ssh.aspx>`_).
If you have installed the ``kerberos`` module and ``ansible_user`` contains ``@`` (e.g. ``username@realm``), Ansible will first attempt Kerberos authentication. *This method uses the principal you are authenticated to Kerberos with on the control machine and not*``ansible_user``. If that fails, either because you are not signed into Kerberos on the control machine or because the corresponding domain account on the remote host is not available, then Ansible will fall back to "plain" username/password authentication.
*``ansible_winrm_scheme``: Specify the connection scheme (``http`` or ``https``) to use for the WinRM connection. Ansible uses ``https`` by default unless the port is 5985.
*``ansible_winrm_path``: Specify an alternate path to the WinRM endpoint. Ansible uses ``/wsman`` by default.
*``ansible_winrm_realm``: Specify the realm to use for Kerberos authentication. If the username contains ``@``, Ansible will use the part of the username after ``@`` by default.
*``ansible_winrm_transport``: Specify one or more transports as a comma-separated list. By default, Ansible will use ``kerberos,plaintext`` if the ``kerberos`` module is installed and a realm is defined, otherwise ``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_operation_timeout_sec``: Increase the default timeout for WinRM operations (default: ``20``).
*``ansible_winrm_read_timeout_sec``: Increase the WinRM read timeout if you experience read timeout errors (default: ``30``), e.g. intermittent network issues.
To automate the setup of WinRM, you can run the `examples/scripts/ConfigureRemotingForAnsible.ps1 <https://github.com/ansible/ansible/blob/devel/examples/scripts/ConfigureRemotingForAnsible.ps1>`_ script on the remote machine in a PowerShell console as an administrator.
The example script accepts a few arguments which Admins may choose to use to modify the default setup slightly, which might be appropriate in some cases.
Pass the ``-ForceNewSSLCert`` switch to force a new SSL certificate to be attached to an already existing winrm listener. (Avoids SSL winrm errors on syspreped Windows images after the CN changes)::
Pass the ``-SkipNetworkProfileCheck`` switch to configure winrm to listen on PUBLIC zone interfaces. (Without this option, the script will fail if any network interface on device is in PUBLIC zone)::
To troubleshoot the ``ConfigureRemotingForAnsible.ps1`` writes every change it makes to the Windows EventLog (useful when run unattendedly). Additionally the ``-Verbose`` option can be used to get more information on screen about what it is doing.
PowerShell 3.0 or higher is needed for most provided Ansible modules for Windows, and is also required to run the above setup script. Note that PowerShell 3.0 is only supported on Windows 7 SP1, Windows Server 2008 SP1, and later releases of Windows.
Looking at an Ansible checkout, copy the `examples/scripts/upgrade_to_ps3.ps1 <https://github.com/ansible/ansible/blob/devel/examples/scripts/upgrade_to_ps3.ps1>`_ script onto the remote host and run a PowerShell console as an administrator. You will now be running PowerShell 3 and can try connectivity again using the ``win_ping`` technique referenced above.
Windows-only modules. These are listed in the `"windows" subcategory of the Ansible module index <http://docs.ansible.com/list_of_windows_modules.html>`_.
In many cases, there is no need to use or write an Ansible module. In particular, the ``script`` module can be used to run arbitrary PowerShell scripts, allowing Windows administrators familiar with PowerShell a very native way to do things, as in the following playbook::
Developing Ansible modules are covered in a `later section of the documentation <http://docs.ansible.com/developing_modules.html>`_, with a focus on Linux/Unix.
What if you want to write Windows modules for Ansible though?
For Windows, Ansible modules are implemented in PowerShell. Skim those Linux/Unix module development chapters before proceeding. Windows modules in the core and extras repo live in a ``windows/`` subdir. Custom modules can go directly into the Ansible ``library/`` directories or those added in ansible.cfg. Documentation lives in a ``.py`` file with the same name. For example, if a module is named ``win_ping``, there will be embedded documentation in the ``win_ping.py`` file, and the actual PowerShell code will live in a ``win_ping.ps1`` file. Take a look at the sources and this will make more sense.
The above magic is necessary to tell Ansible to mix in some common code and also know how to push modules out. The common code contains some nice wrappers around working with hash data structures and emitting JSON results, and possibly a few more useful things. Regular Ansible has this same concept for reusing Python code - this is just the windows equivalent.
Just as with Linux/Unix, facts can be gathered for windows hosts, which will return things such as the operating system version. To see what variables are available about a windows host, run the following::
ansible winhost.example.com -m setup
Note that this command invocation is exactly the same as the Linux/Unix equivalent.
Running individual commands uses the ``win_command <https://docs.ansible.com/ansible/win_command_module.html>`` or ``win_shell <https://docs.ansible.com/ansible/win_shell_module.html>`` module, as opposed to the shell or command module as is common on Linux/Unix operating systems::
Running common DOS commands like ``del``, ``move``, or ``copy`` is unlikely to work on a remote Windows Server using Powershell, but they can work by prefacing the commands with ``CMD /C`` and enclosing the command in double quotes as in this example::
You may wind up with a more readable playbook by using the PowerShell equivalents of DOS commands. For example, to achieve the same effect as the example above, you could use::
Bear in mind that using ``win_command`` or ``win_shell`` will always report ``changed``, and it is your responsiblity to ensure PowerShell will need to handle idempotency as appropriate (the move examples above are inherently not idempotent), so where possible use (or write) a module.
Here's an example of how to use the ``win_stat`` module to test for file existence. Note that the data returned by the ``win_stat`` module is slightly different than what is provided by the Linux equivalent::
form of new modules, tweaks to existing modules, documentation, or something else. Please stop by the ansible-devel mailing list if you would like to get involved and say hi.