Contents

Using PowerShell with Ansible AWX: Part 1

Now that we have PowerShell for Mac & Linux, it’s able to shine in many more use cases, including leveraging the power of the open source configuration management & automation platform RedHat Ansible AWX to execute PowerShell 7 commands & scripts within Ansible Playbooks, directly on the Ansible control node.

Before reading on
The process and configuration outlined in this article (and subsequent articles in this series) is based on an extremely niche use case, and should be taken with a grain of salt. I am sharing my experience with this process because I have been extremely satisfied with the results over the last year.

Ansible AWX, Simple IT Automation

Ansible is incredible. Built on Python and expressed in YAML Playbooks, Ansible enables idempotent agentless configuration management over SSH/WinRM. AWX is a automation platform that enables scheduling, RBAC, logging, and workflow orchestration of Ansible Playbooks.

This series of articles will not cover any information regarding how to use Ansible. For that, check out Jeff Geerling’s Ansible 101 series.

Extending Ansible with scripting

Ansible, despite its massive library of modules, still falls short when performing complex logic, multidimensional loops, and data processing, areas that really require rich language syntax rather than its domain-specific language (DSL) expressed in YAML/jinja2. Additionally, especially for Windows systems, the module library often lacks the necessary functionality to perform all required management operations.

AWX is a crazy-powerful tool for what it is, especially for the price (Free Open Source Software!), but it really only shines within its intended wheelhouse of running Ansible Playbooks. However, the beauty of open source software is that you can customize it to suit your needs, and this allowed me to make AWX the perfect infrastructure automation platform for running scripts to manage both Windows and Linux hosts.

Python vs PowerShell

Most people in this position would write custom Python scripts, extending the existing Python base of Ansible. That would serve their purposes excellently, and is the intended way of augmenting Ansible’s functionality. See Developing Ansible Modules. However, my strength lies in PowerShell, not Python (though I am trying to improve!). The vast majority of my infrastructure automation codebase already exists in PowerShell, so why not leverage the language I’m comfortable with? Enter PowerShell 7.

What about a Windows Bridge Host?

Setting up a Windows Host to run PowerShell scripts is something I’ve explored, and do utilize, for operations requiring Windows OS frameworks like interacting with System Center and Active Directory. However, utilizing and relying on an additional server is sub-optimal in my eyes, and I wanted to leverage all of the tools at my disposal to make the AWX control host as useful as possible.

Adding PowerShell 7 to AWX

AWX is released as a Docker image, meaning that it can be customized to fit each user’s needs. For this guide, we will be adding PowerShell 7, as well as authentication libraries to communicate with Windows systems using PSRemoting with NTLM.

The quickest and easiest way of getting up and running is to utilize the Dockerfile below to create a custom AWX image with PowerShell 7. The gssntlmssp package is used to allow PowerShell to remotely-authenticate to Windows hosts using NTLM.

Note on PowerShell package version
Though the awx Docker image is based on CentOS 8, I’ve found that the RHEL7 version of PowerShell is required to successfully utilize PSRemoting to connect to Windows hosts. The CentOS 8 version cannot successfully authenticate.

Deploying AWX on Docker CE

There are multiple ways to install AWX, but I will be utilizing docker-compose to deploy AWX on a CentOS 8 Azure Virtual Machine running Docker CE.

Connect to Virtual Machine

I deployed my CentOS VM from the Azure Portal. For a step-by-step guide, see the Microsoft Documentation.

The SSH private key (.pem file) is available for download when a VM is deployed using the Azure Portal.

1
ssh -i <private key path> <user>@<virtual machine>
Example
1
ssh -i ~/.ssh/awx_powershell.pem azureuser@10.0.0.1

Install Docker

The steps below are based on the official Docker Documentation for installing Docker on CentOS.

  1. Add the Docker CE repo to the Virtual Machine’s package manager configuration.

    1
    
    sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
    
  2. Install the Docker CE engine and CLI.

    1
    
    sudo yum install docker-ce docker-ce-cli containerd.io
    
  3. Start the Docker daemon and add it as a system startup program.

    1
    2
    
    sudo systemctl enable docker
    sudo systemctl start docker
    
  4. Install Docker compose using Python pip

    1
    
    sudo pip3 install docker-compose
    

Build custom AWX Docker image

Prerequisite
You must have Docker Desktop installed, be remotely connected to a server that has Docker installed, or utilize a service that can build Docker images, such as Azure Pipelines or Github Actions. I will be using a CentOS 8 Azure Virtual Machine with Docker CE installed.

Download AWX PowerShell Dockerfile

Download awx_powershell.dockerfile to your Docker image build environment from the Gist above.

1
curl 'https://gist.githubusercontent.com/RylandDeGregory/e27d3250798f9f1e0c077abbc2754a39/raw' -o awx_powershell.dockerfile

Build AWX image using Docker CLI

Build the Docker image using awx_powershell.dockerfile and tag it with the version of AWX the image is based on (15.0.1 is the latest version at the creation time of this article).

1
sudo docker build -f awx_powershell.dockerfile -t <docker hub username>/awx:<awx_version> .
Example
1
sudo docker build -f awx_powershell.dockerfile -t rylandcd/awx:15.0.1 .

Push custom AWX Docker image to Container Registry

Push the image to a Docker Container Registry such as Docker Hub or Azure Container Registry. I will be using Docker Hub.

  1. Login to Docker Hub using the Docker CLI

    1
    
    sudo docker login
    
  2. Push custom AWX image to Docker Hub.

    1
    
    sudo docker push <docker hub username>/awx:15.0.
    

Install AWX

Caution: Not Production ready
The following steps to install AWX are considered least-effort to get a working installation up and running. Please DO NOT utilize the following AWX configuration in a production environment. You must configure much greater control around application secrets and credentials, as well as infrastructure redundancy and database availability, before utilizing AWX in any capacity beyond Proof of Concept (PoC).
  1. Install Ansible using Python pip in order to run the AWX installer, which is an Ansible Playbook.

    1
    
    sudo pip3 install ansible
    
  2. Create a directory to store AWX installation files.

    1
    
    sudo mkdir /opt/awx && cd /opt/awx
    
  3. Download and extract the version of AWX you wish to install.

    1
    2
    
    curl -LJO https://github.com/ansible/awx/archive/15.0.1.zip
    unzip awx-15.0.1.zip && cd awx-15.0.1
    
  4. Edit the AWX installer inventory file for a customized install.

    1. vi inventory (use whatever text editor you are comfortable with).

    2. Update the dockerhub_base variable to the Docker Hub username hosting the custom AWX image.

      1
      
      dockerhub_base=rylandcd
      
    3. Update the pgdocker and awxcompose variables to use the new /opt/awx directory for application files.

      1
      2
      
      postgres_data_dir="/opt/awx/pgdocker"
      docker_compose_dir="/opt/awx/awxcompose"
      
    4. You can change the default AWX admin account username and password values by modifying the admin_user and admin_password variables.

    5. Write the changes to the file and quit vi by pressing esc, then typing :wq!.

  5. Run the AWX installer using the ansible-playbook CLI tool.

    1
    
    sudo /usr/local/bin/ansible-playbook -i inventory install.yml
    

The Ansible Playbook install.yml will deploy AWX using the custom Docker image that includes PowerShell. Once complete, the output should look similar to the following screenshot. AWX installer output

Once the containers are up and running, the AWX application will begin initializing the PostgreSQL database and redis instance in separate containers (using the official DockerHub images for those applications) and configuring itself. You can track its progress by executing the following command to view the logs of the awx_task container.

1
sudo docker logs -f awx_task

Once the database initialization and AWX bootstrap process is complete, you should see log entries within the awx_task container similar to those in the following screenshot, indicating that AWX was installed successfully. awx_task bootstrap logs

From a web browser on your workstation, navigate to the IP address or hostname of the Virtual Machine hosting the AWX containers (if using an Azure VM, ensure it has a Public IP or is deployed to a Subnet that is accessible from your workstation). You will be see the AWX login page and should authenticate using the default admin username and password (if you didn’t previously set custom values in the AWX installer’s inventory file):

1
2
Username: admin
Password: password

AWX successful install

Running PowerShell 7 scripts on AWX

See part 2 of this series to learn how to execute PowerShell within Ansible Playbooks, run full PowerShell scripts from AWX, and see best practices for output and error handling.