Managing secrets is a challenge in every DevOps environment, I use Azure Key Vault to manage my secrets. When I was getting started working with Key Vault my biggest challenge was not getting secrets in, but how to get them out. The samples we provide with the azure-keyvault NPM package didn’t really fit what I was looking for so I created a Node client example I wanted to share here.
Tl;dr - I have created a GitHub repo with a client.
To use the Node client for Key Vault you will need a few things.
- Azure Key Vault (Obviously)
- Azure Active Directory Application (Not as Obvious)
In my applicaiton I create a .ENV file with the following in it.
KEYVAULT_CLIENT_ID=<AAD Application ID>
KEYVAULT_CLIENT_SECRET=<AAD Application Client Secret>
KEYVAULT_VAULT_URI=<Key Vault Base URI>
KEYVAULT_SECRET_VERSION=<Key Vault Secret Version>
KEYVAULT_SECRET_NAME=<Key Vault Secret Name>
OUTFILE_LOCATION=<File Output Location>
You can use whatever package you want to load .ENV files, but I use dotenv. Once I have my variables, My simple app will grab the secret and write it to a file. If you want to set it as a variable and use it in your application, it is an easy change.
const dotenv = require('dotenv')
const fs = require('fs')
const KeyVault = require('azure-keyvault')
const AuthenticationContext = require('adal-node').AuthenticationContext
// Load the .ENV file -- This will be run from process.env.<variable>
dotenv.config()
// Load the Key Vault Client variables
const clientId = process.env.KEYVAULT_CLIENT_ID
const clientSecret = process.env.KEYVAULT_CLIENT_SECRET
const secretName = process.env.KEYVAULT_SECRET_NAME
const secretVersion = process.env.KEYVAULT_SECRET_VERSION
const vaultUri = process.env.KEYVAULT_VAULT_URI
const outfile = process.env.OUTFILE_LOCATION
// Connect to Keyvault
const authenticator = function (challenge, callback) {
const context = new AuthenticationContext(challenge.authorization)
return context.acquireTokenWithClientCredentials(
challenge.resource,
clientId,
clientSecret,
function (err, tokenResponse) {
if (err) throw err
// Calculate the value to be set in the request's Authorization header and resume the call.
var authorizationValue =
tokenResponse.tokenType + ' ' + tokenResponse.accessToken
return callback(null, authorizationValue)
}
)
}
const credentials = new KeyVault.KeyVaultCredentials(authenticator)
const client = new KeyVault.KeyVaultClient(credentials)
// Get the secret
client.getSecret(vaultUri, secretName, secretVersion, (err, res) => {
if (err) {
throw err
}
fs.writeFile(outfile, res.value, err => {
if (err) {
throw err
}
console.log(`${outfile} created`)
})
})
Hope this little snippet helps you start using Azure Key Vault. In future posts, I will talk about how I am using Key Vault in my CI/CD pipeline.