Skip to content

Commit

Permalink
Merge branch 'master' into options-rewrite
Browse files Browse the repository at this point in the history
  • Loading branch information
Ole Martin Handeland committed Dec 16, 2024
2 parents f5676f1 + dee788f commit b288960
Show file tree
Hide file tree
Showing 96 changed files with 4,706 additions and 578 deletions.
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,6 @@
"workbench.editor.customLabels.patterns": {
"content/**/*index.*md": "${dirname}/${filename}.${extname}"

}
},
"cSpell.language": "en,nb"
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,138 +10,102 @@ aliases:

---

This is a guide on how to set up an Altinn application to create a client that utilizes a Maskinporten integration for
its requests. This is a use case that is relevant when the application are going to perform requests that needs to
be authorized on behalf of the organization owning the application and not the end user owning the instance. By nature,
these requests will have credentials from the private user who logged in to the application and created the new
instance. In order to send these requests on behalf of the organization the following must be done;

1. Ensure organization has access to Azure key vault
2. Create the integration to Maskinporten
at [Samarbeidsportalen](https://samarbeid.digdir.no/)
3. Store the keys from the integration in Azure key vault for
the organisation
4. Set up the application to use the Maskinporten client by retrieving the secrets/keys from Azure key vault.
This guide details how to set up an Altinn application with a HTTP client that utilizes Maskinporten authentication for
its requests. This is useful when the application needs to perform authorized requests on behalf of the app owner,
as opposed to the active user.

In order to set this up, the following must be done:

1. Ensure organization has access to Azure Key Vault.
2. Create the integration to Maskinporten at [Samarbeidsportalen](https://samarbeid.digdir.no/).
3. Store the authentication key for the integration in Azure Key Vault.
4. Set up the application to use the Maskinporten client and retrieve secrets from Azure Key Vault.

## Azure Key Vault Access
Before going forward in this guide, make sure you have access
to Azure key vault for your organization, so the keys
created further on in the guide can be added directly into
the secrets in Azure.
Before proceeding with this guide, make sure you have access to Azure Key Vault for your organization.
This ensures that the keys created further on in the guide can be stored properly as secrets in Azure.

If access is missing, please refer to [Access to logs and secrets](/altinn-studio/guides/administration/access-management/apps).

## Maskinporten Integration

In this section the Maskinporten client will be set up. A part of setting up the client includes creating keys that
should be stored in Azure Key vault later on in the guide. If different people in the organization have access to
In this section we will set up the Maskinporten client. A part of setting up the client includes creating keys that
should be stored in Azure Key Vault later on in the guide. If different people in the organization have access to
different resources needed in this process, please cooperate and do the following steps on the same machine. This is
recommended to avoid sending secrets between machines.

When access to creating secrets in Azure key vault is
confirmed, please proceed to create the integration.
When access to creating secrets in Azure Key Vault is confirmed, please proceed to create the integration.

{{% expandlarge id="guide-mp-int-samarbeid" header="Guide on how to register a new Maskinporten integration in Samarbeidsportalen" %}}

{{% insert "content/altinn-studio/guides/shared/maskinporten-integration/maskinporten-integration-samarbeidsportal.md" %}}
{{% insert "/content/altinn-studio/guides/shared/maskinporten-integration/maskinporten-integration-samarbeidsportal.md" %}}
{{% /expandlarge %}}

## Azure Key Vault Configuration

When preparing the application to use the secrets from Azure Key vault, there are some steps that needs to be done:
When preparing the application to use secrets from Azure Key Vault, there are some steps that need to be done:

1. Add the secrets retrieved during the Maskinporten client configuration to Azure Key vault:
1. Add the secrets retrieved during the Maskinporten client configuration to Azure Key Vault:
- The base64 encoded JWT public and private key pair
- The clientID for the integration
- The client ID for the integration

It is important that the name of these secrets in Azure key vault corresponds
with the name of the section in the appsettings file in the
application repository. E.g. if your appsettings section for
the Maskinporten integration section looks like this:
It is important that the name of these secrets in Azure Key Vault corresponds with the name of the section in the
appsettings file in the application repository. E.g. if your appsettings section for the Maskinporten integration section looks like this:

```json
{
"MaskinportenSettings": {
"MaskinportenSettings": {
"Environment": "test",
"ClientId": "",
"Scope": "altinn:serviceowner/instances.read",
"EncodedJwk": "",
"ExhangeToAltinnToken": true,
"EnableDebugLog": true
}
}
}
```

The secrets in Azure key vault should have names like this:

The secrets in Azure Key Vault should have names like this:
```
MaskinportenSettings--ClientId
MaskinportenSettings--EncodedJwk
```
2. For the application to be able to read the secrets from
Azure key vault the application need to be configured to
do so. See
the [secrets section](../../../reference/configuration/secrets)
to achieve this.
3. Add the appsettings section example
from above into the `appsettings.{env}.json` file.

_NB: The secrets are read by the application on start up so
if changing the secrets after the application is deployed, you
will need to redeploy the application._
2. For the application to be able to read the secrets from Azure Key Vault, it needs to be configured to do so.
See the [secrets section](../../../reference/configuration/secrets) to achieve this.
3. Add the appsettings section example from above into the `appsettings.{env}.json` file.

## Setup Application to use Maskinporten Integration
_Note: The secrets are read by the application on launch so
if you make changes after the application is deployed, you
will need to redeploy the application for them to come into effect._

When modifying the application to use the Maskinporten integration, we need to adapt the `Program.cs` file.
## Setup Application to use Maskinporten Integration

First of all we need to add the MaskinportenHttpClient
service with the appropriate configuration in the function `RegisterCustomAppServices`:
When modifying the application to use the Maskinporten integration, we need to make some changes to the `Program.cs` file.

```csharp
services.AddMaskinportenHttpClient<SettingsJwkClientDefinition, AppClient>(config.GetSection("MaskinportenSettings"));
```
First we need to add the MaskinportenHttpClient service with the appropriate configuration in the `RegisterCustomAppServices` method:

Then we need to add the Azure Key Vault configuration provider to our host.
Start by adding these package references in the project file (`App.csproj`) - get the latest version from NuGet.org:
{{< highlight csharp "linenos=false,hl_lines=5" >}}
void RegisterCustomAppServices(IServiceCollection services, IConfiguration config, IWebHostEnvironment env)
{
// ...

{{< highlight csproj "linenos=false" >}}
<PackageReference Include="Azure.Extensions.AspNetCore.Configuration.Secrets" Version="1.3.1" />
<PackageReference Include="Azure.Identity" Version="1.11.4" />
services.AddMaskinportenHttpClient<SettingsJwkClientDefinition, YourCustomClient>(config.GetSection("MaskinportenSettings"));
}
{{< / highlight >}}

Then we can complete the configuration by adding the Azure Key Vault configuration provider:

{{< highlight csharp "linenos=false,hl_lines=1 8-30" >}}
using Azure.Identity;

// ...
Then we need to add the Azure Key Vault configuration provider to our host. This is done by modifying the `ConfigureWebHostBuilder` method:

{{< highlight csharp "linenos=false,hl_lines=5-9" >}}
void ConfigureWebHostBuilder(IWebHostBuilder builder)
{
builder.ConfigureAppWebHost(args);
builder.ConfigureAppConfiguration(
(context, configuration) =>
{
var section = context.Configuration.GetSection("kvSetting");
var keyVaultUri = section.GetValue<string>("SecretUri");
var clientId = section.GetValue<string>("ClientId");
var clientSecret = section.GetValue<string>("ClientSecret");
var tenantId = section.GetValue<string>("TenantId");

if (
string.IsNullOrWhiteSpace(keyVaultUri)
|| string.IsNullOrWhiteSpace(clientId)
|| string.IsNullOrWhiteSpace(clientSecret)
|| string.IsNullOrWhiteSpace(tenantId)
)
return;

configuration.AddAzureKeyVault(
new Uri(keyVaultUri),
new ClientSecretCredential(tenantId, clientId, clientSecret)
);
}
);

// Add Azure KV provider for TT02 & Prod environments
if (!builder.Environment.IsDevelopment())
{
builder.AddAzureKeyVaultAsConfigProvider();
}
}
{{< / highlight >}}

Original file line number Diff line number Diff line change
Expand Up @@ -10,57 +10,51 @@ aliases:

---

Dette er en guide om hvordan du setter opp en Altinn-applikasjon for å opprette en klient som bruker en
Maskinporten-integrasjon for
sine forespørsler. Dette er relevant når applikasjonen skal utføre forespørsler som må
autentiseres på vegne av organisasjonen som eier applikasjonen, og ikke sluttbrukeren som eier instansen. Av naturen,
vil disse forespørslene ha legitimasjon fra den private brukeren som logget på applikasjonen og opprettet den nye
instansen. For å sende disse forespørslene på vegne av organisasjonen, må følgende gjøres;

1. Forsikre deg om at organisasjonen har tilgang til Azure Key Vault.
2. Opprett integrasjonen til Maskinporten
[Samarbeidsportalen](https://samarbeid.digdir.no/).
3. Lagre nøklene fra integrasjonen i Azure Key Vault for
organisasjonen.
4. Sett opp applikasjonen til å bruke Maskinporten-klienten ved å hente hemmelighetene/nøklene fra Azure Key Vault.
Denne veiledningen viser hvordan du setter opp en Altinn-applikasjon med en HTTP-klient som benytter Maskinporten for
autentisering av forespørslene. Dette er nyttig når applikasjonen må utføre autoriserte forespørsler på vegne av eieren
av applikasjonen, i stedet for den aktive brukeren.

For å sette dette opp, må følgende gjøres:

1. Sørg for at organisasjonen har tilgang til Azure Key Vault.
2. Opprett integrasjonen mot Maskinporten i [Samarbeidsportalen](https://samarbeid.digdir.no/).
3. Lagre autentiseringsnøkkelen for integrasjonen i Azure Key Vault.
4. Konfigurer applikasjonen til å bruke Maskinporten-klienten og hente hemmeligheter fra Azure Key Vault.

## Tilgang til Azure Key Vault

Før du går videre i denne guiden, må du sørge for at du har tilgang
til Azure Key Vault for organisasjonen din, slik at nøklene
som opprettes senere i guiden, kan legges direkte inn i
hemmelighetene i Azure.
Før du går videre med denne veiledningen, må du forsikre deg om at du har tilgang til Azure Key Vault for organisasjonen din.
Dette sikrer at nøklene som opprettes senere i veiledningen kan lagres riktig som hemmeligheter i Azure.

Hvis tilgang mangler, se [Tilgang til logger og hemmeligheter](/nb/altinn-studio/guides/administration/access-management/apps).

## Maskinporten-integrasjon

I denne delen blir Maskinporten-klienten satt opp. En del av oppsettet av klienten inkluderer opprettelse av nøkler som
skal lagres i Azure Key Vault senere i guiden. Hvis ulike personer i organisasjonen har tilgang til
forskjellige ressurser som trengs i denne prosessen, samarbeid og gjør de følgende trinnene på samme maskin. Dette er
anbefalt for å unngå å sende hemmeligheter mellom maskiner.
I denne delen skal vi sette opp Maskinporten-klienten. En del av oppsettet inkluderer opprettelse av nøkler som senere
skal lagres i Azure Key Vault. Hvis ulike personer i organisasjonen har tilgang til forskjellige ressurser som trengs i
denne prosessen, anbefales det å samarbeide og utføre disse trinnene på samme maskin. Dette er for å unngå å sende
hemmeligheter mellom maskiner.

Når tilgang til å opprette hemmeligheter i Azure Key Vault er bekreftet, kan du fortsette med å opprette integrasjonen.

{{% expandlarge id="guide-mp-int-samarbeid" header="Guide om hvordan du registrerer en ny Maskinporten-integrasjon i Samarbeidsportalen" %}}
{{% expandlarge id="guide-mp-int-samarbeid" header="Veiledning om hvordan du registrerer en ny Maskinporten-integrasjon i Samarbeidsportalen" %}}

{{% insert "content/altinn-studio/guides/shared/maskinporten-integration/maskinporten-integration-samarbeidsportal.md" %}}
{{% insert "/content/altinn-studio/guides/shared/maskinporten-integration/maskinporten-integration-samarbeidsportal.md" %}}

{{% /expandlarge %}}

## Konfigurasjon av Azure Key Vault

Når applikasjonen forberedes å bruke hemmelighetene fra Azure Key Vault, er det noen trinn som må gjøres:
Når applikasjonen forberedes til å bruke hemmeligheter fra Azure Key Vault, må følgende trinn utføres:

1. Legg til hemmelighetene hentet under konfigurasjonen av Maskinporten-klienten i Azure Key Vault:
1. Legg til hemmelighetene som ble hentet under konfigurasjon av Maskinporten-klienten, i Azure Key Vault:
- Base64-kodet JWT offentlig og privat nøkkelpar
- Klient-ID for integrasjonen

Det er viktig at navnet på disse hemmelighetene i Azure Key Vault samsvarer
med navnet på seksjonen i appsettings-filen i
applikasjonsrepositoryet. For eksempel, hvis appsettings-seksjonen for
Maskinporten-integrasjonen ser slik ut:
Det er viktig at navnet på disse hemmelighetene i Azure Key Vault tilsvarer navnet på seksjonen i appsettings-filen i
kodebasen til applikasjonen.

For eksempel, hvis seksjonen for Maskinporten-integrasjonen ser slik ut:
```json
{
"MaskinportenSettings": {
Expand All @@ -74,76 +68,46 @@ Når applikasjonen forberedes på å bruke hemmelighetene fra Azure Key Vault, e
}
```

Hemmelighetene i Azure Key Vault burde ha navn som dette:
Må hemmelighetene i Azure Key Vault ha navn som dette:

```
MaskinportenSettings--ClientId
MaskinportenSettings--EncodedJwk
```

2. For at applikasjonen skal kunne lese hemmelighetene fra
Azure Key Vault, må applikasjonen konfigureres til
å gjøre dette. Se
[seksjoner om hemmeligheter](../../../reference/configuration/secrets)
for å oppnå dette.
3. Legg til eksempel på appsettings-seksjonen
ovenfor i `appsettings.{env}.json`-filen.
2. For at applikasjonen skal kunne lese hemmelighetene fra Azure Key Vault, må konfigureres først.
Se [seksjoner om hemmeligheter](../../../reference/configuration/secrets) for hvordan dette oppnås.
3. Legg til appsettings-eksempelet ovenfor i `appsettings.{env}.json`-filen.

_NB: Hemmelighetene leses av applikasjonen ved oppstart, så
hvis du endrer hemmelighetene etter at applikasjonen er publisert, må du
deploye applikasjonen på nytt._
publisere applikasjonen på nytt før endringene trer i kraft._

## Sett opp applikasjonen til å bruke Maskinporten-integrasjonen

Når du endrer applikasjonen for å bruke Maskinporten-integrasjonen, må vi tilpasse filen `Program.cs`.
Når applikasjonen skal tilpasses for å bruke Maskinporten-integrasjonen, må vi gjøre noen endringer i `Program.cs`-filen.

For det første må vi legge til tjenesten MaskinportenHttpClient
med riktig konfigurasjon i funksjonen `RegisterCustomAppServices`:
Først må vi legge til MaskinportenHttpClient-tjenesten med riktig konfigurasjon i metoden `RegisterCustomAppServices`:

```csharp
services.AddMaskinportenHttpClient<SettingsJwkClientDefinition, AppClient>(config.GetSection("MaskinportenSettings"));
```

Deretter må vi legge til Azure Key Vault sin configuration provider til koden vår.
Da trenger vi disse pakkereferansene i prosjektfila (`App.csproj`) - husk å velge siste versjoner fra NuGet.org:
{{< highlight csharp "linenos=false,hl_lines=5" >}}
void RegisterCustomAppServices(IServiceCollection services, IConfiguration config, IWebHostEnvironment env)
{
// ...

{{< highlight csproj "linenos=false" >}}
<PackageReference Include="Azure.Extensions.AspNetCore.Configuration.Secrets" Version="1.3.1" />
<PackageReference Include="Azure.Identity" Version="1.11.4" />
services.AddMaskinportenHttpClient<SettingsJwkClientDefinition, YourCustomClient>(config.GetSection("MaskinportenSettings"));
}
{{< / highlight >}}

Så kan vi konfigurere opp Azure Key Vault configuration provider:

{{< highlight csharp "linenos=false,hl_lines=1 8-30" >}}
using Azure.Identity;

// ...
Deretter må vi legge til Azure Key Vault som konfigurasjonsleverandør til vår host. Dette gjøres ved å endre metoden `ConfigureWebHostBuilder`:

{{< highlight csharp "linenos=false,hl_lines=5-9" >}}
void ConfigureWebHostBuilder(IWebHostBuilder builder)
{
builder.ConfigureAppWebHost(args);
builder.ConfigureAppConfiguration(
(context, configuration) =>
{
var section = context.Configuration.GetSection("kvSetting");
var keyVaultUri = section.GetValue<string>("SecretUri");
var clientId = section.GetValue<string>("ClientId");
var clientSecret = section.GetValue<string>("ClientSecret");
var tenantId = section.GetValue<string>("TenantId");

if (
string.IsNullOrWhiteSpace(keyVaultUri)
|| string.IsNullOrWhiteSpace(clientId)
|| string.IsNullOrWhiteSpace(clientSecret)
|| string.IsNullOrWhiteSpace(tenantId)
)
return;

configuration.AddAzureKeyVault(
new Uri(keyVaultUri),
new ClientSecretCredential(tenantId, clientId, clientSecret)
);
}
);

// Add Azure KV provider for TT02 & Prod environments
if (!builder.Environment.IsDevelopment())
{
builder.AddAzureKeyVaultAsConfigProvider();
}
}
{{< / highlight >}}
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ To avoid spreading the business certificate across many systems,
we opt for creating an asymmetric key (JSON Web Key) and associate it to the newly created integration.
In this example we use [mkjwk.org](https://mkjwk.org/).

- Navigate to `mkjwk.org` in a browser
- Navigate to [mkjwk.org](https://mkjwk.org/) in a browser

- Fill in values like the example below and click _Generate_

Expand Down
Loading

0 comments on commit b288960

Please sign in to comment.