Puppet Azure Key Vault Integration

Puppet Azure Key Vault Integration

Martez Reed

--

Automation is a necessity in today’s IT landscape but with great power comes great responsibility. Properly handling sensitive data such as machine credentials, API keys and passwords isn’t always easy when developing an automated solution. One common challenge is getting a secret from secure storage to an application’s configuration file for use by the application.

Azure helps simplify this process for Azure virtual machines with the use of Azure Key Vault and Azure Managed Identity. Azure Key Vault is a cloud service used to manage keys, secrets, and certificates. Azure Managed Identities enable a virtual machine in this case to be granted permission to the Azure Key Vault using an assigned identity.

This blog post takes a look at how Puppet can integrate with native Azure services to simplify writing a secret stored in Azure Key Vault to an application configuration file on an Azure virtual machine.

Azure Key Vault Puppet Module

The azure_key_vault forge module includes support for server side secrets retrieval using hiera and agent side retrieval using deferred functions. The module utilizes the Azure metadata service to retrieve the access credentials for interacting with Azure Key Vault to access secrets stored in Azure Key Vault.

Server side retrieval (hiera)

The module includes support for a custom hiera backend. This enables puppet code to retrieve sensitive data from Azure Key Vault during a hiera lookup. The Puppet master fetches the sensitive data from the Azure Key Vault and sends the unencrypted data to agent over the secure agent communication channel. The focus of this post is on the agent side retrieval and additional information about the server side retrieval can be found in the module’s documentation.

Agent side retrieval (deferred function)

Puppet 6 includes what are known as deferred functions, these enable functions to run on the agent node as part of a Puppet run. Utilizing deferred functions has a number of advantages over server side retrieval with hiera. One of the biggest advantages is that the sensitive data doesn’t need to be decrypted on the master and then delivered to the agent node.

Azure Key Vault Integration

Now that we understand how we deferred functions work and what the azure_key_vault module supports, we’ll look at an example of the integration.

The example is an application configuration file dynamically populated using Puppet with the password being fetched from Azure Key Vault by the agent node.

Azure Authentication

The agent node virtual machine is expected to be running on Azure and use a managed system identity or a user assigned identity with the appropriate permissions to access the Azure key vault.

Demo App Module

In our demo application Puppet module we need to create an init.pp manifest and a config.yaml.epp template file in module’s files directory.

The following example highlights the Azure Key Vault integration to populate the password in a configuration file. The example uses Puppet’s EPP templating to dynamically create and populate the file content.

---
host: <%= $host %>
password: <%= $admin_password_secret.unwrap %>

The template file is placed in the module’s files directory instead of the templates directory since the template file must be present on the agent node for the deferred rendering. https://puppet.com/docs/puppet/6.17/template_with_deferred_values.html

The following manifest shows how the password is being set by a value retrieved from Azure Key Vault.

class demoapp (
String $key_vault_name = 'grtdevvault',
String $key_vault_secret_name = 'app-password',
String $host = 'grtapp01.grt.local',
) {
$password = Deferred('azure_key_vault::secret',
["$key_vault_name","$key_vault_secret_name",{"metadata_api_version"=>"2018-04-02","vault_api_version"=>"2016-10-01"}])
$hash_variables = {
'admin_password_secret' => $password,
'host' => $host,
}
file { '/opt/demoapp':
ensure => directory,
}
file { '/opt/demoapp/config.yaml':
ensure => file,
content => Deferred('inline_epp',
[file('demoapp/config.yaml.epp'), $hash_variables]),
}
}

Now that our Puppet code has been added, the next Puppet agent run will write the file to the agent node’s filesystem with the unencrypted version of the password in the config.yaml file for use by the application similar to that shown below.

---
host: grtapp01.grt.local
password: Secret12345

This blog post covered a simple and powerful use case for ensuring that sensitive data such as passwords are being stored and handled in a secure manner.

References

Puppet EPP Templates with deferred functions

https://puppet.com/docs/puppet/6.17/template_with_deferred_values.html

Azure virtual machine managed identity

https://docs.microsoft.com/en-us/azure/key-vault/general/tutorial-python-virtual-machine

--

--

Martez Reed

Director of Technical Marketing at Morpheus Data. Operations background with an interest in automation and orchestration.