在和windows server通信前
ansible主机条件
如果使用ansible和windows通信和使用windows模块的话,需要满足以下条件:
1,ansible目前可以在微软的支持或者扩展支持下管理windows版本。ansible可以管理的桌面系统包括win7,8.1,10。server系统包括server 2008,2008 R2, 2012 R2,2016和2019
2,ansible需要PowerShell 3.0和.NET 4.0以上才可以安装上
3,WinRM 监听需要被创建或者激活,详情如下:
注意:这些是ansible连接的基本需求,部分ansible模块需要额外的需求,比如更新版本的操作系统或者PowerShell版本。详情查看官方文档。
powershell & .NET 升级 (暂略)
powershell 查看版本:$PSVersionTable
PS 3.0 会有点bug.
WinRM设置
一旦PowerShell被升级到最新3.0版本,还需要配置WinRM来使得Ansible能够连接主机。WinRM有两个主要的组件来管理与ansible的通信接口。listener和service configuration settings.
脚本ConfigureRemotingForAnsible.ps1可以被用于一些基本设置。这个脚本设置了HTTP&HTTPS的自签名Listener并且是能了服务里的Basic认证选项。
- 在执行这个脚本的时候如果遇到cannot be loaded because running scripts is disabled on this system这个错误,需要执行
Set-ExecutionPolicy RemoteSigned
。
如果使用ConfigureRemotingForAnsible.ps1这个脚本,执行以下脚本:
$url = "https://raw.githubusercontent.com/ansible/ansible/devel/examples/scripts/ConfigureRemotingForAnsible.ps1"
$file = "$env:temp\ConfigureRemotingForAnsible.ps1"
(New-Object -TypeName System.Net.WebClient).DownloadFile($url, $file)
powershell.exe -ExecutionPolicy ByPass -File $file
有两个参数(like -EnableCredSSP and -ForceNewSSLCert)能够在这个脚本中设置,这个脚本的上面有介绍。
这个ConfigureRemotingForAnsible.ps1脚本是用来培训和实验的目的并且不应该用于生产环境, 因为它使能的设置(比如Basic认证)本身就不安全。
WinRM Listener
WinRM监听一个或多个端口的请求,每个端口必须有一个listener创建和配置。
可以通过以下命令查看WinRM服务listener的运行情况。
winrm enumerate winrm/config/Listener
会有类似如下的输出:
Listener
Address = *
Transport = HTTP
Port = 5985
Hostname
Enabled = true
URLPrefix = wsman
CertificateThumbprint
ListeningOn = 10.0.2.15, 127.0.0.1, 192.168.56.155, ::1, fe80::5efe:10.0.2.15%6, fe80::5efe:192.168.56.155%8, fe80::
ffff:ffff:fffe%2, fe80::203d:7d97:c2ed:ec78%3, fe80::e8ea:d765:2c69:7756%7
Listener
Address = *
Transport = HTTPS
Port = 5986
Hostname = SERVER2016
Enabled = true
URLPrefix = wsman
CertificateThumbprint = E6CDAA82EEAF2ECE8546E05DB7F3E01AA47D76CE
ListeningOn = 10.0.2.15, 127.0.0.1, 192.168.56.155, ::1, fe80::5efe:10.0.2.15%6, fe80::5efe:192.168.56.155%8, fe80::
ffff:ffff:fffe%2, fe80::203d:7d97:c2ed:ec78%3, fe80::e8ea:d765:2c69:7756%7
在这个例子中有两个listener被激活,一个是监听HTTP 5985,另一个是HTTPS 5986。里面一些重要的配置选项:
-
Transport
: 推荐使用listener over HTTPS的方式,因为数据会被加密并且不需要其他配置。 -
Port
: linstener监听的端口,默认是5985 HTTP & 5986 HTTPS,这个端口可以按需更改,ansible端也改相应的主机变量ansible_port就可。 -
URLPrefix
: 监听的URL,默认是wsman。如果这个被改了,那么相应的ansible端的ansible_winrm_path也做相应更改。 -
CertificateThumbprint
: 如果listener运行在HTTPS上,这个是windows Certificate Store的指纹用于创建连接。通过在PS中运行以下带着指纹的命令可以得到这个认证的详细信息:
$thumbprint = "E6CDAA82EEAF2ECE8546E05DB7F3E01AA47D76CE"
Get-ChildItem -Path cert:\LocalMachine\My -Recurse | Where-Object { $_.Thumbprint -eq $thumbprint } | Select-Object *
设置WinRM Listener
有三种方法设置WinRM listener:
- 使用
winrm quickconfig
配置HTTP或者winrm quickconfig -transport:https
配置HTTPS。这个是运行在域环*一个linstener情况下最简单的配置方式。这个过程还有一个好处就是可以自动为相应端口打开防火墙并且启动WinRM服务。 - 使用组策略对象的情况。这个是最好的方式去创建一个Listener,在主机是域成员的时候。因为所有的配置都被自动配置好了并且不需要其他的输入。关于组策略对象的信息,可以查看相关文档。
- 使用powershell去创建一个特别的配置,这个过程可以通过以下的powershell命令去实现:
$selector_set = @{
Address = "*"
Transport = "HTTPS"
}
$value_set = @{
CertificateThumbprint = "E6CDAA82EEAF2ECE8546E05DB7F3E01AA47D76CE"
}
New-WSManInstance -ResourceURI "winrm/config/Listener" -SelectorSet $selector_set -ValueSet $value_set
powershell其他的命令可以参考:New-WSManInstance.
注:当创建一个HTTPS listener,需要有证书在LocalMachine\My
cerificate store里,否则大部分的命令都不会成功。
删除WinRM Listener
- 删除所有的listeners
Remove-Item -Path WSMan:\localhost\Listener\* -Recurse -Force
- 只删除跑在HTTPS上的listeners
Get-ChildItem -Path WSMan:\localhost\Listener | Where-Object { $_.Keys -contains "Transport=HTTPS" } | Remove-Item -Recurse -Force
注:Keys
是一个字符串数组,所以可以包含不同的值。默认下Transport=
和Address=
包含的值对应着winrm/config/Listeners
中的值。
WinRM服务选项
有一系列的选项来配置WINRM服务组件,包含认证选项和内存设置。
使用这个命令来查看服务已配置选项:
winrm get winrm/config/Service
winrm get winrm/config/Winrs
然后会有一些类似下面的输出:
Service
RootSDDL = O:NSG:BAD:P(A;;GA;;;BA)(A;;GR;;;IU)S:P(AU;FA;GA;;;WD)(AU;SA;GXGW;;;WD)
MaxConcurrentOperations = 4294967295
MaxConcurrentOperationsPerUser = 1500
EnumerationTimeoutms = 240000
MaxConnections = 300
MaxPacketRetrievalTimeSeconds = 120
AllowUnencrypted = false
Auth
Basic = true
Kerberos = true
Negotiate = true
Certificate = true
CredSSP = true
CbtHardeningLevel = Relaxed
DefaultPorts
HTTP = 5985
HTTPS = 5986
IPv4Filter = *
IPv6Filter = *
EnableCompatibilityHttpListener = false
EnableCompatibilityHttpsListener = false
CertificateThumbprint
AllowRemoteAccess = true
Winrs
AllowRemoteShellAccess = true
IdleTimeout = 7200000
MaxConcurrentUsers = 2147483647
MaxShellRunTime = 2147483647
MaxProcessesPerShell = 2147483647
MaxMemoryPerShellMB = 2147483647
MaxShellsPerUser = 2147483647
虽然这些选项一般都很少更改,但是有一少部分能够很简单的影响winRM的运行并且有助于理解。
一些重要的选项:
-
Service\AllowUnencrypted:
这个选项决定了WinRM是否允许流量在没有数据加密的HTTP下通过。信息只有在ansible_winrm_transport
选项是ntlm
,kerberos
或者credssp
的条件下才可以进行加密。默认情况下这个选项是true
,在调试WinRM消息的时候可以置位false
。 -
Service\Auth\*:
这个标志位定义了认证选项是否被WinRM服务允许。默认情况下,Negotiate (NTLM)
和kerberos
是打开的。 -
Service\Auth\CbtHardeningLevel:
_指定是否隧道绑定令牌没有被验证(None),验证了但是不是必需的(Relaxed),或者是必须要被验证的(Strict)。CBT(Channel Binding Token)只用在NTML和kerberos over HTTPS情况下。 -
Service\CertificateThumbprint:
这是用于加密与CredSSP身份验证一起使用的TLS通道的证书的指纹。默认情况下为空。当WinRM启动的时候,一个自签名证书被生成并且被用于TLS过程中。 -
Winrs\MaxShellRunTime:
这是远程命令被执行的最大时间,单位是毫秒。 -
Winrs\MaxMemoryPerShellMB:
这是最大This is the maximum amount of memory allocated per shell, including the shell’s child processes.
Powershell下修改Service
设置的值:
# 替换winrm/config/Service后面的路径{path}
Set-Item -Path WSMan:\localhost\Service\{path} -Value "value here"
# 例如, 启动Service\Auth\CbtHardeningLevel
Set-Item -Path WSMan:\localhost\Service\Auth\CbtHardeningLevel -Value Strict
PowerShell下修改winrs
的值:
# 替换winrm/config/Winrs后面的路径{path}
Set-Item -Path WSMan:\localhost\Shell\{path} -Value "value here"
# 例如,启动Winrs\MaxShellRunTime
Set-Item -Path WSMan:\localhost\Shell\MaxShellRunTime -Value 2147483647
注:如果主机运行在域环境下的时候,一些选项被设置在组策略对象下,主机不能自己改动。如果设置是由组策略下发的,那么它会在value旁边有[Source="GPO"]
的提示。
Windows SSH设置
Ansible 2.8为Windows主机添加了实验性的SSH连接.
注:使用这个特性需要后果自负。在WINDOWS下使用SSH只是实验性的,该功能在以后版本中可能不是向下兼容的。服务器端的组件是否能使用取决于ansible的版本。
安装Win32-OpenSSH
第一步是安装Win32-OpenSSH
到windows主机上。微软提供的安装方式对ansible来说太旧了。应该采用以下方式:
- 手动安装服务,参考微软官方文档
- 使用
win_chocolatey
安装
- name: install the Win32-OpenSSH service
win_chocolatey:
name: openssh
package_params: /SSHServerFeature
state: present
- 使用Ansible Galaxy role,比如jborean93.win_openssh:
# 需要先把role下载下来
# main.yml
- name: install Win32-OpenSSH service
hosts: windows
gather_facts: no
roles:
- role: jborean93.win_openssh
opt_openssh_setup_service: True
注:Win32-OpenSSH
仍然是一个持续更新改进的测试产品,如果你使用SSH作为和windows的交互选项,强烈建议你使用以上三种方式来安装最新的版本。
配置Win32-OpenSSH
默认Win32-OpenSSH
会使用cmd.exe
作为shell,如果使用其他shell,用ansible任务去定义注册表设置:
- name: set the default shell to PowerShell
win_regedit:
path: HKLM:\SOFTWARE\OpenSSH
name: DefaultShell
data: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
type: string
state: present
# Or revert the settings back to the default, cmd
- name: set the default shell to cmd
win_regedit:
path: HKLM:\SOFTWARE\OpenSSH
name: DefaultShell
state: absent
Win32-OpenSSH认证
Win32-OpenSSH认证方式和linux上的相似。你可以使用纯文本的密码或者SSH公钥,把公钥添加用户文件目录下.ssh
文件夹的authorized_key
中。然后在sshd_config
文件中配置SSH服务,和在Linux中使用方式一样。
当使用SSH密钥验证时,远程会话没有用户的证书并且在尝试连接网络资源时会失败,这个是已知的多跳或者credential delegation问题。有两种解决方式:
- 设置
ansible_password
,使用明文密码认证 - 在需要访问远程资源的用户认证里使用
become
选项在任务里。
配置ansible端
使用ssh和windows交互需要配置两个连接变量:
-
ansible_connection
置为ssh
-
ansible_shell_type
置为cmd
或者powershell
ansible_shell_type
变量需要和windows主机上的DefaultShell
相对应。如果DefaultShell
是默认,那就设置为cmd
,如果是Powershell就设置成powershell
SSH和windows结合的已知问题
windows上的SSH只是实验环境,下面是一些已知问题:
- Win32-OpenSSH在版本
v7.9.0.0p1-Beta
之前的,不能使用powershell
作为shell类型。 - 虽然SCP可能好使,但是SFTP是文件传输或者编码下载文件时的推荐方式。