Engineering Enterprise Authentication: Mastering Ansible WinRM with Kerberos Integration

The orchestration of Windows environments within a Linux-based automation framework necessitates a robust, secure, and scalable authentication mechanism. While NTLM is often the default for small-scale labs, enterprise-grade deployments demand the implementation of Kerberos. Kerberos provides a ticket-based authentication system that eliminates the need to transmit passwords across the network, leveraging a Key Distribution Center (KDC) to verify identities. When integrating Ansible with Windows via WinRM (Windows Remote Management), Kerberos becomes the gold standard for security, particularly when operating within an Active Directory (AD) domain. However, the transition from simple password authentication to Kerberos is fraught with technical hurdles, specifically regarding the Execution Environment (EE) in AWX and Ansible Automation Platform, the configuration of the GSSAPI, and the precise alignment of the krb5.conf file.

The Technical Architecture of WinRM Kerberos Authentication

WinRM operates as the primary gateway for Ansible to communicate with Windows hosts. In a standard setup, WinRM can use various transport mechanisms, but Kerberos is preferred for its mutual authentication and encryption capabilities. A critical technical nuance is that Kerberos provides its own layer of encryption. This means that while HTTPS (port 5986) is often used for security, Kerberos authentication is fundamentally safe even over HTTP (port 5985) because the session is encrypted by the Kerberos protocol itself.

The process involves a three-way handshake between the Ansible Controller (or Execution Environment), the KDC (usually the Active Directory Domain Controller), and the target Windows host. The controller requests a ticket from the KDC, which it then presents to the target host to prove its identity. For this to function, the environment running the Ansible code must have a valid Kerberos configuration and the necessary system libraries to handle GSSAPI (Generic Security Services Application Programming Interface) calls.

Prerequisites and System-Level Dependencies

To achieve a successful Kerberos handshake, the system initiating the connection must be equipped with specific binary dependencies and Python libraries. Without these, Ansible will trigger a catastrophic failure with the error: kerberos: the python kerberos library is not installed.

Mandatory System Packages

The underlying operating system (typically RHEL or a similar derivative) requires the development headers and libraries for Kerberos and GSSAPI. The following installation sequence is required:

sudo yum update sudo yum -y install gcc python3.12-devel krb5-devel krb5-libs krb5-workstation

These packages provide the necessary C headers (krb5-devel) and the workstation tools (krb5-workstation) which include the kinit and klist commands, essential for manual testing and ticket management.

Python Environment Configuration

Once the system libraries are present, the Python environment must be configured to handle the Kerberos transport. This is achieved through the pywinrm library with the kerberos extension.

python3.12 -m pip install --user ansible python3.12 -m pip install --user ansible-lint python3.12 -m pip install --user pywinrm python3.12 -m pip install --user "pywinrm[kerberos]"

The use of the [kerberos] extra in the pip install command ensures that the pywinrm package installs the required dependencies to interface with the system's Kerberos libraries.

Windows Host Configuration and WinRM Optimization

The target Windows machine must be explicitly configured to accept Kerberos requests and allow the specific domain user to execute commands.

Enabling WinRM and HTTP Listeners

The simplest method to enable WinRM is by executing winrm quickconfig on the host, although Enterprise environments typically utilize Group Policy Objects (GPO) for consistent deployment. It is essential to verify that the HTTP listener is active.

To verify the listener status, execute: winrm enumerate winrm/config/Listener

The expected output should confirm that the Transport is HTTP and the Port is 5985.

Validating Kerberos Service Settings

The WinRM service must be configured to allow Kerberos authentication. This can be checked via the following command: winrm get winrm/config/Service

In the output, the Auth section must explicitly show: Kerberos = true

If this is set to false, the Windows host will reject any ticket-based authentication attempts from the Ansible controller, regardless of how correctly the controller is configured.

User Permissions and Access Control

By default, WinRM only permits connections from users within the local Administrators group. For a domain user such as [email protected] to connect, one of two conditions must be met: - The user must be a member of the local Administrators group on the target host. - The user must be granted specific Read and Execute permissions for WinRM.

Administrative permissions can be adjusted using the winrm configSDDL default command to modify the security descriptor for the service.

Implementing Kerberos in AWX and Kubernetes Environments

AWX runs Ansible inside containers (Execution Environments), which introduces a layer of abstraction. Since containers are ephemeral and isolated, they do not have inherent access to the host's /etc/krb5.conf or the Kerberos ticket cache.

The ConfigMap and Volume Mounting Strategy

To provide the Execution Environment (EE) with the necessary realm and KDC information, the krb5.conf file must be injected into the pod.

  1. Create a Kubernetes ConfigMap containing the krb5.conf file.
  2. Create a Container Group in AWX with a custom pod specification.
  3. Mount the krb5.conf ConfigMap into the pod at the path /etc/krb5.conf.

This ensures that every single task execution has access to the domain configuration, allowing the kinit process to locate the KDC.

Kerberos Credential Management in AWX

Within the AWX UI, a specific Credential must be created for the domain user. The credential should map to the domain account (e.g., [email protected]) and be associated with the Job Template.

Inventory and Variable Configuration

The transition to Kerberos requires specific variables in the Ansible inventory to tell the winrm connection plugin how to behave.

Inventory Specification Table

Variable Value Technical Purpose
ansible_connection winrm Tells Ansible to use the WinRM protocol instead of SSH.
ansible_winrm_transport kerberos Forces the use of Kerberos instead of NTLM or Basic auth.
ansible_winrm_server_cert_validation ignore Prevents failure due to self-signed certificates on WinRM.
ansible_port 5986 or 5985 Defines the port (5986 for HTTPS, 5985 for HTTP).
ansible_winrm_kinit_mode managed Instructs Ansible to handle the kinit process automatically.
ansible_winrm_kinit_cmd kinit Specifies the binary used to acquire the Kerberos ticket.
ansible_winrm_operation_timeout_sec 60 Sets the timeout for WinRM operations to prevent hangs.
ansible_winrm_read_timeout_sec 90 Extends the read timeout for long-running Windows tasks.

Example Inventory File

```ini [storageservers] SRV1.homelab.local

[storageservers:vars] ansibleconnection=winrm ansiblewinrmservercertvalidation=ignore ansibleport=5986 ansiblewinrmtransport=kerberos ansiblewinrmoperationtimeoutsec=60 ansiblewinrmreadtimeoutsec=90 ansiblewinrmkinitmode=managed ansiblewinrmkinitcmd=kinit ```

Manual Validation and Troubleshooting in Execution Environments

Before deploying a full Job Template, it is critical to verify that the EE can actually communicate with the KDC.

Testing with Podman and kinit

To simulate the EE environment, one can run a container and manually attempt to acquire a ticket. Because the default environment might not have a persistent filesystem for the cache, a temporary cache file should be created using the KRB5CCNAME variable.

podman run --rm -v "/etc/krb5.conf.d:/etc/krb5.conf.d:O" -it registry.redhat.io/ansible-automation-platform-23/ee-supported-rhel8:latest /bin/bash

Once inside the container: export KRB5CCNAME=$(mktemp) kinit [email protected]

After providing the password, verify the ticket with: klist

The output will confirm the ticket cache location and the expiration time of the service principal. To further validate the connection to a specific target host, the kvno command can be used to request the key version number from the target.

Advanced Configuration: Using Variable Files

For flexible deployments, it is recommended to use separate variable files for WinRM settings. This prevents hardcoding credentials and transport settings in the main playbook.

The winrm_vars.yml Implementation

yaml ansible_user: domainadmin@REALM ansible_password: !unsafe 234%234{435lkj{{lkjsdf ansible_connection: winrm ansible_winrm_transport: kerberos ansible_winrm_cert_validation: ignore

The use of the !unsafe tag is critical here. In Ansible, certain characters in passwords can be misinterpreted as Jinja2 templates. The !unsafe tag preserves the string exactly as written, ensuring that complex passwords containing characters like #, !, or % are passed correctly to the Kerberos authentication layer.

To test this configuration, use the following command: ansible all -i "dc01" -m win_ping --extra-vars "@winrm_vars.yml"

Summary of the Integration Workflow

The successful deployment of Ansible WinRM Kerberos requires a synchronized effort across three layers: the infrastructure, the execution environment, and the Ansible configuration.

  1. Infrastructure Layer: Windows hosts must have WinRM enabled, Kerberos authentication set to true, and the target user added to the local Administrators group or granted specific WinRM permissions.
  2. Execution Environment Layer: The container must possess krb5-devel, krb5-libs, and pywinrm[kerberos]. The krb5.conf must be mounted via a Kubernetes ConfigMap to provide the realm and KDC details.
  3. Ansible Layer: The inventory must specify ansible_winrm_transport=kerberos and ansible_winrm_kinit_mode=managed to automate the ticket acquisition process.

Conclusion

The integration of Kerberos with Ansible WinRM is a complex but necessary requirement for secure enterprise automation. By shifting from password-based authentication to a ticket-based system, organizations reduce the risk of credential exposure and align with security best practices. The primary challenges lie in the "plumbing"—the mounting of configuration files in Kubernetes and the installation of specific GSSAPI libraries in the Execution Environment. When these are correctly implemented, as demonstrated through the use of custom pod specs in AWX and the precise configuration of pywinrm, Ansible gains the ability to manage Windows fleets with the same level of security and efficiency as Linux fleets. The ability to use !unsafe tags for complex passwords and the validation of tickets via kinit and klist within the EE ensures that the system is not only functional but verifiable.

Sources

  1. Kurokobo AWX on K3s - Kerberos Guide
  2. AutomateSQL - Using Kerberos with Ansible
  3. Red Hat Blog - Kerberos for Windows in Ansible Automation Platform 2
  4. Ansible Forum - WinRM Kerberos Authentication

Related Posts