SSL Certificate or Passwordless WinRM setup

Hello,
I have been racking my brain for the last few days trying to setup SSL Certificate based or Passwordless WinRM setup in Ansible. I have a mixed environment of domain and non domain WIndows servers that I would like to have Ansible maintain. So far in my reading and scouring the interwebs, it appears I picked the difficult option of using SSL. Currently, I am trying to use a self signed certificates to make this work. I have followed a few different websites to get this working. Here are three that I have been reading over and over to make this work:

https://docs.ansible.com/ansible/latest/user_guide/windows_winrm.html#certificate

https://vnuggets.com/2019/08/08/ansible-certificate-authentication-to-windows/

http://www.hurryupandwait.io/blog/certificate-password-less-based-authentication-in-winrm

They all make it sound so easy. At the end of their articles it all works. Really impressive to be truthful.

Any way I have a few questions. First, here is what I am doing to try to make this work. I am creating a self-signed cert on my Ansible server (Ubuntu 18.04 using Ansible 2.9.5 with Python 3.6.9) using OpenSSL per the instructions. I copy these over the pem file to my windows server and add this to the Trusted Root and Trusted People store. Then create a self-signed cert using PowerShell for the Windows server and add it to the Local My store. I map the self-signed cert I created in Windows to a local user on the Windows server. The username for the cert creation in OpenSSL matches the username that I am mapping in Windows. Then

I try running “Ansible windows -m win_ping -vvvv”. This is where the documentation and I split ways. Where theirs works, mine results in “msg”: “certificate: the specified credentials were rejected by the server”.
No firewall is enabled as this is just in testing at this point. I do not see in the event log where the Ubuntu server is trying to hit the Windows 2016 server. If I change my host file from certificate to basic or credssp using the ssl option with ignore, it pings fine. However, when telling it to use certificate and pointing to the two pem files that OpenSSL created, I get the message above.

First question would be why am I creating a cert for Ansible on the Linux server and then creating a SSL cert on the Windows server?
Does the Windows Cert need to be installed on the Linux server?
I feel I am missing something simple but for the life of me cannot figure out what.

Any help would be greatly appreciated. If you need extra info, please ask. I will provide all information I can.
Thank you in advance.

WinRM certificate auth is plain simple complex and not recommended to be used. It’s the most complex option to set up and has a loads of caveats and downsides that I wouldn’t really recommend it’s use.

First question would be why am I creating a cert for Ansible on the Linux server and then creating a SSL cert on the Windows server?

WinRM certificate auth is based on X509 mutual authentication [1]. It’s a very enterprise like setup but IMO it’s quite difficult to set up properly and then WinRM adds even more complication on top that reduces it’s effectiveness. But ultimately it balls down to having both the client and server trust each other which requires both entities to have their own X509 certificate and a private key that backs that cert. These keys are used for;

  • Windows - This is the certificate that is used by WinRM to back it’s https endpoint. It’s a server certificate and when used properly it is designed to allow clients who connect to the server the ability to trust it is who it says it is. This cert is required for any auth methods that run on the https endpoint

  • Ansible - This is the certificate that is used by Ansible to authenticate as a local user on the Windows host. This is purely for WinRM certificate auth.

That is why you need to generate 2 certificates, one for the server for it to allow clients to verify it is who it says it is and another for the client (Ansible) to tell the server who it is. So think of the 2nd certificate generated on the Ansible host as something that is unrelated to the cert that is generated by Windows for WinRM.

At the heart of this client certificate setup is 2 files

  • The public X509 certificate with the subject ‘CN=username’ (ansible_winrm_cert_pem)
  • The private X509 key for the above certificate, this should only be Ansible controller (ansible_winrm_cert_key_pem)
    The public key is placed in the Root store so that Windows will trust that it knows the public key sent by Ansible and I believe in a proper CA setup if that key is signed by a known CA authority only the CA authority needs to be in the Root store. It is also placed in the TrustedPeople store as I believe that is required for Windows to trust a cert that is mapped to a local account.

Does the Windows Cert need to be installed on the Linux server?

For you to actually take advantage of the https endpoint yes you should be signing the certs used by the WinRM endpoint with a trusted CA and having that CA installed on your Linux server. This allows Ansible to be able to verify the Windows host it is connecting to is actually who it says it is and not just some rogue server pretending to be it and stealing your information. So while using self signed certs will work it’s breaking a key cornerstone of TLS and a proper enterprise environment should be using their internal CA setup to sign and distribute the keys to the Windows host.

As for the client auth side there is no way to install these certs for use in Ansible as authentication. One of the limitations of the WinRM certificate auth is the fact that you need both the cert and private key as plaintext files on the system. This is a limitation of the underlying Python library we are using and one of the reasons why we don’t recommend you use it.

In the end I highly recommend you move across to using Kerberos auth as that provides both trust and a way to connect without a password (using keytabs). You also don’t need to worry about https endpoints as the message encryption offered by Kerberos is quite strong.

For your domain joined servers but for your non domain hosts there really isn’t a good way of ensuring trust between the hosts. You could still sign the WinRM certs with a known trusted CA and get your trust that way but this would be a manual process. In the end most people just rely on self signed certs for non-domain hosts as you still get encryption, you just miss the trust aspect.

[1] - https://medium.com/sitewards/the-magic-of-tls-x509-and-mutual-authentication-explained-b2162dec4401

You can install open ssh on windows now
Sadly still in beta last I looked but I tested it and could shh from my sensible server to the windows deter with an ssh key and run power shell commands etc

Stu