Ansible for the Windows admin

Boost your efficiency by automating mundane tasks with Ansible for Windows, and learn a little about Linux and Ansible along the way.
248 readers like this.
Team checklist

We are searching for a champion, a Windows administrator willing to venture out into the world of Ansible automation. No, you will not need to know Bash scripting or how to navigate your way around a Linux terminal. All you need is the desire all admins share: to complete mundane tasks as quickly as possible.

While there have been strides in the integration of Windows and Ansible, please be aware that at this present time and as of the latest version of Ansible version, Linux is still required for Ansible to run and manage your remote Windows nodes. However, you should not fret, as currently, Windows has a Linux subsystem called WSL or Windows Subsystem for Linux. There are instructions to help you install WSL

If you are a Windows admin with zero experience with Linux and Ansible, it is neither hard nor time-consuming to get started and run your first Ansible playbook. You can make a positive impact on your organization's infrastructure, increase its return on investment (ROI), and get more time to innovate by automating mundane tasks, such as deploying services or making user account changes, with Ansible playbooks.

Ansible can bring automation to a mixed operating system environment and provides an efficient way to get to an infrastructure-as-code (IaC) state without burdening your administrators. Ansible is not a replacement for System Center Configuration Manager (SCCM) or Chocolatey; it's a supplemental tool that allows you to automate the services your software provides.

Get started

Ansible/Windows architecture

Remoting into Windows servers or clients from the Ansible control machine requires Windows Remote Manager (WinRM) to be properly configured. Fortunately, the Ansible team wrote a PowerShell script, ConfigureRemotingForAnsible, that makes it easy to get started with Ansible for Windows in your development or testing environment. The script configures WinRM on any supported Windows server or client target.

Run the following on Windows PowerShell:

$url = "https://raw.githubusercontent.com/ansible/ansible/devel/examples/scripts/ConfigureRemotingForAnsible.ps1"
$file = "$env:temp\ConfigureRemotingForAnsible.ps1"
(New-Object -TypeName System.Net.WebClient).DownloadFile($url, $file)
powershell.exe -ExecutionPolicy ByPass -File $file
winrm enumerate winrm/config/Listener

Ansible can use multiple authentication transport schemes, including NTLM, Kerberos, and basic authentication. For this tutorial, we will use the Kerberos authentication method (assuming the Windows server is registered to a domain).

The ConfigureRemotingForAnsible script has basic auth enabled by default; to disable basic auth and enable Kerberos, run the following at the command prompt:

winrm set winrm/config/service/auth @{Basic="false"; Kerberos="true"}

Set up your control machine

Our control machine is running CentOS Linux release 7.5.1804(core); you could also use RHEL 7 or Fedora 19 or later releases. To install and configure the control machine to manage Windows target hosts:

  1. On the control machine, install the ansible and python2-winrm packages with the following command:
    yum install -y ansible python2-winrm
  1. On the control machine, install Python Kerberos:
    yum install -y python-requests-kerberos
  1. Open the /etc/krb5.conf file and edit the following setting (using your own domain info):
    [realms]
       EXAMPLE.COM = {
       kdc = ad.example.com
      }
    
    [domain_realm]
      .example.com = EXAMPLE.COM

Set up your inventory

Ansible's inventory consists of all the end nodes or target hosts that can be managed by the Ansible host, which is also known as the Ansible controller. You can configure inventory to be static or dynamic; in this tutorial, we will be configuring static inventory.

While you can configure static inventory in /etc/ansible/hosts, it's a best practice to create a different inventory file that can be edited as needed; e.g., if you need to change the static inventory to a dynamic inventory to accommodate infrastructure changes. The inventory will be configured by groupings. Groups start with square brackets ([ ]), and a collection of servers represents that group (e.g., [group]).

Ansible inventories can take many forms: static file formats, such as .ini, .yaml, and .toml, as well as dynamically generated inventories from scripts or plugins. The .ini format is appropriate for small, simple inventories, which can be as simple as a list of host names to run against.

Ansible allows you to set variables for each group in your Ansible hosts' file by inserting the name of the <server group name>:vars* inside square brackets. The code below sets variables for WinRM on an Ansible control machine.

[linux-server]
linux-web.example.com
[linux-server:vars]
ansible_user=root
ansible_connection=ssh
[win-server]
windows-web
[windows:vars]
ansible_user=Administrator@example.com
ansible_connection=winrm
ansible_port=5986
ansible_winrm_transport=kerberos
ansible_winrm_server_cert_validation=ignore

Ansible can check the ping status of all servers that are part of the groups linux-server or win-server by running an ad-hoc command, such as:

ansible linux-server -i (some local path)/(inventory file) -m ping

or

ansible win-server -m win_ping --ask-pass

Configure IIS & the Apache web application

Create Ansible playbooks

It can be tedious and time-consuming to use Ansible ad-hoc commands when you need to do a task more complex than just pinging a target host or getting the host's uptime information. Ansible playbooks are YAML-formatted files that contain a set of configurations and tasks that achieve an end state on an Ansible Windows or Linux target host. The ad-hoc command above could become:

- hosts: win-server
 gather_facts: no
 tasks:
 - name: Checking connection to {{ inventory_hostname }}
   win_ping:

To run an Ansible playbook, use the ansible-playbook command. The result displays all successful and failed tasks.

Ansible playbook ping

To change the Ansible target hostname, first show the current Ansible target hostname:

ansible win-server -m setup --ask-pass | grep ansible_hostname

Ansible hostname result

Add two tasks to the playbook to change the hostname to the one set in the inventory file and reboot the Ansible target host:

- hosts: win-server
 gather_facts: yes
 tasks:
 - name: Change current hostname to {{ inventory_hostname }}
   win_hostname:
     name: "{{ inventory_hostname }}"
   register: winhostname

 - name: Reboot {{ inventory_hostname }}
   win_reboot:
   when: winhostname.reboot_required

Windows: Configure an IIS website

To create an Internet Information Services (IIS) website:

  • The IIS Windows feature must be installed and running
  • IIS web page documents must be available to the IIS service
  • Windows Firewall must be configured to allow incoming traffic from port 80

The Ansible playbook below produces a running and configured IIS web server on the Ansible target host using the Ansible Windows modules. It handles the following configurations and tasks:

  1. hosts: Names the group of Ansible target hosts the playbook will be running against
  2. gather_facts: Queries a list of the target systems' settings, such as hostname, IP address, MAC address, fully qualified domain name (FQDN), etc.
  3. tasks: Executes a list of Ansible tasks in order:
    1. Checks the connection between the Ansible control machine and the target host to ensure network connectivity
    2. Changes the current hostname of the target host to the Ansible inventory hostname
    3. Installs the IIS feature on the Ansible target host
    4. Copies the web index file from the Ansible control machine to the IIS web home directory on the Ansible target host
    5. Opens port 80 for incoming traffic on the target host firewall
    6. Tests whether the IIS server on the target host is running and is properly configured
- hosts: win-server
  gather_facts: yes
  tasks:
  - name: Install IIS feature on {{ inventory_hostname }}
	win_feature:
  	name: Web-Server
  	state: present
  	restart: no
  	include_sub_features: yes
  	include_management_tools: no

  - name: Move local web index file to {{ inventory_hostname }}
	win_copy:
  	src: files/index.html
  	dest: 'C:\\inetpub\\wwwroot\\index.html'

  - name: Open firewall port 80 for the IIS web server on {{ inventory_hostname }}
	win_firewall_rule:
  	name: "{{ inventory_hostname }}_80"
  	enable: yes
  	state: present
  	localport: 80
  	action: Allow
  	direction: In
  	protocol: Tcp

  - name: Testing IIS is properly configured and running on {{ inventory_hostname }}
	win_uri:
  	url: "http://{{ ansible_fqdn }}"
  	return_content: yes
	register: result
	failed_when: "'Yay! Simple Ansible deployed IIS server ...' not in result.content"

Linux: Configure an Apache web page

If you're asked to be a hybrid admin, you may assume that you'll only be responsible for handling Windows environments. But, with the admin role shifting to DevOps, you might be asked to touch a Linux server or two to support hosts running Apache. Here are some instructions to help you along.

To create an Apache web page:

  1. Apache must be installed
  2. Apache must be enabled and started; this can be done in RHEL using systemd:
    1. systemctl enable httpd
    2. systemctl start httpd
  3. Make firewalld changes to make sure the HTTP/HTTPS ports are added to the firewall rules along with the ports:
    1. command: firewalld-cmd --permanent -add-service={http,https}
    2. command: firewall-cmd --permanent -add-port={80,443}
    3. Run the Ansible playbook below to install and enable Apache without needing to execute single commands. It provides the configurations necessary to deploy an Apache web page in parallel, which means the tasks will run in sequence based on the way they are written. The tasks in order are:
      1. Install the httpd service using the yum module
      2. Create web content using the copy module
      3. Ensure the firewall is enabled and running
      4. Ensure the firewall permits the use of the httpd service
      5. Make sure the httpd service is enabled and running
      6. Test the connectivity webpage config

This Ansible playbook will deploy an Apache web server:

- hosts:  webserver
  become:  true
    gather_facts:  no
  tasks:
-	name: install latest version of Apache
yum:
  name: "(( item }}"
  state: latest
      with_items:
-	httpd
-	httpd-tools
  
  -  name: create web content file
     copy:
       content: "Yay!  Simply deployed Apache webserver …"
       dest: /var/www/html/index.html
  
  - name: firewall enabled and running
    service: 
      enabled: true
      name: firewalld
      state: started
  
  - name: firewalld persists httpd service
    firewalld:
      immediate: yes
      permanent: true
      service: http
      state: enabled

  - name: httpd enabled and running 
    service: 
      name: httpd
      state: started
      enabled: true 

Join the party

There are already about 90 modules available and more are in development. The Windows modules help with Chocolatey, and the majority of the Windows infrastructure can now be managed with Ansible. This allows Windows admins to use the same techniques and practices executed by Linux admins in the long-established Linux culture.

The Windows space is continuing to evolve, and by joining the Ansible community, you can join the biggest automation party around!

User profile image.
Taz Brown, is a Sr. Technical Scrum Master & Agile Expert at Cisco Systems as well as a Product Manager  working with DevOps and Software Development teams.  She is an avid writer and speaker with a diverse background in Scrum, Agile, digital product management, Linux systems engineering, management and deployment of DevOps solutions.  
User profile image.
Abnerson Malivert (RHCA) is an Open Source solution integrator for both private and public sector organizations. His primary focus is on automation, configuration management, Identity Management and patch management. When he’s not working on his home lab, Abnerson loves playing his Stratocaster guitar and spending time with his family.

1 Comment

thanks for sharing.

Creative Commons LicenseThis work is licensed under a Creative Commons Attribution-Share Alike 4.0 International License.