Azure  

How to Create and Retrieve Secrets from Azure Key Vault using .NET Client Library?

In this article, let’s create a .NET console application to create and retrieve secrets from Azure Key Vault using .NET Client Library. Azure Key Vault is a Azure cloud service which provides secure storage and retrieval of various secrets. Secrets can be passwords, encryption keys, certificates for the applications and services, etc. After this exercise one will be able to create and retrieve secrets using .NET Client Library along with creation of Azure key vault resource using Azure CLI and assignment of role to Microsoft Entra (Azure AD) user name.

Following tasks are performed:

  • Create Azure Key Vault resources using Azure CLI.

  • Assign role to Microsoft Entra (Azure AD) user name using Azure CLI.

  • Create and retrieve secrets using .NET Client Library.

  • Sign in to Azure and run application.

  • Clean up resources.

Create Azure Key Vault resource using Azure CLI

Initial task is to create and make ready Azure Key Vault resources using Azure CLI (Azure Cloud Shell) for further usage. Click Cloud Shell button on the menu bar at the top right side of the Azure portal. It will launch an interactive shell which can be used to run the steps outlined in this article. Select a Bash environment. To use code editor In cloud shell toolbar go to Settings menu and than select Go to Classic version.

Create resource group

Resource group is logical container used to hold related resources. It includes resources which required to manage as a group. Key Vault belongs to a resource group. az group create command used to create a group.

az group create \ 
     --name myResourceGroup2 \ 
     --location eastus2 

eastus2 is location code instead of it one can use their nearest region location.

Create Azure Key Vault resource

Once resource group is created next task is to create a Azure Key Vault resource that will be used in next section. az keyvault create command is used to create a Azure key value resource. It will take few minutes to complete the process.

az keyvault create \ 
     --name myKeyVaultName2\ 
     --resource-group myResourceGroup2\ 
     --location eastus2 \ 

Assign role to Microsoft Entra (Azure AD) user name

It is important to assign roles to Microsoft Entra (Azure AD) user name. Roles will define what access and permissions a user has within an organization’s Microsoft cloud environment. Roles determine what resources and actions a user can perform. One by one perform below steps in Azure CLI.

Retrieve userPrincipalName

First, retrieve userPrincipalName from account as mentioned in following command. It retrieves the information about currently authenticated user including their UPN and represents that who the role will be assigned to.

userPrincipal2=$(az rest 
     --method GET 
     --url https://graph.microsoft.com/v1.0/me \
     --headers 'Content-Type=application/json' \
     --query userPrincipalName 
     --output tsv)

Retrieve resource ID

Second, get the resource ID of key vault using below command. This will be used in next step to set the scope for role assignment. Resource ID sets scope for role assignment to specific key vault.

resourceID2=$(az keyvault show \
     --resource-group myResourceGroup2 \
     --name myKeyVaultName2 \ 
     --query id \
     --output tsv)

Create and assign Key Vault Secrets Officer role

Finally, let's create and assign key vault secrets officer role using az role assignment create command. It will give permissions to manage next routines. userPrincipal and resourceID variables are created in first and second steps as above which are used in this command to retrieve actual value at command execution time.

az role assignment create \
     --assignee $userPrincipal2\
     --role "Key Vault Secrets Officer" \
     --scope $resourceID2
  • Key Vault Secrets Officer role: It is to be assigned to Microsoft Entra user before create and retrieve secret. It gives permissions to create, retrieve and delete secrets to user account i.e. it allows to create and read actions.

  • Key Vault Secrets User role: It allows to read action only.

Now, required basic resources are deployed and ready to use. So, let's create a .NET console app.

Create and retrieve secrets using .NET Client Library

Let’s set-up the .NET console application to create and retrieve the secrets from Azure Key Vault using .NET Client Library. Perform the following steps one by one in to Cloud Shell to achieve this.

.NET Project Setup

Set up a console project to add and fetch secrets using .NET Client Library.

  • Create project directory and change to that directory. First create a directory for the project using below command and move to that directory.

mkdir keyvault2
cd keyvault2
  • Create .NET console application to add and fetch secrets through it. dotnet new console command is used to create a .NET console app.

dotnet new console
  • Install Packages - Identity and Secrets packages are required to work with key vault. Run dotnet add package command to add Azure.Identity and Azure.Security.KeyVault.Secrets packages in project to use the SDK.

dotnet add package Azure.Identity
dotnet add package Azure.Security.KeyVault.Secrets

Starter code

Add the below starter code into the project and replace template code in Program.cs file by using editor in Cloud Shell.

  • Application editing - open Program.cs file to edit it in the Azure CLI using code command.

code Program.cs
  • Code replacing - replace existing code of Program.cs with the below code. This is the initial started code and will replace last four commented lines with actual code in next “Complete code” section.

using Azure.Identity;
using Azure.Security.KeyVault.Secrets;

// Replace KEYVAULT-NAME with actual Key Vault name
string keyVaultUrl = "https://KEYVAULT-NAME.vault.azure.net/";

// CREATE - CLIENT

// CREATE - MENU OPTIONS

// LIST - SECRETS

// CREATE - SECRET
  • Save & close - Press ctrl + s to save your changes and continue.

Complete code

Add following code one by one at mentioned commented section to complete the application. Let’s update the code for commented lines for specific operations one by one as described to create client, add menu options, list out secrets, and add secretes to key vault.

  • Create Client - First create an instance of SecretClient class to add and fetch secrets using it. This class is main starting point to perform all the operations against Key Vault. Locate // CREATE CLIENT comment, then add following code directly beneath comment. KEYVAULT-NAME will be actual key value. DefaultAzureCredentialOptions configures authentication options. SecretClient creates Key Vault client

// CREATE - CLIENT

// Configure authentication options to connect with Azure Key Vault
DefaultAzureCredentialOptions defaultAzureCredentialOptions = new()
{
     ExcludeEnvironmentCredential = true,
     ExcludeManagedIdentityCredential = true
};

// Create Key Vault client through URL and authentication credentials
var secretClient = new SecretClient(new Uri(keyVaultUrl), new DefaultAzureCredential(defaultAzureCredentialOptions));
  • Add Menu Options - Locate // CREATE - MENU OPTIONS comment, then add following code directly beneath comment. Option 1 allows to list out all the secrets. Option 2 will add new secret using entered name and value in to Key Vault. Option 3 allows to exit from application.

// CREATE - MENU OPTIONS

// Run application continues until user enters 3 to exit
while (true)
{
     // Display options
     Console.Clear();
     Console.WriteLine("\n ..... Options .....");
     Console.WriteLine("......................");
     Console.WriteLine("1. List of Secrets");
     Console.WriteLine("2. Create New Secret");
     Console.WriteLine("3. Exit");
     Console.WriteLine("......................");
     Console.Write("Enter an option (1, 2, or 3): ");

     // Read user option
     string? inputOption = Console.ReadLine()?.Trim();

     // Check user option to exit application
     if (inputOption == "3")
     {
          Console.WriteLine("Exiting from application. Press any key to continue!");
          Console.ReadLine();
          break;
     }

     // Process user option
     switch (inputOption)
     {
          case "1":
               //call method to list out all secrets
               await ListOfSecrets(secretClient);
               break;
          case "2":
               //call method to create a new secret
               await CreateNewSecret(secretClient);
               break;
          default:
               //invalid option selection message
               Console.WriteLine("Invalid option. Please enter 1, 2, or 3. Press any key to continue!");
               Console.ReadLine();
               break;
     }
}
  • List Secrets - GetPropertiesOfSecretsAsync is used to get all the secret properties in Key Vault. GetSecretAsync retrieves the actual secret value and metadata. Locate // LIST - SECRETS comment, then add following code directly beneath comment.

// LIST - SECRETS

async Task ListOfSecrets(SecretClient client)
{
     try
     {
          Console.Clear();
          Console.WriteLine("Listing of secrets in Key Vault");
          Console.WriteLine("......................");
          
          // Get all secret properties in Key Vault
          bool secretExists = false;
          var secretProperties = client.GetPropertiesOfSecretsAsync();
          
          // Iterate with each secret property to get all secret information
          await foreach (var secretProperty in secretProperties)
          {            
               secretExists = true;
               try
               {
                    // Retrieve actual secret value and metadata
                    var secret = await client.GetSecretAsync(secretProperty.Name);

                    // Print secret details
                    Console.WriteLine($"Name is {secret.Value.Name}");
                    Console.WriteLine($"Value is {secret.Value.Value}");
                    Console.WriteLine($"Created on  {secret.Value.Properties.CreatedOn}");
                    Console.WriteLine("......................");
               }
               catch (Exception ex)// Secrets exception handling
               {
                    Console.WriteLine($"Error message '{secretProperty.Name}': {ex.Message}");
                    Console.WriteLine("......................");
               }
          }

          // Print if no any secret exists
          if (!secretExists)
          {
               Console.WriteLine("No any secret exists.");
          }
     }
     catch (Exception ex)// General exception handling
     {
          Console.WriteLine($"Error message {ex.Message}");
     }

     Console.WriteLine("Press any key to continue!");
     Console.ReadLine();
}
  • Create Secrets - KeyVaultSecret creates a new secret using name and value. SetSecretAsync stores secret in Azure Key Vault. Locate // CREATE - SECRET comment, then add following code directly beneath comment.

// CREATE - SECRET

async Task CreateNewSecret(SecretClient client)
{
     try
     {
          Console.Clear();
          Console.WriteLine("\nCreate new secret");

          // Get secret name
          Console.Write("Enter secret name: ");
          string? secretName = Console.ReadLine()?.Trim();

          // Get secret value
          Console.Write("Enter secret value: ");
          string? secretValue = Console.ReadLine()?.Trim();

          // Check secret name and value for empty   
          if (string.IsNullOrEmpty(secretName) || string.IsNullOrEmpty(secretValue))
          {
               Console.WriteLine("Secret name or value couldn't be blank. Press any key to continue!");
               Console.ReadLine();
               return;
          }

          // Create a new secret using name and value
          var secret = new KeyVaultSecret(secretName, secretValue);

          // Store secret in Azure Key Vault
          await client.SetSecretAsync(secret);

          Console.WriteLine($"Secret '{secretName}' created successfully. Press any key to continue!");
          Console.ReadLine();
     }
     catch (Exception ex)// Secrets exception handling
     {
          Console.WriteLine($"Error message {ex.Message}");
     }
}
  • Save & close - Now it’s time to save and close the file by pressing Ctrl + s to save file and then Ctrl + q to exit the editor. Here, by with this article a complete code is attached in Program.cs file.

Sign into Azure and Run application

Now, application is ready to run. One by one execute the following commands in Azure CLI to run an application and perform the mentioned steps to verify the result outcomes.

  • Sign in - az login command used for sign in. Sign into Azure is mandatory even though cloud shell session already may authenticated.

az login
  • Run application - dotnet run command used to start console application. Application will display menu options system for the app.

dotnet run
  • Output - enter the appropriate options on the screen as following:

    • Enter 1 to list out all the secrets created and it will show no secrets.

    • Select option 2 to create and add new secret using secrete name and value. It will create secrets and can be used later.

    • Enter 1 to list out all the secrets created. and it will show the above created secret details.

    • Enter option 3 to exit and quit the application and until that application will ask options continuously and perform the operation accordingly.

Clean up resources

Once finished the exercise it’s recommended to delete cloud resources are being created to avoid the unnecessary resource usage and any future costs. Deleting a resource group will delete all resources contained within it. Perform following steps one by one in to Azure Portal to achieve this:

  • Navigate to resource group which is being created here and view it’s contents.

  • Delete resource group selection from the toolbar.

  • Choose resource group name and then follow next directions to delete resource group and all the resources it contains.

One can also clean up resources using Azure CLI as following:

Delete role assignment - az role assignment delete command is used to remove role assignment.

az role assignment delete \
     --role "Key Vault Secrets Officer" \
     --scope $resourceID2

Delete key vault - az keyvault delete command is used to remove keyvault.

az keyvault delete \
     --name myKeyVaultName2 \
     --resource-group myResourceGroup2 

Delete resource group - az group delete command is used to remove resource group and it's referenced items.

az group delete \
     --name myResourceGroup2

Summary

Here, a complete process flow is described to create and retrieve secrets from Azure Key Vault using .NET Client Library. "Key Vault Secrets Officer" role is assigned to Microsoft Entra (Azure AD) user name. .NET project is created to create and retrieve the secrets using .NET Client Library DSK. Finally, resources are cleaned up. Here by with this article a complete code of Program.cs file is attached. Following it the list of key commands and classes/objects used in this article:

Commands

  • Create resource group: az group create

  • Create Azure Key Vault resource: az keyvault create

  • Create and assign Key Vault Secrets Officer role: az role assignment create

  • Create .NET console application: dotnet new console

  • Add packages: dotnet add package

  • Delete role assignment: az role assignment delete

  • Delete Key Vault: az keyvault delete

  • Delete resource group: az group delete

Classes or Objects

  • Configure authentication options: DefaultAzureCredentialOptions

  • Create Key Vault client: SecretClient

  • Get all secret properties in Key Vault: GetPropertiesOfSecretsAsync

  • Retrieve actual secret value and metadata: GetSecretAsync

  • Create a new secret using name and value: KeyVaultSecret

  • Store secret in Azure Key Vault: SetSecretAsync