Ansible, in fact, supports five different Windows authentication mechanisms as follows:
- Basic: Supports local accounts only
- Certificate: Supports local accounts only, conceptually similar to SSH key-based authentication
- Kerberos: Supports AD accounts
- NTLM: Supports both local and AD accounts
- CredSSP: Supports both local and AD accounts
It is worth noting that Kerberos, NTLM, and CredSSP all provide message encryption over HTTP, which improves security. However, we have already seen how easy it is to set up WinRM over HTTPS, and WinRM management over plain HTTP is not enabled by default anyway, so we will assume that the communication channel is already encrypted. WinRM is a SOAP protocol meaning it must run over a transport layer such as HTTP or HTTPS. To prevent remote management commands being intercepted on the network, it is best practise to ensure WinRM runs over the HTTPS protocol.
Of these authentication methods, the one that interests us most is Kerberos. Kerberos (for the purpose of this chapter) effectively supersedes NTLM for Ansible authentication against Active Directory accounts. CredSSP provides another mechanism, but there are also security risks relating to the interception of clear-text logons on the target host that are best understood before it is deployed—in fact, it is disabled by default.
Before we move on to configuring Kerberos, a brief note about certificate authentication. Although initially, this might seem appealing, as it is effectively passwordless, current dependencies in Ansible mean that the private key for the certificate authentication must be unencrypted on the Ansible automation host. In this regard, it is actually more secure (and wiser) to place the password for either a basic or Kerberos authentication session in an Ansible vault. We have already covered basic authentication, and so we will focus our efforts on Kerberos here.
As Kerberos authentication only supports Active Directory accounts, it is assumed that the Windows host to be controlled by Ansible is already joined to the domain. It is also assumed that WinRM over HTTPS has already been set up, as discussed earlier in the chapter.
With these requirements in place, the first thing we have to do is install a handful of Kerberos-related packages on the Ansible host itself. The exact packages will depend upon your chosen OS, but on CentOS 7, it would look like this:
sudo yum -y install python-devel krb5-devel krb5-libs krb5-workstation
On Ubuntu 16.04, you would install the following packages:
sudo apt-get install python-dev libkrb5-dev krb5-user
In addition to these packages, we also need to install the pywinrm[kerberos] Python module. Availability of this will vary—on CentOS 7, it is not available as an RPM, so we need to install it through pip as follows:
sudo yum install python-pip gcc
sudo pip install pywinrm[kerberos]
Next, ensure that your Ansible server can resolve your Active Directory (AD)-related DNS entries. The procedure for this will vary according to the OS and network architecture, and so is beyond the scope of this book—suffice to say, your Ansible controller must be able to resolve your domain controller and related entries for the rest of this procedure to work.
With DNS in place, next, add your domain to /etc/krb5.conf. For example, my test domain is mastery.example.com, and my domain controller is WIN-2NJFMR0MNBD.mastery.example.com, so the bottom of my /etc/krb5.conf looks like this:
[realms]
MASTERY.EXAMPLE.COM = {
kdc = WIN-2NJFMR0MNBD.mastery.example.com
}
[domain_realm]
.mastery.example.com = MASTERY.EXAMPLE.COM
Note the capitalization—this is important! Test your Kerberos integration using the kinit command with a known domain user account. Here is an example using the Domain Administrator for my test domain:
Finally, let's create a Windows host inventory—note that it is almost identical to the one we used in our basic authentication example; only this time, we have specified the Kerberos domain after the username:
[windows]
192.168.81.150
[windows:vars]
[email protected]
ansible_password="password"
ansible_port=5986
ansible_connection=winrm
ansible_winrm_server_cert_validation=ignore
Now, we can test connectivity just like before:
Success! The previous result shows successful end-to-end connectivity with Windows, including successful authentication, and access to the WinRM subsystem.