Windows SSH
在较新的 Windows 版本上,您可以使用 SSH 连接到 Windows 主机。这是 WinRM 的另一种连接选项。
注意
虽然自 Ansible 2.8 以来,Ansible 可以将 SSH 连接插件与 Windows 节点一起使用,但官方支持仅在 2.18 版本中添加。
SSH 设置
自 Windows Server 2019 起,Microsoft 通过 Windows 功能提供 OpenSSH 实现。它也可以通过 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,可以使用以下 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
设置为powershell
或cmd
ansible_shell_type
变量应反映在 Windows 主机上配置的 DefaultShell
。也可以为 Windows 主机设置 ssh 下记录的其他 SSH 选项。
SSH 身份验证
使用 Windows 的 Win32-OpenSSH 身份验证类似于 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
hostvar 指定 UPN 用户名,并且 Ansible 在使用 SSH 时将自动使用该用户的 Kerberos 票证。
还可以通过 GSSAPI 身份验证启用无约束委派,以使 Windows 节点能够访问网络资源。要使 GSSAPI 委派工作,kinit
检索的票证必须是可转发的,并且必须使用 -o GSSAPIDelegateCredentials=yes
选项调用 ssh
。要检索可转发的票证,请使用 kinit
的 -f
标志,或者在 /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
可以在 ~/.ssh/config
文件中或作为清单中的 hostvar 变量设置 GSSAPIDelegateCredentials=yes
选项
ansible_ssh_common_args: -o GSSAPIDelegateCredentials=yes
与 psrp
或 winrm
连接插件不同,SSH 连接插件在提供显式用户名和密码时无法获取 Kerberos TGT 票证。这意味着用户在运行 playbook 之前必须具有有效的 Kerberos 票证。
有关如何配置、使用和排查 Kerberos 身份验证的更多信息,请参阅 Kerberos 身份验证。
密码身份验证
密码验证是最不安全的身份验证方法,不建议使用。然而,可以使用密码验证进行 Windows SSH 连接。要在 Ansible 中使用密码验证,请在清单文件或 playbook 中设置 ansible_password
变量。使用密码验证需要在 Ansible 控制节点上安装 sshpass
包。
密码验证的工作方式类似于 WinRM CredSSP 验证,其中用户名和密码被传递给 Windows 主机,然后它会执行无约束委派以访问网络资源。