Secrets
How to deal with secrets and sensitive data in an app.
Administration of secrets in Azure
As an application developer you administer the secrets which the application use in the Azure Key Vault.
Routines for ordering access to your organizations resources are described here.
Configure support for secrets in your app
To make secrets accessible within your application the affiliated helm chart has to be updated.
In your application repository you can find the file values.yaml
in the folder deployment.
Under the section volumeMounts you add the following lines:
- name: altinn-appsettings-secret
mountPath: "/altinn-appsettings-secret"
Under the section volumes you add the following lines:
- name: altinn-appsettings-secret
secret:
secretName: altinn-appsettings-secret
The last part of the file should look something like this after your changes are complete.
How to make use of secrets in your application
You can either add Azure Key Vault as a config provider and use the IOptions pattern to read secrets, or you can use the ISecretsClient
service, which is exposed in the application and can be dependency injected into the class where you need to retrieve a secret.
1. Azure Key Vault as config provider (recommended)
If this approach is chosen, you can use Azure Key Vault in the standard way via IOptions-pattern.
The Altinn.App.Api.Extensions
namespace contains a helper method for this purpose:
IHostApplicationBuilder.AddAzureKeyVaultAsConfigProvider()
This method can be used in Program.cs
like this:
void ConfigureWebHostBuilder(IWebHostBuilder builder)
{
builder.ConfigureAppWebHost(args);
// Add Azure KV provider for TT02 & Prod environments
if (!builder.Environment.IsDevelopment())
{
builder.AddAzureKeyVaultAsConfigProvider();
}
}
AddAzureKeyVaultAsConfigProvider
must occur after the method ConfigureAppWebHost
has been executed, otherwise the app will fail to start.Local mocking can be done with the use of user secrets:
dotnet user-secrets init
dotnet user-secrets set "NetsPaymentSettings:SecretApiKey" "test-secret-key-used-for-documentation"
2. Using ISecretsClient
If you do not wish to add Azure Key Vault as a config provider, you can alternatively use the ISecretsClient
service, which is a wrapper around the retrieval of secrets from Azure Key Vault. This service offers methods for fetching individual secrets as needed.
Code example
In this section, you will find an example of how to use a secret to populate a form field during instantiation.
The logic is implemented in InstantiationHandler.cs
.
using Altinn.App.Models;
using Altinn.App.Services.Interface;
using Altinn.App.Services.Models.Validation;
using Altinn.Platform.Storage.Interface.Models;
using Altinn.App.Core.Internal.Secrets;
using System.Threading.Tasks;
namespace Altinn.App.AppLogic;
public class InstantiationHandler
{
private IProfile _profileService;
private IRegister _registerService;
private ISecretsClient _secretsClient;
/// <summary>
/// Set up access to profile and register services
/// </summary>
public InstantiationHandler(IProfile profileService, IRegister registerService, ISecretsClient secretsClient)
{
_profileService = profileService;
_registerService = registerService;
_secretsClient = secretsClient;
}
/// <summary>
/// Run events related to instantiation
/// </summary>
/// <remarks>
/// For example custom prefill.
/// </remarks>
/// <param name="instance">Instance information</param>
/// <param name="data">The data object created</param>
public async Task DataCreation(Instance instance, object data)
{
if (data.GetType() == typeof(Skjema))
{
Skjema model = (Skjema)data;
model.etatid = await _secretsClient.GetSecretAsync("secretId");
}
await Task.CompletedTask;
}
}
- The class contains a private variable to store the secrets client.
private ISecretsClient _secretsClient;
- The ISecretsClient service is injected in the constructor and is assigned to the private variable.
public InstantiationHandler(IProfile profileService, IRegister registerService, ISecretsClient secretsClient) { _profileService = profileService; _registerService = registerService; _secretsClient = secretsClient; }
- The relevant secret is fetched from Azure Key Vault (or local mock).
await _secretsClient_.GetSecretAsync("secretId");
Local mock
To run your service locally without connecting to Azure Key Vault, you need to create a file named secrets.json
under
the App folder. In the JSON structure, you can include dummy data for the secrets you need. If you have uploaded a
secret in Key Vault with the name “secretId,” the content of the JSON file will look like this:
{
"secretId": "dummy secret value"
}