Sist endret: 13. des. 2024

Secrets

How to deal with secrets and sensitive data in an app.

Administrasjon av hemmeligheter i Azure

Som applikasjonsutvikler administrerer man selv hemmelighetene som applikasjonen benytter i Azure Key Vault.

Rutiner for bestilling av tilgang til din organisasjons ressurser er beskrevet her.

Konfigurer støtte for hemmeligheter i din app

For å tilgjengeliggjøre hemmeligheter i applikasjonen må det gjøres oppdateringer i helm charten tilknyttet applikasjonen.

I applikasjonsrepoet ditt finner du filen values.yaml i mappen deployment.

Under seksjonen volumeMounts legger du til følgende linjer:

- name: altinn-appsettings-secret
  mountPath: "/altinn-appsettings-secret"

Under seksjonen volumes legger du til følgende linjer:

- name: altinn-appsettings-secret
    secret:
      secretName: altinn-appsettings-secret
Vær påpasselig med innrykk når du jobber i values.yaml. I yaml skal indents være mellomrom og ikke tab, benytter du tab vil ikke din yaml være gyldig.

Siste del av filen skal se omtrent slik ut når du har gjort ferdig alle endringer.

Steg 1

Hvordan benytte hemmeligheter i applikasjonen

Man kan enten legge til Azure Key Vault som en config provider og benytte IOptions-pattern for å lese ut hemmeligheter, eller så kan man benytte servicen ISecretsClient er eksponert i applikasjonen og kan dependency injectes i den klassen der du har behov for å hente ut en hemmelighet.

1. Azure Key Vault som config provider (anbefalt)

Om denne fremgangsmåten velges kan man bruke Azure Key Vault på standard måte via IOptions-pattern.

I namespace Altinn.App.Api.Extensions finnes det en hjelpemetode til dette formålet:

IHostApplicationBuilder.AddAzureKeyVaultAsConfigProvider()

Denne metoden kan brukes i Program.cs på følgende måte:

void ConfigureWebHostBuilder(IWebHostBuilder builder)
{
    builder.ConfigureAppWebHost(args);

    // Add Azure KV provider for TT02 & Prod environments
    if (!builder.Environment.IsDevelopment())
    {
        builder.AddAzureKeyVaultAsConfigProvider();
    }
}
Kall til AddAzureKeyVaultAsConfigProvider må skje etter metoden ConfigureAppWebHost har kjørt, hvis ikke vil oppstart feile.

Lokal mocking kan gjøres ved hjelp av user secrets:

dotnet user-secrets init
dotnet user-secrets set "NetsPaymentSettings:SecretApiKey" "test-secret-key-used-for-documentation"

2. Bruk av ISecretsClient

Dersom man ikke ønsker å legge til Azure Key Vault som config provider så kan man alternativt benytte tjenesten ISecretsClient, som er en wrapper rundt uthenging av hemmeligheter fra Azure Key Vault. Her tilbys metoder for å hente ut en og en hemmelighet der de trengs.

Kodeeksempel

I denne seksjonen finner du et eksempel på hvordan man benytter en hemmelighet til å populere et skjemafelt under instansiering.

Logikken er implementert i 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;
    }
}
  1. Den private variabelen for servicen inkluderes i klassen
    private ISecretsClient _secretsClient;
    
  2. ISecretsClient servicen dependency injectes inn i klassen. Og den private variabelen blir assignet en verdi.
    public InstantiationHandler(IProfile profileService, IRegister registerService, ISecretsClient secretsClient)
    {
        _profileService = profileService;
        _registerService = registerService;
        _secretsClient = secretsClient;
    }
    
  3. I metoden der man har behov for hemmeligheten kaller man på servicen. secretId vil være navnet på hemmeligheten i Key Vault (evt. i lokal mock).
    await _secretsClient_.GetSecretAsync("secretId");
    

Lokal mock

For å kunne kjøre tjenesten din lokalt uten å koble seg til Azure Key vault må man opprette filen secrets.json under mappen App. I Json strukturen kan man legge inn dummydata for hemmelighetene man har behov for. Har man lastet opp en hemmelighet i Key Vault med navnet “secretId” vil innholdet i json-filen se slik ut

{
  "secretId": "local secret dummy data"
}