In previous posts we’ve looked at how to look up Secrets from Hashicorp Vault using Ansible and Ansible Tower. We’ve also taken a look at how to integrate Azure Key Vault with Ansible Tower, however I’ve never gotten round to taking a look at how to integrate Ansible itself with Azure Key Vault (without the use of Tower).
Whilst I’ve largley moved away from using Azure Key Vault in favour of Hashicorp Vault I did find myself using it for some tinkering recently so in this post we’ll be looking at how to do the integration, luckily it’s a pretty painless process.
Some Assumptions
For this article, I’m going to be working with an existing Azure Key Vault instance and have already configured an appropriate Service Principal to allow programatic access. What we’re working with will be:
- A single Azure Key Vault instance located at https://tinfoil-keyvault.vault.azure.net.
- This Vault has a single contains a single secret for the purposes of an example, the Secret contains an API token which we’ll use to access another platform (in this case Netbox)
- We’re going to use a Playbook which looks up this token, and then uses this token to create an infrastructure record within Netbox
The azure_keyvault_secret Plugin and Configuration
Unlike the hashi_vault lookup Plugin there is no native lookup Plugin shipped with Ansible to interact with Azure Key Vault, Microsoft do however provide one which can be either installed via the Ansible Galaxy community repo along with the rest of the Azure Preview Modules or pulled directly from GitHub:
#--Download Lookup Plugin from GitHub wget https://github.com/Azure/azure_preview_modules/blob/master/lookup_plugins/azure_keyvault_secret.py #--Install all Azure Preview Modules from Ansible Galaxy ansible-galaxy install azure.azure_preview_modules
If you have not configured a custom location for your Lookup Plugins in your ansible.cfg this file can just be placed alongside your playbook in a directory named lookup_plugins, so your file structure should look like:
├── _playbook.yaml ├── /lookup_plugins │ ├── azure_keyvault_secret.py
The Plugin also requires that a couple of additional python libraries be installed before use which can be obtained as part of the azure-keyvault and azure-common packages:
pip install azure-keyvault azure-common
Before getting started, lets be sure to configure some Environment Variables for AZURE_CLIENT_ID, AZURE_SECRET and AZURE_TENANT. If these aren’t set then we will need to define them inside the playbook which isn’t a secure configuration:
export AZURE_CLIENT_ID=<Service principal Client ID> export AZURE_SECRET=<Service principal Secret> export AZURE_TENANT=<Azure Tenancy ID>
Using The azure_keyvault_secret Plugin
The below examples show the use of the plugin to retrieve a secret and write it out to the console:
--- - name: Lookup secret from Azure Key Vault hosts: localhost gather_facts: false connection: local tasks: - name: Look up secret from Azure Key Vault and output to Console vars: url: 'https://tinfoil-keyvault.vault.azure.net/' secretname: 'netbox-token' debug: msg: "{{ lookup('azure_keyvault_secret', secretname, vault_url=url) }}" ...
In the above example, Line 12 is configured to use the lookup to search the Key Vault, select a named secret and then print the Secret to the console.
This is of course fine for theory, but returning secret information to the console is just about the worst thing you can do in real world scenarios, so let’s try and do something a little more practical.
Using The azure_keyvault_secret Plugin – A Practical Example
Now that we’ve seen how to interact with Secrets from our Key Vault, lets see how we can use our Secret to perform tasks against another platform, in this case we’re going to connect to a Netbox deployment by looking up an API token from our Key Vault and using it to connect to the Netbox API. I’m using one of the great community modules for Netbox from @FragmentedPacket and @amb1s1 to create a new Netbox Device:
--- - name: "Secure Netbox Demo" connection: local hosts: localhost gather_facts: False vars: url: 'https://tinfoil-keyvault.vault.azure.net/' secretname: 'netbox-token' api_token: "{{ lookup('azure_keyvault_secret', secretname, vault_url=url) }}" tasks: - name: Create Netbox Device netbox_device: netbox_url: https://netbox.madcaplaughs.co.uk netbox_token: "{{ api_token }}" data: name: Test Switch device_type: TLSG105S device_role: Managed Switch site: madcaplaughs state: present ...
The variable being defined on Line 9 will now perform the lookup against our Key Vault and contain our API token, it can then be used in the netbox_token argument on Line 14. As both of these are secure inputs our Secret will not be displayed in any return data.