Windows SSH

在较新的 Windows 版本上,您可以使用 SSH 连接到 Windows 主机。这是 WinRM 的替代连接选项。

注意

虽然 Ansible 自 2.8 版本起可以使用 SSH 连接插件连接 Windows 节点,但官方支持仅在 2.18 版本中添加。

SSH 设置

自 Windows Server 2019 起,Microsoft 为 Windows 提供了一个 OpenSSH 实现作为 Windows 功能。它也可以通过 Win32-OpenSSH 下的上游软件包安装。Ansible 官方仅支持 Windows 附带的 OpenSSH 实现,而不支持上游软件包。OpenSSH 版本必须至少为 7.9.0.0。这实际上意味着官方支持从 Windows Server 2022 开始,因为 Server 2019 附带的版本是 7.7.2.1。使用较旧的 Windows 版本或上游软件包可能有效,但不受支持。

要在 Windows Server 2022 及更高版本上安装 OpenSSH 功能,请使用以下 PowerShell 命令

Get-WindowsCapability -Name OpenSSH.Server* -Online |
    Add-WindowsCapability -Online
Set-Service -Name sshd -StartupType Automatic -Status Running

$firewallParams = @{
    Name        = 'sshd-Server-In-TCP'
    DisplayName = 'Inbound rule for OpenSSH Server (sshd) on TCP port 22'
    Action      = 'Allow'
    Direction   = 'Inbound'
    Enabled     = 'True'  # This is not a boolean but an enum
    Profile     = 'Any'
    Protocol    = 'TCP'
    LocalPort   = 22
}
New-NetFirewallRule @firewallParams

$shellParams = @{
    Path         = 'HKLM:\SOFTWARE\OpenSSH'
    Name         = 'DefaultShell'
    Value        = 'C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe'
    PropertyType = 'String'
    Force        = $true
}
New-ItemProperty @shellParams

默认 Shell 配置

默认情况下,Windows 上的 OpenSSH 使用 cmd.exe 作为默认 shell。虽然 Ansible 可以使用此默认 shell,但建议将其更改为 powershell.exe,因为它经过更好的测试,并且应该比使用 cmd.exe 作为默认 shell 更快。要更改默认 shell,可以使用以下 PowerShell 脚本

# Set default to powershell.exe
$shellParams = @{
    Path         = 'HKLM:\SOFTWARE\OpenSSH'
    Name         = 'DefaultShell'
    Value        = 'C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe'
    PropertyType = 'String'
    Force        = $true
}
New-ItemProperty @shellParams

# Set default back to cmd.exe
Remove-ItemProperty -Path HKLM:\SOFTWARE\OpenSSH -Name DefaultShell

新的默认 shell 设置将应用于下一个 SSH 连接,无需重启 sshd 服务。您还可以使用 Ansible 配置默认 shell

- name: set the default shell to PowerShell
  ansible.windows.win_regedit:
    path: HKLM:\SOFTWARE\OpenSSH
    name: DefaultShell
    data: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
    type: string
    state: present

- name: reset SSH connection after shell change
  ansible.builtin.meta: reset_connection

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

- name: reset SSH connection after shell change
  ansible.builtin.meta: reset_connection

meta: reset_connection 非常重要,以确保后续任务将使用新的默认 shell。

Ansible 配置

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

  • ansible_connection 设置为 ssh

  • ansible_shell_type 设置为 powershellcmd

ansible_shell_type 变量应反映 Windows 主机上配置的 DefaultShell。在 ssh 下记录的其他 SSH 选项也可以为 Windows 主机设置。

SSH 身份验证

Win32-OpenSSH 与 Windows 的身份验证类似于 Unix/Linux 主机上的 SSH 身份验证。虽然可以使用许多身份验证方法,但通常在 Windows 上使用三种方法

选项

本地帐户

Active Directory 帐户

凭据委派

密钥

GSSAPI

密码

在大多数情况下,建议使用密钥或 GSSAPI 身份验证而不是密码身份验证。

密钥身份验证

Windows 上的 SSH 密钥身份验证的工作方式与 POSIX 节点的 SSH 密钥身份验证相同。您可以使用 ssh-keygen 命令生成密钥对,并将公钥添加到用户配置文件目录中的 authorized_keys 文件中。私钥应保持安全,不得共享。

一个区别是,管理员用户的 authorized_keys 文件不在用户配置文件目录中的 .ssh 文件夹中,而是在 C:\ProgramData\ssh\administrators_authorized_keys 中。可以通过删除或注释 C:\ProgramData\ssh\sshd_config 中的行,然后重启 sshd 服务,将管理员用户的 authorized_keys 文件的位置更改回用户配置文件目录。

Match Group administrators
    AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys

SSH 密钥可与本地帐户和域帐户一起使用,但会受到双跳问题的困扰。这意味着当使用 SSH 密钥身份验证与 Ansible 时,远程会话将无权访问用户凭据,并且在尝试访问网络资源时将失败。要解决此问题,您可以在任务中使用 become,使用需要访问远程资源的用户凭据。

GSSAPI 身份验证

GSSAPI 身份验证将使用 Kerberos 对 Windows 主机进行用户身份验证。要将 GSSAPI 身份验证与 Ansible 一起使用,必须通过编辑 C:\ProgramData\ssh\sshd_config 文件配置 Windows 服务器以允许 GSSAPI 身份验证。添加以下行或编辑现有行

GSSAPIAuthentication yes

编辑完成后,使用 Restart-Service -Name sshd 重启 sshd 服务。

在 Ansible 控制节点上,您需要安装 Kerberos 并将其配置为 Windows 主机所属的域。如何设置和配置不在本文档的范围内。配置 Kerberos 领域后,您可以使用 kinit 命令获取您正在连接的用户的票证,并使用 klist 验证哪些票证可用

> kinit [email protected]
Password for [email protected]

> klist
Ticket cache: KCM:1000
Default principal: [email protected]

Valid starting     Expires            Service principal
29/08/24 13:54:51  29/08/24 23:54:51  krbtgt/[email protected]
        renew until 05/09/24 13:54:48

获得有效的票证后,您可以使用 ansible_user 主机变量指定 UPN 用户名,当使用 SSH 时,Ansible 将自动使用该用户的 Kerberos 票证。

还可以通过 GSSAPI 身份验证启用不受约束的委派,使 Windows 节点访问网络资源。要使 GSSAPI 委派工作,由 kinit 检索的票证必须是可转发的,并且必须使用 -o GSSAPIDelegateCredentials=yes 选项调用 ssh。要检索可转发的票证,请将 -f 标志与 kinit 一起使用,或者在 /etc/krb5.conf 文件中的 [libdefaults] 下添加 forwardable = true

> kinit -f [email protected]
Password for [email protected]

# -f will show the ticket flags, we want to see F
> klist -f
Ticket cache: KCM:1000
Default principal: [email protected]

Valid starting     Expires            Service principal
29/08/24 13:54:51  29/08/24 23:54:51  krbtgt/[email protected]
        renew until 05/09/24 13:54:48, Flags: FRIA

GSSAPIDelegateCredentials=yes 选项可以在 ~/.ssh/config 文件中设置,也可以作为清单中的主机变量设置

ansible_ssh_common_args: -o GSSAPIDelegateCredentials=yes

psrpwinrm 连接插件不同,当提供显式用户名和密码时,SSH 连接插件无法获取 Kerberos TGT 票证。这意味着用户必须在运行 playbook 之前拥有有效的 Kerberos 票证。

有关如何配置、使用和排除 Kerberos 身份验证故障的更多信息,请参阅 Kerberos 身份验证

密码身份验证

密码身份验证是最不安全的身份验证方法,不建议使用。但是,可以使用密码身份验证与 Windows SSH 一起使用。要将密码身份验证与 Ansible 一起使用,请在清单文件或 playbook 中设置 ansible_password 变量。使用密码身份验证需要在 Ansible 控制节点上安装 sshpass 软件包。

密码身份验证的工作方式类似于 WinRM CredSSP 身份验证,其中用户名和密码被赋予 Windows 主机,并且它将执行不受约束的委派以访问网络资源。