Mat*_*att 3 python ssl https winrm ansible
我有一些 Ansible playbook,想在一些 Windows 主机上运行。我遵循了各种 Ansible 指南来设置 WinRM,它们工作得很好,但默认设置非常不安全,我想要更多的生产准备。然而,关于如何执行此操作的说明却非常少。到目前为止,我已完成以下操作:
在我的 Windows 盒子上:
到目前为止一切顺利,Windows 端似乎运行良好。然而,让 Ansible 进行连接却是一场噩梦。我不知道如何让 Ansible 信任目标上的 HTTPS 证书,尽管添加了它。在我的 Centos 7“推箱”上,我做了以下操作:
ansible_user=ADMINISTRATOR@DOMAIN.COM
ansible_password=密码1
ansible_端口=5986
ansible_connection=winrm
ansible_winrm_scheme=https
/#ansible_winrm_server_cert_validation=忽略
ansible_winrm_transport=credssp
打开认证验证后,连接失败并出现以下错误:
fatal: [host.domain.com]:
UNREACHABLE! => {
"changed": false,
"msg": "credssp: HTTPSConnectionPool(host='host.domain.com', port=5986): Max retries exceeded with url: /wsman (Caused by SSLError(SSLError(\"bad handshake: Error([('SSL routines', 'tls_process_server_certificate', 'certificate verify failed')],)\",),))",
"unreachable": true}
Run Code Online (Sandbox Code Playgroud)
关闭证书验证后,它工作正常。
所以我的问题是:如何让 Ansible 信任我的 CA 证书?
这并不简单。问题是有 3 个不同的群体并不真正想玩:
首先,您需要 3 组 OpenSSL 证书/密钥:自签名证书颁发机构 (CA)、服务器 winRM HTTPS 和目标用户。
CA 证书/密钥没有什么神奇之处;它可以通过以下方式生成:
openssl req -new -out caroot.req -keyout caroot.key -days 730 ...
openssl x509 -req -in caroot.req -extensions v3_ca -signkey caroot.key -out cacert.pem -days 730
Run Code Online (Sandbox Code Playgroud)
这些 OpenSSL 命令还有无数其他选项,它们可能(或不能)在您的特定环境中工作。这是“不想对 OpenSSL 负责”的例子之一。
其次,您将需要 WinRM HTTPS 证书/密钥。首先,您必须生成服务器证书。生成证书的关键细节是证书上的“通用名称”属性必须与目标主机名匹配,就像任何 HTTPS 证书一样。
openssl req -new -out server.req -keyout server.key -days 730 -nodes ...
Run Code Online (Sandbox Code Playgroud)
现在,棘手的部分来了。您不能直接对密钥进行签名;签名过程必须向证书添加一些附加属性,否则它将无法工作。创建一个文本文件,我将其命名为“attributes.txt”,其中包含以下两行:
subjectAltName=DNS:hostname.mycompany.com,DNS:hostname
extendedKeyUsage=serverAuth
Run Code Online (Sandbox Code Playgroud)
第一行“subjectAltName”是必需的,否则 Python/OpenSSL 客户端将拒绝该密钥。您需要用正确的值替换目标主机名。第二行是 Windows 所必需的,否则 Windows 不会将其用作 HTTPS 服务器。
现在使用之前生成的 CA 对密钥进行签名:
openssl x509 -req -in server.req -out server.pem -days 730 -CA caroot.pem -CAkey caroot.key -extfile attributes.txt
Run Code Online (Sandbox Code Playgroud)
另一个小问题:除非您将密钥和证书合并到 PKCS#12 文件中,否则 Windows 不会导入服务器密钥。这可以通过以下命令来完成,该命令创建一个没有密码的 PKCS#12 文件:
openssl pkcs12 -export -password pass: -inkey server.key -in server.pem -out windows.pfx
Run Code Online (Sandbox Code Playgroud)
这将生成一个我们稍后需要的文件“windows.pfx”。
还无聊吗?
接下来我们需要另一个密钥/证书用于用户登录。这是假设我们将在系统上使用本地用户,而不是域用户。(您需要自己完成此操作。)生成密钥与生成服务器密钥几乎相同,只是“通用名称”属性 (CN) 必须与目标用户名匹配。(在以后的使用中,我将称我们的用户为“ansible”)。
openssl req -new -out winlogin.req -keyout winlogin.key -days 730
Run Code Online (Sandbox Code Playgroud)
该私钥将作为登录密钥,类似于 SSH 私钥。接下来,我们必须签署请求。与服务器密钥一样,我们需要添加一些扩展属性,否则不起作用。我们的“attributes.txt”文件必须包含以下行:
subjectAltName=otherName:1.3.6.1.4.1.311.20.2.3;UTF8:ansible@localhost
extendedKeyUsage=clientAuth
Run Code Online (Sandbox Code Playgroud)
“altNames”中的奇怪标识符是一些 Microsoft 专有的东西,它必须包含“ username @localhost”。正如我之前提到的,我使用本地用户“ansible”。ExtendedKeyUsage 属性是必需的,否则 Windows 将不允许使用该密钥进行用户身份验证。最后,我们签署证书:
openssl x509 -req -in winlogin.req -out winlogin.pem -days 730 -CA caroot.pem -CAkey caroot.key -extfile attributes.txt
Run Code Online (Sandbox Code Playgroud)
想让你知道,我在这里开始感到紧张了。我们快到了。最后,将 CA 证书 (caroot.pem)、服务器 PKCS#12 证书/密钥 (windows.pfx) 和用户证书 (winlogin.pem) 复制到目标 Windows 系统的某处。从同一目录运行以下 PowerShell 脚本。它将创建本地 ansible 用户并将所有 SSL 工件导入到其正确的目标位置。抱歉,如果这不是商业质量代码。这也为 ansible 用户提供了一个硬编码的密码,但这无关紧要,可以自由更改。如果这实际上成功运行,并且您在冲击中幸存下来,则可以从 Windows 服务器中删除文件工件(PFX 和 PEM 文件)。
另请注意,此脚本在末尾添加了防火墙规则。当然,必须根据您的环境进行适当修改。
# master script to enable winRM via HTTPS and allow certificate-based
# authentication
# add the local 'ansible' user
$username = "ansible"
$password = ConvertTo-SecureString -string "Ans!b123" -AsPlainText -Force
New-LocalUser -Name $username -AccountNeverExpires -Description "Ansible Remote Management" -Password $password
Add-LocalGroupMember -Member "ansible" -Group "Administrators"
$credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $username, $password
# import the Ansible root CA; certlm should show this in the
# 'Trusted Root Certification Authorities' folder
$caroot = Import-Certificate -FilePath ".\caroot.pem" -CertStoreLocation "Cert:\LocalMachine\Root"
# import the user cert; certlm should show this in the 'Trusted People' folder
$userkey = Import-Certificate -FilePath ".\winlogin.pem" -CertStoreLocation "Cert:\LocalMachine\TrustedPeople"
New-Item -Path WSMan:\localhost\ClientCertificate -subject "ansible@localhost" -URI "*" -Issuer $caroot.Thumbprint -Credential $credential -Force
# import the server certs - should appear in 'Personal' folder. The PFX file
# must contain both the cert and private key
$srvcert = Get-ChildItem -Path ".\windows.pfx" | Import-PFXCertificate -CertStoreLocation "Cert:\LocalMachine\MY" -Exportable
# Now create the winRM instance
$selector_set = @{Address= "*" Transport = "HTTPS" }
$value_set = @{CertificateThumbprint = $srvcert.Thumbprint}
New-WSManInstance -ResourceURI "winrm/config/Listener" -SelectorSet $selector_set -ValueSet $value_set
Set-Item -Path WSMan:\localhost\Service\Auth\Certificate -value $true
# add a firewall rule
New-NetFirewallRule -DisplayName "Ansible WinRM" -Direction Inbound -Protocol "TCP" -LocalPort "5986" -Action Allow -RemoteAddress @("192.16.2.3")
Run Code Online (Sandbox Code Playgroud)
好的,现在 Windows 已经完成了,我们应该为 Ansible 做好准备了。在您的清单中,您将需要以下变量才能应用于 Windows 系统:
ansible_port: 5986
ansible_connection: winrm
ansible_winrm_ca_trust_path: /path/to/caroot.pem
ansible_winrm_transport: certficate
ansible_winrm_cert_pem: /path/to/winlogin.pem
ansible_winrm_cert_key_pem: /path/to/winlogin.key
Run Code Online (Sandbox Code Playgroud)
此时,Ansible 应该使用 HTTPS 和证书身份验证连接到 Windows 服务器。我希望我完成了所有步骤,这是我不久前设置的。
| 归档时间: |
|
| 查看次数: |
14154 次 |
| 最近记录: |