设置 Windows 主机

本文档讨论在 Ansible 可以与 Microsoft Windows 主机通信之前所需的设置。

主机要求

为了使 Ansible 与 Windows 主机通信并使用 Windows 模块,Windows 主机必须满足这些连接的基本要求。

  • 使用 Ansible,您通常可以管理当前版本和 Microsoft 扩展支持下的 Windows 版本。您还可以管理包括 Windows 10 和 11 在内的桌面操作系统,以及包括 Windows Server 2016、2019 和 2022 在内的服务器操作系统。

  • 您需要在 Windows 主机上安装 PowerShell 5.1 或更高版本,以及至少 .NET 4.0。

  • 您需要创建并激活 WinRM 监听器。更多详细信息,请参阅 WinRM 监听器

注意

一些 Ansible 模块有额外的要求,例如更新的操作系统或 PowerShell 版本。请查阅模块文档页面,以确定主机是否满足这些要求。

升级 PowerShell 和 .NET Framework

Ansible 需要 PowerShell 版本 5.1 和 .NET Framework 4.6 或更高版本才能正常工作。旧版不支持的操作系统的基本映像不满足这些要求。您可以使用 Upgrade-PowerShell.ps1 脚本更新这些版本。

这是从 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

&$file -Version 5.1 -Username $username -Password $password -Verbose

在脚本中,file 值可以是 PowerShell 版本 3.0、4.0 或 5.1。

完成后,您需要运行以下 PowerShell 命令

  1. 作为可选但良好的安全实践,您可以将执行策略设置回默认值。

Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force

对于 Windows 服务器,使用 RemoteSigned 值,或者对于 Windows 客户端,使用 Restricted 值。

  1. 删除自动登录。

$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

该脚本确定您需要安装哪些程序(例如 .NET Framework 4.5.2)以及需要存在哪些 PowerShell 版本。如果需要重启,并且设置了 usernamepassword 参数,该脚本将自动重启机器,然后登录。如果未设置 usernamepassword 参数,该脚本将提示用户在需要时手动重启和登录。下次用户登录时,该脚本将从上次中断的地方继续,并持续执行,直到不再需要执行任何操作。

注意

如果您在 Server 2008 上运行脚本,则需要安装 SP2。对于 Server 2008 R2 或 Windows 7,您需要安装 SP1。

在 Windows Server 2008 上,您只能安装 PowerShell 3.0。安装更新版本会导致脚本失败。

usernamepassword 参数以纯文本形式存储在注册表中。脚本完成后运行清理命令,以确保主机上没有存储任何凭据。

WinRM 内存热修复

在 PowerShell v3.0 上,存在一个错误,该错误会限制可用于 WinRM 服务的内存量。使用 Install-WMF3Hotfix.ps1 脚本在受影响的主机上安装热修复,作为系统引导或映像过程的一部分。如果没有这个热修复,Ansible 将无法在 Windows 主机上执行某些命令。

要安装热修复

[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

有关更多详细信息,请参阅 “内存不足”错误,该错误发生在安装了 WMF 3.0 的计算机上,并且自定义了 MaxMemoryPerShellMB 配额 文章。

WinRM 设置

您需要配置 WinRM 服务,以便 Ansible 可以连接到它。WinRM 服务有两个主要组件,它们控制 Ansible 如何与 Windows 主机交互:listenerservice 配置设置。

注意

用于设置此服务的脚本可 在 GitHub 上下载。原因是使用它会导致用户遇到若干问题。很可能它将在未来被完全停用。

WinRM 监听器

WinRM 服务监听一个或多个端口上的请求。每个端口都必须创建一个并配置一个监听器。

要查看当前在 WinRM 服务上运行的监听器

winrm enumerate winrm/config/Listener

这将输出类似于以下内容

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

在上面的示例中,激活了两个监听器。一个在端口 5985 上通过 HTTP 监听,另一个在端口 5986 上通过 HTTPS 监听。一些需要了解的关键选项是

  • Transport:监听器是通过 HTTP 还是 HTTPS 运行。我们建议您使用 HTTPS 上的监听器,因为数据是加密的,无需进行任何其他更改。

  • Port:监听器运行的端口。默认情况下,HTTP 的端口为 5985,HTTPS 的端口为 5986。此端口可以更改为任何所需的端口,并且对应于主机变量 ansible_port

  • URLPrefix:要监听的 URL 前缀。默认情况下,它是 wsman。如果您更改此选项,则需要将主机变量 ansible_winrm_path 设置为相同的值。

  • CertificateThumbprint:如果您使用的是 HTTPS 监听器,这是 Windows 证书存储区中用于连接的证书的指纹。要获取证书本身的详细信息,请在 PowerShell 中运行以下命令,并在其中包含相关的证书指纹

$thumbprint = "E6CDAA82EEAF2ECE8546E05DB7F3E01AA47D76CE"
Get-ChildItem -Path cert:\LocalMachine\My -Recurse | Where-Object { $_.Thumbprint -eq $thumbprint } | Select-Object *

设置 WinRM 监听器

有三种方法可以设置 WinRM 监听器

  • 使用 winrm quickconfig 用于 HTTP,或者 winrm quickconfig -transport:https 用于 HTTPS。这是在域环境之外运行并需要简单监听器时最简单的选项。与其他选项不同,此过程还具有为所需端口打开防火墙并启动 WinRM 服务的额外好处。

  • 使用组策略对象 (GPO)。当主机是域的成员时,这是创建监听器的最佳方式,因为配置会自动完成,无需任何用户输入。有关组策略对象的更多信息,请参阅 组策略对象文档

  • 使用 PowerShell 创建具有特定配置的监听器。这可以通过运行以下 PowerShell 命令来完成

    $selector_set = @{
        Address = "*"
        Transport = "HTTPS"
    }
    $value_set = @{
        CertificateThumbprint = "E6CDAA82EEAF2ECE8546E05DB7F3E01AA47D76CE"
    }
    
    New-WSManInstance -ResourceURI "winrm/config/Listener" -SelectorSet $selector_set -ValueSet $value_set
    

    要查看此 PowerShell 命令的其他选项,请参阅 New-WSManInstance 文档。

注意

创建 HTTPS 监听器时,您必须在 LocalMachine\My 证书存储区中创建并存储证书。

删除 WinRM 监听器

  • 要删除所有 WinRM 监听器

Remove-Item -Path WSMan:\localhost\Listener\* -Recurse -Force
  • 要仅删除通过 HTTPS 运行的监听器

Get-ChildItem -Path WSMan:\localhost\Listener | Where-Object { $_.Keys -contains "Transport=HTTPS" } | Remove-Item -Recurse -Force

注意

Keys 对象是一个字符串数组,因此它可以包含不同的值。默认情况下,它包含 Transport=Address= 的键,它们对应于 winrm enumerate winrm/config/Listeners 命令的值。

WinRM 服务选项

您可以控制 WinRM 服务组件的行为,包括身份验证选项和内存设置。

要获取当前服务配置选项的输出,请运行以下命令

winrm get winrm/config/Service
winrm get winrm/config/Winrs

这将输出类似于以下内容

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

您无需更改大多数这些选项。但是,以下是一些需要了解的重要选项:

  • Service\AllowUnencrypted - 指定 WinRM 是否允许在没有消息加密的情况下进行 HTTP 通信。只有当 ansible_winrm_transport 变量为 ntlmkerberoscredssp 时,消息级加密才可能。默认情况下,此值为 false,您应该仅在调试 WinRM 消息时将其设置为 true

  • Service\Auth\* - 定义您可以与 WinRM 服务一起使用的身份验证选项。默认情况下,Negotiate (NTLM)Kerberos 已启用。

  • Service\Auth\CbtHardeningLevel - 指定是否不验证通道绑定令牌(无)、验证但不强制(宽松)或验证并强制(严格)。只有在通过 HTTPS 使用 NT LAN Manager (NTLM) 或 Kerberos 连接时,才会使用 CBT。

  • Service\CertificateThumbprint - 用于加密与 CredSSP 身份验证一起使用的 TLS 通道的证书的指纹。默认情况下,此为空。当 WinRM 服务启动时会生成自签名证书,并在 TLS 进程中使用。

  • Winrs\MaxShellRunTime - 允许远程命令执行的最大时间(毫秒)。

  • Winrs\MaxMemoryPerShellMB - 为每个 shell 分配的最大内存量,包括其子进程。

要在 PowerShell 中修改 Service 密钥下的设置,您需要在 winrm/config/Service 之后提供选项的路径。

Set-Item -Path WSMan:\localhost\Service\{path} -Value {some_value}

例如,要更改 Service\Auth\CbtHardeningLevel

Set-Item -Path WSMan:\localhost\Service\Auth\CbtHardeningLevel -Value Strict

要在 PowerShell 中修改 Winrs 密钥下的设置,您需要在 winrm/config/Winrs 之后提供选项的路径。

Set-Item -Path WSMan:\localhost\Shell\{path} -Value {some_value}

例如,要更改 Winrs\MaxShellRunTime

Set-Item -Path WSMan:\localhost\Shell\MaxShellRunTime -Value 2147483647

注意

如果您在域环境中运行命令,则其中一些选项由 GPO 设置,无法在主机本身更改。当您使用 GPO 配置密钥时,它包含 [Source="GPO"] 文本,紧挨着值。

常见的 WinRM 问题

WinRM 具有广泛的配置选项,这使得其配置复杂。因此,Ansible 显示的错误实际上可能是主机设置问题。

要确定主机问题,请从另一个 Windows 主机运行以下命令以连接到目标 Windows 主机。

  • 要测试 HTTP

winrs -r:http://server:5985/wsman -u:Username -p:Password ipconfig
  • 要测试 HTTPS

winrs -r:https://server:5986/wsman -u:Username -p:Password -ssl ipconfig

如果证书不可验证,则命令将失败。

  • 要测试 HTTPS 忽略证书验证

$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

如果上述任何命令失败,则问题可能与 WinRM 设置相关。

HTTP 401/凭据被拒绝

HTTP 401 错误表明在初始连接期间身份验证过程失败。您可以检查以下内容以进行故障排除:

  • 凭据是正确的,并在您的清单中使用 ansible_useransible_password 变量正确设置。

  • 用户是本地管理员组的成员,或者已被明确授予访问权限。您可以使用 winrs 命令执行连接测试,以排除此问题。

  • ansible_winrm_transport 变量设置的身份验证选项已在 Service\Auth\* 下启用。

  • 如果通过 HTTP 而不是 HTTPS 运行,请在 ansible_winrm_message_encryption: auto 自定义清单变量中使用 ntlmkerberoscredssp 来启用消息加密。如果您使用其他身份验证选项,或者无法升级已安装的 pywinrm 包,则可以将 Service\AllowUnencrypted 设置为 true。仅建议在进行故障排除时使用此选项。

  • 下游包 pywinrmrequests-ntlmrequests-kerberos 和/或 requests-credssp 已使用 pip 更新到最新版本。

  • 对于 Kerberos 身份验证,请确保 Service\Auth\CbtHardeningLevel 未设置为 Strict

  • 对于基本身份验证或证书身份验证,请确保用户是本地帐户。域帐户不适用于基本身份验证和证书身份验证。

HTTP 500 错误

HTTP 500 错误表明 WinRM 服务存在问题。您可以检查以下内容以进行故障排除:

  • 当前打开的 shell 数量是否已超过 WinRsMaxShellsPerUser。或者,您是否没有超过任何其他 Winrs 配额。

超时错误

有时 Ansible 无法到达主机。这些情况通常表明网络连接存在问题。您可以检查以下内容以进行故障排除:

  • 防火墙没有设置为阻止配置的 WinRM 侦听器端口。

  • 在主机变量设置的端口和路径上启用了 WinRM 侦听器。

  • Windows 主机上的 winrm 服务正在运行,并配置为自动启动。

连接拒绝错误

当您与主机上的 WinRM 服务通信时,可能会遇到一些问题。请检查以下内容以帮助进行故障排除:

  • WinRM 服务已在主机上启动并运行。使用 (Get-Service -Name winrm).Status 命令获取服务的运行状况。

  • 主机防火墙允许在 WinRM 端口上进行通信。默认情况下,HTTP 为 5985,HTTPS 为 5986

有时安装程序可能会重启 WinRM 或 HTTP 服务,并导致此错误。处理此问题的最佳方法是从另一个 Windows 主机使用 win_psexec 模块。

无法加载内置模块

有时 PowerShell 会出现类似以下错误消息的错误:

The 'Out-String' command was found in the module 'Microsoft.PowerShell.Utility', but the module could not be loaded.

在这种情况下,尝试访问 PSModulePath 环境变量指定的路径时,可能会出现问题。

此问题的一个常见原因是 PSModulePath 包含指向文件共享的通用命名约定 (UNC) 路径。此外,双跃点/凭据委派问题会导致 Ansible 进程无法访问这些文件夹。解决此问题的解决方法是:

  • PSModulePath 中删除 UNC 路径。

或者

  • 使用支持凭据委派的身份验证选项,例如 credsspkerberos。您需要启用凭据委派。

有关此问题的更多信息,请参阅 KB4076842

Windows SSH 设置

Ansible 2.8 添加了对 Windows 管理节点的实验性 SSH 连接。

警告

请自行承担使用此功能的风险!在 Windows 上使用 SSH 是实验性的。此实现可能会在将来的版本中进行向后不兼容的更改。服务器端组件的可靠性取决于您的安装版本。

使用 Windows 设置安装 OpenSSH

您可以使用 OpenSSH 将 Windows 10 客户端连接到 Windows Server 2019。OpenSSH 客户端可在 Windows 10 版本 1809 及更高版本上安装。OpenSSH 服务器可在 Windows Server 2019 及更高版本上安装。

有关更多信息,请参阅 Windows 的 OpenSSH 入门

安装 Win32-OpenSSH

要为 Ansible 安装 Win32-OpenSSH 服务,请选择以下安装选项之一:

  • 按照微软提供的 安装说明 手动安装 Win32-OpenSSH

  • 使用 Chocolatey

choco install --package-parameters=/SSHServerFeature openssh
  • 使用 win_chocolatey Ansible 模块

- name: install the Win32-OpenSSH service
  win_chocolatey:
    name: openssh
    package_params: /SSHServerFeature
    state: present
ansible-galaxy install jborean93.win_openssh
  • 在您的剧本中使用该角色

- name: install Win32-OpenSSH service
  hosts: windows
  gather_facts: false
  roles:
  - role: jborean93.win_openssh
    opt_openssh_setup_service: True

注意

Win32-OpenSSH 仍处于 beta 阶段,并且不断更新以包含新功能和错误修复。如果您使用 SSH 作为 Windows 的连接选项,我们强烈建议您安装最新版本。

配置 Win32-OpenSSH Shell

默认情况下,Win32-OpenSSH 使用 cmd.exe 作为 Shell。

  • 要配置不同的 Shell,请使用带有任务的 Ansible 剧本以定义注册表设置。

- 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
  • 要将设置恢复为默认 Shell

- name: set the default shell to cmd
  win_regedit:
    path: HKLM:\SOFTWARE\OpenSSH
    name: DefaultShell
    state: absent

Win32-OpenSSH 身份验证

Win32-OpenSSH 与 Windows 的身份验证类似于 Unix/Linux 主机上的 SSH 身份验证。您可以使用明文密码或 SSH 公钥身份验证。

对于基于密钥的身份验证

  • 将您的公钥添加到用户配置文件目录的 .ssh 文件夹中的 authorized_key 文件中。

  • 使用 sshd_config 文件配置 SSH 服务。

当使用 SSH 密钥身份验证与 Ansible 时,远程会话将无法访问用户凭据,并且在尝试访问网络资源时将失败。这也被称为双跳或凭据委派问题。要解决此问题

  • 通过设置 ansible_password 变量使用明文密码身份验证。

  • 在需要访问远程资源的用户凭据的任务上使用 become 指令。

为 Windows 上的 SSH 配置 Ansible

要配置 Ansible 以使用 Windows 主机的 SSH,您必须设置两个连接变量

  • ansible_connection 设置为 ssh

  • ansible_shell_type 设置为 cmdpowershell

ansible_shell_type 变量应反映在 Windows 主机上配置的 DefaultShell。对于默认 Shell,将 ansible_shell_type 设置为 cmd。或者,如果您将 DefaultShell 更改为 PowerShell,则将 ansible_shell_type 设置为 powershell

Windows 上的 SSH 已知问题

将 SSH 与 Windows 结合使用尚处于实验阶段。目前,存在的问题包括:

  • powershell 是 Shell 类型时,低于 v7.9.0.0p1-Beta 的 Win32-OpenSSH 版本无法正常工作。

  • 虽然安全复制协议 (SCP) 应该可以正常工作,但 SSH 文件传输协议 (SFTP) 是在复制或获取文件时推荐使用的机制。

另请参阅

Ansible 剧本

剧本简介

Ansible 提示和技巧

剧本提示和技巧

Windows 模块列表

Windows 特定模块列表,全部在 PowerShell 中实现

沟通

有问题吗?需要帮助吗?想分享您的想法吗?请访问 Ansible 沟通指南