Managing Windows Hosts with Ansible

So maybe you’ve heard of Ansible, but you have a bunch of windows servers and don’t know how to get started, or maybe you’ve even got an Ansible server set up and are already managing linux servers but don’t know how to get your Windows servers attached too. This guide is for you! I’ll show you how to set up a minimal Ansible install on an Ubuntu server and set up a Windows host to be managed.

One thing of note is that this didn’t work until I applied all the updates to my windows server. The SSH connection worked, but Ansible would just hang forever when connecting to that host.

WinRM vs SSH

In the past the only way to manage a Windows machine with Ansible was to use WinRM. Frankly the documentation for that scares me. The good news is that it’s now possible to run OpenSSH on windows, and experimental support for managing windows hosts over SSH was added in Ansible 2.8. Now we can manage Windows hosts in a way that is familiar to linux admins and is relatively easy to set up.

Part 1 – Ubuntu Setup

Install Ansible on Ubuntu

Installing Ansible on Ubuntu is easy. Just run this on your Ubuntu machine.

sudo apt install -y ansible

That’s it! Ansible is ready to use on the CLI. You can verify with the following command. On my Ubuntu 20.04 server I got Ansible 2.9.6.

ansible --version

Generate SSH Key

I like to use SSH keys so ansible can connect to my remote hosts without needing a password. If you don’t already have an SSH key pair set up, you can create one with the following command.

ssh-keygen

I just accept all the defaults, including no password, but you can customize as desired. Copy your public key and get it over to your windows machine somehow. I just copy it out of my SSH session to my ubuntu box and paste it into notepad on the windows box.

cat ~/.ssh/id_rsa.pub

Part 2 – Windows Setup

Installing Chocolatey

This isn’t strictly required, but for my purposes Chocolatey seems like it might be useful to install and update software, and it can install OpenSSH for us. You can install Chocolatey by pasting the following code snippet into an elevated Powershell prompt. This comes directly from their website here: https://chocolatey.org/install#individual

Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))

Installing OpenSSH

Once Chocolatey is installed, we can install OpenSSH using the following command.

choco install -y --package-parameters=/SSHServerFeature openssh

If you prefer not to use Chocolatey, you can follow these instructions from Microsoft to install OpenSSH manually.

Configure OpenSSH

I want to use SSH key auth so Ansible can connect without needing a password. On a linux machine I’d simply add the Ansible user’s public key to the authorized_keys file on my target machine.

We can do the same on Windows, but first we need to change the OpenSSH config to look in the correct place. By default, the authorized_keys files for administrator accounts are not in the expected location. You can read more about this here.

To restore the expected behaviour, edit C:\ProgramData\ssh\sshd_config and remove or comment out the following two lines at the bottom of the file. You can edit this file using notepad (run as administrator).

Match Group administrators
        AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys

Restart the sshd service.

net stop sshd
net start sshd

Enable SSH with the public key

You’ll need that public key you copied earlier from your ubuntu box.

First, we need to create a folder for the local user ssh config. In a command prompt in your home directory (such as C:\Users\Administrator) run the following command.

mkdir .ssh

Next create your authorized_keys file if it doesn’t exist

type nul >>.ssh\authorized_keys

And open it for editing

notepad .ssh\authorized_keys

Paste your ubuntu public key into this new file and save it.

Finally, we need to modify the permissions of this file to remove Everyone from the file or else sshd will ignore it.

icacls authorized_keys /remove Everyone

Test the SSH connection

From your ubuntu box you should be able to connect to your windows box using SSH!

ssh Administrator@IP_OF_WINDOWS_SVR

If your account is a domain user, enter the username in this format

ssh Administrator@domain.example.com@IP_OF_WINDOWS_SVR

Part 3 – Ansible

Ansible config in a nutshell? We need at minimum an inventory file, and possibly a playbook. The inventory file tells Ansible where the hosts it’s going to manage are located and how to connect to them. The playbook lets you define a list of tasks to run on the hosts in the inventory.

Inventory

On your ubuntu box, create a file called inventory.yml and configure it like so

---
all:
  hosts:
    my_windows_server:
      ansible_shell_type: cmd
      ansible_host: IP_OF_WINDOWS_SVR
      ansible_user: Administrator

If your account is in a domain, be sure to add @domain.example.com to your username.

Test your connection by running the following command

ansible -i inventory.yml -m win_ping my_windows_server

You should get something like the following output

my_windows_server | SUCCESS => {
    "changed": false,
    "ping": "pong"
}

Playbook

Rather than manually running a module with the ansible command, we can string together as many tasks as we like in a playbook. Here’s an example playbook that sets the timezone and opens the RDP port. I’ll call it playbook.yml

---
- hosts: all
  tasks:

  - name: Set timezone to 'Central Standard Time' (GMT-06:00)
    win_timezone:
      timezone: Central Standard Time

  - name: Firewall rule to allow RDP on TCP port 3389
    win_firewall_rule:
      name: Remote Desktop
      localport: 3389
      action: allow
      direction: in
      protocol: tcp
      profiles: [domain, private]
      state: present
      enabled: yes

You can execute the playbook with the following command

ansible-playbook -i inventory.yml playbook.yml

If everything goes to plan you should see output like this

PLAY [all] *************************************************************************************************************

TASK [Gathering Facts] *************************************************************************************************
ok: [my_windows_server]

TASK [Set timezone to 'Central Standard Time' (GMT-06:00)] *************************************************************
changed: [my_windows_server]

TASK [Firewall rule to allow RDP on TCP port 3389] *********************************************************************
changed: [my_windows_server]

PLAY RECAP *************************************************************************************************************
my_windows_server          : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Conclusion

If you made it this far then you should have a minimum viable ansible install capable of managing windows hosts. There is so much more to explore with Ansible, and this guide doesn’t even scratch the surface, but hopefully it helps you get started on your journey.

For further reading on the available windows modules check out the offical documentation here.

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: