Skip to content

Commit

Permalink
Integrate PDP with OED as external authorization source (#474)
Browse files Browse the repository at this point in the history
* Integrate PDP with OED as external authorization source
#343
- Added new OedAuthzClient for integration with the oed-authz API
- Added new dependency to Altinn.ApiClients.Maskinporten v9.0.0
- Added new OedAuthzMaskinportenClientDefinition and Configuration
- Added new OedRoleAssignmentWrapper service
- Added new SBL bridge API client and service for getting SSN from UserId and PartyId

Other relevant changes:
- ContextHandler will now retrieve and evaluate policy for the App or Resource and evaluate the subjects of the rules. If any 'urn:altinn:rolecode' subjects are found Altinn roles will be retrieved. If any 'urn:oed:rolecode' subjects are found OED roles will be retrieved.

Additional PR made for studio-ops repo for both new (Maskinporten client config) and changes existing to configuration values (SBL bridge API path)

* Update for PR comments

* Added caching for getting the subjects from the policy

* NB!: This will change will fail until ABAC project is updated with the new helper on XacmlPolicy for getting attribute values by category.

- Changed some references from OED to Digitalt Dødsbo to match new naming
- Renamed "urn:oed:rolecode" attributeId to "urn:digitaltdodsbo:rolecode"
- Logic for extracting AttributeIds and Values reimplemented as a generic helper method on the XacmlPolicy object in ABAC project

* Fix datatype returned by XacmlPolicy

* Update ABAC package version to 0.0.6

* Marked OedRoleAssignmentWrapper excluded from codecoverage as integration tests rely on mock implementation

* removed quotes character from log statement

---------

Co-authored-by: Jon Kjetil Øye <[email protected]>
  • Loading branch information
jonkjetiloye and Jon Kjetil Øye authored Oct 3, 2023
1 parent 4581c94 commit b0839f1
Show file tree
Hide file tree
Showing 49 changed files with 1,658 additions and 18 deletions.
3 changes: 2 additions & 1 deletion src/Authorization/Altinn.Platform.Authorization.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Altinn.ApiClients.Maskinporten" Version="9.0.0" />
<PackageReference Include="Altinn.Common.AccessTokenClient" Version="1.1.4" />
<PackageReference Include="Altinn.Common.PEP" Version="1.3.0" />
<PackageReference Include="Altinn.Platform.Models" Version="1.2.0" />
Expand All @@ -15,7 +16,7 @@
<PackageReference Include="Azure.Storage.Blobs" Version="12.18.0" />
<PackageReference Include="Azure.Storage.Queues" Version="12.16.0" />
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.21.0" />
<PackageReference Include="Altinn.Authorization.ABAC" Version="0.0.5" />
<PackageReference Include="Altinn.Authorization.ABAC" Version="0.0.6" />
<PackageReference Include="Altinn.Platform.Storage.Interface" Version="3.24.0" />
<PackageReference Include="JWTCookieAuthentication" Version="3.0.1" />
<PackageReference Include="Microsoft.Azure.DocumentDB.Core" Version="2.20.0" />
Expand Down
47 changes: 47 additions & 0 deletions src/Authorization/Clients/OedAuthzClient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using Altinn.Platform.Authorization.Configuration;
using Microsoft.Extensions.Options;

namespace Altinn.Platform.Authorization.Clients
{
/// <summary>
/// Client configuration for Oed Authz API integration
/// </summary>
public class OedAuthzClient
{
/// <summary>
/// Gets an instance of httpclient from httpclientfactory
/// </summary>
public HttpClient Client { get; }

/// <summary>
/// Initializes the http client for retrieving Oed Authz role-assignments
/// </summary>
/// <param name="client">the http client</param>
/// <param name="settings">the general settings configured for the authorization component</param>
public OedAuthzClient(HttpClient client, IOptions<GeneralSettings> settings)
{
GeneralSettings generalSettings = settings.Value;
Client = client;
Client.BaseAddress = new Uri(generalSettings.OedAuthzApiEndpoint);
Client.DefaultRequestHeaders.Clear();
Client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
}

/// <summary>
/// post request that gets OED roleassignments
/// </summary>
/// <param name="requestBody">the request body</param>
/// <param name="token">the bearer token</param>
/// <returns>A <see cref="Task{TResult}"/> representing the result of the asynchronous operation.</returns>
public async Task<HttpResponseMessage> GetOedRoleAssignments(StringContent requestBody, AuthenticationHeaderValue token)
{
Client.DefaultRequestHeaders.Authorization = token;
string endpoint = Client.BaseAddress + "v1/pip";
return await Client.PostAsync(endpoint, requestBody);
}
}
}
36 changes: 36 additions & 0 deletions src/Authorization/Clients/OedAuthzMaskinportenClientDefinition.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using System;
using System.Text;
using System.Threading.Tasks;
using Altinn.ApiClients.Maskinporten.Interfaces;
using Altinn.ApiClients.Maskinporten.Models;
using Altinn.Platform.Authorization.Configuration;
using Microsoft.Extensions.Options;

namespace Altinn.Platform.Authorization.Clients
{
/// <summary>
/// Maskinporten client definition for OED Authz API integration
/// </summary>
public class OedAuthzMaskinportenClientDefinition : IClientDefinition
{
/// <inheritdoc/>
public IMaskinportenSettings ClientSettings { get; set; }

/// <summary>
/// Initializes a new instance of the <see cref="OedAuthzMaskinportenClientDefinition"/> class
/// </summary>
/// <param name="clientSettings">Maskinporten client settings</param>
public OedAuthzMaskinportenClientDefinition(IOptions<OedAuthzMaskinportenClientSettings> clientSettings) => ClientSettings = clientSettings.Value;

/// <inheritdoc/>
public Task<ClientSecrets> GetClientSecrets()
{
ClientSecrets clientSecrets = new ClientSecrets();

byte[] bytesFromBase64Jwk = Convert.FromBase64String(ClientSettings.EncodedJwk);
string jwkJson = Encoding.UTF8.GetString(bytesFromBase64Jwk);
clientSecrets.ClientKey = new Microsoft.IdentityModel.Tokens.JsonWebKey(jwkJson);
return Task.FromResult(clientSecrets);
}
}
}
34 changes: 34 additions & 0 deletions src/Authorization/Clients/ProfileClient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using Altinn.Platform.Authorization.Configuration;
using Microsoft.Extensions.Options;

namespace Altinn.Platform.Authorization.Clients
{
/// <summary>
/// Client configuration for profile api
/// </summary>
public class ProfileClient
{
/// <summary>
/// Gets an instance of httpclient from httpclientfactory
/// </summary>
public HttpClient Client { get; }

/// <summary>
/// Initializes the http client for actor
/// </summary>
/// <param name="client">the http client</param>
/// <param name="generalSettings">the general settings configured for the authorization component</param>
public ProfileClient(HttpClient client, IOptions<GeneralSettings> generalSettings)
{
GeneralSettings settings = generalSettings.Value;
Client = client;
Client.BaseAddress = new Uri(settings.GetBridgeApiEndpoint);
Client.Timeout = new TimeSpan(0, 0, 30);
Client.DefaultRequestHeaders.Clear();
Client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
}
}
}
5 changes: 5 additions & 0 deletions src/Authorization/Configuration/GeneralSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ public string GetBridgeApiEndpoint
/// </summary>
public string OpenIdWellKnownEndpoint { get; set; }

/// <summary>
/// Gets or sets the OED api endpoint
/// </summary>
public string OedAuthzApiEndpoint { get; set; }

/// <summary>
/// Gets the SBL base adress from kubernetes environment variables and appsettings if environment variable is not set
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
using Altinn.ApiClients.Maskinporten.Interfaces;

namespace Altinn.Platform.Authorization.Configuration
{
/// <summary>
/// Configuration for Maskinporten Client for Oed role-assignments API integration
/// </summary>
public class OedAuthzMaskinportenClientSettings : IMaskinportenSettings
{
/// <inheritdoc/>
public string Environment { get; set; }

/// <inheritdoc/>
public string ClientId { get; set; }

/// <inheritdoc/>
public string Scope { get; set; }

/// <inheritdoc/>
public string EncodedJwk { get; set; }

/// <inheritdoc/>
public string Resource { get; set; }

/// <inheritdoc/>
public string CertificatePkcs12Path { get; set; }

/// <inheritdoc/>
public string CertificatePkcs12Password { get; set; }

/// <inheritdoc/>
public string CertificateStoreThumbprint { get; set; }

/// <inheritdoc/>
public string EncodedX509 { get; set; }

/// <inheritdoc/>
public string ConsumerOrgNo { get; set; }

/// <inheritdoc/>
public string EnterpriseUserName { get; set; }

/// <inheritdoc/>
public string EnterpriseUserPassword { get; set; }

/// <inheritdoc/>
public bool? ExhangeToAltinnToken { get; set; }

/// <inheritdoc/>
public string TokenExchangeEnvironment { get; set; }

/// <inheritdoc/>
public bool? UseAltinnTestOrg { get; set; }

/// <inheritdoc/>
public bool? EnableDebugLogging { get; set; }

/// <inheritdoc/>
public bool? OverwriteAuthorizationHeader { get; set; }
}
}
5 changes: 5 additions & 0 deletions src/Authorization/Constants/AltinnXacmlConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,11 @@ public static class MatchAttributeIdentifiers
/// Role Code attribute match indentifier
/// </summary>
public const string RoleAttribute = "urn:altinn:rolecode";

/// <summary>
/// Digitalt Dødsbo Role Code Attribute match identifier
/// </summary>
public const string OedRoleAttribute = "urn:digitaltdodsbo:rolecode";
}

/// <summary>
Expand Down
5 changes: 5 additions & 0 deletions src/Authorization/Constants/XacmlRequestAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ public static class XacmlRequestAttribute
/// </summary>
public const string RoleAttribute = "urn:altinn:rolecode";

/// <summary>
/// Digitalt Dødsbo Role Code Attribute match identifier
/// </summary>
public const string OedRoleAttribute = "urn:digitaltdodsbo:rolecode";

/// <summary>
/// xacml string that represents resource
/// </summary>
Expand Down
2 changes: 1 addition & 1 deletion src/Authorization/Helpers/PolicyHelper.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Text;
Expand Down
32 changes: 32 additions & 0 deletions src/Authorization/Models/Oed/OedRoleAssignment.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using System;
using System.Text.Json.Serialization;

namespace Altinn.Platform.Authorization.Models.Oed
{
/// <summary>
/// Model for OED role assignment
/// </summary>
public class OedRoleAssignment
{
/// <summary>
/// The OED/Digitalt dødsbo role code
/// </summary>
[JsonPropertyName("urn:digitaltdodsbo:rolecode")]
public string OedRoleCode { get; set; }

/// <summary>
/// The deceased person's pid
/// </summary>
public string From { get; set; }

/// <summary>
/// The inheriting person's pid
/// </summary>
public string To { get; set; }

/// <summary>
/// The datetime created
/// </summary>
public DateTime Created { get; set; }
}
}
18 changes: 18 additions & 0 deletions src/Authorization/Models/Oed/OedRoleAssignmentRequest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
namespace Altinn.Platform.Authorization.Models
{
/// <summary>
/// Model for requesting OED/Digitalt dødsbo role assignments between two persons
/// </summary>
public class OedRoleAssignmentRequest
{
/// <summary>
/// The person the OED/Digitalt dødsbo role if provided from (the deceased)
/// </summary>
public string From { get; set; }

/// <summary>
/// The person the OED/Digitalt dødsbo role if provided to
/// </summary>
public string To { get; set; }
}
}
16 changes: 16 additions & 0 deletions src/Authorization/Models/Oed/OedRoleAssignments.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System.Collections.Generic;
using Altinn.Platform.Authorization.Models.Oed;

namespace Altinn.Platform.Authorization.Models
{
/// <summary>
/// Model for a list of OED/Digitalt dødsbo role assignment
/// </summary>
public class OedRoleAssignments
{
/// <summary>
/// The list of OED/Digitalt dødsbo role assignments
/// </summary>
public List<OedRoleAssignment> RoleAssignments { get; set; }
}
}
13 changes: 12 additions & 1 deletion src/Authorization/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
using System.IO;
using System.Reflection;
using System.Threading.Tasks;

using Altinn.ApiClients.Maskinporten.Config;
using Altinn.ApiClients.Maskinporten.Extensions;
using Altinn.ApiClients.Maskinporten.Interfaces;
using Altinn.ApiClients.Maskinporten.Services;
using Altinn.Authorization.ABAC.Interface;
using Altinn.Common.AccessTokenClient.Services;
using Altinn.Common.PEP.Authorization;
Expand Down Expand Up @@ -196,7 +199,9 @@ void ConfigureServices(IServiceCollection services, IConfiguration config)
services.AddHealthChecks().AddCheck<HealthCheck>("authorization_health_check");
services.AddSingleton(config);
services.AddSingleton<IParties, PartiesWrapper>();
services.AddSingleton<IProfile, ProfileWrapper>();
services.AddSingleton<IRoles, RolesWrapper>();
services.AddSingleton<IOedRoleAssignmentWrapper, OedRoleAssignmentWrapper>();
services.AddSingleton<IContextHandler, ContextHandler>();
services.AddSingleton<IDelegationContextHandler, DelegationContextHandler>();
services.AddSingleton<IPolicyRetrievalPoint, PolicyRetrievalPoint>();
Expand All @@ -208,16 +213,22 @@ void ConfigureServices(IServiceCollection services, IConfiguration config)
services.AddSingleton<IDelegationMetadataRepository, DelegationMetadataRepository>();
services.AddSingleton<IDelegationChangeEventQueue, DelegationChangeEventQueue>();
services.AddSingleton<IEventMapperService, EventMapperService>();

services.Configure<GeneralSettings>(config.GetSection("GeneralSettings"));
services.Configure<AzureStorageConfiguration>(config.GetSection("AzureStorageConfiguration"));
services.Configure<AzureCosmosSettings>(config.GetSection("AzureCosmosSettings"));
services.Configure<PostgreSQLSettings>(config.GetSection("PostgreSQLSettings"));
services.Configure<PlatformSettings>(config.GetSection("PlatformSettings"));
OedAuthzMaskinportenClientSettings oedAuthzMaskinportenClientSettings = config.GetSection("OedAuthzMaskinportenClientSettings").Get<OedAuthzMaskinportenClientSettings>();
services.Configure<OedAuthzMaskinportenClientSettings>(config.GetSection("OedAuthzMaskinportenClientSettings"));
services.AddMaskinportenHttpClient<SettingsJwkClientDefinition, OedAuthzMaskinportenClientDefinition>(oedAuthzMaskinportenClientSettings);
services.AddHttpClient<IRegisterService, RegisterService>();
services.AddHttpClient<PartyClient>();
services.AddHttpClient<ProfileClient>();
services.AddHttpClient<RolesClient>();
services.AddHttpClient<SBLClient>();
services.AddHttpClient<ResourceRegistryClient>();
services.AddHttpClient<OedAuthzClient>();
services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddSingleton<IAccessTokenGenerator, AccessTokenGenerator>();
services.AddTransient<ISigningCredentialsResolver, SigningCredentialsResolver>();
Expand Down
Loading

0 comments on commit b0839f1

Please sign in to comment.