# Unable to connect to Windows 2016 over HTTPS using self signed certificates;  using ansible securely in a mixed active directory environment

**URL:** <https://forum.ansible.com/t/unable-to-connect-to-windows-2016-over-https-using-self-signed-certificates-using-ansible-securely-in-a-mixed-active-directory-environment/32050>\
**Category:** Ansible Project\
**Tags:** windows\
**Created:** [January 24, 2020, 5:34pm UTC](https://forum.ansible.com/t/unable-to-connect-to-windows-2016-over-https-using-self-signed-certificates-using-ansible-securely-in-a-mixed-active-directory-environment/32050 "2020-01-24T17:34:36Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![Dan\_Hebert](https://avatars.discourse-cdn.com/v4/letter/d/6a8cbe/32.png) [@Dan\_Hebert](https://forum.ansible.com/u/Dan_Hebert)\
**Post date:** [January 24, 2020, 5:34pm UTC](https://forum.ansible.com/t/unable-to-connect-to-windows-2016-over-https-using-self-signed-certificates-using-ansible-securely-in-a-mixed-active-directory-environment/32050/1 "2020-01-24T17:34:36Z")

</div>

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](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](https://docs.ansible.com/ansible/latest/user_guide/windows_winrm.html)

E **nable 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](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.
