Mastering Azure Key Vault Integration for .NET Web APIs

Mohamed Mohsen
9 min readMay 6, 2024

--

Embark on a journey to secure your .NET Web API application with Azure Key Vault. In this comprehensive guide, I’ll walk you through the seamless integration of your application with Azure Key Vault, Microsoft’s cutting-edge cloud service for securely storing and managing sensitive information.

As of the time of writing, the latest version of .NET is .NET 9. If you are using an older version of .NET, the configurations may differ slightly or remain the same.

Now, let’s dive in and unlock the full potential of Azure Key Vault in your .NET Web API application!

What is Azure Key Vault?

Azure Key Vault is a cloud service provided by Microsoft Azure for securely storing and managing sensitive information such as keys, secrets, certificates, and connection strings. It helps in protecting cryptographic keys and secrets used by cloud applications and services.

Why Azure Key Vault?

  1. Centralized Management: Key Vault centralizes sensitive data storage and management.
  2. Security: Ensures high-level security for cryptographic keys and secrets.
  3. Monitoring Access and Usage: You can monitor activity by enabling logging for your vaults.
    ​ ​ ​​​ ​ ​​​ ​​ ​ ​​​ ​ ​​​ ​. Archive to a storage account.
    ​ ​ ​​​ ​ ​​​ ​​ ​ ​​​ ​ ​​​ ​. Stream to an event hub.
    ​ ​ ​​​ ​ ​​​ ​​ ​ ​​​ ​ ​​​ ​. Send the logs to Azure Monitor logs.
  4. Compliance: Helps meet regulatory standards with access controls and auditing.
  5. Integration: Seamlessly integrates with Azure services and applications.
  6. Developer Productivity: Simplifies data management, allowing focus on application development.

Integrate with .NET9 Web API

To seamlessly integrate a .NET Web API application with Azure Key Vault, follow these steps:

  1. Create and configure Azure Key Vault secrets.
  2. Register your application in Azure App Registrations.
  3. Incorporate the secret configurations into the appsettings.json
  4. Utilize dependency injection to inject the secrets, enabling their use throughout the application.

Create and configure Azure Key Vault secrets

If you’ve already created your Key Vault, feel free to skip the initial steps.

To create and configure Azure Key Vault secrets:

  1. Navigate to the Azure portal homepage and search for “Key Vault”.
Azure portal search bar

2. Create a new Key Vault and select a unique name for it.

3. Choose the pricing tier based on your requirements.

Azure Key Vault offers two service tiers: Standard and Premium.

The Standard tier encrypts data with a software key, while the Premium tier includes hardware security module (HSM)-protected keys.
You can review the details on the Azure Key Vault pricing page.

For this demonstration, I’ve selected the Standard tier, but you have the option to choose Premium if needed.

4. Set the permission level

Now, navigate to the “Access configuration” tab, where you’ll be able to configure the permission model.

Authorization may be done via Azure role-based access control (Azure RBAC) or Key Vault access policy.

Azure RBAC can be used for both management of the vaults and to access data stored in a vault, while key vault access policy can only be used when attempting to access data stored in a vault.

5. Keep all settings as default and proceed to create the Key Vault.

6. After creating the Key Vault, navigate to the created resource, and from the left sidebar, go to “Secrets” to create a new secret.

7. Select your desired secret name.

In this example, I’m creating a secret named “MyConnectionString”.

If you encounter a warning or error after creating the secret, following the steps outlined in this Stack Overflow solution will resolve the issue.

Warning
Error

Remember:

  • Azure Key Vault is a cloud service for securely storing and accessing secrets.
  • A secret is anything that you want to tightly control access to, such as API keys, passwords, certificates, or cryptographic keys.

Register our application in Azure App Registrations.

Back to the Azure portal homepage and search for “app registrations”.

Azure portal search bar

Create a new registration and specify your application name, then proceed to create it.

By registering our app, we are informing the Key Vault that we have an application that needs to access the Key Vault secrets.

New registration

After registration, although we have a registered app and a Key Vault, we still need to connect them.

This is achieved by creating a client secret for our registered application and adding an authorization role policy.

This policy informs the Key Vault to grant our application access to the secrets.

Create a new client secret.

Navigate to “Certificates & secrets” in App Registrations from the left sidebar, then create a new client secret and specify the secret name.

New client secret

Next, add the necessary policy with role assignment. Navigate to the Key Vault resource, select “Access control (IAM)” from the left sidebar, then choose the “Role assignments” tab, and click “Create role assignment”.

Search for the required role. In this example, I used an admin role. Make sure to select the needed role, then click “Next” and proceed to create it.

Before proceeding to the next section, ensure you have the following information ready:

  • Vault URI
  • Client Id
  • Tenant Id
  • Client Secret
  • Secret name (for testing purposes)
Vault URI
Client Id and Tenant Id
Client Secret
Secret name

Incorporate the secret configurations into the appsettings.json

Next, open the appsettings.json file and add the following section:

"AzureKeyVault": {
"VaultURI": "Your vault URI",
"ClientId": "Your client id",
"TenantId": "Your tenant id",
"ClientSecret": "Your client secret"
}

You can enhance security further by utilizing secrets.json instead. However, remember that secrets.json will not be pushed to the Git repository. Each team member will need to create it manually to maintain security standards.

Utilize dependency injection to inject the secrets, enabling their use throughout the application

Firstly, install the necessary NuGet packages.

dotnet add package Azure.Identity
dotnet add package Azure.Security.KeyVault.Secrets
dotnet add package Azure.Extensions.AspNetCore.Configuration.Secrets

Next, we need to inject the Key Vault service into the IConfiguration service, allowing us to retrieve the vault secrets from IConfiguration at runtime.

// Program.cs

using Azure.Identity;

builder.Configuration.AddAzureKeyVault(
new Uri(builder.Configuration["AzureKeyVault:VaultURI"]!),
new ClientSecretCredential(
tenantId: builder.Configuration["AzureKeyVault:TenantId"]!,
clientId: builder.Configuration["AzureKeyVault:ClientId"]!,
clientSecret: builder.Configuration["AzureKeyVault:ClientSecret"]!
));

Well done! We have configured our application to retrieve all the required configurations from the vault in addition to appsettings.json file.

Retrieval Preceding

After integrating the Key Vault secrets, we now have four potential sources from which to retrieve a key’s value: Azure Key Vault, appsettings.json, environment variables, and secrets.json.

Here is the precedence order from highest to lowest:

  1. Azure Key Vault
  2. secrets.json
  3. appsettings.json
  4. environment variables

Testing

Let’s create an endpoint that takes the secret name as a string parameter and returns its value from Azure Key Vault.

[ApiController]
[Route("[controller]")]
public class VaultController : ControllerBase
{
private readonly IConfiguration _configuration;

public VaultController(IConfiguration configuration)
{
_configuration = configuration;
}

[HttpGet]
[Route("secret")]
public string? GetSecret(string secretName)
{
return _configuration[secretName];
}
}

Run the application and open the Swagger window. Try sending your secret name in the endpoint. It should return the secret value if it’s in the Azure Key Vault secrets. Otherwise, it will attempt to search based on the precedence order.

Remember, the secret name is case-insensitive, so you can write it in lowercase, uppercase, or mixed case; it will be normalized at the end.

Retrieving key vault secret value

Monitoring: Logging

After you create one or more key vaults, you’ll likely want to monitor how and when your key vaults are accessed, and by whom.

What is logged:

  1. Authenticated REST API requests and failed attempts.
  2. Key vault operations like creation, deletion, and access policy changes.
  3. Key and secret operations such as creation, modification, and listing.
  4. Unauthenticated requests resulting in a 401 response.
  5. Azure Event Grid notifications for expiration and policy changes.

Log sample:

{
"time": "2024-05-06T20:47:43.4966268Z",
"category": "AuditEvent",
"operationName": "VaultGet",
"resultType": "Success",
"correlationId": "a3007d05-6es4-4d78-a541-XXXXXXXXXXXX",
"callerIpAddress": "xx.78.xx.172",
"identity": {
"claim": {
"http://schemas.microsoft.com/identity/claims/objectidentifier": "2b46553d-rl15-3ec5-bc4d-XXXXXXXXXXXX",
"appid": "11c174dc-1526-4a9a-f79b-XXXXXXXXXXXX"
}
},
"properties": {
"id": "https://my-keyvault-00001.vault.azure.net/",
"clientInfo": "",
"requestUri": "https://management.azure.com/subscriptions/361DA5D4-A47A-4C79-AFDD-XXXXXXXXXXXX/resourceGroups/my-resource-group/providers/Microsoft.KeyVault/vaults/my-keyvault-00001?api-version=2019-09-01",
"httpStatusCode": 200,
"properties": {
"sku": {
"Family": "A",
"Name": "Standard",
"Capacity": null
},
"tenantId": "2bc9q3c3-372a-79e5-aa0b-XXXXXXXXXXXX",
"networkAcls": null,
"enabledForDeployment": false,
"enabledForDiskEncryption": false,
"enabledForTemplateDeployment": false,
"enableSoftDelete": true,
"softDeleteRetentionInDays": 90,
"enableRbacAuthorization": true,
"enablePurgeProtection": null
}
},
"resourceId": "/SUBSCRIPTIONS/361DA5D4-A47A-4C79-AFDD-XXXXXXXXXXXX/RESOURCEGROUPS/MY-RESOURCE-GROUP/PROVIDERS/MICROSOFT.KEYVAULT/VAULTS/MY-KEYVAULT-00001",
"operationVersion": "2019-09-01",
"resultSignature": "OK",
"durationMs": "16"
}

Enable logging to Log Analytics and Blob Containers

The following steps are copied from Microsoft documentation.

  • From the Resource pane menu, select Diagnostic settings, and then Add diagnostic setting
Microsoft reserved image (link)
  • Under Category groups, select both audit and allLogs.
  • If Azure Log Analytics is the destination, select Send to Log Analytics workspace and choose your subscription and workspace from the drop-down menus.
    You may also select Archive to a storage account and choose your subscription and storage account from the drop-down menus.
Microsoft reserved image (link)
  • When you’ve selected your desired options, select Save.
Microsoft reserved image (link)

Explore Blob Containers logs:

To generate some logs, run the testing application again.

Navigate to the configured storage account and locate the blob containers. You should find a new blob container named “insights-logs-auditevent”. Navigate to the deepest folder to find log files in JSON format.

Generated log file in JSON format

Protection

If your secrets are accessed by anonymous users or compromised in any way, it’s crucial to detect and respond to such incidents promptly.

Microsoft offers a solution for this called “Azure Sentinel.” By implementing trapped keys, Azure Sentinel notifies you immediately whenever someone accesses them.

You can find a comprehensive demonstration of this feature in a YouTube video.

Microsoft Sentinel

References

https://azure.microsoft.com/en-us/pricing/details/key-vault/

--

--

Mohamed Mohsen

Software Engineer @Microsoft | .NET | Azure Cloud Services | System Design | Architecture