Configure Ansible to use a Managed Identity with Azure Dynamic Inventory
Published Jan 13 2020 12:01 AM 7,647 Views
Microsoft

Hello again, Chris Wallen here and in this post, I’m going to show you how to use a managed identity to manage resources using Azure dynamic inventory with Ansible. If you’re not familiar with managed identities, see this overview of managed identities for Azure resources. Basically, they just provide a method of authenticating to Azure without the need to store credentials in code or on any local resource. Now, before we get into the technical details, let’s go over the different sources of Azure credentials that Ansible can use to authenticate when using dynamic inventory:

When using dynamic inventory, you can use any of the following methods to provide your Azure credentials to Ansible

 

  • Storing them in a plain-text credential file
  • Setting Environment variables that store the credentials
  • Using the currently logged in Azure CLI credentials
  • Using a managed identity

 

Obviously, the first option is the least secure as your credentials are stored in a flat-file that could be read by anyone with access. The second option is more secure; however, it requires you to either create more automation to set the environment variables for the ansible user, permanently set them in the user profile, which requires you again to store them in plain text, or set the variables manually. The third option is also secure, but does not lend itself to automation as you have to manually sign in to the CLI each time you want to use dynamic inventory. This just leaves us with option 4. This is the most secure as you’re not required to store credentials anywhere in code or on the local machine nor do you have to take any manual steps to authenticate. The only requirement is that your Ansible control server must be running in Azure. Once the managed identity is assigned, you can easily control the level of access to resources by using role-based access. Ok, now that we have that out of the way, let’s talk about the prerequisites.

 

Prerequisites

  1. The commands in this guide assume the use of Azure CLI in Azure Cloud Shell. You can also use a local CLI; however, if you’re not running on Linux, you’ll need to convert the commands for Powershell or command prompt.
  2. An Ansible control server (v2.8 at minimum) deployed in Azure. For installation steps, see Ansible’s Microsoft Azure Guide
  3. At least one VM in Azure (Linux or Windows). You’ll also need to have it configured for communication with Ansible (ssh or winrm depending on OS)

Now, on to the dynamic inventory configuration. First, we’ll need a managed identity to assign to our Ansible control server.

 

Create a managed identity

You can use either a system-assigned or user-assigned identity. To decide which type is best for you, see the differences between a system-assigned and user-assigned managed identity. Regardless of which type you choose; we’ll need to first create the identity using Azure CLI in Azure Cloud Shell.

 

NOTE: If you already have an identity created, skip to the section titled Assign RBAC rights to the managed identity

 

User-Assigned Identity

To create a new user-assigned identity, run the below command, replacing RG-NAME with the name of the resource group for the identity, and IDENTITY-NAME with the name of the identity.

 

az identity create -g RG-NAME -n IDENTITY-NAME

 

System-Assigned Identity

For a system-assigned identity, run the following command, where RG-NAME is the name of the resource group and VMNAME is the name of the Ansible control server

 

az vm identity assign -g RG -n VMNAME

 

Assign RBAC rights to the managed identity

Now that we have the identity created, we need to assign it rights to Azure resources. I chose to give mine Reader rights on the resource group that I’ll be using for dynamic inventory. If you want to use multiple resource groups for your inventory, you’ll need to follow this procedure for each one.

 

User-Assigned Identity

To assign Reader for a resource group to a user-assigned identity, run the below commands in the Cloud Shell. To run the commands, you’ll need to replace IDENTITY-NAME with the name of the managed identity you created in the previous step and replace the scope with the resource id of the resource group to assign the rights to (found under properties blade of the resource group)

 

spID=$(az identity show -n IDENTITY-NAME -g RG --query '[principalId]' -o tsv)

az role assignment create --assignee $spID --role ‘Reader’ --scope /subscriptions/SUBID/resourceGroups/RG-NAME

 

Example:

az role assignment create --assignee $spID --role ‘Reader’ --scope /subscriptions/ fddda745-b9e7-43e4-9a2a-45fa890210ed /resourceGroups/myDemoRG

 

System-Assigned Identity

To assign Reader rights for a resource group to a system-assigned identity, run the following commands in the Cloud Shell. To run the commands, replace ANSIBLE-VM with the name of the Ansible VM as it appears in the portal and replace the scope with the resource id of the resource group to assign the rights to (found under properties blade of the resource group

 

spID=$(az resource list -n VM-NAME --query [*].identity.principalId --out tsv)

az role assignment create --assignee $spID --role ‘Reader’ --scope /subscriptions/SUBID/resourceGroups/RG-NAME

 

Example:

az role assignment create --assignee $spID --role ‘Reader’ --scope /subscriptions/ fddda745-b9e7-43e4-9a2a-45fa890210ed /resourceGroups/myDemoRG

 

Configure dynamic inventory

With Ansible 2.8 and later, dynamic inventory is handled through the azure_rm plugin. To configure the VMs for dynamic inventory, I used this tutorial. I’ll summarize the steps below:

 

Configure Azure Resources

Add a tag to the virtual machines you want to inventory. To create the tag, run the below command. Make sure to replace RG-NAME and VM-NAME with values appropriate for your environment.

 

az vm update \

    --resource-group RG-NAME \

    --name VM-NAME \

    --set tags.mytag=demo

 

Create the dynamic inventory file

Use the steps below to setup the Ansible directory and create the inventory file

  1. Open an SSH session to your Ansible control server
  2. Run the following command to create a directory structure for Ansible under your users home directory

 

mkdir -p ~/ansible/inventory

 

cd ~/ansible/inventory

 

  1. Use the editor of your choice to create the inventory file. The one requirement is that the file name must end in aure_rm and can have either .yml or .yaml extension. For example, I named my file: demo_azure_rm.yaml. Once created, add the following contents to the file, being sure to replace RG-NAME with the name of the resource group that contains the VMs you want to manage.

 

plugin: azure_rm

include_vm_resource_groups:

- RG-NAME

auth_source: msi

 

keyed_groups:

- prefix: mytestgroup

  key: tags.mytag | default('none')

 

exclude_host_filters:

- powerstate != 'running'

 

Before moving on to the next section, let’s take a second and go over the inventory file to make sure all of the parameters are clear.

 

  1. The auth_source parameter specifies the type of authentication to use. With the MSI value, Ansible will use the assigned managed identity for authentication. For other available auth types, see Ansible’s azure_rm guide
  2. The keyed_groups section will create a group based on the specified parameter. This is where the tag we created earlier comes into play. The prefix parameter defines the group name that we'll use for the hosts that match the condition specified for the key parameter. The group name will be a combination of the string you specify + _key. The key parameter is looking for all VMs in the resource group that have the mytag tag. All of these VMs will be grouped by the value of the mytag tag. For this example, a host group named mytestgroup_demo will be created as that was the value of the tag I created.
  3. The exclude_host_filters section will exclude any hosts that match the condition. In this case, any hosts not in a running state will be excluded. This section can be removed if you’re not concerned with the VMs status.

 

Test the configuration

Now that we have everything setup, it’s time to test our configuration. In order to do so, let’s run an ad-hoc command against the inventory file:

 

ansible mytestgroup_demo -m ping -i ~/ansible/inventory/demo_azure_rm.yaml

 

You should see output similar to the following:

 

clipboard_image_0.png

 

NOTE: The ping module will only work against Linux VMs. If testing against Windows, use the win_ping module.

 

And that’s it. You now have Azure dynamic inventory setup in Ansible. In my next post, I’ll take this a step further and show how you can use dynamic inventory to apply DSC configuration to Windows VMs in Azure.

 

1 Comment
Version history
Last update:
‎Jan 16 2020 08:19 AM
Updated by: