mirror of https://github.com/ansible/ansible.git
update Windows docs (#30783)
* first round of splitting and expanding Windows docs * Added info about WinRM and started the usage page * more details onf usage around command/shell * added more info * missed a page * added info about hotfix and ps upgrade script * Added DSC information * filled in FAQ and fixed up links * changes per PR review and typo fixes found by myself * fixed sanity check * updated external script URLS * Edits * Edits * Edits * Copy edits. * More copy edits. * Added info about becoming a local service account * some formatting changes on become and DSC indent fix * Copy edits/rewrites * Copy edits/rewrites * minor updates to UAC text, typos * minor wording updates * minor wording tweaks/typos * minor wording tweaks/typos * minor tweaks/typos * fix indent issue * fix title underline length * fix quote issuepull/31505/merge
parent
381b18fd80
commit
f2fed10ad8
@ -1,526 +1,4 @@
|
||||
Windows Support
|
||||
===============
|
||||
|
||||
.. contents:: Topics
|
||||
|
||||
.. _windows_how_does_it_work:
|
||||
|
||||
Windows: How Does It Work
|
||||
`````````````````````````
|
||||
|
||||
As you may have already read, Ansible manages Linux/Unix machines using SSH by default.
|
||||
|
||||
Starting in version 1.7, Ansible also contains support for managing Windows machines. This uses
|
||||
native PowerShell remoting, rather than SSH.
|
||||
|
||||
Ansible will still be run from a Linux control machine, and uses the "winrm" Python module to talk to remote hosts.
|
||||
While not supported by Microsoft or Ansible, this Linux control machine can be a Windows Subsystem for Linux (WSL) bash shell.
|
||||
|
||||
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.
|
||||
|
||||
.. _windows_installing:
|
||||
|
||||
Installing on the Control Machine
|
||||
`````````````````````````````````
|
||||
|
||||
On a Linux control machine::
|
||||
|
||||
pip install "pywinrm>=0.2.2"
|
||||
|
||||
.. Note:: on distributions with multiple python versions, use pip2 or pip2.x, where x matches the python minor version Ansible is running under.
|
||||
|
||||
|
||||
.. _windows_control_machine:
|
||||
|
||||
Using a Windows control machine
|
||||
```````````````````````````````
|
||||
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
|
||||
`these instructions <https://www.jeffgeerling.com/blog/2017/using-ansible-through-windows-10s-subsystem-linux>`_.
|
||||
This requires a reboot.
|
||||
|
||||
Once WSL is enabled, you can open the Bash terminal. At the prompt, you can quickly start using the latest Ansible release by running the following commands::
|
||||
|
||||
sudo apt-get update
|
||||
sudo apt-get install python-pip git libffi-dev libssl-dev -y
|
||||
pip install ansible pywinrm
|
||||
|
||||
# this step is only necessary for Windows builds earlier than 16188, and must be repeated each time bash is launched,
|
||||
# unless bash is launched as ``bash --login``
|
||||
# see https://github.com/Microsoft/BashOnWindows/issues/2148 and
|
||||
# https://github.com/Microsoft/BashOnWindows/issues/816#issuecomment-301216901 for details
|
||||
source ~/.profile
|
||||
|
||||
After you've successfully run these commands, you can start to create your inventory, write example playbooks and start targeting systems using the plethora of available Windows modules.
|
||||
|
||||
If you want to run Ansible from source for development purposes, simply uninstall the pip-installed version (which will leave all the necessary dependencies behind), then clone the Ansible source, and run the hacking script to configure it to run from source::
|
||||
|
||||
pip uninstall ansible -y
|
||||
git clone https://github.com/ansible/ansible.git
|
||||
source ansible/hacking/env-setup
|
||||
|
||||
.. Note:: Ansible is also reported to "work" on Cygwin, but installation is more cumbersome, and will incur sporadic failures due to Cygwin's implementation of ``fork()``.
|
||||
|
||||
|
||||
Authentication Options
|
||||
``````````````````````
|
||||
|
||||
When connecting to a Windows host there are different authentication options that can be used. The options and the features they support are:
|
||||
|
||||
+-------------+----------------+---------------------------+-----------------------+
|
||||
| Option | Local Accounts | Active Directory Accounts | Credential Delegation |
|
||||
+=============+================+===========================+=======================+
|
||||
| Basic | Yes | No | No |
|
||||
+-------------+----------------+---------------------------+-----------------------+
|
||||
| Certificate | Yes | No | No |
|
||||
+-------------+----------------+---------------------------+-----------------------+
|
||||
| Kerberos | No | Yes | Yes |
|
||||
+-------------+----------------+---------------------------+-----------------------+
|
||||
| NTLM | Yes | Yes | No |
|
||||
+-------------+----------------+---------------------------+-----------------------+
|
||||
| CredSSP | Yes | Yes | Yes |
|
||||
+-------------+----------------+---------------------------+-----------------------+
|
||||
|
||||
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 because it uses both a public and private key to access a local Windows user account. This removes the need for using a password.
|
||||
|
||||
This requires two variables that specify the path to both the PEM file containing the certificate (cert_pem) and the related private key file (cert_key_pem).
|
||||
|
||||
ansible_winrm_cert_pem:
|
||||
ansible_winrm_cert_key_pem:
|
||||
|
||||
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.
|
||||
|
||||
Installing python-kerberos dependencies
|
||||
---------------------------------------
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
# Via Yum
|
||||
yum -y install python-devel krb5-devel krb5-libs krb5-workstation
|
||||
|
||||
# Via Apt (Ubuntu)
|
||||
sudo apt-get install python-dev libkrb5-dev krb5-user
|
||||
|
||||
# Via Portage (Gentoo)
|
||||
emerge -av app-crypt/mit-krb5
|
||||
emerge -av dev-python/setuptools
|
||||
|
||||
# Via pkg (FreeBSD)
|
||||
sudo pkg install security/krb5
|
||||
|
||||
# Via OpenCSW (Solaris)
|
||||
pkgadd -d http://get.opencsw.org/now
|
||||
/opt/csw/bin/pkgutil -U
|
||||
/opt/csw/bin/pkgutil -y -i libkrb5_3
|
||||
|
||||
# Via Pacman (Arch Linux)
|
||||
pacman -S krb5
|
||||
|
||||
Installing python-kerberos
|
||||
--------------------------
|
||||
|
||||
Once you've installed the necessary dependencies, the python-kerberos wrapper can be installed via pip:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pip install pywinrm[kerberos]
|
||||
|
||||
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.
|
||||
|
||||
Configuring Kerberos
|
||||
--------------------
|
||||
|
||||
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:
|
||||
|
||||
In the section that starts with
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[realms]
|
||||
|
||||
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:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[realms]
|
||||
|
||||
MY.DOMAIN.COM = {
|
||||
kdc = domain-controller1.my.domain.com
|
||||
kdc = domain-controller2.my.domain.com
|
||||
}
|
||||
|
||||
|
||||
and in the [domain_realm] section add a line like the following for each domain you want to access:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[domain_realm]
|
||||
.my.domain.com = MY.DOMAIN.COM
|
||||
|
||||
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
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
klist
|
||||
|
||||
Automatic kerberos ticket management
|
||||
------------------------------------
|
||||
|
||||
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.
|
||||
|
||||
Troubleshooting kerberos connections
|
||||
------------------------------------
|
||||
|
||||
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.
|
||||
|
||||
.. _windows_inventory:
|
||||
|
||||
|
||||
CredSSP
|
||||
+++++++
|
||||
|
||||
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.
|
||||
|
||||
Inventory
|
||||
`````````
|
||||
|
||||
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::
|
||||
|
||||
[windows]
|
||||
winserver1.example.com
|
||||
winserver2.example.com
|
||||
|
||||
.. include:: ../rst_common/ansible_ssh_changes_note.rst
|
||||
|
||||
In ``group_vars/windows.yml``, define the following inventory variables::
|
||||
|
||||
# it is suggested that these be encrypted with ansible-vault:
|
||||
# ansible-vault edit group_vars/windows.yml
|
||||
|
||||
ansible_user: Administrator
|
||||
ansible_password: SecretPasswordGoesHere
|
||||
ansible_port: 5986
|
||||
ansible_connection: winrm
|
||||
# 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:
|
||||
ansible_winrm_server_cert_validation: ignore
|
||||
|
||||
Attention for the older style variables (``ansible_ssh_*``): ansible_ssh_password doesn't exist, should be ansible_ssh_pass.
|
||||
|
||||
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.
|
||||
|
||||
When using your playbook, don't forget to specify ``--ask-vault-pass`` to provide the password to unlock the file.
|
||||
|
||||
Test your configuration like so, by trying to contact your Windows nodes. Note this is not an ICMP ping, but tests the Ansible
|
||||
communication channel that leverages Windows remoting::
|
||||
|
||||
ansible windows [-i inventory] -m win_ping --ask-vault-pass
|
||||
|
||||
If you haven't done anything to prep your systems yet, this won't work yet. This is covered in a later
|
||||
section about how to enable PowerShell remoting - and if necessary - how to upgrade PowerShell to
|
||||
a version that is 3 or higher.
|
||||
|
||||
You'll run this command again later though, to make sure everything is working.
|
||||
|
||||
Since 2.0, the following custom inventory variables are also supported for additional configuration of WinRM connections
|
||||
|
||||
* ``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_kerberos_delegation``: Set to ``true`` to enable delegation of commands on the remote host when using kerberos.
|
||||
* ``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.
|
||||
* ``ansible_winrm_*``: Any additional keyword arguments supported by ``winrm.Protocol`` may be provided.
|
||||
|
||||
.. _windows_system_prep:
|
||||
|
||||
Windows System Prep
|
||||
```````````````````
|
||||
|
||||
In order for Ansible to manage your windows machines, you will have to enable and configure PowerShell remoting.
|
||||
|
||||
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 ``-CertValidityDays`` option to customize the expiration date of the generated certificate::
|
||||
|
||||
powershell.exe -File ConfigureRemotingForAnsible.ps1 -CertValidityDays 100
|
||||
|
||||
Pass the ``-EnableCredSSP`` switch to enable CredSSP as an authentication option::
|
||||
|
||||
powershell.exe -File ConfigureRemotingForAnsible.ps1 -EnableCredSSP
|
||||
|
||||
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)::
|
||||
|
||||
powershell.exe -File ConfigureRemotingForAnsible.ps1 -ForceNewSSLCert
|
||||
|
||||
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)::
|
||||
|
||||
powershell.exe -File ConfigureRemotingForAnsible.ps1 -SkipNetworkProfileCheck
|
||||
|
||||
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.
|
||||
|
||||
.. note::
|
||||
On Windows 7 and Server 2008 R2 machines, due to a bug in Windows
|
||||
Management Framework 3.0, it may be necessary to install this
|
||||
hotfix http://support.microsoft.com/kb/2842230 to avoid receiving
|
||||
out of memory and stack overflow exceptions. Newly-installed Server 2008
|
||||
R2 systems which are not fully up to date with windows updates are known
|
||||
to have this issue.
|
||||
|
||||
Windows 8.1 and Server 2012 R2 are not affected by this issue as they
|
||||
come with Windows Management Framework 4.0.
|
||||
|
||||
.. _getting_to_powershell_three_or_higher:
|
||||
|
||||
Getting to PowerShell 3.0 or higher
|
||||
```````````````````````````````````
|
||||
|
||||
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.
|
||||
|
||||
.. _what_windows_modules_are_available:
|
||||
|
||||
What modules are available
|
||||
``````````````````````````
|
||||
|
||||
Most of the Ansible modules in core Ansible are written for a combination of Linux/Unix machines and arbitrary web services, though there are various
|
||||
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 addition, the following core modules/action-plugins work with Windows:
|
||||
|
||||
* add_host
|
||||
* assert
|
||||
* async_status
|
||||
* debug
|
||||
* fail
|
||||
* fetch
|
||||
* group_by
|
||||
* include
|
||||
* include_role
|
||||
* include_vars
|
||||
* meta
|
||||
* pause
|
||||
* raw
|
||||
* script
|
||||
* set_fact
|
||||
* set_stats
|
||||
* setup
|
||||
* slurp
|
||||
* template (also: win_template)
|
||||
* wait_for_connection
|
||||
|
||||
Some modules can be utilised in playbooks that target windows by delegating to localhost, depending on what you are
|
||||
attempting to achieve. For example, ``assemble`` can be used to create a file on your ansible controller that is then
|
||||
sent to your windows targets using ``win_copy``.
|
||||
|
||||
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::
|
||||
|
||||
- hosts: windows
|
||||
tasks:
|
||||
- script: foo.ps1 --argument --other-argument
|
||||
|
||||
But also the ``win_shell`` module allows for running Powershell snippets inline::
|
||||
|
||||
- hosts: windows
|
||||
tasks:
|
||||
- name: Remove Appx packages (and their hindering file assocations)
|
||||
win_shell: |
|
||||
Get-AppxPackage -name "Microsoft.ZuneMusic" | Remove-AppxPackage
|
||||
Get-AppxPackage -name "Microsoft.ZuneVideo" | Remove-AppxPackage
|
||||
|
||||
.. _developers_developers_developers:
|
||||
|
||||
Developers: Supported modules and how it works
|
||||
``````````````````````````````````````````````
|
||||
|
||||
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.
|
||||
|
||||
Modules (ps1 files) should start as follows::
|
||||
|
||||
#!powershell
|
||||
# <license>
|
||||
|
||||
# WANT_JSON
|
||||
# POWERSHELL_COMMON
|
||||
|
||||
# code goes here, reading in stdin as JSON and outputting JSON
|
||||
|
||||
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.
|
||||
|
||||
What modules you see in ``windows/`` are just a start. Additional modules may be submitted as pull requests to github.
|
||||
|
||||
.. _windows_facts:
|
||||
|
||||
Windows Facts
|
||||
`````````````
|
||||
|
||||
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.
|
||||
|
||||
.. _windows_playbook_example:
|
||||
|
||||
Windows Playbook Examples
|
||||
`````````````````````````
|
||||
|
||||
Here is an example of pushing and running a PowerShell script::
|
||||
|
||||
- name: test script module
|
||||
hosts: windows
|
||||
tasks:
|
||||
- name: run test script
|
||||
script: files/test_script.ps1
|
||||
|
||||
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::
|
||||
|
||||
- name: test raw module
|
||||
hosts: windows
|
||||
tasks:
|
||||
- name: run ipconfig
|
||||
win_command: ipconfig
|
||||
register: ipconfig
|
||||
- debug: var=ipconfig
|
||||
|
||||
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::
|
||||
|
||||
- name: another raw module example
|
||||
hosts: windows
|
||||
tasks:
|
||||
- name: Move file on remote Windows Server from one location to another
|
||||
win_command: CMD /C "MOVE /Y C:\teststuff\myfile.conf C:\builds\smtp.conf"
|
||||
|
||||
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::
|
||||
|
||||
- name: another raw module example demonstrating powershell one liner
|
||||
hosts: windows
|
||||
tasks:
|
||||
- name: Move file on remote Windows Server from one location to another
|
||||
win_command: Powershell.exe "Move-Item C:\teststuff\myfile.conf C:\builds\smtp.conf"
|
||||
|
||||
Bear in mind that using ``win_command`` or ``win_shell`` will always report ``changed``, and it is your responsibility 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::
|
||||
|
||||
- name: test stat module
|
||||
hosts: windows
|
||||
tasks:
|
||||
- name: test stat module on file
|
||||
win_stat: path="C:/Windows/win.ini"
|
||||
register: stat_file
|
||||
|
||||
- debug: var=stat_file
|
||||
|
||||
- name: check stat_file result
|
||||
assert:
|
||||
that:
|
||||
- "stat_file.stat.exists"
|
||||
- "not stat_file.stat.isdir"
|
||||
- "stat_file.stat.size > 0"
|
||||
- "stat_file.stat.md5"
|
||||
|
||||
.. _windows_contributions:
|
||||
|
||||
Windows Contributions
|
||||
`````````````````````
|
||||
|
||||
Windows support in Ansible is still relatively new, and contributions are quite welcome, whether this is in the
|
||||
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.
|
||||
|
||||
.. seealso::
|
||||
|
||||
:doc:`dev_guide/developing_modules`
|
||||
How to write modules
|
||||
:doc:`playbooks`
|
||||
Learning Ansible's configuration management language
|
||||
`List of Windows Modules <http://docs.ansible.com/list_of_windows_modules.html>`_
|
||||
Windows specific module list, all implemented in PowerShell
|
||||
`Mailing List <http://groups.google.com/group/ansible-project>`_
|
||||
Questions? Help? Ideas? Stop by the list on Google Groups
|
||||
`irc.freenode.net <http://irc.freenode.net>`_
|
||||
#ansible IRC chat channel
|
||||
This page has been split up and moved to the new section :doc:`windows`.
|
||||
|
@ -0,0 +1,18 @@
|
||||
Windows Guides
|
||||
``````````````
|
||||
|
||||
The following sections provide information on managing
|
||||
Windows hosts with Ansible.
|
||||
|
||||
Because Windows is a non-POSIX-compliant operating system, there are differences between
|
||||
how Ansible interacts with them and the way Windows works. These guides will highlight
|
||||
some of the differences between Linux/Unix hosts and hosts running Windows.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
windows_setup
|
||||
windows_winrm
|
||||
windows_usage
|
||||
windows_dsc
|
||||
windows_faq
|
@ -0,0 +1,334 @@
|
||||
Desired State Configuration
|
||||
===========================
|
||||
|
||||
.. contents:: Topics
|
||||
|
||||
What is Desired State Configuration?
|
||||
````````````````````````````````````
|
||||
Desired State Configuration, or DSC, is a tool built into PowerShell that can
|
||||
be used to define a Windows host setup through code. The overall purpose of DSC
|
||||
is the same as Ansible, it is just executed in a different manner. Since
|
||||
Ansible 2.4, the ``win_dsc`` module has been added and can be used to leverage
|
||||
existing DSC resources when interacting with a Windows host.
|
||||
|
||||
More details on DSC can be viewed at `DSC Overview <https://docs.microsoft.com/en-us/powershell/dsc/overview>`_.
|
||||
|
||||
Host Requirements
|
||||
`````````````````
|
||||
To use the ``win_dsc`` module, a Windows host must have PowerShell v5.0 or
|
||||
newer installed. All supported hosts, except for Windows Server 2008 (non R2) can be
|
||||
upgraded to PowerShell v5.
|
||||
|
||||
Once the PowerShell requirements have been met, using DSC is as simple as
|
||||
creating a task with the ``win_dsc`` module.
|
||||
|
||||
Why Use DSC?
|
||||
````````````
|
||||
DSC and Ansible modules have a common goal which is to define and ensure the state of a
|
||||
resource. Because of
|
||||
this, resources like the DSC `File resource <https://docs.microsoft.com/en-us/powershell/dsc/fileresource>`_
|
||||
and Ansible ``win_file`` can be used to achieve the same result. Deciding which to use depends
|
||||
on the scenario.
|
||||
|
||||
Reasons for using an Ansible module over a DSC resource:
|
||||
|
||||
* The host does not support PowerShell v5.0, or it cannot easily be upgraded
|
||||
* The DSC resource does not offer a feature present in an Ansible module. For example
|
||||
win_regedit can manage the ``REG_NONE`` property type, while the DSC
|
||||
``Registry`` resource cannot
|
||||
* DSC resources have limited check mode support, while some Ansible modules have
|
||||
better checks
|
||||
* DSC resources do not support diff mode, while some Ansible modules do
|
||||
* Custom resources require further installation steps to be run on the host
|
||||
beforehand, while Ansible modules are in built-in to Ansible
|
||||
* There are bugs in a DSC resource where an Ansible module works
|
||||
|
||||
Reasons for using a DSC resource over an Ansible module:
|
||||
|
||||
* The Ansible module does not support a feature present in a DSC resource
|
||||
* There is no Ansible module available
|
||||
* There are bugs in an existing Ansible module
|
||||
|
||||
In the end, it doesn't matter whether the task is performed with DSC or an
|
||||
Ansible module; what matters is that the task is performed correctly and the
|
||||
playbooks are still readable. If you have more experience with DSC over Ansible
|
||||
and it does the job, just use DSC for that task.
|
||||
|
||||
How to Use DSC?
|
||||
```````````````
|
||||
The ``win_dsc`` module takes in a free-form of options so that it changes
|
||||
according to the resource it is managing. A list of built in resources can be
|
||||
found at `resources <https://docs.microsoft.com/en-us/powershell/dsc/resources>`_.
|
||||
|
||||
Using the the `Registry <https://docs.microsoft.com/en-us/powershell/dsc/registryresource>`_
|
||||
resource as an example, this is the DSC definition as documented by Microsoft::
|
||||
|
||||
Registry [string] #ResourceName
|
||||
{
|
||||
Key = [string]
|
||||
ValueName = [string]
|
||||
[ Ensure = [string] { Enable | Disable } ]
|
||||
[ Force = [bool] ]
|
||||
[ Hex = [bool] ]
|
||||
[ DependsOn = [string[]] ]
|
||||
[ ValueData = [string[]] ]
|
||||
[ ValueType = [string] { Binary | Dword | ExpandString | MultiString | Qword | String } ]
|
||||
}
|
||||
|
||||
When defining the task, ``resource_name`` must be set to the DSC resource being
|
||||
used - in this case the ``resource_name`` should be set to ``Registry``. The
|
||||
``module_version`` can refer to a specific version of the DSC resource
|
||||
installed; if left blank it will default to the latest version. The other
|
||||
options are parameters that are used to define the resource, such as ``Key`` and
|
||||
``ValueName``. While the options in the task are not case sensitive,
|
||||
keeping the case as-is is recommended becuase it makes it easier to distinguish DSC
|
||||
resource options from Ansible's ``win_dsc`` options.
|
||||
|
||||
This is what the Ansible task version of the above DSC Registry resource would look like::
|
||||
|
||||
- name: use win_dsc module with the Registry DSC resource
|
||||
win_dsc:
|
||||
resource_name: Registry
|
||||
Ensure: Present
|
||||
Key: HKEY_LOCAL_MACHINE\SOFTWARE\ExampleKey
|
||||
ValueName: TestValue
|
||||
ValueData: TestData
|
||||
|
||||
Property Types
|
||||
--------------
|
||||
Each DSC resource property has a type that is associated with it. Ansible
|
||||
will try to convert the defined options to the correct type during execution.
|
||||
For simple types like ``[string]`` and ``[bool]`` this is a simple operation,
|
||||
but complex types like ``[PSCredential]`` or arrays (like ``[string[]]``) this
|
||||
require certain rules.
|
||||
|
||||
PSCredential
|
||||
++++++++++++
|
||||
A ``[PSCredential]`` object is used to store credentials in a secure way, but
|
||||
Ansible has no way to serialize this over JSON. To set a DSC PSCredential property,
|
||||
the definition of that parameter should have two entries that are suffixed with
|
||||
``_username`` and ``_password`` for the username and password respectively.
|
||||
For example::
|
||||
|
||||
PsDscRunAsCredential_username: '{{ansible_user}}'
|
||||
PsDscRunAsCredential_password: '{{ansible_password}}'
|
||||
|
||||
SourceCredential_username: AdminUser
|
||||
SourceCredential_password: PasswordForAdminUser
|
||||
|
||||
.. Note:: You should set ``no_log: true`` on the task definition in
|
||||
Ansible to ensure any credentials used are not stored in any log file or
|
||||
console output.
|
||||
|
||||
Simple Type Arrays
|
||||
++++++++++++++++++
|
||||
Simple type arrays like ``[string[]]`` or ``[UInt32[]]`` are defined as a comma
|
||||
separated string which are then cast to their type. For example,
|
||||
to define a simple type array in Ansible::
|
||||
|
||||
# [string[]]
|
||||
ValueData: entry1, entry2, entry3
|
||||
|
||||
# [UInt32[]]
|
||||
ReturnCode: 0,3010
|
||||
|
||||
Run As Another User
|
||||
-------------------
|
||||
By default, DSC runs each resource as the SYSTEM account and not the account
|
||||
that Ansible use to run the module. This means that resources that are dynamically
|
||||
loaded based on a user profile, like the ``HKEY_CURRENT_USER`` registry hive,
|
||||
will be loaded under the ``SYSTEM`` profile. The parameter
|
||||
`PsDscRunAsCredential`` is a parameter that can be set for every DSC resource
|
||||
force the DSC engine to run under a different account. As
|
||||
``PsDscRunAsCredential`` has a type of ``PSCredential``, it is defined with the
|
||||
``_username`` and ``_password`` suffix.
|
||||
|
||||
Using the Registry resource type as an example, this is how to define a task
|
||||
to access the ``HKEY_CURRENT_USER`` hive of the Ansible user::
|
||||
|
||||
- name: use win_dsc with PsDscRunAsCredential to run as a different user
|
||||
win_dsc:
|
||||
resource_name: Registry
|
||||
Ensure: Present
|
||||
Key: HKEY_CURRENT_USER\ExampleKey
|
||||
ValueName: TestValue
|
||||
ValueData: TestData
|
||||
PsDscRunAsCredential_username: '{{ansible_user}}'
|
||||
PsDscRunAsCredential_password: '{{ansible_password}}'
|
||||
no_log: true
|
||||
|
||||
Custom DSC Resources
|
||||
````````````````````
|
||||
DSC resources are not limited to the built-in options from Microsoft. Custom
|
||||
modules can be installed to manage other resources that are not usually available.
|
||||
|
||||
Finding Custom DSC Resources
|
||||
----------------------------
|
||||
You can use the
|
||||
`PSGallery <https://www.powershellgallery.com/>`_ to find custom resources, along with documentation on how to install them on a Windows host.
|
||||
|
||||
The ``Find-DscResource`` cmdlet can also be used to find custom resources. For example:
|
||||
|
||||
.. code-block:: powershell
|
||||
|
||||
# find all DSC resources in the configured repositories
|
||||
Find-DscResource
|
||||
|
||||
# find all DSC resources that relate to SQL
|
||||
Find-DscResource -ModuleName "*sql*"
|
||||
|
||||
.. Note:: DSC resources developed by Microsoft that start with ``x``, means the
|
||||
resource is experimental and comes with no support.
|
||||
|
||||
Installing a Custom Resource
|
||||
----------------------------
|
||||
There are three ways that a DSC resource can be installed on a host:
|
||||
|
||||
* Manually with the ``Install-Module`` cmdlet
|
||||
* Using the ``win_psmodule`` Ansible module
|
||||
* Saving the module manually and copying it another host
|
||||
|
||||
This is an example of installing the ``xWebAdministration`` resources using
|
||||
``win_psmodule``::
|
||||
|
||||
- name: install xWebAdministration DSC resource
|
||||
win_psmodule:
|
||||
name: xWebAdministration
|
||||
state: present
|
||||
|
||||
Once installed, the win_dsc module will be able to use the resource by referencing it
|
||||
with the ``resource_name`` option.
|
||||
|
||||
The first two methods above only work when the host has access to the internet.
|
||||
When a host does not have internet access, the module must first be installed
|
||||
using the methods above on another host with internet access and then copied
|
||||
across. To save a module to a local filepath, the following PowerShell cmdlet
|
||||
can be run::
|
||||
|
||||
Save-Module -Name xWebAdministration -Path C:\temp
|
||||
|
||||
This will create a folder called ``xWebAdministration`` in ``C:\temp`` which
|
||||
can be copied to any host. For PowerShell to see this offline resource, it must
|
||||
be copied to a directory set in the ``PSModulePath`` environment variable.
|
||||
In most cases the path ``C:\Program Files\WindowsPowerShell\Module`` is set
|
||||
through this variable, but the ``win_path`` module can be used to add different
|
||||
paths.
|
||||
|
||||
Examples
|
||||
````````
|
||||
Extract a zip file
|
||||
------------------
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
- name: extract a zip file
|
||||
win_dsc:
|
||||
resource_name: Archive
|
||||
Destination: c:\temp\output
|
||||
Path: C:\temp\zip.zip
|
||||
Ensure: Present
|
||||
|
||||
Create a directory
|
||||
------------------
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
- name: create file with some text
|
||||
win_dsc:
|
||||
resource_name: File
|
||||
DestinationPath: C:\temp\file
|
||||
Contents: |
|
||||
Hello
|
||||
World
|
||||
Ensure: Present
|
||||
Type: File
|
||||
|
||||
- name: create directory that is hidden is set with the System attribute
|
||||
win_dsc:
|
||||
resource_name: File
|
||||
DestinationPath: C:\temp\hidden-directory
|
||||
Attributes: Hidden,System
|
||||
Ensure: Present
|
||||
Type: Directory
|
||||
|
||||
Interact with Azure
|
||||
-------------------
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
- name: install xAzure DSC resources
|
||||
win_psmodule:
|
||||
name: xAzure
|
||||
state: present
|
||||
|
||||
- name: create virtual machine in Azure
|
||||
win_dsc:
|
||||
resource_name: xAzureVM
|
||||
ImageName: a699494373c04fc0bc8f2bb1389d6106__Windows-Server-2012-R2-201409.01-en.us-127GB.vhd
|
||||
Name: DSCHOST01
|
||||
ServiceName: ServiceName
|
||||
StorageAccountName: StorageAccountName
|
||||
InstanceSize: Medium
|
||||
Windows: True
|
||||
Ensure: Present
|
||||
Credential_username: '{{ansible_user}}'
|
||||
Credential_password: '{{ansible_password}}'
|
||||
|
||||
Setup IIS Website
|
||||
-----------------
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
- name: install xWebAdministration module
|
||||
win_psmodule:
|
||||
name: xWebAdministration
|
||||
state: present
|
||||
|
||||
- name: install IIS features that are required
|
||||
win_dsc:
|
||||
resource_name: WindowsFeature
|
||||
Name: '{{item}}'
|
||||
Ensure: Present
|
||||
with_items:
|
||||
- Web-Server
|
||||
- Web-Asp-Net45
|
||||
|
||||
- name: remove Default Web Site
|
||||
win_dsc:
|
||||
resource_name: xWebsite
|
||||
Name: Default Web Site
|
||||
Ensure: Absent
|
||||
|
||||
- name: setup web content
|
||||
win_dsc:
|
||||
resource_name: File
|
||||
DestinationPath: C:\inetpub\IISSite\index.html
|
||||
Type: File
|
||||
Contents: |
|
||||
<html>
|
||||
<head><title>IIS Site</title></head>
|
||||
<body>This is the body</body>
|
||||
</html>
|
||||
Ensure: present
|
||||
|
||||
- name: create new website
|
||||
win_dsc:
|
||||
resource_name: xWebsite
|
||||
Name: NewIISSite
|
||||
State: Started
|
||||
PhysicalPath: C:\inetpub\IISSite\index.html
|
||||
|
||||
.. seealso::
|
||||
|
||||
:doc:`index`
|
||||
The documentation index
|
||||
:doc:`playbooks`
|
||||
An introduction to playbooks
|
||||
:doc:`playbooks_best_practices`
|
||||
Best practices advice
|
||||
`List of Windows Modules <http://docs.ansible.com/list_of_windows_modules.html>`_
|
||||
Windows specific module list, all implemented in PowerShell
|
||||
`User Mailing List <http://groups.google.com/group/ansible-project>`_
|
||||
Have a question? Stop by the google group!
|
||||
`irc.freenode.net <http://irc.freenode.net>`_
|
||||
#ansible IRC chat channel
|
@ -0,0 +1,208 @@
|
||||
Windows Frequently Asked Questions
|
||||
==================================
|
||||
|
||||
Here are some commonly asked questions in regards to Ansible and Windows and
|
||||
their answers.
|
||||
|
||||
.. note:: This document covers questions about managing Microsoft Windows servers with Ansible.
|
||||
For questions about Ansible Core, please see the
|
||||
`FAQ page <http://docs.ansible.com/ansible/latest/faq.html>`_.
|
||||
|
||||
Does Ansible work with Windows XP or Server 2003?
|
||||
``````````````````````````````````````````````````
|
||||
Ansible does not support managing Windows XP or Server 2003 hosts. The
|
||||
supported operating system versions are:
|
||||
|
||||
* Windows Server 2008
|
||||
* Windows Server 2008 R2
|
||||
* Windows Server 2012
|
||||
* Windows Server 2012 R2
|
||||
* Windows Server 2016
|
||||
* Windows 7
|
||||
* Windows 8.1
|
||||
* Windows 10
|
||||
|
||||
Ansible also has minimum PowerShell version requirements - please see
|
||||
:doc:`windows_setup` for the lastest information.
|
||||
|
||||
Can I Manage Windows Nano Server?
|
||||
`````````````````````````````````
|
||||
Windows Nano Server is not currently supported by Ansible, since it does
|
||||
not have access to the full .NET Framework that is used by the majority of the
|
||||
modules and internal components.
|
||||
|
||||
Can Ansible run on Windows?
|
||||
```````````````````````````
|
||||
No, Ansible cannot run on a Windows host and can only manage Windows hosts, but
|
||||
Ansible can be run under the Windows Subsystem for Linux (WSL).
|
||||
|
||||
.. note:: The Windows Subsystem for Linux is not supported by Microsoft or
|
||||
Ansible and should not be used for production systems.
|
||||
|
||||
To install Ansible on WSL, the following commands
|
||||
can be run in the bash terminal:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
sudo apt-get update
|
||||
sudo apt-get install python-pyp git libffi-dev libssl-dev -y
|
||||
pip install ansible pywinrm
|
||||
|
||||
To run Ansible from source instead of a release on the WSL, simply uninstall the pip
|
||||
installed version and then clone the git repo.
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
pip uninstall ansible -y
|
||||
git clone https://github.com/ansible/ansible.git
|
||||
source ansible/hacking/env-setup
|
||||
|
||||
# to enable Ansible on login, run the following
|
||||
echo ". ~/ansible/hacking/env-setup -q' >> ~/.bashrc
|
||||
|
||||
Can I use SSH keys to authenticate?
|
||||
```````````````````````````````````
|
||||
Windows uses WinRM as the transport protocol. WinRM supports a wide range of
|
||||
authentication options. The closet option to SSH keys is to use the certificate
|
||||
authentication option which maps an X509 certificate to a local user.
|
||||
|
||||
The way that these certificates are generated and mapped to a user is different
|
||||
from the SSH implementation; consult the :doc:`windows_winrm` documentation for
|
||||
more information.
|
||||
|
||||
Why can I run a command locally that does not work under Ansible?
|
||||
`````````````````````````````````````````````````````````````````
|
||||
Ansible executes commands through WinRM. These processes are different from
|
||||
running a command locally in these ways:
|
||||
|
||||
* Unless using an authentication option like CredSSP or Kerberos with
|
||||
credential delegation, the WinRM process does not have the ability to
|
||||
delegate the user's credentials to a network resource, causing ``Access is
|
||||
Denied`` errors.
|
||||
|
||||
* All processes run under WinRM are in a non-interactive session. Applications
|
||||
that require an interactive session will not work.
|
||||
|
||||
* When running through WinRM, Windows restricts access to internal Windows
|
||||
APIs like the Windows Update API and DPAPI, which some installers and
|
||||
programs rely on.
|
||||
|
||||
Some ways to bypass these restrictions are to:
|
||||
|
||||
* Use ``become``, which runs a command as it would when run locally. This will
|
||||
bypass most WinRM restrictions, as Windows is unaware the process is running
|
||||
under WinRM when ``become`` is used. See the :doc:`become` documentation for more
|
||||
information.
|
||||
|
||||
* Use a scheduled task, which can be created with ``win_scheduled_task``. Like
|
||||
``become``, it will bypass all WinRM restrictions, but it can only be used to run
|
||||
commands, not modules.
|
||||
|
||||
* Use ``win_psexec`` to run a command on the host. PSExec does not use WinRM
|
||||
and so will bypass any of the restrictions.
|
||||
|
||||
* To access network resources without any of these workarounds, an
|
||||
authentication option that supports credential delegation can be used. Both
|
||||
CredSSP and Kerberos with credential delegation enabled can support this.
|
||||
|
||||
See :doc:`become` more info on how to use become. The limitations section at
|
||||
:doc:`windows_winrm` has more details around WinRM limitations.
|
||||
|
||||
This program won't install with Ansible
|
||||
```````````````````````````````````````
|
||||
See `the question <http://docs.ansible.com/ansible/latest/windows_faq.html#i-can-run-this-command-locally-but-it-does-not-work-under-ansible>`_ for more information about WinRM limitations.
|
||||
|
||||
What modules are available?
|
||||
```````````````````````````
|
||||
Most of the Ansible modules in Ansible Core are written for a combination of
|
||||
Linux/Unix machines and arbitrary web services. These modules are written in
|
||||
Python and most of them do not work on Windows.
|
||||
|
||||
Because of this, there are dedicated Windows modules that are written in
|
||||
PowerShell and are meant to be run on Windows hosts. A list of this modules
|
||||
can be found `here <http://docs.ansible.com/list_of_windows_modules.html>`_.
|
||||
|
||||
In addition, the following Ansible Core modules/action-plugins work with Windows:
|
||||
|
||||
* add_host
|
||||
* assert
|
||||
* async_status
|
||||
* debug
|
||||
* fail
|
||||
* fetch
|
||||
* group_by
|
||||
* include
|
||||
* include_role
|
||||
* include_vars
|
||||
* meta
|
||||
* pause
|
||||
* raw
|
||||
* script
|
||||
* set_fact
|
||||
* set_stats
|
||||
* setup
|
||||
* slurp
|
||||
* template (also: win_tempate)
|
||||
* wait_for_connection
|
||||
|
||||
Can I run Python modules?
|
||||
`````````````````````````
|
||||
No, the WinRM connection protocol is set to use PowerShell modules, so Python
|
||||
modules will not work. A way to bypass this issue to use
|
||||
``delegate_to: localhost`` to run a Python module on the Ansible controller.
|
||||
This is useful if during a playbook, an external service needs to be contacted
|
||||
and there is no equivalent Windows module available.
|
||||
|
||||
Can I connect over SSH?
|
||||
```````````````````````
|
||||
Microsoft has announced and is developing a fork of OpenSSH for Windows that
|
||||
allows remote manage of Windows servers through the SSH protocol instead of
|
||||
WinRM. While this can be installed and used right now for normal SSH clients,
|
||||
it is still in beta from Microsoft and the required functionality has not been
|
||||
developed within Ansible yet.
|
||||
|
||||
There are future plans on adding this feature and this page will be updated
|
||||
once more information can be shared.
|
||||
|
||||
Why is connecting to the host via ssh failing?
|
||||
``````````````````````````````````````````````
|
||||
When trying to connect to a Windows host and the output error indicates that
|
||||
SSH was used, then this is an indication that the connection vars are not set
|
||||
properly or the host is not inheriting them correctly.
|
||||
|
||||
Make sure ``ansible_connection: winrm`` is set in the inventory for the Windows
|
||||
host.
|
||||
|
||||
Why are my credentials are being rejected?
|
||||
``````````````````````````````````````````
|
||||
This can be due to a myriad of reasons unrelated to incorrect credentials.
|
||||
|
||||
See HTTP 401/Credentials Rejected at :doc:`windows_setup` for a more detailed
|
||||
guide of this could mean.
|
||||
|
||||
Why am I getting an error SSL CERTIFICATE_VERIFY_FAILED?
|
||||
````````````````````````````````````````````````````````
|
||||
When the Ansible controller is running on Python 2.7.9+ or an older version of Python that
|
||||
has backported SSLContext (like Python 2.7.5 on RHEL 7), the controller will attempt to
|
||||
validate the certificate WinRM is using for an HTTPS connection. If the
|
||||
certificate cannot be validated (such as in the case of a self signed cert), it will
|
||||
fail the verification process.
|
||||
|
||||
To ignore certificate validation, add
|
||||
``ansible_winrm_server_cert_validation: ignore`` to inventory for the Windows
|
||||
host.
|
||||
|
||||
.. seealso::
|
||||
|
||||
:doc:`index`
|
||||
The documentation index
|
||||
:doc:`windows`
|
||||
The Windows documentation index
|
||||
:doc:`playbooks`
|
||||
An introduction to playbooks
|
||||
:doc:`playbooks_best_practices`
|
||||
Best practices advice
|
||||
`User Mailing List <http://groups.google.com/group/ansible-project>`_
|
||||
Have a question? Stop by the google group!
|
||||
`irc.freenode.net <http://irc.freenode.net>`_
|
||||
#ansible IRC chat channel
|
@ -0,0 +1,455 @@
|
||||
Setting up a Windows Host
|
||||
=========================
|
||||
This document discusses the setup that is required before Ansible can communicate with a Microsoft Windows host.
|
||||
|
||||
.. contents:: Topics
|
||||
|
||||
Host Requirements
|
||||
`````````````````
|
||||
For Ansible to communicate to a Windows host and use Windows modules, the
|
||||
Windows host must meet the following requirements:
|
||||
|
||||
* Ansible's supported Windows versions generally match those under current
|
||||
and extended support from Microsoft. Supported desktop OSs include
|
||||
Windows 7, 8.1, and 10, and supported server OSs are Windows Server 2008,
|
||||
2008 R2, 2012, 2012 R2, and 2016.
|
||||
|
||||
* Ansible requires PowerShell 3.0 or newer and at least .NET 4.0 to be
|
||||
installed on the Windows host.
|
||||
|
||||
* A WinRM listener should be created and activated. More details for this can be
|
||||
found below.
|
||||
|
||||
.. Note:: While these are the base requirements for Ansible connectivity, some Ansible
|
||||
modules have additional requirements, such as a newer OS or PowerShell
|
||||
version. Please consult the module's documentation page
|
||||
to determine whether a host meets those requirements.
|
||||
|
||||
Upgrading PowerShell and .NET Framework
|
||||
---------------------------------------
|
||||
Ansible requires PowerShell version 3.0 and .NET Framework 4.0 or newer to function on older operating systems like Server 2008 and Windows 7. The base image does not meet this
|
||||
requirement. You can use the `Upgrade-PowerShell.ps1 <https://github.com/jborean93/ansible-windows/blob/master/scripts/Upgrade-PowerShell.ps1>`_ script to update these.
|
||||
|
||||
This is an example of how to run this script from PowerShell:
|
||||
|
||||
.. code-block:: powershell
|
||||
|
||||
$url = "https://raw.githubusercontent.com/jborean93/ansible-windows/master/scripts/Upgrade-PowerShell.ps1"
|
||||
$file = "$env:SystemDrive\temp\Upgrade-PowerShell.ps1"
|
||||
$username = "Administrator"
|
||||
$password = "Password"
|
||||
|
||||
(New-Object -TypeName System.Net.WebClient).DownloadFile($url, $file)
|
||||
Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Force
|
||||
|
||||
# version can be 3.0, 4.0 or 5.1
|
||||
&$file -Version 5.1 -Username $username -Password $password -Verbose
|
||||
|
||||
Once completed, you will need to remove auto logon
|
||||
and set the execution policy back to the default of ``Restricted``. You can
|
||||
do this with the following PowerShell commands:
|
||||
|
||||
.. code-block:: powershell
|
||||
|
||||
# this isn't needed but is a good security practice to complete
|
||||
Set-ExecutionPolicy -ExecutionPolicy Restricted -Force
|
||||
|
||||
$reg_winlogon_path = "HKLM:\Software\Microsoft\Windows NT\CurrentVersion\Winlogon"
|
||||
Set-ItemProperty -Path $reg_winlogon_path -Name AutoAdminLogon -Value 0
|
||||
Remove-ItemProperty -Path $reg_winlogon_path -Name DefaultUserName -ErrorAction SilentlyContinue
|
||||
Remove-ItemProperty -Path $reg_winlogon_path -Name DefaultPassword -ErrorAction SilentlyContinue
|
||||
|
||||
The script works by checking to see what programs need to be installed
|
||||
(such as .NET Framework 4.5.2) and what PowerShell version is required. If a reboot
|
||||
is required and the ``username`` and ``password`` parameters are set, the
|
||||
script will automatically reboot and logon when it comes back up from the
|
||||
reboot. The script will continue until no more actions are required and the
|
||||
PowerShell version matches the target version. If the ``username`` and
|
||||
``password`` parameters are not set, the script will prompt the user to
|
||||
manually reboot and logon when required. When the user is next logged in, the
|
||||
script will continue where it left off and the process continues until no more
|
||||
actions are required.
|
||||
|
||||
.. Note:: If running on Server 2008, then SP2 must be installed. If running on
|
||||
Server 2008 R2 or Windows 7, then SP1 must be installed.
|
||||
|
||||
.. Note:: Windows Server 2008 can only install PowerShell 3.0; specifying a
|
||||
newer version will result in the script failing.
|
||||
|
||||
.. Note:: The ``username`` and ``password`` parameters are stored in plain text
|
||||
in the registry. Make sure the cleanup commands are run after the script finishes
|
||||
to ensure no credentials are still stored on the host.
|
||||
|
||||
WinRM Memory Hotfix
|
||||
-------------------
|
||||
When running on PowerShell v3.0, there is a bug with the WinRM service that
|
||||
limits the amount of memory available to WinRM. Without this hotfix installed,
|
||||
Ansible will fail to execute certain commands on the Windows host. These
|
||||
hotfixes should installed as part of the system bootstapping or
|
||||
imaging process. The script `Install-WMF3Hotfix.ps1 <https://github.com/jborean93/ansible-windows/blob/master/scripts/Install-WMF3Hotfix.ps1>`_ can be used to install the hotfix on affected hosts.
|
||||
|
||||
The following PowerShell command will install the hotfix:
|
||||
|
||||
.. code-block:: powershell
|
||||
|
||||
$url = "https://raw.githubusercontent.com/jborean93/ansible-windows/master/scripts/Install-WMF3Hotfix.ps1"
|
||||
$file = "$env:SystemDrive\temp\Install-WMF3Hotfix.ps1"
|
||||
|
||||
(New-Object -TypeName System.Net.WebClient).DownloadFile($url, $file)
|
||||
powershell.exe -ExecutionPolicy ByPass -File $file -Verbose
|
||||
|
||||
WinRM Setup
|
||||
```````````
|
||||
Once Powershell has been upgraded to at least version 3.0, the final step is for the
|
||||
WinRM service to be configured so that Ansible can connect to it. There are two
|
||||
main components of the WinRM service that governs how Ansible can interface with
|
||||
the Windows host: the ``listener`` and the ``service`` configuration settings.
|
||||
|
||||
Details about each component can be read below, but the script
|
||||
`ConfigureRemotingForAnsible.ps1 <https://github.com/ansible/ansible/blob/devel/examples/scripts/ConfigureRemotingForAnsible.ps1>`_
|
||||
can be used to set up the basics. This script sets up both HTTP and HTTPS
|
||||
listeners with a self-signed certificate and enables the ``Basic``
|
||||
authentication option on the service.
|
||||
|
||||
To use this script, run the following in PowerShell:
|
||||
|
||||
.. code-block:: powershell
|
||||
|
||||
$url = "https://raw.githubusercontent.com/ansible/ansible/devel/examples/scripts/ConfigureRemotingForAnsible.ps1"
|
||||
$file = "$env:SystemDrive\temp\ConfigureRemotingForAnsible.ps1"
|
||||
|
||||
(New-Object -TypeName System.Net.WebClient).DownloadFile($url, $file)
|
||||
|
||||
powershell.exe -ExecutionPolicy ByPass -File $file
|
||||
|
||||
There are different switches and parameters (like ``-EnableCredSSP`` and
|
||||
``-ForceNewSSLCert``) that can be set alongside this script. The documentation
|
||||
for these options are located at the top of the script itself.
|
||||
|
||||
.. Note:: The ConfigureRemotingForAnsible.ps1 script is intended for training and
|
||||
development purposes only and should not be used in a
|
||||
production environment, since it enables settings (like ``Basic`` authentication)
|
||||
that can be inherently insecure.
|
||||
|
||||
WinRM Listener
|
||||
--------------
|
||||
The WinRM services listens for requests on one or more ports. Each of these ports must have a
|
||||
listener created and configured.
|
||||
|
||||
To view the current listeners that are running on the WinRM service, run the
|
||||
following command::
|
||||
|
||||
winrm enumerate winrm/config/Listeners
|
||||
|
||||
This will output something like the following::
|
||||
|
||||
Listener
|
||||
Address = *
|
||||
Transport = HTTP
|
||||
Port = 5985
|
||||
Hostname
|
||||
Enabled = true
|
||||
URLPrefix = wsman
|
||||
CertificateThumbprint
|
||||
ListeningOn = 10.0.2.15, 127.0.0.1, 192.168.56.155, ::1, fe80::5efe:10.0.2.15%6, fe80::5efe:192.168.56.155%8, fe80::
|
||||
ffff:ffff:fffe%2, fe80::203d:7d97:c2ed:ec78%3, fe80::e8ea:d765:2c69:7756%7
|
||||
|
||||
Listener
|
||||
Address = *
|
||||
Transport = HTTPS
|
||||
Port = 5986
|
||||
Hostname = SERVER2016
|
||||
Enabled = true
|
||||
URLPrefix = wsman
|
||||
CertificateThumbprint = E6CDAA82EEAF2ECE8546E05DB7F3E01AA47D76CE
|
||||
ListeningOn = 10.0.2.15, 127.0.0.1, 192.168.56.155, ::1, fe80::5efe:10.0.2.15%6, fe80::5efe:192.168.56.155%8, fe80::
|
||||
ffff:ffff:fffe%2, fe80::203d:7d97:c2ed:ec78%3, fe80::e8ea:d765:2c69:7756%7
|
||||
|
||||
In the example above there are two listeners activated; one is listening on
|
||||
port 5985 over HTTP and the other is listening on port 5986 over HTTPS. Some of
|
||||
the key options that are useful to understand are:
|
||||
|
||||
* ``Transport``: Whether the listener is run over HTTP or HTTPS, it is
|
||||
recommended to use a listener over HTTPS as the data is encrypted without
|
||||
any further changes required.
|
||||
|
||||
* ``Port``: The port the listener runs on, by default it is ``5985`` for HTTP
|
||||
and ``5986`` for HTTPS. This port can be changed to whatever is required and
|
||||
corresponds to the host var ``ansible_port``.
|
||||
|
||||
* ``URLPrefix``: The URL prefix to listen on, by default it is ``wsman``. If
|
||||
this is changed, the host var ``ansible_winrm_path`` must be set to the same
|
||||
value.
|
||||
|
||||
* ``CertificateThumbprint``: If running over an HTTPS listener, this is the
|
||||
thumbprint of the certificate in the Windows Certificate Store that is used
|
||||
in the connection. To get the details of the certificate itself, run this
|
||||
command with the relevant certificate thumbprint in PowerShell:
|
||||
|
||||
.. code-block:: powershell
|
||||
|
||||
$thumbprint = "E6CDAA82EEAF2ECE8546E05DB7F3E01AA47D76CE"
|
||||
Get-ChildItem -Path cert:\LocalMachine\My -Recurse | Where-Object { $_.Thumbprint -eq $thumbprint } | Select-Object *
|
||||
|
||||
Setup WinRM Listener
|
||||
++++++++++++++++++++
|
||||
There are three ways to set up a WinRM listener:
|
||||
|
||||
* Using ``winrm quickconfig`` for HTTP or
|
||||
``winrm quickconfig -transport:https`` for HTTPS. This is the easiest option
|
||||
to use when running outside of a domain environment and a simple listener is
|
||||
required. Unlike the other options, this process also has the added benefit of
|
||||
opening up the Firewall for the ports required and starts the WinRM service.
|
||||
|
||||
* Using Group Policy Objects. This is the best way to create a listener when the
|
||||
host is a member of a domain because the configuration is done automatically
|
||||
without any user input. For more information on group policy objects, see the
|
||||
`Group Policy Objects documentation <https://msdn.microsoft.com/en-us/library/aa374162(v=vs.85).aspx>`_.
|
||||
|
||||
* Using PowerShell to create the listener with a specific configuration. This
|
||||
can be done by running the following PowerShell commands:
|
||||
|
||||
.. code-block:: powershell
|
||||
|
||||
$selector_set = @{
|
||||
Address = "*"
|
||||
Transport = "HTTPS"
|
||||
}
|
||||
$value_set = @{
|
||||
CertificateThumbprint = "E6CDAA82EEAF2ECE8546E05DB7F3E01AA47D76CE"
|
||||
}
|
||||
|
||||
New-WSManInstance -ResourceURI "winrm/config/Listener" -SelectorSet $selector_set -ValueSet $value_set
|
||||
|
||||
To see the other options with this PowerShell cmdlet, see
|
||||
`New-WSManInstance <https://docs.microsoft.com/en-us/powershell/module/microsoft.wsman.management/new-wsmaninstance?view=powershell-5.1>`_.
|
||||
|
||||
.. Note:: When creating an HTTPS listener, an existing certificate needs to be
|
||||
created and stored in the ``LocalMachine\My`` certificate store. Without a
|
||||
certificate being present in this store, most commands will fail.
|
||||
|
||||
Delete WinRM Listener
|
||||
+++++++++++++++++++++
|
||||
To remove a WinRM listener:
|
||||
|
||||
.. code-block: powershell
|
||||
|
||||
# remove all listeners
|
||||
Remove-Item -Path WSMan:\localhost\Listener\* -Recurse -Force
|
||||
|
||||
# only remove listeners that are run over HTTPS
|
||||
Get-ChildItem -Path WSMan:\localhost\Listener | Where-Object { $_.Keys -contains "Transport=HTTPS" } | Remove-Item -Recurse -Force
|
||||
|
||||
.. Note:: The ``Keys`` object is an array of strings, so it can contain different
|
||||
values. By default it contains a key for ``Transport=`` and ``Address=``
|
||||
which correspond to the values from winrm enumerate winrm/config/Listeners.
|
||||
|
||||
WinRM Service Options
|
||||
---------------------
|
||||
There are a number of options that can be set to control the behavior of the WinRM service component,
|
||||
including authentication options and memory settings.
|
||||
|
||||
To get an output of the current service configuration options, run the
|
||||
following command::
|
||||
|
||||
winrm get winrm/config/Service
|
||||
winrm get winrm/config/Winrs
|
||||
|
||||
This will output something like the following::
|
||||
|
||||
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 = true
|
||||
CredSSP = true
|
||||
CbtHardeningLevel = Relaxed
|
||||
DefaultPorts
|
||||
HTTP = 5985
|
||||
HTTPS = 5986
|
||||
IPv4Filter = *
|
||||
IPv6Filter = *
|
||||
EnableCompatibilityHttpListener = false
|
||||
EnableCompatibilityHttpsListener = false
|
||||
CertificateThumbprint
|
||||
AllowRemoteAccess = true
|
||||
|
||||
Winrs
|
||||
AllowRemoteShellAccess = true
|
||||
IdleTimeout = 7200000
|
||||
MaxConcurrentUsers = 2147483647
|
||||
MaxShellRunTime = 2147483647
|
||||
MaxProcessesPerShell = 2147483647
|
||||
MaxMemoryPerShellMB = 2147483647
|
||||
MaxShellsPerUser = 2147483647
|
||||
|
||||
While many of these options should rarely be changed, a few can easily impact
|
||||
the operations over WinRM and are useful to understand. Some of the important
|
||||
options are:
|
||||
|
||||
* ``Service\AllowUnencrypted``: This option defines whether WinRM will allow
|
||||
traffic that is run over HTTP without message encryption. Message level
|
||||
encryption is only supported when ``ansible_winrm_transport`` is ``ntlm``,
|
||||
``kerberos`` or ``credssp``. By default this is ``false`` and should only be
|
||||
set to ``true`` when debugging WinRM messages.
|
||||
|
||||
* ``Service\Auth\*``: These flags define what authentication
|
||||
options are allowed with the WinRM service. By default, ``Negotiate (NTLM)``
|
||||
and ``Kerberos`` are enabled.
|
||||
|
||||
* ``Service\Auth\CbtHardeningLevel``: Specifies whether channel binding tokens are
|
||||
not verified (None), verified but not required (Relaxed), or verified and
|
||||
required (Strict). CBT is only used when connecting with NTLM or Kerberos
|
||||
over HTTPS. The downstream libraries that Ansible currently uses only support
|
||||
passing the CBT with NTLM authentication. Using Kerberos with
|
||||
``CbtHardeningLevel = Strict`` will result in a ``404`` error.
|
||||
|
||||
* ``Service\CertificateThumbprint``: This is the thumbprint of the certificate
|
||||
used to encrypt the TLS channel used with CredSSP authentication. By default
|
||||
this is empty; a self-signed certificate is generated when the WinRM service
|
||||
starts and is used in the TLS process.
|
||||
|
||||
* ``Winrs\MaxShellRunTime``: This is the maximum time, in milliseconds, that a
|
||||
remote command is allowed to execute.
|
||||
|
||||
* ``Winrs\MaxMemoryPerShellMB``: This is the maximum amount of memory allocated
|
||||
per shell, including the shell's child processes.
|
||||
|
||||
To modify a setting under the ``Service`` key in PowerShell, the following
|
||||
command can be used:
|
||||
|
||||
.. code-block:: powershell
|
||||
|
||||
# substitute {path} with the path to the option after winrm/config/Service
|
||||
Set-Item -Path WSMan:\localhost\Service\{path} -Value "value here"
|
||||
|
||||
# for example, to change Service\Auth\CbtHardeningLevel run
|
||||
Set-Item -Path WSMan:\localhost\Service\Auth\CbtHardeningLevel -Value Strict
|
||||
|
||||
To modify a setting under the ``Winrs`` key in PowerShell, the following
|
||||
command can be used:
|
||||
|
||||
.. code-block:: powershell
|
||||
|
||||
# substitute {path} with the path to the option after winrm/config/Winrs
|
||||
Set-Item -Path WSMan:\localhost\Shell\{path} -Value "value here"
|
||||
|
||||
# for example, to change Winrs\MaxShellRunTime run
|
||||
Set-Item -Path WSMan:\localhost\Shell\MaxShellRunTime -Value 2147483647
|
||||
|
||||
.. Note:: If running in a domain environment, some of these options are set by
|
||||
GPO and cannot be changed on the host itself. When a key has been
|
||||
configured with GPO, it contains the text ``[Source="GPO"]`` next to the value.
|
||||
|
||||
Common WinRM Issues
|
||||
-------------------
|
||||
Because WinRM has a wide range of configuration options, it can be difficult
|
||||
to setup and configure. Because of this complexity, issues that are shown by Ansible
|
||||
could in fact be issues with the host setup instead.
|
||||
|
||||
One easy way to determine whether a problem is a host issue is to
|
||||
run the following command from another Windows host to connect to the
|
||||
target Windows host::
|
||||
|
||||
# test out HTTP
|
||||
winrs -r:http://server:5985/wsman -u:Username -p:Password ipconfig
|
||||
|
||||
# test out HTTPS (will fail if the cert is not verifiable)
|
||||
winrs -r:http://server:5985/wsman -u:Username -p:Password -ssl ipconfig
|
||||
|
||||
# test out HTTPS, ignoring certificate verification
|
||||
$username = "Username"
|
||||
$password = ConvertTo-SecureString -String "Password" -AsPlainText -Force
|
||||
$cred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $username, $password
|
||||
|
||||
$session_option = New-PSSessionOption -SkipCACheck -SkipCNCheck -SkipRevocationCheck
|
||||
Invoke-Command -ComputerName server -UseSSL -ScriptBlock { ipconfig } -Credential $cred -SessionOption $session_option
|
||||
|
||||
If this fails, the issue is probably related to the WinRM setup. If it works, the issue may not be related to the WinRM setup; please continue reading for more troubleshooting suggestions.
|
||||
|
||||
HTTP 401/Credentials Rejected
|
||||
+++++++++++++++++++++++++++++
|
||||
A HTTP 401 error indicates the authentication process failed during the initial
|
||||
connection. Some things to check for this are:
|
||||
|
||||
* Verify that the credentials are correct and set properly in your inventory with
|
||||
``ansible_user`` and ``ansible_password``
|
||||
|
||||
* Ensure that the user is a member of the local Administrators group or has been explicitly
|
||||
granted access (a connection test with the ``winrs`` command can be used to
|
||||
rule this out).
|
||||
|
||||
* Make sure that the authentication option set by ``ansible_winrm_transport`` is enabled under
|
||||
``Service\Auth\*``
|
||||
|
||||
* If running over HTTP and not HTTPS, use ``ntlm``, ``kerberos`` or ``credssp``
|
||||
with ``ansible_winrm_message_encryption: auto`` to enable message encryption.
|
||||
If using another authentication option or if the installed pywinrm version cannot be
|
||||
upgraded, the ``Service\AllowUnencrypted`` can be set to ``true`` but this is
|
||||
only recommended for troubleshooting
|
||||
|
||||
* Ensure the downstream packages ``pywinrm``, ``requests-ntlm``,
|
||||
``requests-kerberos``, and/or ``requests-credssp`` are up to date using ``pip``.
|
||||
|
||||
* If using Kerberos authentication, ensure that ``Service\Auth\CbtHardeningLevel`` is
|
||||
not set to ``Strict``.
|
||||
|
||||
* When using Basic or Certificate authentication, make sure that the user is a local account and
|
||||
not a domain account. Domain accounts do not work with Basic and Certificate
|
||||
authentication.
|
||||
|
||||
HTTP 500 Error
|
||||
++++++++++++++
|
||||
These indicate an error has occured with the WinRM service. Some things
|
||||
to check for include:
|
||||
|
||||
* Verify that the number of current open shells has not exceeded either
|
||||
``WinRsMaxShellsPerUser`` or any of the other Winrs quotas haven't been
|
||||
exceeded.
|
||||
|
||||
Timeout Errors
|
||||
+++++++++++++++
|
||||
These usually indicate an error with the network connection where
|
||||
Ansible is unable to reach the host. Some things to check for include:
|
||||
|
||||
* Make sure the firewall is not set to block the configured WinRM listener ports
|
||||
* Ensure that a WinRM listener is enabled on the port and path set by the host vars
|
||||
* Ensure that the ``winrm`` service is running on the Windows host and configured for
|
||||
automatic start
|
||||
|
||||
Connection Refused Errors
|
||||
+++++++++++++++++++++++++
|
||||
These usually indicate an error when trying to communicate with the
|
||||
WinRM service on the host. Some things to check for:
|
||||
|
||||
* Ensure that the WinRM service is up and running on the host. Use
|
||||
``(Get-Service -Name winrm).Status`` to get the status of the service.
|
||||
* Check that the host firewall is allowing traffic over the WinRM port. By default
|
||||
this is ``5985`` for HTTP and ``5986`` for HTTPS.
|
||||
|
||||
Sometimes an installer may restart the WinRM or HTTP service and cause this error. The
|
||||
best way to deal with this is to use ``win_psexec`` from another
|
||||
Windows host.
|
||||
|
||||
.. seealso::
|
||||
|
||||
:doc:`index`
|
||||
The documentation index
|
||||
:doc:`playbooks`
|
||||
An introduction to playbooks
|
||||
:doc:`playbooks_best_practices`
|
||||
Best practices advice
|
||||
`List of Windows Modules <http://docs.ansible.com/list_of_windows_modules.html>`_
|
||||
Windows specific module list, all implemented in PowerShell
|
||||
`User Mailing List <http://groups.google.com/group/ansible-project>`_
|
||||
Have a question? Stop by the google group!
|
||||
`irc.freenode.net <http://irc.freenode.net>`_
|
||||
#ansible IRC chat channel
|
@ -0,0 +1,491 @@
|
||||
Using Ansible and Windows
|
||||
=========================
|
||||
When using Ansible to manage Windows, many of the syntax and rules that apply
|
||||
for Unix/Linux hosts also apply to Windows, but there are still some differences
|
||||
when it comes to components like path separators and OS-specific tasks.
|
||||
This document covers details specific to using Ansible for Windows.
|
||||
|
||||
.. contents:: Topics
|
||||
|
||||
Use Cases
|
||||
`````````
|
||||
Ansible can be used to orchestrate a multitude of tasks on Windows servers.
|
||||
Below are some examples and info about common tasks.
|
||||
|
||||
Installing Software
|
||||
-------------------
|
||||
There are three main ways that Ansible can be used to install software:
|
||||
|
||||
* Using the ``win_chocolatey`` module. This sources the program data from the default
|
||||
public `Chocolatey <https://chocolatey.org/>`_ repository. Internal repositories can
|
||||
be used instead by setting the ``source`` option.
|
||||
|
||||
* Using the ``win_package`` module. This installs software using an MSI or .exe installer
|
||||
from a local/network path or URL.
|
||||
|
||||
* Using the ``win_command`` or ``win_shell`` module to run an installer manually.
|
||||
|
||||
The ``win_chocolatey`` module is recommended since it has the most complete logic for checking to see if a package has already been installed and is up-to-date.
|
||||
|
||||
Below are some examples of using all three options to install 7-Zip::
|
||||
|
||||
# install/uninstall with chocolatey
|
||||
- name: ensure 7-Zip is installed via Chocolatey
|
||||
win_chocolatey:
|
||||
name: 7zip
|
||||
state: present
|
||||
|
||||
- name: ensure 7-Zip is not installed via Chocolatey
|
||||
win_chocolatey:
|
||||
name: 7zip
|
||||
state: absent
|
||||
|
||||
# install/uninstall with win_package
|
||||
- name: download the 7-Zip package
|
||||
win_get_url:
|
||||
url: http://www.7-zip.org/a/7z1701-x64.msi
|
||||
dest: C:\temp\7z.msi
|
||||
|
||||
- name: ensure 7-Zip is installed via win_package
|
||||
win_package:
|
||||
path: C:\temp\7z.msi
|
||||
state: present
|
||||
|
||||
- name: ensure 7-Zip is not installed via win_package
|
||||
win_package:
|
||||
path: C:\temp\7z.msi
|
||||
state: absent
|
||||
|
||||
# install/uninstall with win_command
|
||||
- name: download the 7-Zip package
|
||||
win_get_url:
|
||||
url: http://www.7-zip.org/a/7z1701-x64.msi
|
||||
dest: C:\temp\7z.msi
|
||||
|
||||
- name: check if 7-Zip is already installed
|
||||
win_reg_stat:
|
||||
name: HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{23170F69-40C1-2702-1701-000001000000}
|
||||
register: 7zip_installed
|
||||
|
||||
- name: ensure 7-Zip is installed via win_command
|
||||
win_command: C:\Windows\System32\msiexec.exe /i C:\temp\7z.msi /qn /norestart
|
||||
when: 7zip_installed.exists == False
|
||||
|
||||
- name: ensure 7-Zip is uninstalled via win_command
|
||||
win_command: C:\Windows\System32\msiexec.exe /x {23170F69-40C1-2702-1701-000001000000} /qn /norestart
|
||||
when: 7zip_installed.exists == True
|
||||
|
||||
Some installers like Microsoft Office or SQL Server require credential delegation or
|
||||
access to components restricted by WinRM. The best method to bypass these
|
||||
issues is to use ``become`` with the task. With ``become``, Ansible will run
|
||||
the installer as if it were run interactively on the host.
|
||||
|
||||
.. Note:: Many installers do not properly pass back error information over WinRM. In these cases, if the install has been verified to work locally the recommended method is to use become.
|
||||
|
||||
.. Note:: Some installers restart the WinRM or HTTP services, or cause them to become temporarily unavailable, making Ansible assume the system is unreachable.
|
||||
|
||||
Installing Updates
|
||||
------------------
|
||||
The ``win_updates`` and ``win_hotfix`` modules can be used to install updates
|
||||
or hotfixes on a host. The module ``win_updates`` is used to install multiple
|
||||
updates by category, while ``win_hotfix`` can be used to install a single
|
||||
update or hotfix file that has been downloaded locally.
|
||||
|
||||
.. Note:: The ``win_hotfix`` module has a requirement that the DISM PowerShell cmdlets are
|
||||
present. These cmdlets were only added by default on Windows Server 2012
|
||||
and newer and must be installed on older Windows hosts.
|
||||
|
||||
The following example shows how ``win_updates`` can be used::
|
||||
|
||||
- name: install all critical and security updates
|
||||
win_updates:
|
||||
category_names:
|
||||
- CriticalUpdates
|
||||
- SecurityUpdates
|
||||
state: installed
|
||||
register: update_result
|
||||
|
||||
- name: reboot host if required
|
||||
win_reboot:
|
||||
when: update_result.reboot_required
|
||||
|
||||
The following example show how ``win_hotfix`` can be used to install a single
|
||||
update or hotfix::
|
||||
|
||||
- name: download KB3172729 for Server 2012 R2
|
||||
win_get_url:
|
||||
url: http://download.windowsupdate.com/d/msdownload/update/software/secu/2016/07/windows8.1-kb3172729-x64_e8003822a7ef4705cbb65623b72fd3cec73fe222.msu
|
||||
dest: C:\temp\KB3172729.msu
|
||||
|
||||
- name: install hotfix
|
||||
win_hotfix:
|
||||
hotfix_kb: KB3172729
|
||||
source: C:\temp\KB3172729.msu
|
||||
state: present
|
||||
register: hotfix_result
|
||||
|
||||
- name: reboot host if required
|
||||
win_reboot:
|
||||
when: hotfix_result.reboot_required
|
||||
|
||||
Set Up Users and Groups
|
||||
-----------------------
|
||||
Ansible can be used to create Windows users and groups both locally and on a domain.
|
||||
|
||||
Local
|
||||
+++++
|
||||
The modules ``win_user``, ``win_group`` and ``win_group_membership`` manage
|
||||
Windows users, groups and group memberships locally.
|
||||
|
||||
The following is an example of creating local accounts and groups that can
|
||||
access a folder on the same host::
|
||||
|
||||
- name: create local group to contain new users
|
||||
win_group:
|
||||
name: LocalGroup
|
||||
description: Allow access to C:\Development folder
|
||||
|
||||
- name: create local user
|
||||
win_user:
|
||||
name: '{{item.name}}'
|
||||
password: '{{item.password}}'
|
||||
groups: LocalGroup
|
||||
update_password: no
|
||||
password_never_expired: yes
|
||||
with_items:
|
||||
- name: User1
|
||||
password: Password1
|
||||
- name: User2
|
||||
password: Password2
|
||||
|
||||
- name: create Development folder
|
||||
win_file:
|
||||
path: C:\Development
|
||||
state: directory
|
||||
|
||||
- name: set ACL of Development folder
|
||||
win_acl:
|
||||
path: C:\Development
|
||||
rights: FullControl
|
||||
state: present
|
||||
type: allow
|
||||
user: LocalGroup
|
||||
|
||||
- name: remove parent inheritance of Development folder
|
||||
win_acl_inheritance:
|
||||
path: C:\Development
|
||||
reorganize: yes
|
||||
state: absent
|
||||
|
||||
Domain
|
||||
++++++
|
||||
The modules ``win_domain_user`` and ``win_domain_group`` manages users and
|
||||
groups in a domain. The below is an example of ensuring a batch of domain users
|
||||
are created::
|
||||
|
||||
- name: ensure each account is created
|
||||
win_domain_user:
|
||||
name: '{{item.name}}'
|
||||
upn: '{{item.name}}@MY.DOMAIN.COM'
|
||||
password: '{{item.password}}'
|
||||
password_never_expires: no
|
||||
groups:
|
||||
- Test User
|
||||
- Application
|
||||
company: Ansible
|
||||
update_password: on_create
|
||||
with_items:
|
||||
- name: Test User
|
||||
password: Password
|
||||
- name: Admin User
|
||||
password: SuperSecretPass01
|
||||
- name: Dev User
|
||||
password: '@fvr3IbFBujSRh!3hBg%wgFucD8^x8W5'
|
||||
|
||||
Running Commands
|
||||
----------------
|
||||
In cases where there is no appropriate module available for a task,
|
||||
a command or script can be run using the ``win_shell``, ``win_command``, ``raw``, and ``script`` modules.
|
||||
|
||||
The ``raw`` module simply executes a Powershell command remotely. Since ``raw``
|
||||
has none of the wrappers that Ansible typically uses, ``become``, ``async``
|
||||
and environment variables do not work.
|
||||
|
||||
The ``script`` module executes a script from the Ansible controller on
|
||||
one or more Windows hosts. Like ``raw``, ``script`` currently does not support
|
||||
``become``, ``async``, or environment variables.
|
||||
|
||||
The ``win_command`` module is used to execute a command which is either an
|
||||
executable or batch file, while the ``win_shell`` module is used to execute commands within a shell.
|
||||
|
||||
Choosing Command or Shell
|
||||
+++++++++++++++++++++++++
|
||||
The ``win_shell`` and ``win_command`` modules can both be used to execute a command or commands.
|
||||
The ``win_shell`` module is run within a shell-like process like ``PowerShell`` or ``cmd``, so it has access to shell
|
||||
operators like ``<``, ``>``, ``|``, ``;``, ``&&``, and ``||``. Multi-lined commands can also be run in ``win_shell``.
|
||||
|
||||
The ``win_command`` module simply runs a process outside of a shell. It can still
|
||||
run a shell command like ``mkdir`` or ``New-Item`` by passing the shell commands
|
||||
to a shell executable like ``cmd.exe`` or ``PowerShell.exe``.
|
||||
|
||||
Here are some examples of using ``win_command`` and ``win_shell``::
|
||||
|
||||
- name: run a command under PowerShell
|
||||
win_shell: Get-Service -Name service | Stop-Service
|
||||
|
||||
- name: run a command under cmd
|
||||
win_shell: mkdir C:\temp
|
||||
args:
|
||||
executable: cmd.exe
|
||||
|
||||
- name: run a multiple shell commands
|
||||
win_shell: |
|
||||
New-Item -Path C:\temp -ItemType Directory
|
||||
Remove-Item -Path C:\temp -Force -Recurse
|
||||
$path_info = Get-Item -Path C:\temp
|
||||
$path_info.FullName
|
||||
|
||||
- name: run an executable using win_command
|
||||
win_command: whoami.exe
|
||||
|
||||
- name: run a cmd command
|
||||
win_command: cmd.exe /c mkdir C:\temp
|
||||
|
||||
- name: run a vbs script
|
||||
win_command: cscript.exe script.vbs
|
||||
|
||||
.. Note:: Some commands like ``mkdir``, ``del``, and ``copy`` only exist in
|
||||
the CMD shell. To run them with ``win_command`` they must be
|
||||
prefixed with ``cmd.exe /c``.
|
||||
|
||||
Argument Rules
|
||||
++++++++++++++
|
||||
When running a command through ``win_command``, the standard Windows argument
|
||||
rules apply:
|
||||
|
||||
* Each argument is delimited by a white space, which can either be a space or a
|
||||
tab.
|
||||
|
||||
* An argument can be surrounded by double quotes ``"``. Anything inside these
|
||||
quotes is interpreted as a single argument even if it contains whitespace.
|
||||
|
||||
* A double quote preceded by a backslash ``\`` is interpreted as just a double
|
||||
quote ``"`` and not as an argument delimiter.
|
||||
|
||||
* Backslashes are interpreted literally unless it immediately preceeds double
|
||||
quotes; for example ``\`` == ``\`` and ``\"`` == ``"``
|
||||
|
||||
* If an even number of backslashes is followed by a double quote, one
|
||||
backslash is used in the argument for every pair, and the double quote is
|
||||
used as a string delimiter for the argument.
|
||||
|
||||
* If an odd number of backslashes is followed by a double quote, one backslash
|
||||
is used in the argument for every pair, and the double quote is escaped and
|
||||
made a literal double quote in the argument.
|
||||
|
||||
With those rules in mind, here are some examples of quoting::
|
||||
|
||||
- win_command: C:\temp\executable.exe argument1 "argument 2" "C:\path\with space" "double \"quoted\""
|
||||
|
||||
argv[0] = C:\temp\executable.exe
|
||||
argv[1] = argument1
|
||||
argv[2] = argument 2
|
||||
argv[3] = C:\path\with space
|
||||
argv[4] = double "quoted"
|
||||
|
||||
- win_command: '"C:\Program Files\Program\program.exe" "escaped \\\" backslash" unqouted-end-backslash\'
|
||||
|
||||
argv[0] = C:\Program Files\Program\program.exe
|
||||
argv[1] = escaped \" backslash
|
||||
argv[2] = unquoted-end-backslash\
|
||||
|
||||
# due to YAML and Ansible parsing '\"' must be written as '{% raw %}\\{% endraw %}"'
|
||||
- win_command: C:\temp\executable.exe C:\no\space\path "arg with end \ before end quote{% raw %]\\{% endraw %}"
|
||||
|
||||
argv[0] = C:\temp\executable.exe
|
||||
argv[1] = C:\no\space\path
|
||||
argv[2] = arg with end \ before end quote\"
|
||||
|
||||
For more information, see `escaping arguments <https://msdn.microsoft.com/en-us/library/17w5ykft(v=vs.85).aspx>`_.
|
||||
|
||||
Creating and Running a Scheduled Task
|
||||
-------------------------------------
|
||||
WinRM has some restrictions in place that cause errors when running certain
|
||||
commands. One way to bypass these restrictions is to run a command through a
|
||||
scheduled task. A scheduled task is a Windows component that provides the
|
||||
ability to run an executable on a schedule and under a different account.
|
||||
|
||||
Ansible version 2.5 added modules that make it easier to work with scheduled tasks in Windows.
|
||||
The following is an example of running a script as a scheduled task that deletes itself after
|
||||
running::
|
||||
|
||||
- name: create scheduled task to run a process
|
||||
win_scheduled_task:
|
||||
name: adhoc-task
|
||||
username: SYSTEM
|
||||
actions:
|
||||
- path: PowerShell.exe
|
||||
arguments: |
|
||||
Start-Sleep -Seconds 30 # this isn't required, just here as a demonstration
|
||||
New-Item -Path C:\temp\test -ItemType Directory
|
||||
# remove this action if the task shouldn't be deleted on completion
|
||||
- path: cmd.exe
|
||||
arguments: /c schtasks.exe /Delete /TN "adhoc-task" /F
|
||||
triggers:
|
||||
- type: registration
|
||||
|
||||
- name: wait for the scheduled task to complete
|
||||
win_scheduled_task_stat:
|
||||
name: adhoc-task
|
||||
register: task_stat
|
||||
until: (task_stat.state is defined and task_stat.state.status != "TASK_STATE_RUNNING") or (task_stat.task_exists == False)
|
||||
retries: 12
|
||||
delay: 10
|
||||
|
||||
.. Note:: The modules used in the above example were updated/added in Ansible
|
||||
version 2.5.
|
||||
|
||||
Path Formatting for Windows
|
||||
```````````````````````````
|
||||
Windows differs from a traditional POSIX operating system in many ways. One of
|
||||
the major changes is the shift from ``/`` as the path separator to ``\``. This
|
||||
can cause major issues with how playbooks are written, since ``\`` is often used
|
||||
as an escape character on POSIX systems.
|
||||
|
||||
Ansible allows two different styles of syntax; each deals with path separators for Windows differently:
|
||||
|
||||
YAML Style
|
||||
----------
|
||||
When using the YAML syntax for tasks, the rules are well-defined by the YAML
|
||||
standard:
|
||||
|
||||
* When using a normal string (without quotes), YAML will not consider the
|
||||
backslash an escape character.
|
||||
|
||||
* When using single quotes ``'``, YAML will not consider the backslash an
|
||||
escape character.
|
||||
|
||||
* When using double quotes ``"``, the backslash is considered an escape
|
||||
character and needs to escaped with another backslash.
|
||||
|
||||
.. Note:: You should only quote strings when it is absolutely
|
||||
necessary or required by YAML, and then use single quotes.
|
||||
|
||||
The YAML specification considers the following `escape sequences <http://www.yaml.org/spec/current.html#id2517668>`_:
|
||||
|
||||
* ``\0``, ``\``, ``"``, ``\a``, ``\b``, ``\e``, ``\f``, ``\n``, ``\r``, ``\t``
|
||||
and ``\v`` -- Single character escape
|
||||
|
||||
* ``<TAB>``, ``<SPACE>``, ``<NBSP>``, ``<LNSP>``, ``<PSP>`` -- Special
|
||||
characters
|
||||
|
||||
* ``\x..`` -- 2-digit hex escape
|
||||
|
||||
* ``\u....`` -- 4-digit hex escape
|
||||
|
||||
* ``\U........`` -- 8-digit hex escape
|
||||
|
||||
Here are some examples on how to write Windows paths::
|
||||
|
||||
GOOD
|
||||
tempdir: C:\Windows\Temp
|
||||
|
||||
WORKS
|
||||
tempdir: 'C:\Windows\Temp'
|
||||
tempdir: "C:\\Windows\\Temp"
|
||||
|
||||
BAD, BUT SOMETIMES WORKS
|
||||
tempdir: C:\\Windows\\Temp
|
||||
tempdir: 'C:\\Windows\\Temp'
|
||||
tempdir: C:/Windows/Temp
|
||||
|
||||
FAILS
|
||||
tempdir: "C:\Windows\Temp"
|
||||
|
||||
---
|
||||
# example of single quotes when they are required
|
||||
- name: copy tomcat config
|
||||
win_copy:
|
||||
src: log4j.xml
|
||||
dest: '{{tc_home}}\lib\log4j.xml'
|
||||
|
||||
Legacy key=value Style
|
||||
----------------------
|
||||
The legacy ``key=value`` syntax is used on the command line for adhoc commands,
|
||||
or inside playbooks. The use of this style is discouraged within playbooks
|
||||
because backslash characters need to be escaped, making playbooks harder to read.
|
||||
The legacy syntax depends on the specific implementation in Ansible, and quoting
|
||||
(both single and double) does not have any effect on how it is parsed by
|
||||
Ansible.
|
||||
|
||||
The Ansible key=value parser parse_kv() considers the following escape
|
||||
sequences:
|
||||
|
||||
* ``\``, ``'``, ``"``, ``\a``, ``\b``, ``\f``, ``\n``, ``\r``, ``\t`` and
|
||||
``\v`` -- Single character escape
|
||||
|
||||
* ``\x..`` -- 2-digit hex escape
|
||||
|
||||
* ``\u....`` -- 4-digit hex escape
|
||||
|
||||
* ``\U........`` -- 8-digit hex escape
|
||||
|
||||
* ``\N{...}`` -- Unicode character by name
|
||||
|
||||
This means that the backslash is an escape character for some sequences, and it
|
||||
is usually safer to escape a backslash when in this form.
|
||||
|
||||
Here are some examples of using Windows paths with the key=value style::
|
||||
|
||||
GOOD
|
||||
tempdir=C:\\Windows\\Temp
|
||||
|
||||
WORKS
|
||||
tempdir='C:\\Windows\\Temp'
|
||||
tempdir="C:\\Windows\\Temp"
|
||||
|
||||
BAD, BUT SOMETIMES WORKS
|
||||
tempdir=C:\Windows\Temp
|
||||
tempdir='C:\Windows\Temp'
|
||||
tempdir="C:\Windows\Temp"
|
||||
tempdir=C:/Windows/Temp
|
||||
|
||||
FAILS
|
||||
tempdir=C:\Windows\temp
|
||||
tempdir='C:\Windows\temp'
|
||||
tempdir="C:\Windows\temp"
|
||||
|
||||
The failing examples don't fail outright but will substitute ``\t`` with the
|
||||
``<TAB>`` character resulting in ``tempdir`` being ``C:\Windows<TAB>emp``.
|
||||
|
||||
Limitations
|
||||
```````````
|
||||
Some things you cannot do with Ansible and Windows are:
|
||||
|
||||
* Upgrade PowerShell
|
||||
|
||||
* Interact with the WinRM listeners
|
||||
|
||||
Because WinRM is reliant on the services being online and running during normal operations, you cannot upgrade PowerShell or interact with WinRM listeners with Ansible. Both of these actions will cause the connection to fail. This can technically be avoided by using ``async`` or a scheduled task, but those methods are fragile if the process it runs breaks the underlying connection Ansible uses, and are best left to the bootstrapping process or before an image is
|
||||
created.
|
||||
|
||||
Developing Windows Modules
|
||||
``````````````````````````
|
||||
Because Ansible modules for Windows are written in PowerShell, the development
|
||||
guides for Windows modules differ substantially from those for standard standard modules. Please see
|
||||
:doc:`dev_guide/developing_modules_general_windows` for more information.
|
||||
|
||||
.. seealso::
|
||||
|
||||
:doc:`index`
|
||||
The documentation index
|
||||
:doc:`playbooks`
|
||||
An introduction to playbooks
|
||||
:doc:`playbooks_best_practices`
|
||||
Best practices advice
|
||||
`List of Windows Modules <http://docs.ansible.com/list_of_windows_modules.html>`_
|
||||
Windows specific module list, all implemented in PowerShell
|
||||
`User Mailing List <http://groups.google.com/group/ansible-project>`_
|
||||
Have a question? Stop by the google group!
|
||||
`irc.freenode.net <http://irc.freenode.net>`_
|
||||
#ansible IRC chat channel
|
@ -0,0 +1,710 @@
|
||||
Windows Remote Management
|
||||
=========================
|
||||
Unlike Linux/Unix hosts, which use SSH by default, Windows hosts are
|
||||
configured with WinRM. This topic covers how to configure and use WinRM with Ansible.
|
||||
|
||||
.. contents:: Topics
|
||||
|
||||
What is WinRM?
|
||||
``````````````
|
||||
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 <https://github.com/diyan/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.2.2"
|
||||
|
||||
.. Note:: on distributions with multiple python versions, use pip2 or pip2.x,
|
||||
where x matches the python minor version Ansible is running under.
|
||||
|
||||
Authentication Options
|
||||
``````````````````````
|
||||
When connecting to a Windows host, there are several different options that can be used
|
||||
when authentication with an account. The authentication type may be set on inventory
|
||||
hosts or groups with the ``ansible_winrm_transport`` variable.
|
||||
|
||||
The following matrix is a high level overview of the options:
|
||||
|
||||
+-------------+----------------+---------------------------+-----------------------+-----------------+
|
||||
| Option | Local Accounts | Active Directory Accounts | Credential Delegation | HTTP Encryption |
|
||||
+=============+================+===========================+=======================+=================+
|
||||
| Basic | Yes | No | No | No |
|
||||
+-------------+----------------+---------------------------+-----------------------+-----------------+
|
||||
| Certificate | Yes | No | No | No |
|
||||
+-------------+----------------+---------------------------+-----------------------+-----------------+
|
||||
| Kerberos | No | Yes | Yes | Yes |
|
||||
+-------------+----------------+---------------------------+-----------------------+-----------------+
|
||||
| NTLM | Yes | Yes | No | Yes |
|
||||
+-------------+----------------+---------------------------+-----------------------+-----------------+
|
||||
| CredSSP | Yes | Yes | Yes | Yes |
|
||||
+-------------+----------------+---------------------------+-----------------------+-----------------+
|
||||
|
||||
Basic
|
||||
-----
|
||||
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::
|
||||
|
||||
ansible_user: LocalUsername
|
||||
ansible_password: Password
|
||||
ansible_connection: winrm
|
||||
ansible_winrm_transport: basic
|
||||
|
||||
Basic authentication is not enabled by default on a Windows host but can be
|
||||
enabled by running the following in PowerShell:
|
||||
|
||||
.. code-block:: powershell
|
||||
|
||||
Set-Item -Path WSMan:\localhost\Service\Auth\Basic -Value $true
|
||||
|
||||
Certificate
|
||||
-----------
|
||||
Certificate authentication uses certificates as keys similar to SSH key
|
||||
pairs, but the file format and key generation process is different.
|
||||
|
||||
The following example shows host vars configured for certificate authentication::
|
||||
|
||||
ansible_connection: winrm
|
||||
ansible_winrm_cert_pem: /path/to/certificate/public/key.pem
|
||||
ansible_winrm_cert_key_pem: /path/to/certificate/private/key.pem
|
||||
ansible_winrm_transport: certificate
|
||||
|
||||
Certificate authentication is not enabled by default on a Windows host but can
|
||||
be enabled by running the following in PowerShell:
|
||||
|
||||
.. code-block:: powershell
|
||||
|
||||
Set-Item -Path WSMan:\localhost\Service\Auth\Certificate -Value $true
|
||||
|
||||
.. Note:: Encrypted private keys cannot be used as the urllib3 library that
|
||||
is used by Ansible for WinRM does not support this functionality.
|
||||
|
||||
Generate a Certificate
|
||||
++++++++++++++++++++++
|
||||
A certificate must be generated before it can be mapped to a local user.
|
||||
This can be done using one of the following methods:
|
||||
|
||||
* OpenSSL
|
||||
* PowerShell, using the ``New-SelfSignedCertificate`` cmdlet
|
||||
* Active Directory Certificate Services
|
||||
|
||||
Active Directory Certificate Services is beyond of scope in this documentation but may be
|
||||
the best option to use when running in a domain environment. For more information,
|
||||
see the `Active Directory Certificate Services documentation <https://technet.microsoft.com/en-us/library/cc732625(v=ws.11).aspx>`_.
|
||||
|
||||
.. Note:: 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.
|
||||
|
||||
To generate a certificate with ``OpenSSL``:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
# set the name of the local user that will have the key mapped to
|
||||
USERNAME="username"
|
||||
|
||||
cat > openssl.conf << EOL
|
||||
distinguished_name = req_distinguished_name
|
||||
[req_distinguished_name]
|
||||
[v3_req_client]
|
||||
extendedKeyUsage = clientAuth
|
||||
subjectAltName = otherName:1.3.6.1.4.1.311.20.2.3;UTF8:$USERNAME@localhost
|
||||
EOL
|
||||
|
||||
export OPENSSL_CONF=openssl.conf
|
||||
openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -out cert.pem -outform PEM -keyout cert_key.pem -subj "/CN=$USERNAME" -extensions v3_req_client
|
||||
rm openssl.conf
|
||||
|
||||
|
||||
To generate a certificate with ``New-SelfSignedCertificate``:
|
||||
|
||||
.. code-block:: powershell
|
||||
|
||||
# set the name of the local user that will have the key mapped
|
||||
$username = "username"
|
||||
$output_path = "C:\temp"
|
||||
|
||||
# instead of generating a file, the cert will be added to the personal
|
||||
# LocalComputer folder in the certificate store
|
||||
$cert = New-SelfSignedCertificate -Type Custom `
|
||||
-Subject "CN=$username" `
|
||||
-TextExtension @("2.5.29.37={text}1.3.6.1.5.5.7.3.2","2.5.29.17={text}upn=$username@localhost") `
|
||||
-KeyUsage DigitalSignature,KeyEncipherment `
|
||||
-KeyAlgorithm RSA `
|
||||
-KeyLength 2048
|
||||
|
||||
# export the public key
|
||||
$pem_output = @()
|
||||
$pem_output += "-----BEGIN CERTIFICATE-----"
|
||||
$pem_output += [System.Convert]::ToBase64String($cert.RawData) -replace ".{64}", "$&`n"
|
||||
$pem_output += "-----END CERTIFICATE-----"
|
||||
[System.IO.File]::WriteAllLines("$output_path\cert.pem", $pem_output)
|
||||
|
||||
# export the private key in a PFX file
|
||||
[System.IO.File]::WriteAllBytes("$output_path\cert.pfx", $cert.Export("Pfx"))
|
||||
|
||||
|
||||
.. Note:: To convert the PFX file to a private key that pywinrm can use, run
|
||||
the following command with OpenSSL
|
||||
``openssl pkcs12 -in cert.pfx -nocerts -nodes -out cert_key.pem -passin pass: -passout pass:``
|
||||
|
||||
Import a Certificate to the Certificate Store
|
||||
+++++++++++++++++++++++++++++++++++++++++++++
|
||||
Once a certificate has been generated, the issuing certificate needs to be
|
||||
imported into the ``Trusted Root Certificate Authorities`` of the
|
||||
``LocalMachine`` store, and the client certificate public key must be present
|
||||
in the ``Trusted People`` folder of the ``LocalMachine`` store. For this example,
|
||||
both the issuing certificate and public key are the same.
|
||||
|
||||
Following example shows how to import the issuing certificate:
|
||||
|
||||
.. code-block:: powershell
|
||||
|
||||
$cert = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Certificate2
|
||||
$cert.Import("cert.pem")
|
||||
|
||||
$store_name = [System.Security.Cryptography.X509Certificates.StoreName]::Root
|
||||
$store_location = [System.Security.Cryptography.X509Certificates.StoreLocation]::LocalMachine
|
||||
$store = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Store -ArgumentList $store_name, $store_location
|
||||
$store.Open("MaxAllowed")
|
||||
$store.Add($cert)
|
||||
$store.Close()
|
||||
|
||||
|
||||
.. Note:: If using ADCS to generate the certificate, then the issuing
|
||||
certificate will already be imported and this step can be skipped.
|
||||
|
||||
The code to import the client certificate public key is:
|
||||
|
||||
.. code-block:: powershell
|
||||
|
||||
$cert = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Certificate2
|
||||
$cert.Import("cert.pem")
|
||||
|
||||
$store_name = [System.Security.Cryptography.X509Certificates.StoreName]::TrustedPeople
|
||||
$store_location = [System.Security.Cryptography.X509Certificates.StoreLocation]::LocalMachine
|
||||
$store = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Store -ArgumentList $store_name, $store_location
|
||||
$store.Open("MaxAllowed")
|
||||
$store.Add($cert)
|
||||
$store.Close()
|
||||
|
||||
|
||||
Mapping a Certificate to an Account
|
||||
+++++++++++++++++++++++++++++++++++
|
||||
Once the certificate has been imported, it needs to be mapped to the local user account.
|
||||
|
||||
This can be done with the following PowerShell command:
|
||||
|
||||
.. code-block:: powershell
|
||||
|
||||
$username = "username"
|
||||
$password = ConvertTo-SecureString -String "password" -AsPlainText -Force
|
||||
$credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $username, $password
|
||||
|
||||
# this is the issuer thumbprint which in the case of a self generated cert
|
||||
# is the public key thumbprint, additional logic may be required for other
|
||||
# scenarios
|
||||
$thumbprint = (Get-ChildItem -Path cert:\LocalMachine\root | Where-Object { $_.Subject -eq "CN=$username" }).Thumbprint
|
||||
|
||||
New-Item -Path WSMan:\localhost\ClientCertificate `
|
||||
-Subject "$username@localhost" `
|
||||
-URI * `
|
||||
-Issuer $thumbprint `
|
||||
-Credential $credential `
|
||||
-Force
|
||||
|
||||
|
||||
Once this is complete, the hostvar ``ansible_winrm_cert_pem`` should be set to
|
||||
the path of the public key and the ``ansible_winrm_cert_key_pem`` variable should be set to
|
||||
the path of the private key.
|
||||
|
||||
NTLM
|
||||
----
|
||||
NTLM is an older authentication mechanism used by Microsoft that can support
|
||||
both local and domain accounts. NTLM is enabled by default on the WinRM
|
||||
service, so no setup is required before using it.
|
||||
|
||||
NTLM is the easiest authentication protocol to use and is more secure than
|
||||
``Basic`` authentication. If running in a domain environment, ``Kerberos`` should be used
|
||||
instead of NTLM.
|
||||
|
||||
Kerberos has several advantages over using NTLM:
|
||||
|
||||
* NTLM is an older protocol and does not support newer encryption
|
||||
protocols.
|
||||
* NTLM is slower to authenticate because it requires more round trips to the host in
|
||||
the authentication stage.
|
||||
* Unlike Kerberos, NTLM does not allow credential delegation.
|
||||
|
||||
This example shows host variables configured to use NTLM authentication::
|
||||
|
||||
ansible_user: LocalUsername
|
||||
ansible_password: Password
|
||||
ansible_connection: winrm
|
||||
ansible_winrm_transport: ntlm
|
||||
|
||||
Kerberos
|
||||
--------
|
||||
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::
|
||||
|
||||
ansible_user: username@MY.DOMAIN.COM
|
||||
ansible_password: Password
|
||||
ansible_connection: winrm
|
||||
ansible_winrm_transport: kerberos
|
||||
|
||||
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_keytab: the path to the keytab file
|
||||
ansible_winrm_kerberos_delegation: allows the credentials to traverse multiple hops
|
||||
ansible_winrm_kerberos_hostname_override: the hostname to be used for the kerberos exchange
|
||||
|
||||
Installing the Kerberos Library
|
||||
+++++++++++++++++++++++++++++++
|
||||
Some system dependencies that must be installed prior to using Kerberos. The script below lists the dependencies based on the distro:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
# Via Yum (RHEL/Centos/Fedora)
|
||||
yum -y install python-devel krb5-devel krb5-libs krb5-workstation
|
||||
|
||||
# Via Apt (Ubuntu)
|
||||
sudo apt-get install python-dev libkrb5-dev krb5-user
|
||||
|
||||
# Via Portage (Gentoo)
|
||||
emerge -av app-crypt/mit-krb5
|
||||
emerge -av dev-python/setuptools
|
||||
|
||||
# Via Pkg (FreeBSD)
|
||||
sudo pkg install security/krb5
|
||||
|
||||
# Via OpenCSW (Solaris)
|
||||
pkgadd -d http://get.opencsw.org/now
|
||||
/opt/csw/bin/pkgutil -U
|
||||
/opt/csw/bin/pkgutil -y -i libkrb5_3
|
||||
|
||||
# Via Pacman (Arch Linux)
|
||||
pacman -S krb5
|
||||
|
||||
|
||||
Once the dependencies have been installed, the ``python-kerberos`` wrapper can
|
||||
be install using ``pip``:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
pip install pywinrm[kerberos]
|
||||
|
||||
|
||||
Configuring Host Kerberos
|
||||
+++++++++++++++++++++++++
|
||||
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:
|
||||
|
||||
::
|
||||
|
||||
[realms]
|
||||
MY.DOMAIN.COM = {
|
||||
kdc = domain-controller1.my.domain.com
|
||||
kdc = domain-controller2.my.domain.com
|
||||
}
|
||||
|
||||
In the section that starts with:
|
||||
|
||||
::
|
||||
|
||||
[domain_realm]
|
||||
|
||||
Add a line like the following for each domain that Ansible needs access for:
|
||||
|
||||
::
|
||||
|
||||
[domain_realm]
|
||||
.my.domain.com = MY.DOMAIN.COM
|
||||
|
||||
You can configure other settings in this file such as the default domain. See
|
||||
`krb5.conf <https://web.mit.edu/kerberos/krb5-1.12/doc/admin/conf_files/krb5_conf.html>`_
|
||||
for more details.
|
||||
|
||||
Automatic Kerberos Ticket Management
|
||||
++++++++++++++++++++++++++++++++++++
|
||||
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.
|
||||
|
||||
Manual Kerberos Ticket Management
|
||||
+++++++++++++++++++++++++++++++++
|
||||
To manually manage Kerberos tickets, the ``kinit`` binary is used. To
|
||||
obtain a new ticket the following command is used:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
kinit username@MY.DOMAIN.COM
|
||||
|
||||
.. Note:: The domain must match the configured Kerberos realm exactly, and must be in upper case.
|
||||
|
||||
To see what tickets (if any) have been acquired, use the following command:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
klist
|
||||
|
||||
To destroy all the tickets that have been acquired, use the following command:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
kdestroy
|
||||
|
||||
Troubleshooting Kerberos
|
||||
++++++++++++++++++++++++
|
||||
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::
|
||||
|
||||
kinit -C username@MY.DOMAIN.COM
|
||||
klist
|
||||
|
||||
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
|
||||
-------
|
||||
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.
|
||||
|
||||
To use CredSSP authentication, the host vars are configured like so::
|
||||
|
||||
ansible_user: Username
|
||||
ansible_password: Password
|
||||
ansible_connection: winrm
|
||||
ansible_winrm_transport: credssp
|
||||
|
||||
There are some extra host variables that can be set as shown below::
|
||||
|
||||
ansible_winrm_credssp_disable_tlsv1_2: when true, will not use TLS 1.2 in the CredSSP auth process
|
||||
|
||||
CredSSP authentication is not enabled by default on a Windows host, but can
|
||||
be enabled by running the following in PowerShell:
|
||||
|
||||
.. code-block:: powershell
|
||||
|
||||
Enable-WSManCredSSP -Role Server -Force
|
||||
|
||||
Installing CredSSP Library
|
||||
++++++++++++++++++++++++++
|
||||
|
||||
The ``requests-credssp`` wrapper can be installed using ``pip``:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pip install pywinrm[credssp]
|
||||
|
||||
CredSSP and TLS 1.2
|
||||
+++++++++++++++++++
|
||||
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 <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>`_
|
||||
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:
|
||||
|
||||
.. code-block:: powershell
|
||||
|
||||
$reg_path = "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProvider\SCHANNEL\Protocols\TLS 1.2"
|
||||
New-Item -Path $reg_path
|
||||
New-Item -Path "$reg_path\Server"
|
||||
New-Item -Path "$reg_path\Client"
|
||||
|
||||
New-ItemProperty -Path "$reg_path\Server" -Name "Enabled" -Value 1 -PropertyType DWord
|
||||
New-ItemProperty -Path "$reg_path\Server" -Name "DisabledByDefault" -Value 0 -PropertyType DWord
|
||||
New-ItemProperty -Path "$reg_path\Client" -Name "Enabled" -Value 1 -PropertyType DWord
|
||||
New-ItemProperty -Path "$reg_path\Client" -Name "DisabledByDefault" -Value 0 -PropertyType DWord
|
||||
|
||||
Set CredSSP Certificate
|
||||
+++++++++++++++++++++++
|
||||
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:
|
||||
|
||||
.. code-block:: powershell
|
||||
|
||||
# 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
|
||||
|
||||
Non-Administrator Accounts
|
||||
``````````````````````````
|
||||
WinRM is configured by default to only allow connections from accounts in the local
|
||||
``Administrators`` group. This can be changed by running:
|
||||
|
||||
.. code-block:: powershell
|
||||
|
||||
winrm configSDDL default
|
||||
|
||||
This will display an ACL editor, where new users or groups may be added. To run commands
|
||||
over WinRM, users and groups must have at least the ``Read`` and ``Execute`` permissions
|
||||
enabled.
|
||||
|
||||
While non-administrative accounts can be used with WinRM, most typical server administration
|
||||
tasks require some level of administrative access, so the utility is usually limited.
|
||||
|
||||
WinRM Encryption
|
||||
````````````````
|
||||
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:
|
||||
|
||||
.. code-block:: powershell
|
||||
|
||||
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.
|
||||
|
||||
Inventory Options
|
||||
`````````````````
|
||||
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.yml
|
||||
|
||||
ansible_connection: winrm
|
||||
|
||||
# may also be passed on the command-line via --user
|
||||
ansible_user: Administrator
|
||||
|
||||
# may also be supplied at runtime with --ask-pass
|
||||
ansible_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``.
|
||||
|
||||
As of Ansible 2.0, 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_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 ``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_operation_timeout_sec``: Increase the default timeout for
|
||||
WinRM operations, Ansible uses ``20`` by default
|
||||
|
||||
* ``ansible_winrm_read_timeout_sec``: Increase the WinRM read timeout, Ansible
|
||||
uses ``30`` by default. Useful if there are intermittent network issues and
|
||||
read timeout errors keep occurring
|
||||
|
||||
* ``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_*``: Any additional keyword arguments supported by
|
||||
``winrm.Protocol`` may be provided in place of ``*``
|
||||
|
||||
In addtion, 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``.
|
||||
|
||||
Limitations
|
||||
```````````
|
||||
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.
|
||||
|
||||
|
||||
.. seealso::
|
||||
|
||||
:doc:`index`
|
||||
The documentation index
|
||||
:doc:`playbooks`
|
||||
An introduction to playbooks
|
||||
:doc:`playbooks_best_practices`
|
||||
Best practices advice
|
||||
`List of Windows Modules <http://docs.ansible.com/list_of_windows_modules.html>`_
|
||||
Windows specific module list, all implemented in PowerShell
|
||||
`User Mailing List <http://groups.google.com/group/ansible-project>`_
|
||||
Have a question? Stop by the google group!
|
||||
`irc.freenode.net <http://irc.freenode.net>`_
|
||||
#ansible IRC chat channel
|
Loading…
Reference in New Issue