issue #78082 create win user guide (#78099)

This commit is contained in:
Don Naro
2022-06-23 16:31:49 -04:00
committed by GitHub
parent 08327c698c
commit 4cfa0b07fc
18 changed files with 2978 additions and 2926 deletions
+1
View File
@@ -42,6 +42,7 @@ Ansible releases a new major release approximately twice a year. The core applic
:caption: Using Ansible
user_guide/index
win_guide/index
.. toctree::
:maxdepth: 2
+1
View File
@@ -49,6 +49,7 @@ This documentation covers the version of ``ansible-core`` noted in the upper lef
:caption: Using Ansible Core
user_guide/index
win_guide/index
.. toctree::
:maxdepth: 2
-1
View File
@@ -123,5 +123,4 @@ Here is the complete list of resources in the Ansible User Guide:
../plugins/plugins
../reference_appendices/playbooks_keywords
intro_bsd
windows
collections_using
@@ -1,4 +1,4 @@
Windows Support
===============
This page has been split up and moved to the new section :ref:`windows`.
You can find documentation for using Ansible on Windows at :ref:`win_guide_index`.
+3 -18
View File
@@ -1,21 +1,6 @@
.. _windows:
:orphan:
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_performance
windows_faq
You can find documentation for using Ansible on Windows at :ref:`win_guide_index`.
+3 -503
View File
@@ -1,506 +1,6 @@
:orphan:
Desired State Configuration
===========================
.. contents:: Topics
:local:
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 take advantage of
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/scripting/dsc/overview?view=powershell-7.2>`_.
Host Requirements
`````````````````
To use the ``win_dsc`` module, a Windows host must have PowerShell v5.0 or
newer installed. All supported hosts 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/scripting/dsc/reference/resources/windows/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 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/scripting/dsc/resources/resources>`_.
Using the `Registry <https://docs.microsoft.com/en-us/powershell/scripting/dsc/reference/resources/windows/registryresource>`_
resource as an example, this is the DSC definition as documented by Microsoft:
.. code-block:: powershell
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 because 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:
.. code-block:: yaml+jinja
- 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
Starting in Ansible 2.8, the ``win_dsc`` module automatically validates the
input options from Ansible with the DSC definition. This means Ansible will
fail if the option name is incorrect, a mandatory option is not set, or the
value is not a valid choice. When running Ansible with a verbosity level of 3
or more (``-vvv``), the return value will contain the possible invocation
options based on the ``resource_name`` specified. Here is an example of the
invocation output for the above ``Registry`` task:
.. code-block:: ansible-output
changed: [2016] => {
"changed": true,
"invocation": {
"module_args": {
"DependsOn": null,
"Ensure": "Present",
"Force": null,
"Hex": null,
"Key": "HKEY_LOCAL_MACHINE\\SOFTWARE\\ExampleKey",
"PsDscRunAsCredential_password": null,
"PsDscRunAsCredential_username": null,
"ValueData": [
"TestData"
],
"ValueName": "TestValue",
"ValueType": null,
"module_version": "latest",
"resource_name": "Registry"
}
},
"module_version": "1.1",
"reboot_required": false,
"verbose_set": [
"Perform operation 'Invoke CimMethod' with following parameters, ''methodName' = ResourceSet,'className' = MSFT_DSCLocalConfigurationManager,'namespaceName' = root/Microsoft/Windows/DesiredStateConfiguration'.",
"An LCM method call arrived from computer SERVER2016 with user sid S-1-5-21-3088887838-4058132883-1884671576-1105.",
"[SERVER2016]: LCM: [ Start Set ] [[Registry]DirectResourceAccess]",
"[SERVER2016]: [[Registry]DirectResourceAccess] (SET) Create registry key 'HKLM:\\SOFTWARE\\ExampleKey'",
"[SERVER2016]: [[Registry]DirectResourceAccess] (SET) Set registry key value 'HKLM:\\SOFTWARE\\ExampleKey\\TestValue' to 'TestData' of type 'String'",
"[SERVER2016]: LCM: [ End Set ] [[Registry]DirectResourceAccess] in 0.1930 seconds.",
"[SERVER2016]: LCM: [ End Set ] in 0.2720 seconds.",
"Operation 'Invoke CimMethod' complete.",
"Time taken for configuration job to complete is 0.402 seconds"
],
"verbose_test": [
"Perform operation 'Invoke CimMethod' with following parameters, ''methodName' = ResourceTest,'className' = MSFT_DSCLocalConfigurationManager,'namespaceName' = root/Microsoft/Windows/DesiredStateConfiguration'.",
"An LCM method call arrived from computer SERVER2016 with user sid S-1-5-21-3088887838-4058132883-1884671576-1105.",
"[SERVER2016]: LCM: [ Start Test ] [[Registry]DirectResourceAccess]",
"[SERVER2016]: [[Registry]DirectResourceAccess] Registry key 'HKLM:\\SOFTWARE\\ExampleKey' does not exist",
"[SERVER2016]: LCM: [ End Test ] [[Registry]DirectResourceAccess] False in 0.2510 seconds.",
"[SERVER2016]: LCM: [ End Set ] in 0.3310 seconds.",
"Operation 'Invoke CimMethod' complete.",
"Time taken for configuration job to complete is 0.475 seconds"
]
}
The ``invocation.module_args`` key shows the actual values that were set as
well as other possible values that were not set. Unfortunately, this will not
show the default value for a DSC property, only what was set from the Ansible
task. Any ``*_password`` option will be masked in the output for security
reasons; if there are any other sensitive module options, set ``no_log: True``
on the task to stop all task output from being logged.
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[]]``)
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:
.. code-block:: yaml+jinja
PsDscRunAsCredential_username: '{{ ansible_user }}'
PsDscRunAsCredential_password: '{{ ansible_password }}'
SourceCredential_username: AdminUser
SourceCredential_password: PasswordForAdminUser
.. Note:: On versions of Ansible older than 2.8, you should set ``no_log: yes``
on the task definition in Ansible to ensure any credentials used are not
stored in any log file or console output.
A ``[PSCredential]`` is defined with ``EmbeddedInstance("MSFT_Credential")`` in
a DSC resource MOF definition.
CimInstance Type
++++++++++++++++
A ``[CimInstance]`` object is used by DSC to store a dictionary object based on
a custom class defined by that resource. Defining a value that takes in a
``[CimInstance]`` in YAML is the same as defining a dictionary in YAML.
For example, to define a ``[CimInstance]`` value in Ansible:
.. code-block:: yaml+jinja
# [CimInstance]AuthenticationInfo == MSFT_xWebAuthenticationInformation
AuthenticationInfo:
Anonymous: no
Basic: yes
Digest: no
Windows: yes
In the above example, the CIM instance is a representation of the class
`MSFT_xWebAuthenticationInformation <https://github.com/dsccommunity/xWebAdministration/blob/master/source/DSCResources/MSFT_xWebSite/MSFT_xWebSite.schema.mof>`_.
This class accepts four boolean variables, ``Anonymous``, ``Basic``,
``Digest``, and ``Windows``. The keys to use in a ``[CimInstance]`` depend on
the class it represents. Please read through the documentation of the resource
to determine the keys that can be used and the types of each key value. The
class definition is typically located in the ``<resource name>.schema.mof``.
HashTable Type
++++++++++++++
A ``[HashTable]`` object is also a dictionary but does not have a strict set of
keys that can/need to be defined. Like a ``[CimInstance]``, define it as a
normal dictionary value in YAML. A ``[HashTable]]`` is defined with
``EmbeddedInstance("MSFT_KeyValuePair")`` in a DSC resource MOF definition.
Arrays
++++++
Simple type arrays like ``[string[]]`` or ``[UInt32[]]`` are defined as a list
or as a comma-separated string which is then cast to their type. Using a list
is recommended because the values are not manually parsed by the ``win_dsc``
module before being passed to the DSC engine. For example, to define a simple
type array in Ansible:
.. code-block:: yaml+jinja
# [string[]]
ValueData: entry1, entry2, entry3
ValueData:
- entry1
- entry2
- entry3
# [UInt32[]]
ReturnCode: 0,3010
ReturnCode:
- 0
- 3010
Complex type arrays like ``[CimInstance[]]`` (array of dicts), can be defined
like this example:
.. code-block:: yaml+jinja
# [CimInstance[]]BindingInfo == MSFT_xWebBindingInformation
BindingInfo:
- Protocol: https
Port: 443
CertificateStoreName: My
CertificateThumbprint: C676A89018C4D5902353545343634F35E6B3A659
HostName: DSCTest
IPAddress: '*'
SSLFlags: 1
- Protocol: http
Port: 80
IPAddress: '*'
The above example is an array with two values of the class `MSFT_xWebBindingInformation <https://github.com/dsccommunity/xWebAdministration/blob/master/source/DSCResources/MSFT_xWebSite/MSFT_xWebSite.schema.mof>`_.
When defining a ``[CimInstance[]]``, be sure to read the resource documentation
to find out what keys to use in the definition.
DateTime
++++++++
A ``[DateTime]`` object is a DateTime string representing the date and time in
the `ISO 8601 <https://www.w3.org/TR/NOTE-datetime>`_ date time format. The
value for a ``[DateTime]`` field should be quoted in YAML to ensure the string
is properly serialized to the Windows host. Here is an example of how to define
a ``[DateTime]`` value in Ansible:
.. code-block:: yaml+jinja
# As UTC-0 (No timezone)
DateTime: '2019-02-22T13:57:31.2311892+00:00'
# As UTC+4
DateTime: '2019-02-22T17:57:31.2311892+04:00'
# As UTC-4
DateTime: '2019-02-22T09:57:31.2311892-04:00'
All the values above are equal to a UTC date time of February 22nd 2019 at
1:57pm with 31 seconds and 2311892 milliseconds.
Run As Another User
-------------------
By default, DSC runs each resource as the SYSTEM account and not the account
that Ansible uses 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, and
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:
.. code-block:: yaml+jinja
- 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: yes
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 to another host
The following is an example of installing the ``xWebAdministration`` resources using
``win_psmodule``:
.. code-block:: yaml+jinja
- 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:
.. code-block:: powershell
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+jinja
- 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+jinja
- 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+jinja
- 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: yes
Ensure: Present
Credential_username: '{{ ansible_user }}'
Credential_password: '{{ ansible_password }}'
Setup IIS Website
-----------------
.. code-block:: yaml+jinja
- 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
loop:
- Web-Server
- Web-Asp-Net45
- 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
BindingInfo:
- Protocol: https
Port: 8443
CertificateStoreName: My
CertificateThumbprint: C676A89018C4D5902353545343634F35E6B3A659
HostName: DSCTest
IPAddress: '*'
SSLFlags: 1
- Protocol: http
Port: 8080
IPAddress: '*'
AuthenticationInfo:
Anonymous: no
Basic: yes
Digest: no
Windows: yes
.. seealso::
:ref:`playbooks_intro`
An introduction to playbooks
:ref:`playbooks_best_practices`
Tips and tricks for playbooks
:ref:`List of Windows Modules <windows_modules>`
Windows specific module list, all implemented in PowerShell
`User Mailing List <https://groups.google.com/group/ansible-project>`_
Have a question? Stop by the google group!
:ref:`communication_irc`
How to join Ansible chat channels
This page has moved to :ref:`windows_dsc`.
+2 -253
View File
@@ -1,257 +1,6 @@
.. _windows_faq:
:orphan:
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
:ref:`general FAQ page <ansible_faq>`.
Does Ansible work with Windows XP or Server 2003?
``````````````````````````````````````````````````
Ansible does not work with Windows XP or Server 2003 hosts. Ansible does work with these Windows operating system versions:
* Windows Server 2008 :sup:`1`
* Windows Server 2008 R2 :sup:`1`
* Windows Server 2012
* Windows Server 2012 R2
* Windows Server 2016
* Windows Server 2019
* Windows 7 :sup:`1`
* Windows 8.1
* Windows 10
1 - See the :ref:`Server 2008 FAQ <windows_faq_server2008>` entry for more details.
Ansible also has minimum PowerShell version requirements - please see
:ref:`windows_setup` for the latest information.
.. _windows_faq_server2008:
Are Server 2008, 2008 R2 and Windows 7 supported?
`````````````````````````````````````````````````
Microsoft ended Extended Support for these versions of Windows on January 14th, 2020, and Ansible deprecated official support in the 2.10 release. No new feature development will occur targeting these operating systems, and automated testing has ceased. However, existing modules and features will likely continue to work, and simple pull requests to resolve issues with these Windows versions may be accepted.
Can I manage Windows Nano Server with Ansible?
``````````````````````````````````````````````
Ansible does not currently work with Windows Nano Server, since it does
not have access to the full .NET Framework that is used by the majority of the
modules and internal components.
.. _windows_faq_ansible:
Can Ansible run on Windows?
```````````````````````````
No, Ansible can only manage Windows hosts. Ansible cannot run on a Windows host
natively, though it can run under the Windows Subsystem for Linux (WSL).
.. note:: The Windows Subsystem for Linux is not supported by 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-pip git libffi-dev libssl-dev -y
pip install --user 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
If you encounter timeout errors when running Ansible on the WSL, this may be due to an issue
with ``sleep`` not returning correctly. The following workaround may resolve the issue:
.. code-block:: shell
mv /usr/bin/sleep /usr/bin/sleep.orig
ln -s /bin/true /usr/bin/sleep
Another option is to use WSL 2 if running Windows 10 later than build 2004.
.. code-block:: shell
wsl --set-default-version 2
Can I use SSH keys to authenticate to Windows hosts?
````````````````````````````````````````````````````
You cannot use SSH keys with the WinRM or PSRP connection plugins.
These connection plugins use X509 certificates for authentication instead
of the SSH key pairs that SSH uses.
The way X509 certificates are generated and mapped to a user is different
from the SSH implementation; consult the :ref:`windows_winrm` documentation for
more information.
Ansible 2.8 has added an experimental option to use the SSH connection plugin,
which uses SSH keys for authentication, for Windows servers. See :ref:`this question <windows_faq_ssh>`
for more information.
.. _windows_faq_winrm:
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 :ref:`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, you can use
CredSSP or Kerberos with credential delegation enabled.
See :ref:`become` more info on how to use become. The limitations section at
:ref:`windows_winrm` has more details around WinRM limitations.
This program won't install on Windows with Ansible
``````````````````````````````````````````````````
See :ref:`this question <windows_faq_winrm>` for more information about WinRM limitations.
What Windows 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 these modules
can be found :ref:`here <windows_modules>`.
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_template)
* wait_for_connection
Ansible Windows modules exist in the :ref:`plugins_in_ansible.windows`, :ref:`plugins_in_community.windows`, and :ref:`plugins_in_chocolatey.chocolatey` collections.
Can I run Python modules on Windows hosts?
``````````````````````````````````````````
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.
.. _windows_faq_ssh:
Can I connect to Windows hosts over SSH?
````````````````````````````````````````
Ansible 2.8 has added an experimental option to use the SSH connection plugin
to manage Windows hosts. To connect to Windows hosts over SSH, you must install and configure the `Win32-OpenSSH <https://github.com/PowerShell/Win32-OpenSSH>`_
fork that is in development with Microsoft on
the Windows host(s). While most of the basics should work with SSH,
``Win32-OpenSSH`` is rapidly changing, with new features added and bugs
fixed in every release. It is highly recommend you `install <https://github.com/PowerShell/Win32-OpenSSH/wiki/Install-Win32-OpenSSH>`_ the latest release
of ``Win32-OpenSSH`` from the GitHub Releases page when using it with Ansible
on Windows hosts.
To use SSH as the connection to a Windows host, set the following variables in
the inventory:
.. code-block:: shell
ansible_connection=ssh
# Set either cmd or powershell not both
ansible_shell_type=cmd
# ansible_shell_type=powershell
The value for ``ansible_shell_type`` should either be ``cmd`` or ``powershell``.
Use ``cmd`` if the ``DefaultShell`` has not been configured on the SSH service
and ``powershell`` if that has been set as the ``DefaultShell``.
Why is connecting to a Windows host via SSH failing?
````````````````````````````````````````````````````
Unless you are using ``Win32-OpenSSH`` as described above, you must connect to
Windows hosts using :ref:`windows_winrm`. If your Ansible output indicates that
SSH was used, either you did not set the connection vars properly or the host is not inheriting them correctly.
Make sure ``ansible_connection: winrm`` is set in the inventory for the Windows
host(s).
Why are my credentials being rejected?
``````````````````````````````````````
This can be due to a myriad of reasons unrelated to incorrect credentials.
See HTTP 401/Credentials Rejected at :ref:`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::
:ref:`windows`
The Windows documentation index
:ref:`about_playbooks`
An introduction to playbooks
:ref:`playbooks_best_practices`
Tips and tricks for playbooks
`User Mailing List <https://groups.google.com/group/ansible-project>`_
Have a question? Stop by the google group!
:ref:`communication_irc`
How to join Ansible chat channels
This page has moved to :ref:`windows_faq`.
@@ -1,61 +1,6 @@
.. _windows_performance:
:orphan:
Windows performance
===================
This document offers some performance optimizations you might like to apply to
your Windows hosts to speed them up specifically in the context of using Ansible
with them, and generally.
Optimize PowerShell performance to reduce Ansible task overhead
---------------------------------------------------------------
To speed up the startup of PowerShell by around 10x, run the following
PowerShell snippet in an Administrator session. Expect it to take tens of
seconds.
.. note::
If native images have already been created by the ngen task or service, you
will observe no difference in performance (but this snippet will at that
point execute faster than otherwise).
.. code-block:: powershell
function Optimize-PowershellAssemblies {
# NGEN powershell assembly, improves startup time of powershell by 10x
$old_path = $env:path
try {
$env:path = [Runtime.InteropServices.RuntimeEnvironment]::GetRuntimeDirectory()
[AppDomain]::CurrentDomain.GetAssemblies() | % {
if (! $_.location) {continue}
$Name = Split-Path $_.location -leaf
if ($Name.startswith("Microsoft.PowerShell.")) {
Write-Progress -Activity "Native Image Installation" -Status "$name"
ngen install $_.location | % {"`t$_"}
}
}
} finally {
$env:path = $old_path
}
}
Optimize-PowershellAssemblies
PowerShell is used by every Windows Ansible module. This optimization reduces
the time PowerShell takes to start up, removing that overhead from every invocation.
This snippet uses `the native image generator, ngen <https://docs.microsoft.com/en-us/dotnet/framework/tools/ngen-exe-native-image-generator#WhenToUse>`_
to pre-emptively create native images for the assemblies that PowerShell relies on.
Fix high-CPU-on-boot for VMs/cloud instances
--------------------------------------------
If you are creating golden images to spawn instances from, you can avoid a disruptive
high CPU task near startup via `processing the ngen queue <https://docs.microsoft.com/en-us/dotnet/framework/tools/ngen-exe-native-image-generator#native-image-service>`_
within your golden image creation, if you know the CPU types won't change between
golden image build process and runtime.
Place the following near the end of your playbook, bearing in mind the factors that can cause native images to be invalidated (`see MSDN <https://docs.microsoft.com/en-us/dotnet/framework/tools/ngen-exe-native-image-generator#native-images-and-jit-compilation>`_).
.. code-block:: yaml
- name: generate native .NET images for CPU
win_dotnet_ngen:
This page has moved to :ref:`windows_performance`.
+2 -574
View File
@@ -1,578 +1,6 @@
.. _windows_setup:
:orphan:
Setting up a Windows Host
=========================
This document discusses the setup that is required before Ansible can communicate with a Microsoft Windows host.
.. contents::
:local:
Host Requirements
`````````````````
For Ansible to communicate to a Windows host and use Windows modules, the
Windows host must meet these requirements:
* Ansible can generally manage Windows versions under current
and extended support from Microsoft. Ansible can manage desktop OSs including
Windows 8.1, and 10, and server OSs including Windows Server 2012, 2012 R2,
2016, 2019, and 2022.
* 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
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$url = "https://raw.githubusercontent.com/jborean93/ansible-windows/master/scripts/Upgrade-PowerShell.ps1"
$file = "$env: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 (``Restricted `` for Windows clients, or ``RemoteSigned`` for Windows servers). 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 RemoteSigned -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 be installed as part of the system bootstrapping 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
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$url = "https://raw.githubusercontent.com/jborean93/ansible-windows/master/scripts/Install-WMF3Hotfix.ps1"
$file = "$env:temp\Install-WMF3Hotfix.ps1"
(New-Object -TypeName System.Net.WebClient).DownloadFile($url, $file)
powershell.exe -ExecutionPolicy ByPass -File $file -Verbose
For more details, please refer to the `Hotfix document <https://support.microsoft.com/en-us/help/2842230/out-of-memory-error-on-a-computer-that-has-a-customized-maxmemorypersh>`_ from Microsoft.
WinRM Setup
```````````
Once Powershell has been upgraded to at least version 3.0, the final step is to
configure the WinRM service 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.
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:
.. code-block:: powershell
winrm enumerate winrm/config/Listener
This will output something like:
.. code-block:: powershell
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:
.. code-block:: powershell
winrm get winrm/config/Service
winrm get winrm/config/Winrs
This will output something like:
.. code-block:: powershell
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 possible 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.
* ``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:
.. 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:
.. 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:
.. code-block:: powershell
# 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:https://server:5986/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 occurred 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.
Failure to Load Builtin Modules
+++++++++++++++++++++++++++++++
If powershell fails with an error message similar to ``The 'Out-String' command was found in the module 'Microsoft.PowerShell.Utility', but the module could not be loaded.``
then there could be a problem trying to access all the paths specified by the ``PSModulePath`` environment variable.
A common cause of this issue is that the ``PSModulePath`` environment variable contains a UNC path to a file share and
because of the double hop/credential delegation issue the Ansible process cannot access these folders. The way around
this problems is to either:
* Remove the UNC path from the ``PSModulePath`` environment variable, or
* Use an authentication option that supports credential delegation like ``credssp`` or ``kerberos`` with credential delegation enabled
See `KB4076842 <https://support.microsoft.com/en-us/help/4076842>`_ for more information on this problem.
Windows SSH Setup
`````````````````
Ansible 2.8 has added an experimental SSH connection for Windows managed nodes.
.. warning::
Use this feature at your own risk!
Using SSH with Windows is experimental, the implementation may make
backwards incompatible changes in feature releases. The server side
components can be unreliable depending on the version that is installed.
Installing OpenSSH using Windows Settings
-----------------------------------------
OpenSSH can be used to connect Window 10 clients to Windows Server 2019.
OpenSSH Client is available to install on Windows 10 build 1809 and later, while OpenSSH Server is available to install on Windows Server 2019 and later.
Please refer `this guide <https://docs.microsoft.com/en-us/windows-server/administration/openssh/openssh_install_firstuse>`_.
Installing Win32-OpenSSH
------------------------
The first step to using SSH with Windows is to install the `Win32-OpenSSH <https://github.com/PowerShell/Win32-OpenSSH>`_
service on the Windows host. Microsoft offers a way to install ``Win32-OpenSSH`` through a Windows
capability but currently the version that is installed through this process is
too old to work with Ansible. To install ``Win32-OpenSSH`` for use with
Ansible, select one of these installation options:
* Manually install the service, following the `install instructions <https://github.com/PowerShell/Win32-OpenSSH/wiki/Install-Win32-OpenSSH>`_
from Microsoft.
* Install the `openssh <https://chocolatey.org/packages/openssh>`_ package using Chocolatey:
.. code-block:: powershell
choco install --package-parameters=/SSHServerFeature openssh
* Use ``win_chocolatey`` to install the service
.. code-block:: yaml
- name: install the Win32-OpenSSH service
win_chocolatey:
name: openssh
package_params: /SSHServerFeature
state: present
* Use an existing Ansible Galaxy role like `jborean93.win_openssh <https://galaxy.ansible.com/jborean93/win_openssh>`_:
.. code-block:: powershell
# Make sure the role has been downloaded first
ansible-galaxy install jborean93.win_openssh
.. code-block:: yaml
# main.yml
- name: install Win32-OpenSSH service
hosts: windows
gather_facts: no
roles:
- role: jborean93.win_openssh
opt_openssh_setup_service: True
.. note:: ``Win32-OpenSSH`` is still a beta product and is constantly
being updated to include new features and bugfixes. If you are using SSH as
a connection option for Windows, it is highly recommend you install the
latest release from one of the 3 methods above.
Configuring the Win32-OpenSSH shell
-----------------------------------
By default ``Win32-OpenSSH`` will use ``cmd.exe`` as a shell. To configure a
different shell, use an Ansible task to define the registry setting:
.. code-block:: yaml
- name: set the default shell to PowerShell
win_regedit:
path: HKLM:\SOFTWARE\OpenSSH
name: DefaultShell
data: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
type: string
state: present
# Or revert the settings back to the default, cmd
- name: set the default shell to cmd
win_regedit:
path: HKLM:\SOFTWARE\OpenSSH
name: DefaultShell
state: absent
Win32-OpenSSH Authentication
----------------------------
Win32-OpenSSH authentication with Windows is similar to SSH
authentication on Unix/Linux hosts. You can use a plaintext password or
SSH public key authentication, add public keys to an ``authorized_key`` file
in the ``.ssh`` folder of the user's profile directory, and configure the
service using the ``sshd_config`` file used by the SSH service as you would on
a Unix/Linux host.
When using SSH key authentication with Ansible, the remote session won't have access to the
user's credentials and will fail when attempting to access a network resource.
This is also known as the double-hop or credential delegation issue. There are
two ways to work around this issue:
* Use plaintext password auth by setting ``ansible_password``
* Use ``become`` on the task with the credentials of the user that needs access to the remote resource
Configuring Ansible for SSH on Windows
--------------------------------------
To configure Ansible to use SSH for Windows hosts, you must set two connection variables:
* set ``ansible_connection`` to ``ssh``
* set ``ansible_shell_type`` to ``cmd`` or ``powershell``
The ``ansible_shell_type`` variable should reflect the ``DefaultShell``
configured on the Windows host. Set to ``cmd`` for the default shell or set to
``powershell`` if the ``DefaultShell`` has been changed to PowerShell.
Known issues with SSH on Windows
--------------------------------
Using SSH with Windows is experimental, and we expect to uncover more issues.
Here are the known ones:
* Win32-OpenSSH versions older than ``v7.9.0.0p1-Beta`` do not work when ``powershell`` is the shell type
* While SCP should work, SFTP is the recommended SSH file transfer mechanism to use when copying or fetching a file
.. seealso::
:ref:`about_playbooks`
An introduction to playbooks
:ref:`playbooks_best_practices`
Tips and tricks for playbooks
:ref:`List of Windows Modules <windows_modules>`
Windows specific module list, all implemented in PowerShell
`User Mailing List <https://groups.google.com/group/ansible-project>`_
Have a question? Stop by the google group!
:ref:`communication_irc`
How to join Ansible chat channels
This page has moved to :ref:`windows_setup`.
+3 -514
View File
@@ -1,517 +1,6 @@
:orphan:
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
:local:
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:
.. code-block:: yaml+jinja
# 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: https://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: https://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:
.. code-block:: yaml+jinja
- 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:
.. code-block:: yaml+jinja
- 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:
.. code-block:: yaml+jinja
- 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_expires: yes
loop:
- 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:
.. code-block:: yaml+jinja
- 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
loop:
- 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``:
.. code-block:: yaml+jinja
- 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 precedes 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:
.. code-block:: yaml+jinja
- 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" unquoted-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:
.. code-block:: yaml+jinja
- 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 <https://yaml.org/spec/current.html#id2517668>`_:
* ``\0``, ``\\``, ``\"``, ``\_``, ``\a``, ``\b``, ``\e``, ``\f``, ``\n``, ``\r``, ``\t``,
``\v``, ``\L``, ``\N`` and ``\P`` -- 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:
.. code-block:: ini
# 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
This is an example which will fail:
.. code-block:: text
# FAILS
tempdir: "C:\Windows\Temp"
This example shows the use of single quotes when they are required:
.. code-block:: yaml+jinja
---
- 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 ad hoc 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:
.. code-block:: ini
# 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
:ref:`developing_modules_general_windows` for more information.
.. seealso::
:ref:`playbooks_intro`
An introduction to playbooks
:ref:`playbooks_best_practices`
Tips and tricks for playbooks
:ref:`List of Windows Modules <windows_modules>`
Windows specific module list, all implemented in PowerShell
`User Mailing List <https://groups.google.com/group/ansible-project>`_
Have a question? Stop by the google group!
:ref:`communication_irc`
How to join Ansible chat channels
This page has moved to :ref:`windows_usage`.
File diff suppressed because it is too large Load Diff
+26
View File
@@ -0,0 +1,26 @@
.. _win_guide_index:
########################
Using Ansible on Windows
########################
.. note::
**Making Open Source More Inclusive**
Red Hat is committed to replacing problematic language in our code, documentation, and web properties. We are beginning with these four terms: master, slave, blacklist, and whitelist. We ask that you open an issue or pull request if you come upon a term that we have missed. For more details, see `our CTO Chris Wright's message <https://www.redhat.com/en/blog/making-open-source-more-inclusive-eradicating-problematic-language>`_.
Welcome to the Ansible guide for Microsoft Windows.
This guide shows you how to set up Ansible on a Windows host, configure WinRM for Ansible, perform operations, and tune performance.
Additionally, because Windows is not a POSIX-compliant operating system, Ansible interacts with Windows hosts differently to Linux/Unix hosts.
You can find information about those differences, and everything you need to know about using Ansible on Windows, in this guide.
.. toctree::
:maxdepth: 2
windows_setup
windows_usage
windows_winrm
windows_dsc
windows_performance
windows_faq
+508
View File
@@ -0,0 +1,508 @@
.. _windows_dsc:
Desired State Configuration
===========================
.. contents:: Topics
:local:
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 take advantage of
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/scripting/dsc/overview?view=powershell-7.2>`_.
Host Requirements
`````````````````
To use the ``win_dsc`` module, a Windows host must have PowerShell v5.0 or
newer installed. All supported hosts 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/scripting/dsc/reference/resources/windows/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 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/scripting/dsc/resources/resources>`_.
Using the `Registry <https://docs.microsoft.com/en-us/powershell/scripting/dsc/reference/resources/windows/registryresource>`_
resource as an example, this is the DSC definition as documented by Microsoft:
.. code-block:: powershell
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 because 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:
.. code-block:: yaml+jinja
- 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
Starting in Ansible 2.8, the ``win_dsc`` module automatically validates the
input options from Ansible with the DSC definition. This means Ansible will
fail if the option name is incorrect, a mandatory option is not set, or the
value is not a valid choice. When running Ansible with a verbosity level of 3
or more (``-vvv``), the return value will contain the possible invocation
options based on the ``resource_name`` specified. Here is an example of the
invocation output for the above ``Registry`` task:
.. code-block:: ansible-output
changed: [2016] => {
"changed": true,
"invocation": {
"module_args": {
"DependsOn": null,
"Ensure": "Present",
"Force": null,
"Hex": null,
"Key": "HKEY_LOCAL_MACHINE\\SOFTWARE\\ExampleKey",
"PsDscRunAsCredential_password": null,
"PsDscRunAsCredential_username": null,
"ValueData": [
"TestData"
],
"ValueName": "TestValue",
"ValueType": null,
"module_version": "latest",
"resource_name": "Registry"
}
},
"module_version": "1.1",
"reboot_required": false,
"verbose_set": [
"Perform operation 'Invoke CimMethod' with following parameters, ''methodName' = ResourceSet,'className' = MSFT_DSCLocalConfigurationManager,'namespaceName' = root/Microsoft/Windows/DesiredStateConfiguration'.",
"An LCM method call arrived from computer SERVER2016 with user sid S-1-5-21-3088887838-4058132883-1884671576-1105.",
"[SERVER2016]: LCM: [ Start Set ] [[Registry]DirectResourceAccess]",
"[SERVER2016]: [[Registry]DirectResourceAccess] (SET) Create registry key 'HKLM:\\SOFTWARE\\ExampleKey'",
"[SERVER2016]: [[Registry]DirectResourceAccess] (SET) Set registry key value 'HKLM:\\SOFTWARE\\ExampleKey\\TestValue' to 'TestData' of type 'String'",
"[SERVER2016]: LCM: [ End Set ] [[Registry]DirectResourceAccess] in 0.1930 seconds.",
"[SERVER2016]: LCM: [ End Set ] in 0.2720 seconds.",
"Operation 'Invoke CimMethod' complete.",
"Time taken for configuration job to complete is 0.402 seconds"
],
"verbose_test": [
"Perform operation 'Invoke CimMethod' with following parameters, ''methodName' = ResourceTest,'className' = MSFT_DSCLocalConfigurationManager,'namespaceName' = root/Microsoft/Windows/DesiredStateConfiguration'.",
"An LCM method call arrived from computer SERVER2016 with user sid S-1-5-21-3088887838-4058132883-1884671576-1105.",
"[SERVER2016]: LCM: [ Start Test ] [[Registry]DirectResourceAccess]",
"[SERVER2016]: [[Registry]DirectResourceAccess] Registry key 'HKLM:\\SOFTWARE\\ExampleKey' does not exist",
"[SERVER2016]: LCM: [ End Test ] [[Registry]DirectResourceAccess] False in 0.2510 seconds.",
"[SERVER2016]: LCM: [ End Set ] in 0.3310 seconds.",
"Operation 'Invoke CimMethod' complete.",
"Time taken for configuration job to complete is 0.475 seconds"
]
}
The ``invocation.module_args`` key shows the actual values that were set as
well as other possible values that were not set. Unfortunately, this will not
show the default value for a DSC property, only what was set from the Ansible
task. Any ``*_password`` option will be masked in the output for security
reasons; if there are any other sensitive module options, set ``no_log: True``
on the task to stop all task output from being logged.
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[]]``)
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:
.. code-block:: yaml+jinja
PsDscRunAsCredential_username: '{{ ansible_user }}'
PsDscRunAsCredential_password: '{{ ansible_password }}'
SourceCredential_username: AdminUser
SourceCredential_password: PasswordForAdminUser
.. Note:: On versions of Ansible older than 2.8, you should set ``no_log: yes``
on the task definition in Ansible to ensure any credentials used are not
stored in any log file or console output.
A ``[PSCredential]`` is defined with ``EmbeddedInstance("MSFT_Credential")`` in
a DSC resource MOF definition.
CimInstance Type
++++++++++++++++
A ``[CimInstance]`` object is used by DSC to store a dictionary object based on
a custom class defined by that resource. Defining a value that takes in a
``[CimInstance]`` in YAML is the same as defining a dictionary in YAML.
For example, to define a ``[CimInstance]`` value in Ansible:
.. code-block:: yaml+jinja
# [CimInstance]AuthenticationInfo == MSFT_xWebAuthenticationInformation
AuthenticationInfo:
Anonymous: no
Basic: yes
Digest: no
Windows: yes
In the above example, the CIM instance is a representation of the class
`MSFT_xWebAuthenticationInformation <https://github.com/dsccommunity/xWebAdministration/blob/master/source/DSCResources/MSFT_xWebSite/MSFT_xWebSite.schema.mof>`_.
This class accepts four boolean variables, ``Anonymous``, ``Basic``,
``Digest``, and ``Windows``. The keys to use in a ``[CimInstance]`` depend on
the class it represents. Please read through the documentation of the resource
to determine the keys that can be used and the types of each key value. The
class definition is typically located in the ``<resource name>.schema.mof``.
HashTable Type
++++++++++++++
A ``[HashTable]`` object is also a dictionary but does not have a strict set of
keys that can/need to be defined. Like a ``[CimInstance]``, define it as a
normal dictionary value in YAML. A ``[HashTable]]`` is defined with
``EmbeddedInstance("MSFT_KeyValuePair")`` in a DSC resource MOF definition.
Arrays
++++++
Simple type arrays like ``[string[]]`` or ``[UInt32[]]`` are defined as a list
or as a comma-separated string which is then cast to their type. Using a list
is recommended because the values are not manually parsed by the ``win_dsc``
module before being passed to the DSC engine. For example, to define a simple
type array in Ansible:
.. code-block:: yaml+jinja
# [string[]]
ValueData: entry1, entry2, entry3
ValueData:
- entry1
- entry2
- entry3
# [UInt32[]]
ReturnCode: 0,3010
ReturnCode:
- 0
- 3010
Complex type arrays like ``[CimInstance[]]`` (array of dicts), can be defined
like this example:
.. code-block:: yaml+jinja
# [CimInstance[]]BindingInfo == MSFT_xWebBindingInformation
BindingInfo:
- Protocol: https
Port: 443
CertificateStoreName: My
CertificateThumbprint: C676A89018C4D5902353545343634F35E6B3A659
HostName: DSCTest
IPAddress: '*'
SSLFlags: 1
- Protocol: http
Port: 80
IPAddress: '*'
The above example is an array with two values of the class `MSFT_xWebBindingInformation <https://github.com/dsccommunity/xWebAdministration/blob/master/source/DSCResources/MSFT_xWebSite/MSFT_xWebSite.schema.mof>`_.
When defining a ``[CimInstance[]]``, be sure to read the resource documentation
to find out what keys to use in the definition.
DateTime
++++++++
A ``[DateTime]`` object is a DateTime string representing the date and time in
the `ISO 8601 <https://www.w3.org/TR/NOTE-datetime>`_ date time format. The
value for a ``[DateTime]`` field should be quoted in YAML to ensure the string
is properly serialized to the Windows host. Here is an example of how to define
a ``[DateTime]`` value in Ansible:
.. code-block:: yaml+jinja
# As UTC-0 (No timezone)
DateTime: '2019-02-22T13:57:31.2311892+00:00'
# As UTC+4
DateTime: '2019-02-22T17:57:31.2311892+04:00'
# As UTC-4
DateTime: '2019-02-22T09:57:31.2311892-04:00'
All the values above are equal to a UTC date time of February 22nd 2019 at
1:57pm with 31 seconds and 2311892 milliseconds.
Run As Another User
-------------------
By default, DSC runs each resource as the SYSTEM account and not the account
that Ansible uses 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, and
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:
.. code-block:: yaml+jinja
- 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: yes
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 to another host
The following is an example of installing the ``xWebAdministration`` resources using
``win_psmodule``:
.. code-block:: yaml+jinja
- 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:
.. code-block:: powershell
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+jinja
- 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+jinja
- 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+jinja
- 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: yes
Ensure: Present
Credential_username: '{{ ansible_user }}'
Credential_password: '{{ ansible_password }}'
Setup IIS Website
-----------------
.. code-block:: yaml+jinja
- 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
loop:
- Web-Server
- Web-Asp-Net45
- 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
BindingInfo:
- Protocol: https
Port: 8443
CertificateStoreName: My
CertificateThumbprint: C676A89018C4D5902353545343634F35E6B3A659
HostName: DSCTest
IPAddress: '*'
SSLFlags: 1
- Protocol: http
Port: 8080
IPAddress: '*'
AuthenticationInfo:
Anonymous: no
Basic: yes
Digest: no
Windows: yes
.. seealso::
:ref:`playbooks_intro`
An introduction to playbooks
:ref:`playbooks_best_practices`
Tips and tricks for playbooks
:ref:`List of Windows Modules <windows_modules>`
Windows specific module list, all implemented in PowerShell
`User Mailing List <https://groups.google.com/group/ansible-project>`_
Have a question? Stop by the google group!
:ref:`communication_irc`
How to join Ansible chat channels
+257
View File
@@ -0,0 +1,257 @@
.. _windows_faq:
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
:ref:`general FAQ page <ansible_faq>`.
Does Ansible work with Windows XP or Server 2003?
``````````````````````````````````````````````````
Ansible does not work with Windows XP or Server 2003 hosts. Ansible does work with these Windows operating system versions:
* Windows Server 2008 :sup:`1`
* Windows Server 2008 R2 :sup:`1`
* Windows Server 2012
* Windows Server 2012 R2
* Windows Server 2016
* Windows Server 2019
* Windows 7 :sup:`1`
* Windows 8.1
* Windows 10
1 - See the :ref:`Server 2008 FAQ <windows_faq_server2008>` entry for more details.
Ansible also has minimum PowerShell version requirements - please see
:ref:`windows_setup` for the latest information.
.. _windows_faq_server2008:
Are Server 2008, 2008 R2 and Windows 7 supported?
`````````````````````````````````````````````````
Microsoft ended Extended Support for these versions of Windows on January 14th, 2020, and Ansible deprecated official support in the 2.10 release. No new feature development will occur targeting these operating systems, and automated testing has ceased. However, existing modules and features will likely continue to work, and simple pull requests to resolve issues with these Windows versions may be accepted.
Can I manage Windows Nano Server with Ansible?
``````````````````````````````````````````````
Ansible does not currently work with Windows Nano Server, since it does
not have access to the full .NET Framework that is used by the majority of the
modules and internal components.
.. _windows_faq_ansible:
Can Ansible run on Windows?
```````````````````````````
No, Ansible can only manage Windows hosts. Ansible cannot run on a Windows host
natively, though it can run under the Windows Subsystem for Linux (WSL).
.. note:: The Windows Subsystem for Linux is not supported by 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-pip git libffi-dev libssl-dev -y
pip install --user 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
If you encounter timeout errors when running Ansible on the WSL, this may be due to an issue
with ``sleep`` not returning correctly. The following workaround may resolve the issue:
.. code-block:: shell
mv /usr/bin/sleep /usr/bin/sleep.orig
ln -s /bin/true /usr/bin/sleep
Another option is to use WSL 2 if running Windows 10 later than build 2004.
.. code-block:: shell
wsl --set-default-version 2
Can I use SSH keys to authenticate to Windows hosts?
````````````````````````````````````````````````````
You cannot use SSH keys with the WinRM or PSRP connection plugins.
These connection plugins use X509 certificates for authentication instead
of the SSH key pairs that SSH uses.
The way X509 certificates are generated and mapped to a user is different
from the SSH implementation; consult the :ref:`windows_winrm` documentation for
more information.
Ansible 2.8 has added an experimental option to use the SSH connection plugin,
which uses SSH keys for authentication, for Windows servers. See :ref:`this question <windows_faq_ssh>`
for more information.
.. _windows_faq_winrm:
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 :ref:`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, you can use
CredSSP or Kerberos with credential delegation enabled.
See :ref:`become` more info on how to use become. The limitations section at
:ref:`windows_winrm` has more details around WinRM limitations.
This program won't install on Windows with Ansible
``````````````````````````````````````````````````
See :ref:`this question <windows_faq_winrm>` for more information about WinRM limitations.
What Windows 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 these modules
can be found :ref:`here <windows_modules>`.
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_template)
* wait_for_connection
Ansible Windows modules exist in the :ref:`plugins_in_ansible.windows`, :ref:`plugins_in_community.windows`, and :ref:`plugins_in_chocolatey.chocolatey` collections.
Can I run Python modules on Windows hosts?
``````````````````````````````````````````
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.
.. _windows_faq_ssh:
Can I connect to Windows hosts over SSH?
````````````````````````````````````````
Ansible 2.8 has added an experimental option to use the SSH connection plugin
to manage Windows hosts. To connect to Windows hosts over SSH, you must install and configure the `Win32-OpenSSH <https://github.com/PowerShell/Win32-OpenSSH>`_
fork that is in development with Microsoft on
the Windows host(s). While most of the basics should work with SSH,
``Win32-OpenSSH`` is rapidly changing, with new features added and bugs
fixed in every release. It is highly recommend you `install <https://github.com/PowerShell/Win32-OpenSSH/wiki/Install-Win32-OpenSSH>`_ the latest release
of ``Win32-OpenSSH`` from the GitHub Releases page when using it with Ansible
on Windows hosts.
To use SSH as the connection to a Windows host, set the following variables in
the inventory:
.. code-block:: shell
ansible_connection=ssh
# Set either cmd or powershell not both
ansible_shell_type=cmd
# ansible_shell_type=powershell
The value for ``ansible_shell_type`` should either be ``cmd`` or ``powershell``.
Use ``cmd`` if the ``DefaultShell`` has not been configured on the SSH service
and ``powershell`` if that has been set as the ``DefaultShell``.
Why is connecting to a Windows host via SSH failing?
````````````````````````````````````````````````````
Unless you are using ``Win32-OpenSSH`` as described above, you must connect to
Windows hosts using :ref:`windows_winrm`. If your Ansible output indicates that
SSH was used, either you did not set the connection vars properly or the host is not inheriting them correctly.
Make sure ``ansible_connection: winrm`` is set in the inventory for the Windows
host(s).
Why are my credentials being rejected?
``````````````````````````````````````
This can be due to a myriad of reasons unrelated to incorrect credentials.
See HTTP 401/Credentials Rejected at :ref:`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::
:ref:`windows`
The Windows documentation index
:ref:`about_playbooks`
An introduction to playbooks
:ref:`playbooks_best_practices`
Tips and tricks for playbooks
`User Mailing List <https://groups.google.com/group/ansible-project>`_
Have a question? Stop by the google group!
:ref:`communication_irc`
How to join Ansible chat channels
@@ -0,0 +1,61 @@
.. _windows_performance:
Windows performance
===================
This document offers some performance optimizations you might like to apply to
your Windows hosts to speed them up specifically in the context of using Ansible
with them, and generally.
Optimize PowerShell performance to reduce Ansible task overhead
---------------------------------------------------------------
To speed up the startup of PowerShell by around 10x, run the following
PowerShell snippet in an Administrator session. Expect it to take tens of
seconds.
.. note::
If native images have already been created by the ngen task or service, you
will observe no difference in performance (but this snippet will at that
point execute faster than otherwise).
.. code-block:: powershell
function Optimize-PowershellAssemblies {
# NGEN powershell assembly, improves startup time of powershell by 10x
$old_path = $env:path
try {
$env:path = [Runtime.InteropServices.RuntimeEnvironment]::GetRuntimeDirectory()
[AppDomain]::CurrentDomain.GetAssemblies() | % {
if (! $_.location) {continue}
$Name = Split-Path $_.location -leaf
if ($Name.startswith("Microsoft.PowerShell.")) {
Write-Progress -Activity "Native Image Installation" -Status "$name"
ngen install $_.location | % {"`t$_"}
}
}
} finally {
$env:path = $old_path
}
}
Optimize-PowershellAssemblies
PowerShell is used by every Windows Ansible module. This optimization reduces
the time PowerShell takes to start up, removing that overhead from every invocation.
This snippet uses `the native image generator, ngen <https://docs.microsoft.com/en-us/dotnet/framework/tools/ngen-exe-native-image-generator#WhenToUse>`_
to pre-emptively create native images for the assemblies that PowerShell relies on.
Fix high-CPU-on-boot for VMs/cloud instances
--------------------------------------------
If you are creating golden images to spawn instances from, you can avoid a disruptive
high CPU task near startup via `processing the ngen queue <https://docs.microsoft.com/en-us/dotnet/framework/tools/ngen-exe-native-image-generator#native-image-service>`_
within your golden image creation, if you know the CPU types won't change between
golden image build process and runtime.
Place the following near the end of your playbook, bearing in mind the factors that can cause native images to be invalidated (`see MSDN <https://docs.microsoft.com/en-us/dotnet/framework/tools/ngen-exe-native-image-generator#native-images-and-jit-compilation>`_).
.. code-block:: yaml
- name: generate native .NET images for CPU
win_dotnet_ngen:
@@ -0,0 +1,578 @@
.. _windows_setup:
Setting up a Windows Host
=========================
This document discusses the setup that is required before Ansible can communicate with a Microsoft Windows host.
.. contents::
:local:
Host Requirements
`````````````````
For Ansible to communicate to a Windows host and use Windows modules, the
Windows host must meet these requirements:
* Ansible can generally manage Windows versions under current
and extended support from Microsoft. Ansible can manage desktop OSs including
Windows 8.1, and 10, and server OSs including Windows Server 2012, 2012 R2,
2016, 2019, and 2022.
* 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
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$url = "https://raw.githubusercontent.com/jborean93/ansible-windows/master/scripts/Upgrade-PowerShell.ps1"
$file = "$env: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 (``Restricted `` for Windows clients, or ``RemoteSigned`` for Windows servers). 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 RemoteSigned -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 be installed as part of the system bootstrapping 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
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$url = "https://raw.githubusercontent.com/jborean93/ansible-windows/master/scripts/Install-WMF3Hotfix.ps1"
$file = "$env:temp\Install-WMF3Hotfix.ps1"
(New-Object -TypeName System.Net.WebClient).DownloadFile($url, $file)
powershell.exe -ExecutionPolicy ByPass -File $file -Verbose
For more details, please refer to the `Hotfix document <https://support.microsoft.com/en-us/help/2842230/out-of-memory-error-on-a-computer-that-has-a-customized-maxmemorypersh>`_ from Microsoft.
WinRM Setup
```````````
Once Powershell has been upgraded to at least version 3.0, the final step is to
configure the WinRM service 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.
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:
.. code-block:: powershell
winrm enumerate winrm/config/Listener
This will output something like:
.. code-block:: powershell
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:
.. code-block:: powershell
winrm get winrm/config/Service
winrm get winrm/config/Winrs
This will output something like:
.. code-block:: powershell
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 possible 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.
* ``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:
.. 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:
.. 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:
.. code-block:: powershell
# 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:https://server:5986/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 occurred 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.
Failure to Load Builtin Modules
+++++++++++++++++++++++++++++++
If powershell fails with an error message similar to ``The 'Out-String' command was found in the module 'Microsoft.PowerShell.Utility', but the module could not be loaded.``
then there could be a problem trying to access all the paths specified by the ``PSModulePath`` environment variable.
A common cause of this issue is that the ``PSModulePath`` environment variable contains a UNC path to a file share and
because of the double hop/credential delegation issue the Ansible process cannot access these folders. The way around
this problems is to either:
* Remove the UNC path from the ``PSModulePath`` environment variable, or
* Use an authentication option that supports credential delegation like ``credssp`` or ``kerberos`` with credential delegation enabled
See `KB4076842 <https://support.microsoft.com/en-us/help/4076842>`_ for more information on this problem.
Windows SSH Setup
`````````````````
Ansible 2.8 has added an experimental SSH connection for Windows managed nodes.
.. warning::
Use this feature at your own risk!
Using SSH with Windows is experimental, the implementation may make
backwards incompatible changes in feature releases. The server side
components can be unreliable depending on the version that is installed.
Installing OpenSSH using Windows Settings
-----------------------------------------
OpenSSH can be used to connect Window 10 clients to Windows Server 2019.
OpenSSH Client is available to install on Windows 10 build 1809 and later, while OpenSSH Server is available to install on Windows Server 2019 and later.
Please refer `this guide <https://docs.microsoft.com/en-us/windows-server/administration/openssh/openssh_install_firstuse>`_.
Installing Win32-OpenSSH
------------------------
The first step to using SSH with Windows is to install the `Win32-OpenSSH <https://github.com/PowerShell/Win32-OpenSSH>`_
service on the Windows host. Microsoft offers a way to install ``Win32-OpenSSH`` through a Windows
capability but currently the version that is installed through this process is
too old to work with Ansible. To install ``Win32-OpenSSH`` for use with
Ansible, select one of these installation options:
* Manually install the service, following the `install instructions <https://github.com/PowerShell/Win32-OpenSSH/wiki/Install-Win32-OpenSSH>`_
from Microsoft.
* Install the `openssh <https://chocolatey.org/packages/openssh>`_ package using Chocolatey:
.. code-block:: powershell
choco install --package-parameters=/SSHServerFeature openssh
* Use ``win_chocolatey`` to install the service
.. code-block:: yaml
- name: install the Win32-OpenSSH service
win_chocolatey:
name: openssh
package_params: /SSHServerFeature
state: present
* Use an existing Ansible Galaxy role like `jborean93.win_openssh <https://galaxy.ansible.com/jborean93/win_openssh>`_:
.. code-block:: powershell
# Make sure the role has been downloaded first
ansible-galaxy install jborean93.win_openssh
.. code-block:: yaml
# main.yml
- name: install Win32-OpenSSH service
hosts: windows
gather_facts: no
roles:
- role: jborean93.win_openssh
opt_openssh_setup_service: True
.. note:: ``Win32-OpenSSH`` is still a beta product and is constantly
being updated to include new features and bugfixes. If you are using SSH as
a connection option for Windows, it is highly recommend you install the
latest release from one of the 3 methods above.
Configuring the Win32-OpenSSH shell
-----------------------------------
By default ``Win32-OpenSSH`` will use ``cmd.exe`` as a shell. To configure a
different shell, use an Ansible task to define the registry setting:
.. code-block:: yaml
- name: set the default shell to PowerShell
win_regedit:
path: HKLM:\SOFTWARE\OpenSSH
name: DefaultShell
data: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
type: string
state: present
# Or revert the settings back to the default, cmd
- name: set the default shell to cmd
win_regedit:
path: HKLM:\SOFTWARE\OpenSSH
name: DefaultShell
state: absent
Win32-OpenSSH Authentication
----------------------------
Win32-OpenSSH authentication with Windows is similar to SSH
authentication on Unix/Linux hosts. You can use a plaintext password or
SSH public key authentication, add public keys to an ``authorized_key`` file
in the ``.ssh`` folder of the user's profile directory, and configure the
service using the ``sshd_config`` file used by the SSH service as you would on
a Unix/Linux host.
When using SSH key authentication with Ansible, the remote session won't have access to the
user's credentials and will fail when attempting to access a network resource.
This is also known as the double-hop or credential delegation issue. There are
two ways to work around this issue:
* Use plaintext password auth by setting ``ansible_password``
* Use ``become`` on the task with the credentials of the user that needs access to the remote resource
Configuring Ansible for SSH on Windows
--------------------------------------
To configure Ansible to use SSH for Windows hosts, you must set two connection variables:
* set ``ansible_connection`` to ``ssh``
* set ``ansible_shell_type`` to ``cmd`` or ``powershell``
The ``ansible_shell_type`` variable should reflect the ``DefaultShell``
configured on the Windows host. Set to ``cmd`` for the default shell or set to
``powershell`` if the ``DefaultShell`` has been changed to PowerShell.
Known issues with SSH on Windows
--------------------------------
Using SSH with Windows is experimental, and we expect to uncover more issues.
Here are the known ones:
* Win32-OpenSSH versions older than ``v7.9.0.0p1-Beta`` do not work when ``powershell`` is the shell type
* While SCP should work, SFTP is the recommended SSH file transfer mechanism to use when copying or fetching a file
.. seealso::
:ref:`about_playbooks`
An introduction to playbooks
:ref:`playbooks_best_practices`
Tips and tricks for playbooks
:ref:`List of Windows Modules <windows_modules>`
Windows specific module list, all implemented in PowerShell
`User Mailing List <https://groups.google.com/group/ansible-project>`_
Have a question? Stop by the google group!
:ref:`communication_irc`
How to join Ansible chat channels
@@ -0,0 +1,519 @@
.. _windows_usage:
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
:local:
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:
.. code-block:: yaml+jinja
# 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: https://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: https://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:
.. code-block:: yaml+jinja
- 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:
.. code-block:: yaml+jinja
- 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:
.. code-block:: yaml+jinja
- 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_expires: yes
loop:
- 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:
.. code-block:: yaml+jinja
- 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
loop:
- 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``:
.. code-block:: yaml+jinja
- 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 precedes 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:
.. code-block:: yaml+jinja
- 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" unquoted-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:
.. code-block:: yaml+jinja
- 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 <https://yaml.org/spec/current.html#id2517668>`_:
* ``\0``, ``\\``, ``\"``, ``\_``, ``\a``, ``\b``, ``\e``, ``\f``, ``\n``, ``\r``, ``\t``,
``\v``, ``\L``, ``\N`` and ``\P`` -- 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:
.. code-block:: ini
# 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
This is an example which will fail:
.. code-block:: text
# FAILS
tempdir: "C:\Windows\Temp"
This example shows the use of single quotes when they are required:
.. code-block:: yaml+jinja
---
- 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 ad hoc 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:
.. code-block:: ini
# 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
:ref:`developing_modules_general_windows` for more information.
.. seealso::
:ref:`playbooks_intro`
An introduction to playbooks
:ref:`playbooks_best_practices`
Tips and tricks for playbooks
:ref:`List of Windows Modules <windows_modules>`
Windows specific module list, all implemented in PowerShell
`User Mailing List <https://groups.google.com/group/ansible-project>`_
Have a question? Stop by the google group!
:ref:`communication_irc`
How to join Ansible chat channels
File diff suppressed because it is too large Load Diff