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 username@REALM.COM
Password for username@REALM.COM
> klist
Ticket cache: KCM:1000
Default principal: username@REALM.COM
Valid starting Expires Service principal
29/08/24 13:54:51 29/08/24 23:54:51 krbtgt/REALM.COM@REALM.COM
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 username@REALM.COM
Password for username@REALM.COM
# -f will show the ticket flags, we want to see F
> klist -f
Ticket cache: KCM:1000
Default principal: username@REALM.COM
Valid starting Expires Service principal
29/08/24 13:54:51 29/08/24 23:54:51 krbtgt/REALM.COM@REALM.COM
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 主机,然后它将执行无约束委派以访问网络资源。