Windows 远程管理
与默认使用 SSH 的 Linux/Unix 主机不同,Windows 主机配置了 WinRM。本主题介绍如何在 Ansible 中配置和使用 WinRM。
什么是 WinRM?
WinRM 是 Windows 用于远程与其他服务器通信的管理协议。它是一个基于 SOAP 的协议,通过 HTTP/HTTPS 通信,包含在所有最新的 Windows 操作系统中。从 Windows Server 2012 开始,WinRM 默认启用,但在大多数情况下,需要额外的配置才能将 WinRM 与 Ansible 结合使用。
Ansible 使用 pywinrm 包通过 WinRM 与 Windows 服务器通信。它不会默认安装在 Ansible 包中。
如果您选择了 pipx
安装说明,您可以通过运行以下命令来安装它
pipx inject ansible pywinrm # if you installed ansible with pipx
pipx inject ansible-core pywinrm # if you installed ansible-core with pipx
或者,如果您选择了 pip
安装说明
pip install "pywinrm>=0.3.0"
注意
在具有多个 Python 版本的发行版中,请使用 pip2 或 pip2.x,其中 x 与 Ansible 运行所在的 Python 次要版本匹配。
警告
在最新版本中,在 MacOS 上的 Ansible 中使用 winrm
或 psrp
连接插件通常会导致失败。这是一个已知问题,发生在 Python 堆栈的深处,Ansible 无法改变它。今天唯一的解决方法是设置环境变量 no_proxy=*
并避免使用 Kerberos 身份验证。
WinRM 身份验证选项
连接到 Windows 主机时,使用帐户进行身份验证时可以使用几种不同的选项。身份验证类型可以在清单主机或组上使用 ansible_winrm_transport
变量进行设置。
以下矩阵是选项的高级概述
选项 |
本地帐户 |
Active Directory 帐户 |
凭据委派 |
HTTP 加密 |
---|---|---|---|---|
基本 |
是 |
否 |
否 |
否 |
证书 |
是 |
否 |
否 |
否 |
Kerberos |
否 |
是 |
是 |
是 |
NTLM |
是 |
是 |
否 |
是 |
CredSSP |
是 |
是 |
是 |
是 |
基本
基本身份验证是使用最简单的身份验证选项之一,但也是最不安全的。这是因为用户名和密码只是 base64 编码的,如果未使用安全通道(例如 HTTPS),那么任何人都可以对其进行解码。基本身份验证只能用于本地帐户(不能用于域帐户)。
以下示例显示为基本身份验证配置的主机变量
ansible_user: LocalUsername
ansible_password: Password
ansible_connection: winrm
ansible_winrm_transport: basic
基本身份验证在 Windows 主机上默认未启用,但可以通过在 PowerShell 中运行以下命令来启用
Set-Item -Path WSMan:\localhost\Service\Auth\Basic -Value $true
证书
证书身份验证使用证书作为密钥,类似于 SSH 密钥对,但文件格式和密钥生成过程不同。
以下示例显示为证书身份验证配置的主机变量
ansible_connection: winrm
ansible_winrm_cert_pem: /path/to/certificate/public/key.pem
ansible_winrm_cert_key_pem: /path/to/certificate/private/key.pem
ansible_winrm_transport: certificate
证书身份验证在 Windows 主机上默认未启用,但可以通过在 PowerShell 中运行以下命令来启用
Set-Item -Path WSMan:\localhost\Service\Auth\Certificate -Value $true
注意
无法使用加密的私钥,因为 Ansible 用于 WinRM 的 urllib3 库不支持此功能。
注意
要启用使用 TLS 1.3 连接的证书身份验证,需要 Python 3.8+、3.7.1 或 3.6.7 和 Python 包 urllib3==2.0.7 或更高版本。
.._winrm_certificate_generate
生成证书
必须生成证书才能将其映射到本地用户。这可以使用以下方法之一来完成
OpenSSL
PowerShell,使用
New-SelfSignedCertificate
cmdletActive Directory 证书服务
Active Directory 证书服务超出了本文档的范围,但可能是域环境中使用的最佳选择。有关更多信息,请参阅 Active Directory 证书服务文档。
注意
使用 PowerShell cmdlet New-SelfSignedCertificate
生成用于身份验证的证书仅适用于从 Windows 10 或 Windows Server 2012 R2 主机或更高版本生成。仍然需要 OpenSSL 从 PFX 证书中提取私钥到 PEM 文件,以便 Ansible 使用。
要使用 OpenSSL
生成证书
# Set the name of the local user that will have the key mapped to
USERNAME="username"
cat > openssl.conf << EOL
distinguished_name = req_distinguished_name
[req_distinguished_name]
[v3_req_client]
extendedKeyUsage = clientAuth
subjectAltName = otherName:1.3.6.1.4.1.311.20.2.3;UTF8:$USERNAME@localhost
EOL
export OPENSSL_CONF=openssl.conf
openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -out cert.pem -outform PEM -keyout cert_key.pem -subj "/CN=$USERNAME" -extensions v3_req_client
rm openssl.conf
要使用 New-SelfSignedCertificate
生成证书
# Set the name of the local user that will have the key mapped
$username = "username"
$output_path = "C:\temp"
# Instead of generating a file, the cert will be added to the personal
# LocalComputer folder in the certificate store
$cert = New-SelfSignedCertificate -Type Custom `
-Subject "CN=$username" `
-TextExtension @("2.5.29.37={text}1.3.6.1.5.5.7.3.2","2.5.29.17={text}upn=$username@localhost") `
-KeyUsage DigitalSignature,KeyEncipherment `
-KeyAlgorithm RSA `
-KeyLength 2048
# Export the public key
$pem_output = @()
$pem_output += "-----BEGIN CERTIFICATE-----"
$pem_output += [System.Convert]::ToBase64String($cert.RawData) -replace ".{64}", "$&`n"
$pem_output += "-----END CERTIFICATE-----"
[System.IO.File]::WriteAllLines("$output_path\cert.pem", $pem_output)
# Export the private key in a PFX file
[System.IO.File]::WriteAllBytes("$output_path\cert.pfx", $cert.Export("Pfx"))
注意
要将 PFX 文件转换为 pywinrm 可以使用的私钥,请使用 OpenSSL 运行以下命令 openssl pkcs12 -in cert.pfx -nocerts -nodes -out cert_key.pem -passin pass: -passout pass:
将证书导入证书存储
生成证书后,需要将颁发证书导入 Trusted Root Certificate Authorities
的 LocalMachine
存储中,并且客户端证书公钥必须存在于 Trusted People
的 LocalMachine
存储文件夹中。在此示例中,颁发证书和公钥相同。
以下示例显示如何导入颁发证书
$cert = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Certificate2 "cert.pem"
$store_name = [System.Security.Cryptography.X509Certificates.StoreName]::Root
$store_location = [System.Security.Cryptography.X509Certificates.StoreLocation]::LocalMachine
$store = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Store -ArgumentList $store_name, $store_location
$store.Open("MaxAllowed")
$store.Add($cert)
$store.Close()
注意
如果使用 ADCS 生成证书,那么颁发证书将已经被导入,并且可以跳过此步骤。
导入客户端证书公钥的代码是
$cert = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Certificate2 "cert.pem"
$store_name = [System.Security.Cryptography.X509Certificates.StoreName]::TrustedPeople
$store_location = [System.Security.Cryptography.X509Certificates.StoreLocation]::LocalMachine
$store = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Store -ArgumentList $store_name, $store_location
$store.Open("MaxAllowed")
$store.Add($cert)
$store.Close()
将证书映射到帐户
导入证书后,将其映射到本地用户帐户
$username = "username"
$password = ConvertTo-SecureString -String "password" -AsPlainText -Force
$credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $username, $password
# This is the issuer thumbprint which in the case of a self generated cert
# is the public key thumbprint, additional logic may be required for other
# scenarios
$thumbprint = (Get-ChildItem -Path cert:\LocalMachine\root | Where-Object { $_.Subject -eq "CN=$username" }).Thumbprint
New-Item -Path WSMan:\localhost\ClientCertificate `
-Subject "$username@localhost" `
-URI * `
-Issuer $thumbprint `
-Credential $credential `
-Force
完成此操作后,主机变量 ansible_winrm_cert_pem
应设置为公钥路径,而 ansible_winrm_cert_key_pem
变量应设置为私钥路径。
NTLM
NTLM 是 Microsoft 使用的较旧的身份验证机制,它可以支持本地帐户和域帐户。NTLM 在 WinRM 服务中默认启用,因此在使用它之前无需进行任何设置。
NTLM 是最容易使用的身份验证协议,比 Basic
身份验证更安全。如果在域环境中运行,应使用 Kerberos
而不是 NTLM。
Kerberos 比使用 NTLM 具有几个优点
NTLM 是一个较旧的协议,不支持更新的加密协议。
NTLM 速度较慢,因为它在身份验证阶段需要与主机进行更多往返。
与 Kerberos 不同,NTLM 不允许凭据委派。
此示例显示配置为使用 NTLM 身份验证的主机变量
ansible_user: LocalUsername
ansible_password: Password
ansible_connection: winrm
ansible_winrm_transport: ntlm
Kerberos
Kerberos 是在域环境中运行时推荐使用的身份验证选项。Kerberos 支持诸如凭据委派和通过 HTTP 进行消息加密等功能,并且是通过 WinRM 可用的更安全选项之一。
Kerberos 需要在 Ansible 主机上进行一些额外的设置工作,才能正确使用它。
以下示例显示为 Kerberos 身份验证配置的主机变量
ansible_user: username@MY.DOMAIN.COM
ansible_password: Password
ansible_connection: winrm
ansible_port: 5985
ansible_winrm_transport: kerberos
从 Ansible 版本 2.3 开始,Kerberos 票证将根据 ansible_user
和 ansible_password
创建。如果在较旧版本的 Ansible 上运行,或者 ansible_winrm_kinit_mode
为 manual
,则必须先获取 Kerberos 票证。有关更多详细信息,请参见下文。
可以设置一些额外的主机变量
ansible_winrm_kinit_mode: managed/manual (manual means Ansible will not obtain a ticket)
ansible_winrm_kinit_cmd: the kinit binary to use to obtain a Kerberos ticket (default to kinit)
ansible_winrm_service: overrides the SPN prefix that is used, the default is ``HTTP`` and should rarely ever need changing
ansible_winrm_kerberos_delegation: allows the credentials to traverse multiple hops
ansible_winrm_kerberos_hostname_override: the hostname to be used for the Kerberos exchange
安装 Kerberos 库
在使用 Kerberos 之前,必须安装一些系统依赖项。以下脚本根据发行版列出了依赖项
# Through Yum (RHEL/Centos/Fedora for the older version)
yum -y install gcc python-devel krb5-devel krb5-libs krb5-workstation
# Through DNF (RHEL/Centos/Fedora for the newer version)
dnf -y install gcc python3-devel krb5-devel krb5-libs krb5-workstation
# Through Apt (Ubuntu older than 20.04 LTS (focal))
sudo apt-get install python-dev libkrb5-dev krb5-user
# Through Apt (Ubuntu newer than 20.04 LTS)
sudo apt-get install python3-dev libkrb5-dev krb5-user
# Through Portage (Gentoo)
emerge -av app-crypt/mit-krb5
emerge -av dev-python/setuptools
# Through Pkg (FreeBSD)
sudo pkg install security/krb5
# Through OpenCSW (Solaris)
pkgadd -d http://get.opencsw.org/now
/opt/csw/bin/pkgutil -U
/opt/csw/bin/pkgutil -y -i libkrb5_3
# Through Pacman (Arch Linux)
pacman -S krb5
安装完依赖项后,可以安装 python-kerberos
包装器。
如果您选择了 pipx
安装说明,您可以通过运行以下命令来安装它
pipx inject ansible pywinrm[kerberos] # if you installed ansible with pipx
pipx inject ansible-core pywinrm[kerberos] # if you installed ansible-core with pipx
或者,如果您选择了 pip
安装说明
pip install pywinrm[kerberos]
注意
虽然 Ansible 一直支持通过 pywinrm
进行 Kerberos 身份验证,但可选功能或更安全的选择可能只在较新版本的 pywinrm
和/或 pykerberos
库中可用。建议您将每个版本升级到最新版本,以解决任何警告或错误。这可以通过 pip
等工具或 dnf
、yum
、apt
等系统包管理器来完成,但可用包名称和版本可能因工具而异。
配置主机 Kerberos
安装完依赖项后,需要配置 Kerberos 以便它可以与域通信。此配置通过 /etc/krb5.conf
文件完成,该文件随上述脚本中的包一起安装。
要配置 Kerberos,在以以下内容开头的部分
[realms]
添加完整的域名以及主 Active Directory 域控制器和辅助域控制器的完全限定域名。它应该看起来像这样
[realms]
MY.DOMAIN.COM = {
kdc = domain-controller1.my.domain.com
kdc = domain-controller2.my.domain.com
}
在以以下内容开头的部分
[domain_realm]
为 Ansible 需要访问的每个域添加类似以下的一行
[domain_realm]
.my.domain.com = MY.DOMAIN.COM
您可以在此文件中配置其他设置,例如默认域。有关更多详细信息,请参阅 krb5.conf。
自动 Kerberos 票证管理
Ansible 2.3 及更高版本默认在为主机指定了 ansible_user
和 ansible_password
时自动管理 Kerberos 票证。在此过程中,将在每个主机上的临时凭据缓存中创建一个新票证。这将在每个任务执行之前完成,以最大程度地减少票证过期的可能性。临时凭据缓存会在每个任务完成后删除,并且不会干扰默认凭据缓存。
要禁用自动票证管理,请通过清单设置 ansible_winrm_kinit_mode=manual
。
自动票证管理需要控制主机系统路径上的标准 kinit
二进制文件。要指定不同的位置或二进制文件名,请将 ansible_winrm_kinit_cmd
主机变量设置为指向 MIT krbv5 kinit
兼容二进制文件的完全限定路径。
手动 Kerberos 票证管理
要手动管理 Kerberos 票证,请使用 kinit
二进制文件。要获取新票证,请使用以下命令
kinit username@MY.DOMAIN.COM
注意
域必须与配置的 Kerberos 领域完全匹配,并且必须为大写。
要查看已获取的票证(如果有),请使用以下命令
klist
要销毁所有已获取的票证,请使用以下命令
kdestroy
排查 Kerberos 问题
Kerberos 依赖于正确配置的环境才能正常工作。要排查 Kerberos 问题,请确保
为 Windows 主机设置的主机名为 FQDN,而不是 IP 地址。* 如果您使用 IP 地址连接,您将收到错误消息 Kerberos 数据库中未找到服务器。* 要确定您是使用 IP 地址还是 FQDN 连接,请使用 -vvv 标志运行您的剧本(或调用
win_ping
模块)。正向和反向 DNS 查找在域中正常工作。要测试这一点,请按名称 ping Windows 主机,然后使用
nslookup
使用返回的 IP 地址。使用 IP 地址在nslookup
上时,应该返回相同的名称。Ansible 主机时钟与 AD 域控制器同步。Kerberos 对时间敏感,即使是少量时钟漂移也会导致票证生成过程失败。
确保域的完全限定域名已在
krb5.conf
文件中配置。要检查这一点,请运行kinit -C username@MY.DOMAIN.COM klist
如果
klist
返回的域名与请求的域名不同,则正在使用别名。需要更新krb5.conf
文件,以便使用完全限定域名而不是别名。如果已替换或修改了默认 Kerberos 工具(某些 IdM 解决方案可能会这样做),这可能会在安装或升级 Python Kerberos 库时导致问题。截至本文撰写之时,该库名为
pykerberos
,已知可与 MIT 和 Heimdal Kerberos 库一起使用。要解决pykerberos
安装问题,请确保已满足 Kerberos 的系统依赖项(请参阅:安装 Kerberos 库),从 PATH 环境变量中删除任何自定义 Kerberos 工具路径,并重试 Python Kerberos 库包的安装。
CredSSP
CredSSP 身份验证是一种较新的身份验证协议,允许凭据委派。这是通过在身份验证成功后加密用户名和密码,并使用 CredSSP 协议将它们发送到服务器来实现的。
因为用户名和密码被发送到服务器以用于双跳身份验证,请确保 Windows 主机与之通信的主机没有被入侵并且是可信的。
CredSSP 可用于本地帐户和域帐户,并且还支持通过 HTTP 进行消息加密。
要使用 CredSSP 身份验证,请按如下所示配置主机变量
ansible_user: Username
ansible_password: Password
ansible_connection: winrm
ansible_winrm_transport: credssp
一些额外的主机变量可以按如下所示设置
ansible_winrm_credssp_disable_tlsv1_2: when true, will not use TLS 1.2 in the CredSSP auth process
CredSSP 身份验证默认情况下未在 Windows 主机上启用,但可以通过在 PowerShell 中运行以下命令来启用
Enable-WSManCredSSP -Role Server -Force
安装 CredSSP 库
可以使用 pip
安装 requests-credssp
包装器
pip install pywinrm[credssp]
CredSSP 和 TLS 1.2
默认情况下,requests-credssp
库配置为通过 TLS 1.2 协议进行身份验证。TLS 1.2 默认情况下已安装并启用,适用于 Windows Server 2012 和 Windows 8 及更高版本。
有两种方法可以将旧主机与 CredSSP 配合使用
安装并启用修补程序以启用 TLS 1.2 支持(建议用于 Server 2008 R2 和 Windows 7)。
在清单中设置
ansible_winrm_credssp_disable_tlsv1_2=True
以通过 TLS 1.0 运行。这是连接到 Windows Server 2008 时唯一的选项,因为 Windows Server 2008 无法支持 TLS 1.2
有关如何在 Windows 主机上启用 TLS 1.2 的更多信息,请参阅 TLS 1.2 支持。
设置 CredSSP 证书
CredSSP 通过 TLS 协议加密凭据,默认情况下使用自签名证书。WinRM 服务配置下的 CertificateThumbprint
选项可用于指定另一个证书的指纹。
注意
此证书配置独立于 WinRM 侦听器证书。使用 CredSSP,消息传输仍然通过 WinRM 侦听器发生,但通道内的 TLS 加密消息使用服务级证书。
要显式设置要用于 CredSSP 的证书
# Note the value $certificate_thumbprint will be different in each
# situation, this needs to be set based on the cert that is used.
$certificate_thumbprint = "7C8DCBD5427AFEE6560F4AF524E325915F51172C"
# Set the thumbprint value
Set-Item -Path WSMan:\localhost\Service\CertificateThumbprint -Value $certificate_thumbprint
非管理员帐户
默认情况下,WinRM 配置为仅允许来自本地 Administrators
组中帐户的连接。可以通过运行以下命令来更改此设置
winrm configSDDL default
这将显示一个 ACL 编辑器,可以在其中添加新用户或组。要通过 WinRM 运行命令,用户和组必须至少启用 Read
和 Execute
权限。
虽然非管理员帐户可与 WinRM 一起使用,但大多数典型的服务器管理任务都需要某种程度的管理员访问权限,因此实用程序通常受到限制。
WinRM 加密
默认情况下,WinRM 在通过未加密的通道运行时将无法正常工作。如果通过 HTTP 上的 TLS(HTTPS)或使用消息级加密,WinRM 协议将认为通道已加密。建议使用 TLS 与 WinRM 配合使用,因为它适用于所有身份验证选项,但需要在 WinRM 侦听器上创建和使用证书。
如果在域环境中,ADCS 可以为主机创建由域本身颁发的证书。
如果使用 HTTPS 不可行,则在身份验证选项为 NTLM
、Kerberos
或 CredSSP
时,可以使用 HTTP。这些协议将在将 WinRM 负载发送到服务器之前使用它们自己的加密方法对其进行加密。在通过 HTTPS 运行时不会使用消息级加密,因为加密使用更安全的 TLS 协议。如果需要传输和消息加密,请在主机变量中设置 ansible_winrm_message_encryption=always
。
注意
通过 HTTP 的消息级加密需要 pywinrm>=0.3.0。
最后的手段是在 Windows 主机上禁用加密要求。这仅应用于开发和调试目的,因为从 Ansible 发送的任何内容都可以被查看或操纵,并且远程会话可以被同一网络上的任何人完全接管。要禁用加密要求
Set-Item -Path WSMan:\localhost\Service\AllowUnencrypted -Value $true
注意
除非绝对必要,否则不要禁用加密检查。这样做可能会允许敏感信息(例如凭据和文件)被网络上的其他人拦截。
清单选项
Ansible 的 Windows 支持依赖于几个标准变量来指示远程主机的用户名、密码和连接类型。这些变量最容易在清单中设置,但可以在 host_vars
/ group_vars
级别设置。
在设置库存时,需要以下变量
# 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 through --user
ansible_user: Administrator
# May also be supplied at runtime with --ask-pass
ansible_password: SecretPasswordGoesHere
使用上述变量,Ansible 将通过 HTTPS 使用基本身份验证连接到 Windows 主机。如果 ansible_user
具有类似 username@MY.DOMAIN.COM
的 UPN 值,则身份验证选项将自动尝试使用 Kerberos,除非 ansible_winrm_transport
已设置为除 kerberos
之外的其他值。
以下自定义库存变量也支持用于 WinRM 连接的额外配置
ansible_port
: WinRM 将在其上运行的端口,HTTPS 为5986
,这是默认端口,而 HTTP 为5985
ansible_winrm_scheme
: 指定用于 WinRM 连接的连接方案 (http
或https
)。Ansible 默认使用https
,除非ansible_port
为5985
ansible_winrm_path
: 指定 WinRM 端点的备用路径,Ansible 默认使用/wsman
ansible_winrm_realm
: 指定用于 Kerberos 身份验证的领域。如果ansible_user
包含@
,Ansible 默认将使用@
后用户名的一部分ansible_winrm_transport
: 指定一个或多个身份验证传输选项,以逗号分隔的列表形式。默认情况下,如果安装了kerberos
模块并定义了领域,Ansible 将使用kerberos, basic
,否则将使用plaintext
ansible_winrm_server_cert_validation
: 指定服务器证书验证模式 (ignore
或validate
)。Ansible 在 Python 2.7.9 及更高版本上默认为validate
,这将导致针对 Windows 自签名证书的证书验证错误。除非在 WinRM 侦听器上配置了可验证证书,否则应将其设置为ignore
ansible_winrm_operation_timeout_sec
: 延长 WinRM 操作的默认超时时间,Ansible 默认使用20
ansible_winrm_read_timeout_sec
: 延长 WinRM 读取超时时间,Ansible 默认使用30
。如果存在间歇性网络问题,并且持续出现读取超时错误,则此选项很有用ansible_winrm_message_encryption
: 指定要使用的消息加密操作 (auto
,always
,never
),Ansible 默认使用auto
。auto
表示仅当ansible_winrm_scheme
为http
并且ansible_winrm_transport
支持消息加密时才会使用消息加密。always
表示将始终使用消息加密,而never
表示将永远不会使用消息加密ansible_winrm_ca_trust_path
: 用于指定与certifi
模块中使用的 cacert 容器不同的容器。有关更多详细信息,请参见 HTTPS 证书验证部分。ansible_winrm_send_cbt
: 当通过 HTTPS 使用ntlm
或kerberos
时,身份验证库将尝试发送通道绑定令牌以缓解中间人攻击。此标志控制是否发送这些绑定(默认值:true
)。ansible_winrm_*
:winrm.Protocol
支持的任何其他关键字参数都可以替换为*
此外,每个身份验证选项还需要设置特定的变量。有关更多信息,请参见上面有关身份验证的部分。
注意
Ansible 2.0 已弃用 ansible_ssh_user
, ansible_ssh_pass
, ansible_ssh_host
和 ansible_ssh_port
中的“ssh”,将其变为 ansible_user
, ansible_password
, ansible_host
和 ansible_port
。如果使用的是 Ansible 2.0 之前的版本,则应使用旧样式 (ansible_ssh_*
)。较短的变量在 Ansible 的旧版本中会被忽略,不会发出警告。
注意
ansible_winrm_message_encryption
不同于通过 TLS 完成的传输加密。即使 ansible_winrm_message_encryption=never
,WinRM 负载仍将通过 TLS 在 HTTPS 上运行时加密。
IPv6 地址
可以使用 IPv6 地址代替 IPv4 地址或主机名。此选项通常在库存中设置。Ansible 将尝试使用 ipaddress 包解析地址并正确传递给 pywinrm
。
在使用 IPv6 地址定义主机时,只需像添加 IPv4 地址或主机名一样添加 IPv6 地址
[windows-server]
2001:db8::1
[windows-server:vars]
ansible_user=username
ansible_password=password
ansible_connection=winrm
注意
ipaddress 库默认情况下仅包含在 Python 3.x 中。要在 Python 2.7 中使用 IPv6 地址,请确保运行 pip install ipaddress
,这将安装一个移植的包。
HTTPS 证书验证
作为 TLS 协议的一部分,将验证证书以确保主机与主题匹配,并且客户端信任服务器证书的发行机构。当使用自签名证书或设置 ansible_winrm_server_cert_validation: ignore
时,将绕过这些安全机制。虽然自签名证书始终需要 ignore
标志,但从证书颁发机构签发的证书仍然可以验证。
在域环境中设置 HTTPS 侦听器的一种更常见的方法是使用 Active Directory 证书服务 (AD CS)。AD CS 用于从证书签名请求 (CSR) 生成签名证书。如果 WinRM HTTPS 侦听器使用由其他机构签发的证书,例如 AD CS,则可以将 Ansible 设置为在 TLS 握手过程中信任该发行机构。
要使 Ansible 信任像 AD CS 这样的证书颁发机构 (CA),可以将 CA 的发行机构证书导出为 PEM 编码的证书。然后可以将此证书本地复制到 Ansible 控制节点并用作证书验证的来源,也称为 CA 链。
CA 链可以包含一个或多个发行机构证书,每个条目都包含在一行上。然后,要将自定义 CA 链用作验证过程的一部分,请将 ansible_winrm_ca_trust_path
设置为文件路径。如果未设置此变量,则将使用默认的 CA 链,该链位于 Python 包 certifi 的安装路径中。
注意
每个 HTTP 调用都由 Python requests 库完成,该库不使用系统内置的证书存储作为信任机构。如果服务器的证书发行机构仅添加到系统的信任存储中,则证书验证将失败。
TLS 1.2 支持
由于 WinRM 在 HTTP 协议上运行,因此使用 HTTPS 表示使用 TLS 协议加密 WinRM 消息。TLS 将自动尝试协商对客户端和服务器都可用的最佳协议和密码套件。如果无法找到匹配项,则 Ansible 将报错,显示类似于以下的消息
HTTPSConnectionPool(host='server', port=5986): Max retries exceeded with url: /wsman (Caused by SSLError(SSLError(1, '[SSL: UNSUPPORTED_PROTOCOL] unsupported protocol (_ssl.c:1056)')))
通常,这是当 Windows 主机未配置为支持 TLS v1.2 时,但也可能意味着 Ansible 控制节点安装了较旧的 OpenSSL 版本。
Windows 8 和 Windows Server 2012 默认情况下已安装并启用了 TLS v1.2,但较旧的主机(例如 Server 2008 R2 和 Windows 7)必须手动启用。
注意
Server 2008 的 TLS 1.2 修补程序存在一个错误,这将阻止 Ansible 连接到 Windows 主机。这意味着 Server 2008 无法配置为使用 TLS 1.2。Server 2008 R2 和 Windows 7 不受此问题的影响,可以使用 TLS 1.2。
要验证 Windows 主机支持哪些协议,可以在 Ansible 控制节点上运行以下命令
openssl s_client -connect <hostname>:5986
输出将包含有关 TLS 会话的信息,而 Protocol
行将显示协商的版本
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
Protocol : TLSv1
Cipher : ECDHE-RSA-AES256-SHA
Session-ID: 962A00001C95D2A601BE1CCFA7831B85A7EEE897AECDBF3D9ECD4A3BE4F6AC9B
Session-ID-ctx:
Master-Key: ....
Start Time: 1552976474
Timeout : 7200 (sec)
Verify return code: 21 (unable to verify the first certificate)
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-GCM-SHA384
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
Protocol : TLSv1.2
Cipher : ECDHE-RSA-AES256-GCM-SHA384
Session-ID: AE16000050DA9FD44D03BB8839B64449805D9E43DBD670346D3D9E05D1AEEA84
Session-ID-ctx:
Master-Key: ....
Start Time: 1552976538
Timeout : 7200 (sec)
Verify return code: 21 (unable to verify the first certificate)
如果主机返回的是 TLSv1
,则应将其配置为启用 TLS v1.2。您可以通过运行以下 PowerShell 脚本来完成此操作
Function Enable-TLS12 {
param(
[ValidateSet("Server", "Client")]
[String]$Component = "Server"
)
$protocols_path = 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols'
New-Item -Path "$protocols_path\TLS 1.2\$Component" -Force
New-ItemProperty -Path "$protocols_path\TLS 1.2\$Component" -Name Enabled -Value 1 -Type DWORD -Force
New-ItemProperty -Path "$protocols_path\TLS 1.2\$Component" -Name DisabledByDefault -Value 0 -Type DWORD -Force
}
Enable-TLS12 -Component Server
# Not required but highly recommended to enable the Client side TLS 1.2 components
Enable-TLS12 -Component Client
Restart-Computer
以下 Ansible 任务也可以用来启用 TLS v1.2
- name: enable TLSv1.2 support
win_regedit:
path: HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\{{ item.type }}
name: '{{ item.property }}'
data: '{{ item.value }}'
type: dword
state: present
register: enable_tls12
loop:
- type: Server
property: Enabled
value: 1
- type: Server
property: DisabledByDefault
value: 0
- type: Client
property: Enabled
value: 1
- type: Client
property: DisabledByDefault
value: 0
- name: reboot if TLS config was applied
win_reboot:
when: enable_tls12 is changed
还有其他方法可以配置 Windows 主机提供的 TLS 协议以及密码套件。一种可以提供管理这些设置的 GUI 的工具是 Nartac Software 的 IIS Crypto。
WinRM 限制
由于 WinRM 协议的设计,在使用 WinRM 时存在一些限制,这些限制会导致为 Ansible 创建剧本时出现问题。其中包括
大多数身份验证类型不委托凭据,这会导致在访问网络资源或安装某些程序时出现身份验证错误。
通过 WinRM 运行时,对 Windows 更新 API 的许多调用都被阻止。
由于没有凭据委托,或者因为它们通过 WinRM 访问禁止的 Windows API(如 WUA),一些程序无法通过 WinRM 安装。
WinRM 下的命令是在非交互式会话下完成的,这可能会阻止某些命令或可执行文件运行。
您无法运行与
DPAPI
交互的进程,而DPAPI
被一些安装程序(如 Microsoft SQL Server)使用。
以下是一些缓解这些限制的方法:
将
ansible_winrm_transport
设置为credssp
或kerberos
(以及ansible_winrm_kerberos_delegation=true
)以绕过双跳问题并访问网络资源。使用
become
绕过所有 WinRM 限制并以本地方式运行命令。与使用credssp
等身份验证传输不同,这将消除非交互式限制和 API 限制,例如 WUA 和 DPAPI。使用计划任务运行命令,该命令可以使用
win_scheduled_task
模块创建。与become
一样,这会绕过所有 WinRM 限制,但只能运行命令,而不能运行模块。
另请参阅
- Ansible 剧本
剧本简介
- Ansible 提示和技巧
剧本技巧和窍门
- Windows 模块列表
Windows 特定模块列表,全部在 PowerShell 中实现
- 用户邮件列表
有问题?请访问 Google 群组!
- 实时聊天
如何加入 Ansible 聊天频道