Ansible Certificate认证
Ansible在对Windows主机控制时,不同于Linux主机通过SSH协议进行密码和秘钥认证,在对Windows主机进行控制时最常见的使用Windows用户名和密码通过NTLM
进行认证,但是在需求环境中,当平台将Windows主机分配给用户之后,会出现用户自行修改密码的情况。
为了避免这种情况,可以通过Certificate
证书认证,在《Ansible官方文档》中提供了以下五种认证方式
此文档只描述通过Certificate进行认证。
需要注意的是Certificate
并不能通过域用户进行认证,如果通过域用户可使用NTLM
或者Kerberos
进行认证。
环境要求
Windows主机
-- Powershell >= 3.0
-- .NET >= 4.0
-- 激活WinRM服务
Ansible主机
-- 安装Ansible
-- 安装pywinrm模块
开启WinRM基于证书认证
Set-Item -Path WSMan:\localhost\Service\Auth\Certificate -Value $true
创建本地用户账户
相关的ps1脚本可以使用Windows PowerShell ISE进行编辑运行
使用基于证书认证的WinRM,需要将证书映射到本地用户上,可以直接映射到本地用户上,但是需求环境每个主机本地用户是不经相同,所以最好是创建一个特定的用户用于Ansible管理。
以下脚本可以创建一个名为ansibleuser
的本地用户账户,并设置其密码为An@passw0rd
,始终处于活跃状态密码不过期。
$UserAccountName = 'ansibleuser'
$UserAccountPassword = (ConvertTo-SecureString -String 'An@passw0rd' -AsPlainText -Force)
if (-not (Get-LocalUser -Name $UserAccountName -ErrorAction Ignore)) {
$newUserParams = @{
Name = $UserAccountName
AccountNeverExpires = $true
PasswordNeverExpires = $true
Password = $UserAccountPassword
}
$null = New-LocalUser @newUserParams
}
创建证书
创建证书可以通过以下两种方式进行生成
1、在使用Openssl
进行生成
2、在PowerShell使用New-SelfSignedCertificate
进行生成
Openssl生成证书
在一台安装了Openssl
的Linux主机上创建以下Shell
脚本
## This is the public key generated from the Ansible server using:
cat > openssl.conf << EOL
distinguished_name = req_distinguished_name
[req_distinguished_name]
[v3_req_client]
extendedKeyUsage = clientAuth
subjectAltName = otherName:1.3.6.1.4.1.311.20.2.3;UTF8:ansibletestuser@localhost
EOL
export OPENSSL_CONF=openssl.conf
openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -out cert.pem -outform PEM -keyout cert_key.pem -subj "/CN=ansibleuser" -extensions v3_req_client
rm openssl.conf
然后执行此脚本,在脚本所在目录会生成一对公/密钥(cert_key.pem/cert.pem)
New-SelfSignedCertificate生成证书
$username = "ansibleuser"
$output_path = "C:\temp"
# Instead of generating a file, the cert will be added to the personal
# LocalComputer folder in the certificate store
$cert = New-SelfSignedCertificate -Type Custom `
-Subject "CN=$username" `
-TextExtension @("2.5.29.37={text}1.3.6.1.5.5.7.3.2","2.5.29.17={text}upn=$username@localhost") `
-KeyUsage DigitalSignature,KeyEncipherment `
-KeyAlgorithm RSA `
-KeyLength 2048
# Export the public key
$pem_output = @()
$pem_output += "-----BEGIN CERTIFICATE-----"
$pem_output += [System.Convert]::ToBase64String($cert.RawData) -replace ".{64}", "$&`n"
$pem_output += "-----END CERTIFICATE-----"
[System.IO.File]::WriteAllLines("$output_path\cert.pem", $pem_output)
# Export the private key in a PFX file
[System.IO.File]::WriteAllBytes("$output_path\cert.pfx", $cert.Export("Pfx"))
会在C:\temp
下生成秘钥对,但是生成的秘钥是pfx
格式的,所以需要Anisble在使用的时候需要通过Openssl
使用以下命令进行转化为.pem
,其中passin/passout
为创建证书时使用密码,但是以上脚本中为加密,所以密码为空。
openssl pkcs12 -in cert.pfx -nocerts -nodes -out cert_key.pem -passin pass: -passout pass:
导入证书
生成证书之后[若是使用Openssl生成,将其公钥上传到Windows的C盘],需要使用以下命令将其证书导入到受信任的根证书颁发机构和受信任的人证书存储区
$pubKeyFilePath = 'C:\cert.pem'
$null = Import-Certificate -FilePath $pubKeyFilePath -CertStoreLocation 'Cert:\LocalMachine\Root'
$null = Import-Certificate -FilePath $pubKeyFilePath -CertStoreLocation 'Cert:\LocalMachine\TrustedPeople'
创建服务器证书
使用以下命令将创建自签证书存储到LocalMachine\My
下
$hostname = hostname
$serverCert = New-SelfSignedCertificate -DnsName $hostName -CertStoreLocation 'Cert:\LocalMachine\My'
证书映射本地用户
将证书映射到本地用户,是为了确保当Ansible通过证书连接到windows主机时,它将以本地用户身份执行所有指令,这样可以使用Ansible连接windows进行执行命令是都是通过ansibleuser
用户进行操作
$credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $UserAccountName, $UserAccountPassword
$ansibleCert = Get-ChildItem -Path 'Cert:\LocalMachine\Root' | Where-Object {$_.Subject -eq 'CN=ansibleuser'}
$params = @{
Path = 'WSMan:\localhost\ClientCertificate'
Subject = "$UserAccountName@localhost"
URI = '*'
Issuer = $ansibleCert.Thumbprint
Credential = $credential
Force = $true
}
New-Item @params
设置LocalAccountTokenFilterPolicy
LocalAccountTokenFilterPolicy
是用于控制过滤本地管理员组中所有本地用户的远程连接访问令牌的策略。当此参数设置为1
时,则策略允许使用明文凭据或密码哈希,从本地管理员组的任何成员获得高完整性访问令牌的远程连接。
$newItemParams = @{
Path = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System'
Name = 'LocalAccountTokenFilterPolicy'
Value = 1
PropertyType = 'DWORD'
Force = $true
}
$null = New-ItemProperty @newItemParams
将本地用户账户加入到管理员组
Get-LocalUser -Name $UserAccountName | Add-LocalGroupMember -Group 'Administrators'
至此全部的配置完成,在Ansible的hosts文件中配置以下内容,测试是否可正常使用
ansible_connection: winrm
ansible_winrm_cert_pem: /path/to/certificate/public/cert.pem
ansible_winrm_cert_key_pem: /path/to/certificate/private/cert_key.pem
ansible_winrm_transport: certificate