Bootstrap Play for PHX Domain

Step-by-step guide to running the bootstrap play for configuring secure WinRM HTTPS in a simulated PHX domain environment, including certificate review, execution, and verification for Ansible automation on Windows hosts.

Projects:  c2platform/phx/ansible ,  c2platform.wincore


Overview

In the PHX domain, Windows hosts are not immediately prepared for Ansible automation. By default, only WinRM over HTTP is configured, which Ansible can use in combination with Kerberos for authentication. While this setup provides some security through Kerberos, it sends credentials unencrypted over the network, posing potential risks in certain scenarios.

To enhance security, the bootstrap play configures WinRM over HTTPS using the custom module c2platform.wincore.winrm_https_config. This enables subsequent Ansible plays to connect securely via HTTPS.

The bootstrap play in the PHX domain includes additional tasks beyond WinRM configuration. However, in the open-source PHX reference implementation (PXD development environment), it currently focuses solely on managing WinRM HTTPS.

In the PXD development environment, Vagrant uses WinRM HTTPS by default, so it doesn’t fully simulate the initial HTTP-only setup in the PHX domain. To test and simulate the WinRM HTTPS configuration process, we will use the node pxd-ubuntu-devtop as domain user tony. This user defaults to SSH for Ansible connections, allowing you to manage (e.g., change or delete) the WinRM HTTPS setup via SSH and then verify the module’s functionality by switching to WinRM.

This guide provides a step-by-step process to run and verify the bootstrap play, ensuring secure Ansible operations in a simulated PHX-like environment.

Prerequisites

Before starting, ensure you have completed the following:

Step 1: Log In as Tony

Connect to the development desktop:

vagrant ssh pxd-ubuntu-devtop

Switch to user tony:

sudo su - tony

Create a forwardable TGT (Ticket-Granting Ticket) for Kerberos authentication. This allows the ticket to be passed to other services or hosts, enabling seamless multi-hop authentication without re-entering credentials:

echo 'Supersecret!' | kinit -f

Verify the ticket with klist to confirm it’s forwardable (look for the “forwardable” flag).

Step 2: Save and Review Current Certificate

Before running the bootstrap play and replacing the WinRM HTTPS configuration, save the TLS/SSL certificate and review it. This allows verification that the module actually replaces the certificate with a new one.

Open another terminal on your host machine and connect as user vagrant to the node pxd-ubuntu-devtop:

phx
vagrant ssh pxd-ubuntu-devtop

Save the certificate to a file:

echo -n | openssl s_client -connect pxd-win1.c2.org:5986 | \
sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > /vagrant/winrm.pem

Review the certificate details, including subject, issuer, validity dates, subject alternative names, and SHA-256 fingerprint:

echo -n | openssl s_client -connect pxd-win1.c2.org:5986 -servername pxd-win1.c2.org 2>/dev/null \
| openssl x509 -noout -subject -issuer -dates -ext subjectAltName -fingerprint -sha256

This command connects to the WinRM HTTPS endpoint, extracts the certificate, and displays key metadata without saving the full certificate. The output will look similar to this (actual values may vary):

subject=CN = WIN-EI2VV283LJN
issuer=CN = WIN-EI2VV283LJN
notBefore=Sep  4 05:52:57 2023 GMT
notAfter=Sep  3 05:52:57 2026 GMT
X509v3 Subject Alternative Name:
    DNS:WIN-EI2VV283LJN, DNS:WIN-EI2VV283LJN
sha256 Fingerprint=FD:26:43:A2:4B:36:FB:5D:8F:E9:F6:94:30:A9:A6:E1:AE:01:F6:F5:3F:F6:8A:DB:D3:A7:03:48:93:BE:5C:59

Note the fingerprint and dates for comparison after running the bootstrap play.

Step 3: Run Bootstrap Play

User tony uses a customized inventory via the environment variable ANSIBLE_INVENTORY, which defaults to SSH connections. For more details, see:

Activate the Python virtual environment (which includes Ansible) and navigate to the inventory project directory:

phx

Set the Ansible Vault password file:

export ANSIBLE_VAULT_PASSWORD_FILE=/usr/local/bin/vault-client.sh

Run the bootstrap play. This should show the WinRM HTTPS task as “changed”, indicating the default WinRM HTTPS configuration from the Vagrant box was modified:

ansible-playbook plays/mgmt/bootstrap.yml
Show output
(pxd) tony@pxd-ubuntu-devtop:~/git/gitlab/c2/ansible-phx$ ansible-playbook plays/mgmt/bootstrap.yml
ini_path: /home/tony@c2.org/git/gitlab/c2/ansible-phx/hosts.ini

PLAY [Windows] ***************************************************************************************************************

TASK [Gathering Facts] *******************************************************************************************************
ok: [pxd-win1]

TASK [WinRM HTTPS] ***********************************************************************************************************
changed: [pxd-win1]

PLAY RECAP *******************************************************************************************************************
pxd-win1                   : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Step 4: Verify WinRM HTTPS Configuration

To test WinRM HTTPS, switch to a Kerberos-enabled WinRM inventory:

export ANSIBLE_INVENTORY="Vagrantfile.yml,hosts.ini,hosts-kerberos-override.ini,hosts-kerberos-winrm-override.ini"

Re-run the bootstrap play. The WinRM HTTPS task should now show as “ok” (not changed), confirming the configuration is already in place:

ansible-playbook plays/mgmt/bootstrap.yml

To confirm WinRM is being used, run with verbose output and check for WinRM connections:

ansible-playbook plays/mgmt/bootstrap.yml -vvv | grep WINRM
Show output
(pxd) tony@pxd-ubuntu-devtop:~/git/gitlab/c2/ansible-phx$ ansible-playbook plays/mgmt/bootstrap.yml
ini_path: /home/tony@c2.org/git/gitlab/c2/ansible-phx/hosts.ini

PLAY [Windows] ***************************************************************************************************************

TASK [Gathering Facts] *******************************************************************************************************
ok: [pxd-win1]

TASK [WinRM HTTPS] ***********************************************************************************************************
ok: [pxd-win1]

PLAY RECAP *******************************************************************************************************************
pxd-win1                   : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
(pxd) tony@pxd-ubuntu-devtop:~/git/gitlab/c2/ansible-phx$ ansible-playbook plays/mgmt/bootstrap.yml -vvv | grep WINRM
<pxd-win1.c2.org> ESTABLISH WINRM CONNECTION FOR USER:  on PORT 5986 TO pxd-win1.c2.org
<pxd-win1.c2.org> ESTABLISH WINRM CONNECTION FOR USER:  on PORT 5986 TO pxd-win1.c2.org

This verification ensures the WinRM HTTPS setup is functional and secure for Ansible operations.

Review

Bootstrap Playbook

 plays/mgmt/bootstrap.yml

---
- name: Windows
  hosts: pxd-win1

  tasks:
    - name: WinRM HTTPS
      c2platform.wincore.winrm_https_config:
        computer_name: "{{ inventory_hostname }}"
        dns_name: "{{ inventory_hostname }}.c2.org"
        state: present

 plugins/modules/winrm_https_config.ps1

Review New/Changed Certificate

After running the bootstrap play, review the new certificate to confirm it has been updated. As user vagrant on pxd-ubuntu-devtop, save the new certificate:

echo -n | openssl s_client -connect pxd-win1.c2.org:5986 | \
sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > /vagrant/winrm-new.pem

Compare it with the original saved certificate if needed (e.g., using diff /vagrant/winrm.pem /vagrant/winrm-new.pem).

Review the new certificate details:

echo -n | openssl s_client -connect pxd-win1.c2.org:5986 -servername pxd-win1.c2.org 2>/dev/null \
| openssl x509 -noout -subject -issuer -dates -ext subjectAltName -fingerprint -sha256

Compare the output with the original from Step 2. Look for changes in the fingerprint, dates, or other details indicating a new certificate has been generated and applied.

Review WinRM listeners

Additionally, on the Windows host (pxd-win1), use PowerShell to enumerate the WinRM listeners and verify the HTTPS listener is active with the new certificate thumbprint:

winrm enumerate winrm/config/listener

Example output (actual thumbprint and details will vary):

Listener
    Address = *
    Transport = HTTP
    Port = 5985
    Hostname
    Enabled = true
    URLPrefix = wsman
    CertificateThumbprint
    ListeningOn = 10.0.2.15, 127.0.0.1, 192.168.61.12, ::1, fe80::6d9c:c6e5:e15e:a485%4, fe80::e861:af06:658a:d7a7%7

Listener
    Address = *
    Transport = HTTPS
    Port = 5986
    Hostname
    Enabled = true
    URLPrefix = wsman
    CertificateThumbprint = 6DCA065A5A29EFAD9BF136828270558324340BC1
    ListeningOn = 10.0.2.15, 127.0.0.1, 192.168.61.12, ::1, fe80::6d9c:c6e5:e15e:a485%4, fe80::e861:af06:658a:d7a7%7

This confirms the HTTPS listener is configured with the new certificate.

Additional Notes

  • The bootstrap play is crucial for transitioning from insecure HTTP to secure HTTPS WinRM in production-like environments.
  • In real PHX domains, additional tasks may include certificate management, firewall adjustments, or integration with enterprise CAs.
  • For troubleshooting, check WinRM listener status on the Windows host using winrm enumerate winrm/config/listener via PowerShell.
  • Always handle Kerberos tickets securely to avoid unauthorized access.

Last modified May 13, 2026: phx bootstrap play PHX-616 (d8c75a2)