Skip to content

Managing Secrets

Managing Secrets

Since we are using a RSA key for our authentication stragedy, we’ll need to setup a secret management solution for development and we can also use this opporuntity to setup a production ready solution using Azure Key Vault.

Managing Secrets During Development with Azure Key Vault

Setup Azure Key Vault

To manage our secrets for both development and production we’ll use Azure Key Vault. Typically you might use something like dotnet user-secrets but since we’ll have a lot of projects to manage it’s easier to use something that isn’t tied to a specific project.

If you haven’t already create a key vault in Azure. You can do this with the Azure CLI or the Azure Portal.

Terminal window
# create keyvolt if you haven't already
az keyvault create --name <key-vault-name> --resource-group <resource-group-name> --location <location>

After we have the key vault created we can use the following bash script to setup our first secrets. This script will generate a RSA key pair that can be used to sign and verify JWT tokens across our different micro services.

setup-secrets.sh
KEY_VAULT_NAME=OneHundredDays
RG_NAME=OneHundredDays
LOCATION=eastus
# generate RSA key pair
openssl genpkey -algorithm RSA -out private_key.pem -pkeyopt rsa_keygen_bits:2048 && \
openssl rsa -pubout -in private_key.pem -out public_key.pem &&
# set secrets
az keyvault secret set --vault-name KEY_VAULT_NAME --name "private-key" --value "$(cat private_key.pem)" && \
az keyvault secret set --vault-name KEY_VAULT_NAME --name "public-key" --value "$(cat public_key.pem)" && \
# rm from local
rm private_key.pem public_key.pem

Updating our App Host

As with our other integrations we’ll add a reference to the hosting package that supports the resource we want to use.

OneHundredDays.Api.csproj
<PackageReference Include="Aspire.Hosting.Azure.KeyVault" Version="8.2.2" />

Next we’ll create a resource if we are in publish mode. Otherwise we’ll simply get a connection string to an already existing key vault.

/100Days.AppHost/Program.cs
var secrets =
builder.ExecutionContext.IsPublishMode
? builder.AddAzureKeyVault(name: "secrets")
: builder.AddConnectionString("secrets");

Than in our consuming projects we’ll add a reference to the aspire keyvault package.

100Days.<Service>.csproj
<PackageReference Include="Aspire.Azure.Security.KeyVault" Version="8.2.2" />

To connect locally to the key vault you will need to be signed in to the az CLI and have the appropriate permissions to access the key vault. Since this is something we will want the majority of our projects to have access to we can create an extension method in our ServiceDefaults project.

/100Days.ServiceDefaults/Program.cs
public static class KeyVaultExtensions
{
/// <summary>
/// Configure Azure Key Vault secrets for the application.
/// The key vault URL is retrieved from the connection string named "secrets".
/// This must be configured in the AppHost Project.
/// </summary>
/// <param name="builder">The WebApplication Builder</param>
public static void AddAzureKeyVaultSecrets(this IHostApplicationBuilder builder)
{
if (builder.Environment.IsDevelopment())
{
var keyVaultUrl = builder.Configuration.GetConnectionString("secrets");
ArgumentException.ThrowIfNullOrEmpty(keyVaultUrl, nameof(keyVaultUrl));
builder.Configuration.AddAzureKeyVault(
new Uri(keyVaultUrl),
// using the default azure credential provider will use the az cli
new DefaultAzureCredential()
);
}
else
{
// Add Azure Key Vault secret values to app configuration (must be the same name you gave the resource in the apphost)
builder.Configuration.AddAzureKeyVaultSecrets("secrets");
}
}
}

And in our Program.cs file we can now add the following line to any of our services:

/100Days.<Service>/Program.cs
builder.AddAzureKeyVaultSecrets();