Windows SSH
在较新的 Windows 版本上,您可以使用 SSH 连接到 Windows 主机。这是 WinRM 的替代连接选项。
注意
虽然 Ansible 自 Ansible 2.8 版本起就可以将 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 快。要更改默认 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
主机变量指定 UPN 用户名,Ansible 在使用 SSH 时将自动使用该用户的 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
可以在 ~/.ssh/config
文件中或清单中作为主机变量设置 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 主机,然后它将执行无约束委派以访问网络资源。