Good afternoon,
I have been trying to get ansible working over a Windows 2016 HTTPS listener with encryption using TLS encryption and self-signed certificate authentication.
User authentication over HTTP is not going to be sufficient. The environment where I work is a mix of nodes where some use active directory.
Here is the matrix for authentication:
https://docs.ansible.com/ansible/latest/user_guide/windows_winrm.html
Given this matrix, I expected that I would have been able to authenticate with a local account that is part of the administrators group using certificates. I followed this process, taken from the Windows ansible guides:
https://docs.ansible.com/ansible/latest/user_guide/windows_winrm.html
Enable TLS
Function Enable-TLS12 {
param(
[ValidateSet(“Server”, “Client”)]
[String]$Component = “Server”
)
$protocols_path = ‘HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols’
New-Item -Path “$protocols_path\TLS 1.2$Component” -Force
New-ItemProperty -Path “$protocols_path\TLS 1.2$Component” -Name Enabled -Value 1 -Type DWORD -Force
New-ItemProperty -Path “$protocols_path\TLS 1.2$Component” -Name DisabledByDefault -Value 0 -Type DWORD -Force
}
Enable-TLS12 -Component Server
Not required but highly recommended to enable the Client side TLS 1.2 components
Enable-TLS12 -Component Client
Restart-Computer
Enable certificate authentication
Set-Item -Path WSMan:\localhost\Service\Auth\Certificate -Value $true
Enable LocalTestAccount certificate
Please note that I changed the -TextExtension which corresponds to the EKU to have the trailing digit be a 1 instead of a 2, which differs from: https://docs.ansible.com/ansible/latest/user_guide/windows_winrm.html#generate-a-certificate
Using the code from the documentation gives an EKU error: “The Enhanced Key Usage (EKU) field of the certificate is not set to “Server Authentication””
$username = “LocalTestAccount”
$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.1”,“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”))
Import LocalTestAccount
$cert = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Certificate2
$cert.Import(“C:\temp\LocalTestAccount\cert.pem”)
$store_name = [System.Security.Cryptography.X509Certificates.StoreName]::Root
$store_location = [System.Security.Cryptography.X509Certificates.StoreLocation]::LocalMachine
$store = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Store -ArgumentList $store_name, $store_location
$store.Open(“MaxAllowed”)
$store.Add($cert)
$store.Close()
Map certificate to LocalTestAccount
$username = “LocalTestAccount”
$password = ConvertTo-SecureString -String “my_password” -AsPlainText -Force
$credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $username, $password
This is the issuer thumbprint which in the case of a self generated cert
is the public key thumbprint, additional logic may be required for other
scenarios
$thumbprint = (Get-ChildItem -Path cert:\LocalMachine\root | Where-Object { $_.Subject -eq “CN=$username” }).Thumbprint
New-Item -Path WSMan:\localhost\ClientCertificate `
-Subject “$username@localhost” `
-URI * `
-Issuer $thumbprint `
-Credential $credential `
-Force
Create HTTPS Listener with Certificate
$selector_set = @{
Address = “*”
Transport = “HTTPS”
}
$value_set = @{
CertificateThumbprint = “my thumbprint code here”
}
Get-ChildItem -Path cert:\LocalMachine\My -Recurse | Where-Object { $_.Thumbprint -eq “my thumbprint code here” } | Select-Object *
New-WSManInstance -ResourceURI “winrm/config/Listener” -SelectorSet $selector_set -ValueSet $value_set
To be run on my Linux machine
Extract private key
openssl pkcs12 -in cert.pfx -nocerts -nodes -out cert_key.pem -passin pass: -passout pass:
certificate: cert.pem
The checks that I run:
Enumerate listeners (Microsoft documentation)
winrm enumerate winrm/config/Listener
SSL HTTPS enablement check
$listeners = Get-ChildItem WSMan:\localhost\Listener
If (!($listeners | Where-Object {$_.Keys -like “TRANSPORT=HTTPS”}))
{
Write-Host “SSL not enabled”
}
else
{
Write-Host “SSL enabled”
}
Ansible connection configuration flags (from my hosts file)
I have used multiple combinations of the below to get this to work. I’m trying to force port 5986 specifically for the encryption.
[dev:vars]
ansible_connection=winrm
ansible_user=LocalTestAccount
#ansible_winrm_transport=credssp
#ansible_pass=
#ansible_winrm_server_cert_validation=validate
#ansible_winrm_message_encryption=always
ansible_winrm_scheme=https
ansible_port=5986
ansible_winrm_cert_pem=/materials/LocalTestAccount_certificates/cert.pem
ansible_winrm_cert_key_pem=/materials/LocalTestAccount_certificates/cert_key.pem
ansible_winrm_server_cert_validation=ignore
ansible_winrm_transport=certificate
Error message
<10.138.12.123> ESTABLISH WINRM CONNECTION FOR USER: LocalTestAccount on PORT 5986 TO 10.138.12.123
10.138.12.123 | UNREACHABLE! => {
“changed”: false,
“msg”: “certificate: the specified credentials were rejected by the server”,
“unreachable”: true
}
Ansible version information
ansible --version
ansible 2.8.2
As long as we have LocalTestAccount available as part of the Administrators group, my understanding is that with certificates I could run any of the Windows modules and enjoy the benefits of encryption. At the end of the day, we need a recommended solution for mixed active directory nodes, full encryption, and preferably not using passwords in the configuration files.
If my certificate attempt is close and will satisfy my security concerns, please advise on how to fix it. If this is not the recommended path, please recommend something different.
Thank you.