---
source_url: https://itmustbecode.com/azure-key-vault-secrets-in-dataverse/
title: Azure Key Vault Secrets in Dataverse
date: 2022-01-25T05:21:28+00:00
categories:
  - blog
tags:
  - custom-api
  - dataverse
  - environment-variable
  - key-vault
  - plugin
word_count: 1268
reading_time_minutes: 6
type: posts
---

**Environment variables** in Dataverse are a powerful vehicule to develop portable customizations between different environment. Recently, a new **Secret** Data Type was introduced that enables the use of secrets stored in **Azure Key Vaults** 🔐 .

The integration between **Dataverse** and **Azure Key Vault** was long-awaited and I am really happy to see it materialize. It brings new kind of use cases and an **additional security layer** to protect sensitive information needed in platform customizations.

In this post, I will share my findings setting up the key vaults. And, while most of the documentation and videos out there are showing how to consume secret environment variables in **PowerAutomate** Flows, I will focus on their usage inside **Dataverse Plugin** code.

## **Azure Key Vault setup**

The first step is to setup an **Azure Key Vault** to hold the secrets and give **Dataverse environments** the right to read the secrets stored in the vault.

The [official documentation](https://docs.microsoft.com/en-us/powerapps/maker/data-platform/environmentvariables#use-azure-key-vault-secrets?WT.mc_id=DX-MVP-5004959) gives really good instructions on how to configure your key vaults so I will not repeat everything here. The main steps are :

1. Enable **Microsoft.PowerPlatform** as a **resource provider** in your Azure subscription
1. Create a **Key Vault**
1. Give proper security role to the **Dataverse application**

There are 2 **permission model** available in a Key Vault

- Vault access policy
- Azure role-based access control (RBAC)

{{< figure src="./image-18.png" alt="" caption="" >}}

The [official documentation](https://docs.microsoft.com/en-us/powerapps/maker/data-platform/environmentvariables#use-azure-key-vault-secrets?WT.mc_id=DX-MVP-5004959) assumes that the **permission model** of the Key Vault is ' **Vault access policy**' follow the instructions if that is your case.

If you use Role-based access control ( **RBAC**), you need to grant the **Key Vault Secrets User** role to the Dataverse application. Here's how to do it in the Azure portal :

Head to the **Access control (IAM)** blade and add a **Role Assignment**, and select **Key Vault Secrets User**.

{{< figure src="./image-19.png" alt="" caption="" >}}

{{< figure src="./image-20.png" alt="" caption="" >}}

You will be prompted to select the members. Type **Dataverse** in the search box and the Dataverse application service principal will be proposed. Select the **Dataverse application** and save.

{{< figure src="./image-21.png" alt="" caption="" >}}

{{< figure src="./image-22.png" alt="" caption="" >}}

In the **Access control (IAM)**, you can now assess that the Dataverse application as proper access to ther Key Vault.

{{< figure src="./image-23.png" alt="" caption="" >}}

> 🔔 Be aware that once you granted the read secrets permissions to the Dataverse application on a given Key Vault, **all the Dataverse environments** in your tenant are entitled to read secrets from this vault.
>
> So as a best practice, its a good idea to have **dedicated** Key Vaults for Dataverse secrets usage only and don't mix up secrets from other systems.
>
> It's also recommended to have seperate key vaults for all your different environments (ex. DEV, QA, PROD)

## **Create a Secret in the Key Vault**

For our example, we will create a secret with the following properties.

- Name : TopSecret
- Value : '🔐 For Your Eyes 👀 Only 🔐'

Given that your user has admin rights on the key vault secrets, head to the **Secrets** blade of the Key Vault and select **Generate/Import**.

{{< figure src="./image-29.png" alt="" caption="" >}}

{{< figure src="./image-13.png" alt="" caption="" >}}

Notice that you can even set an an activation and/or expiration date. That's a feature that is not possible using a normal Environment variable. This could be quite useful in certain scenarios.

## **Create a Secret Environment Variable**

We're almost there. Now we need to create an **Environment Variable** of type **Secret** in Dataverse that will reference the secret that we just created in the key vault.

Switch to the PowerApps Maker portal and open a solution. Here, I created a solution called 'KeyVault Test' and added an Environment Variable from the ' **New**' option in the top menu.

{{< figure src="./image-15.png" alt="" caption="" >}}

{{< figure src="./image-16.png" alt="" caption="" >}}

> _Note : The user who creates the environment variable must have **read** permission on the specific key vault_. This provides an additional layer of security

Be sure to choose the ' **Secret**' data type and **'Azure Key Vault**' as the Secret Store. Then click on **New Azure Key Vault secret reference** where you'll be asked to enter the info needed to resolve your key.

- **Azure subscription Id**
- **Resource Group Name**
- **Azure Key Vault Name**
- **Secret Name** : we will use 'TopSecret' wich is the name of the secret defined earlier

{{< figure src="./image-24.png" alt="" caption="" >}}

{{< figure src="./image-25.png" alt="" caption="" >}}

Once saved, the Environment Variable will only hold the **reference** to the secret in the key vault without storing its value inside your Dataverse environment. Think of it as a pointer.

The reference to the key vault secret will be stored in the **EnvironmentVariableValue** table using this form :

```
/subscriptions/{subscriptionid}/resourceGroups/{resourcegroupname}/providers/Microsoft.KeyVault/vaults/{keyvaultname}/secrets/{secretname}
```

## **Retrieve the Secret Value**

In order to retrieve the Environment variable secret value, the platform exposes an unbound **Custom Api** called **RetrieveEnvironmentVariableSecretValue** that can be called at runtime inside customizations.

One of the easiest way to test this API is to fire-up the **XrmToolBox** and open the **[Custom API Tester](https://www.xrmtoolbox.com/plugins/Rappen.XrmToolBox.CustomAPITester/)** tool by [Jonas Rapp](https://twitter.com/rappen).

Select the **RetrieveEnvironmentVariableSecretValue** custom API and set the name of the variable to fetch as the **EnvironmentVariableName** input. Execute the API and the secret value will be received in the **EnvironmentVariableSecretValue** output, as seen in the image below.

{{< figure src="./image-26.png" alt="" caption="" >}}

Since the Custom API is adressable, it's also possible to make a direct call to the Dataverse web API to retrieve the secret value.

```
POST => https://{{baseurl}}/api/data/v9.2/RetrieveEnvironmentVariableSecretValue

BODY :
{
    "EnvironmentVariableName" : "{VariableName}"
}

```

{{< figure src="./image-34.png" alt="" caption="" >}}

## **Using Secrets in Plugin code**

Awesome, now let see how we can leverage the usage of a Secret Environment Variable in a Dataverse **Plugin**.

It's only a matter of making a call to the **RetrieveEnvironmentVariableSecretValue** API inside the code of the plugin.

Here's an example using **Late Bound** coding style. You need to create an **OrganizationRequest** object and set the **EnvironmentVariableName** parameter. Upon execution of the request, the secret value will be found in the **EnvironmentVariableSecretValue** Results collection of the response.

I personally prefer the **Early Bound** coding style for my plugin development. Early bound classes can be generated not only for Tables (Entities) but also for Custom Actions/API.

My weapon of choice for early bound classes generation is the **[spkl Task Runner](https://github.com/scottdurow/SparkleXrm/wiki/spkl)** by [Scott Durow](https://twitter.com/ScottDurow). Just add **RetrieveEnvironmentVariableSecretValue** in the " **actions**" section of the spkl.json configuration file.

{{< figure src="./image-30.png" alt="" caption="" >}}

This will produce specialized **RetrieveEnvironmentVariableSecretValueRequest** and **RetrieveEnvironmentVariableSecretValueResponse** that can be used instead of the generic OrganizationRequest used in the late bound example. Difference here is that there are **no magic strings** only concrete objects with properly typed properties.

Now, when deployed and registered on Create of a contact record, eighter of the plugins showed above will produce the following. _I'm just throwing an error with the secret value_.

{{< figure src="./image-28.png" alt="" caption="" >}}

{{< figure src="./image-27.png" alt="" caption="" >}}

I used the technique showed above to enhance my own [**Dataverse-CustomApis**](https://github.com/drivardxrm/Dataverse-CustomApis) collection community project.
{{< linkcard url="https://github.com/drivardxrm/Dataverse-CustomApis" title="GitHub - drivardxrm/Dataverse-CustomApis: Collection of Dataverse Custom Apis" summary="Collection of Dataverse Custom Apis. Contribute to drivardxrm/Dataverse-CustomApis development by creating an account on GitHub." image="/linkcards/e9ffe6985986dfe4.png" domain="github.com" new_tab="true" nofollow="true" >}}

In this project I expose a Custom API called **GetEnvironmentVariable**. This API takes the name of an environmenmt variable as an Input and returns a bunch of information on the variable. Most importantly, it casts the value accordingly depending on the type (String, Boolean, Number and now ... 🎉 **Secret**).

As you can see below, when the **GetEnvironmentVariable** API is called with a variable Key of type Secret. The secret value is resolved in the **ValueSecret** output property.

{{< figure src="./image-32.png" alt="" caption="" >}}

Install the [latest release](https://github.com/drivardxrm/Dataverse-CustomApis/releases/latest) of the solution if you want to try it.

## **Takeaway**

I'm thrilled by the addition of the **Secret** data type for Dataverse Environment Variables and I see a lot of potential use cases in my current projects.

There are a lot of **benefits** to store secrets in Key vaults instead of Dataverse tables. Think about logging, monitoring, key rotation just to name a few.

Here are some other great resources and use cases on the subject :

- [Environment Variable Secrets - YouTube](https://www.youtube.com/watch?v=A4eQ7BMxeX4)
- [Access Azure Key Vault Secrets using Environment Variables. #CitizenCan E15 \| 365.Training - YouTube](https://www.youtube.com/watch?v=molG-VK4xKI)

Photo by **[George Becker](https://www.pexels.com/@eye4dtail?utm_content=attributionCopyText&utm_medium=referral&utm_source=pexels)** from **[Pexels](https://www.pexels.com/photo/close-up-of-keys-333837/?utm_content=attributionCopyText&utm_medium=referral&utm_source=pexels)**

