From 57ed6a866f235d84b0316069d0a5fb4cd6de7159 Mon Sep 17 00:00:00 2001 From: Jordan Borean Date: Thu, 4 Jan 2018 03:26:53 +1000 Subject: [PATCH] windows: Add IPv6 address support and docs to go with it (#34072) * windows: Add IPv6 address support and docs to go with it * minor docs fix * fixed some doc sentances --- docs/docsite/rst/windows_winrm.rst | 50 ++++++++++++++++++------- lib/ansible/plugins/connection/winrm.py | 20 +++++++++- 2 files changed, 55 insertions(+), 15 deletions(-) diff --git a/docs/docsite/rst/windows_winrm.rst b/docs/docsite/rst/windows_winrm.rst index 9b025d7341..8f43990619 100644 --- a/docs/docsite/rst/windows_winrm.rst +++ b/docs/docsite/rst/windows_winrm.rst @@ -25,7 +25,7 @@ with the Ansible package, but can be installed by running the following:: Authentication Options `````````````````````` When connecting to a Windows host, there are several different options that can be used -when authentication with an account. The authentication type may be set on inventory +when authenticating with an account. The authentication type may be set on inventory hosts or groups with the ``ansible_winrm_transport`` variable. The following matrix is a high level overview of the options: @@ -97,7 +97,7 @@ This can be done using one of the following methods: * Active Directory Certificate Services Active Directory Certificate Services is beyond of scope in this documentation but may be -the best option to use when running in a domain environment. For more information, +the best option to use when running in a domain environment. For more information, see the `Active Directory Certificate Services documentation `_. .. Note:: Using the PowerShell cmdlet ``New-SelfSignedCertificate`` to generate @@ -142,7 +142,7 @@ To generate a certificate with ``New-SelfSignedCertificate``: -KeyUsage DigitalSignature,KeyEncipherment ` -KeyAlgorithm RSA ` -KeyLength 2048 - + # export the public key $pem_output = @() $pem_output += "-----BEGIN CERTIFICATE-----" @@ -236,7 +236,7 @@ service, so no setup is required before using it. NTLM is the easiest authentication protocol to use and is more secure than ``Basic`` authentication. If running in a domain environment, ``Kerberos`` should be used -instead of NTLM. +instead of NTLM. Kerberos has several advantages over using NTLM: @@ -271,7 +271,7 @@ The following example shows host vars configured for Kerberos authentication:: ansible_winrm_transport: kerberos As of Ansible version 2.3, the Kerberos ticket will be created based on -``ansible_user`` and ``ansible_password``. If running on an older version of +``ansible_user`` and ``ansible_password``. If running on an older version of Ansible or when ``ansible_winrm_kinit_mode`` is ``manual``, a Kerberos ticket must already be obtained. See below for more details. @@ -471,7 +471,7 @@ CredSSP and TLS 1.2 +++++++++++++++++++ By default the ``requests-credssp`` library is configured to authenticate over the TLS 1.2 protocol. TLS 1.2 is installed and enabled by default for Windows Server 2012 -and Windows 8 and more recent releases. +and Windows 8 and more recent releases. There are two ways that older hosts can be used with CredSSP: @@ -479,12 +479,12 @@ There are two ways that older hosts can be used with CredSSP: for Server 2008 R2 and Windows 7). * Set ``ansible_winrm_credssp_disable_tlsv1_2=True`` in the inventory to run - over TLS 1.0. This is the only option when connecting to Windows Server 2008, which + over TLS 1.0. This is the only option when connecting to Windows Server 2008, which has no way of supporting TLS 1.2 To enable TLS 1.2 support on Server 2008 R2 and Windows 7, the optional update `KRB3080079 `_ -needs to be installed. +needs to be installed. Once the update has been applied and the Windows host rebooted, run the following PowerShell commands to enable TLS 1.2: @@ -507,7 +507,7 @@ CredSSP works by encrypting the credentials through the TLS protocol and uses a another certificate. .. Note:: This certificate configuration is independent of the WinRM listener - certificate. With CredSSP, message transport still occurs over the WinRM listener, + certificate. With CredSSP, message transport still occurs over the WinRM listener, but the TLS-encrypted messages inside the channel use the service-level certificate. To explicitly set the certificate to use for CredSSP: @@ -531,7 +531,7 @@ WinRM is configured by default to only allow connections from accounts in the lo winrm configSDDL default This will display an ACL editor, where new users or groups may be added. To run commands -over WinRM, users and groups must have at least the ``Read`` and ``Execute`` permissions +over WinRM, users and groups must have at least the ``Read`` and ``Execute`` permissions enabled. While non-administrative accounts can be used with WinRM, most typical server administration @@ -581,12 +581,11 @@ When setting up the inventory, the following variables are required:: # it is suggested that these be encrypted with ansible-vault: # ansible-vault edit group_vars/windows.yml - ansible_connection: winrm # may also be passed on the command-line via --user ansible_user: Administrator - + # may also be supplied at runtime with --ask-pass ansible_password: SecretPasswordGoesHere @@ -657,6 +656,29 @@ for each authentication option. See the section on authentication above for more encryption done over TLS. The WinRM payload is still encrypted with TLS when run over HTTPS, even if ``ansible_winrm_message_encryption=never``. +IPv6 Addresses +`````````````` +IPv6 addresses can be used instead of IPv4 addresses or hostnames. This option +is normally set in an inventory. Ansible will attempt to parse the address +using the `ipaddress `_ +package and pass to pywinrm correctly. + +When defining a host using an IPv6 address, just add the IPv6 address as you +would an IPv4 address or hostname:: + + [windows-server] + 2001:db8::1 + + [windows-server:vars] + ansible_user=username + ansible_password=password + ansible_connection=winrm + + +.. Note:: The ipaddress library is only included by default in Python 3.x. To + use IPv6 addresses in Python 2.6 and 2.7, make sure to run + ``pip install ipaddress`` which installs a backported package. + Limitations ``````````` Due to the design of the WinRM protocol , there are a few limitations @@ -675,9 +697,9 @@ These include: * Commands under WinRM are done under a non-interactive session, which can prevent certain commands or executables from running. -* You cannot run a process that interacts with ``DPAPI``, which is used by some +* You cannot run a process that interacts with ``DPAPI``, which is used by some installers (like Microsoft SQL Server). - + Some of these limitations can be mitigated by doing one of the following: * Set ``ansible_winrm_transport`` to ``credssp`` or ``kerberos`` (with diff --git a/lib/ansible/plugins/connection/winrm.py b/lib/ansible/plugins/connection/winrm.py index 5c5e43aef7..0332ba6cff 100644 --- a/lib/ansible/plugins/connection/winrm.py +++ b/lib/ansible/plugins/connection/winrm.py @@ -144,6 +144,13 @@ try: except ImportError as e: HAS_PEXPECT = False +# used to try and parse the hostname and detect if IPv6 is being used +try: + import ipaddress + HAS_IPADDRESS = True +except ImportError: + HAS_IPADRESS = False + try: from __main__ import display except ImportError: @@ -297,7 +304,18 @@ class Connection(ConnectionBase): ''' display.vvv("ESTABLISH WINRM CONNECTION FOR USER: %s on PORT %s TO %s" % (self._winrm_user, self._winrm_port, self._winrm_host), host=self._winrm_host) - netloc = '%s:%d' % (self._winrm_host, self._winrm_port) + + winrm_host = self._winrm_host + if HAS_IPADDRESS: + display.vvvv("checking if winrm_host %s is an IPv6 address" % winrm_host) + try: + ipaddress.IPv6Address(winrm_host) + except ipaddress.AddressValueError: + pass + else: + winrm_host = "[%s]" % winrm_host + + netloc = '%s:%d' % (winrm_host, self._winrm_port) endpoint = urlunsplit((self._winrm_scheme, netloc, self._winrm_path, '', '')) errors = [] for transport in self._winrm_transport: