2

For an Azure function, running on Linux, using Node.js runtime v14,
I want to read app configuration using @azure/app-configuration,
when some config values are cleartext, but others are connection strings to keyvault.

My colleague, writing in C#, is using the ConfigureKeyVault method on AzureAppConfigurationOptions to configure the Azure App Configuration SDK to automatically parse, fetch, and decode secrets from their connections strings.

I'd like to do the same in nodejs, but did not find a similar method in the API docs

Will I have to do something like this?

async function getConfig(key: string): Promise<string> {
  const maybeConnectionString = await appConfigurationClient.getConfigurationSetting({ key });
  if (maybeConnectionString.startsWith('@Microsoft.KeyVault'))
    return await keyVaultClient.getSecret(maybeConnectionString);
  else
    return maybeConnectionString;
}
Benny Powers
  • 5,398
  • 4
  • 32
  • 55

2 Answers2

3

Benny Powers, yes, you are right. To use Key Vault reference in Node.js, you will have to fetch the key-value, parse the value for the secret identifier, and then retrieve the actual secret from the Key Vault. This has been implemented as part of the .NET config provider as you mentioned, but you will have to do this if you are using the JS SDK.

In terms of implementation, you should first check whether the key-value has content-type of application/vnd.microsoft.appconfig.keyvaultref+json;charset=utf-8. If so, it means this key-value is a Key Vault reference. Then you can parse the value. The value is in JSON format, something like {"uri":"https://xxxxxx.vault.azure.net/secrets/....."}. What the uri points to is the secret identifier. Once you have the secret identifier, you can fetch the actual secret by using the Key Valut client like you did.

Zhenlan Wang
  • 1,213
  • 8
  • 10
  • If you're getting the value from App config via env vars, you won't have access to the content-type, so you'll have to do a `string.startsWith('{"uri"')` check. Then you have to parse the `uri` as a url, get the `pathname`, and delete `/secrets/`, only *then* can you pass it to the kvClient... not great ergonomics tbh. I would think the azure keyvault SDK should do this parsing internally for me, or at least expose some `getSecretFromReference(ref: parsedJsonReference)` – Benny Powers Mar 16 '21 at 14:05
  • 1
    Right, the content-type is only available if you use the App Configuration SDK. It's not available if you use the config provider. We are considering adding extensibility to the config provider in the future so you don't have to use the SDK directly just for this. More details are in https://github.com/Azure/AppConfiguration-DotnetProvider/issues/157. – Zhenlan Wang Mar 21 '21 at 08:37
0

Below code can work:

Import modules:

import { SecretClient } from "@azure/keyvault-secrets";
import { DefaultAzureCredential } from "@azure/identity";

Logic to get secret:

let vaultUrl = `https://yourkeyvaultname.vault.azure.net/`;
let credentials = new DefaultAzureCredential();

let client = new SecretClient(vaultUrl, credentials);
let secret_value = (await client.getSecret("yoursecretname")).value

And I notice you mentioned tag 'azure-function', so there is no need to use key-vault SDK. You can add this to the configuration settings of function app(this only work after function app been deployed to azure.):

@Microsoft.KeyVault(SecretUri=<secret identifier>)

Then create a function app identity, and let the function identity access have the corresponding access policy to the keyvault. After that, you can get the secret by simply accessing environment variables.

halfer
  • 19,824
  • 17
  • 99
  • 186
Cindy Pau
  • 13,085
  • 1
  • 15
  • 27