Windows SSH
在较新的 Windows 版本中,您可以使用 SSH 连接到 Windows 主机。这是 WinRM 的替代连接选项。
注意
虽然 Ansible 自 Ansible 2.8 版本起就可以将 SSH 连接插件与 Windows 节点一起使用,但官方支持仅在 2.18 版本中添加。
SSH 设置
Microsoft 从 Windows Server 2019 开始在 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,可以使用以下 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 上使用三种方法
选项 |
本地帐户 |
活动目录帐户 |
凭据委派 |
---|---|---|---|
密钥 |
是 |
是 |
否 |
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 用户名,并且 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
GSSAPIDelegateCredentials=yes
选项可以在 ~/.ssh/config
文件中或作为清单中的主机变量设置
ansible_ssh_common_args: -o GSSAPIDelegateCredentials=yes
与 psrp
或 winrm
连接插件不同,SSH 连接插件在提供显式用户名和密码时无法获取 Kerberos TGT 票证。这意味着用户必须在运行 playbook 之前拥有有效的 Kerberos 票证。
有关如何配置、使用和排除 Kerberos 身份验证故障的更多信息,请参阅 Kerberos 身份验证。
密码认证
密码认证是最不安全的认证方法,不建议使用。但是,可以使用密码认证与 Windows SSH。要使用 Ansible 的密码认证,请在清单文件或剧本中设置 ansible_password
变量。使用密码认证需要在 Ansible 控制节点上安装 sshpass
软件包。
密码认证的工作原理类似于 WinRM CredSSP 认证,其中用户名和密码被提供给 Windows 主机,它将执行不受约束的委托以访问网络资源。