Skip to content

Commit dee51f1

Browse files
authored
Merge pull request #1279 from ITfoxtec/test
Test
2 parents c3be742 + 69ba51d commit dee51f1

22 files changed

+219
-154
lines changed

.github/workflows/ci_test_docker.yaml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,17 @@ jobs:
3333
uses: docker/[email protected]
3434
with:
3535
images: ${{ secrets.DOCKERHUB_ORG }}/foxids
36-
tags: |
36+
tags: |
37+
type=raw,value=${{ steps.get-version.outputs.version }}-test
3738
type=raw,value=latest-test,enable=true
3839
3940
- name: Docker meta
4041
id: meta-fc
4142
uses: docker/[email protected]
4243
with:
4344
images: ${{ secrets.DOCKERHUB_ORG }}/foxids-control
44-
tags: |
45+
tags: |
46+
type=raw,value=${{ steps.get-version.outputs.version }}-test
4547
type=raw,value=latest-test,enable=true
4648
4749
- name: Login to Docker Hub

Kubernetes/k8s-foxids-ingress-deployment.yaml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@ kind: Ingress
33
metadata:
44
name: foxids-ingress-http
55
annotations:
6-
#Rate Limiting
7-
#nginx.ingress.kubernetes.io/limit-connections: "20"
8-
#nginx.ingress.kubernetes.io/limit-rpm: "300"
9-
#nginx.ingress.kubernetes.io/limit-rps: "10"
10-
#nginx.ingress.kubernetes.io/limit-whitelist: "xxx.xxx.xxx.xxx" # your IP Address
6+
# Rate Limiting, docs https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#rate-limiting
7+
#nginx.ingress.kubernetes.io/limit-whitelist: "x.x.x.x/x" # Configure the internal network to be excluded from rate-limiting, you can specify a list of IPs or CIDRs to allow
8+
#nginx.ingress.kubernetes.io/limit-connections: "20" # Limit the number of connections per IP address
9+
#nginx.ingress.kubernetes.io/limit-rpm: "300" # Limit the number of requests per minute per IP address
10+
#nginx.ingress.kubernetes.io/limit-rps: "10" # Limit the number of requests per second per IP address
1111
#Buffer
1212
nginx.ingress.kubernetes.io/proxy-buffers-number: "4"
1313
nginx.ingress.kubernetes.io/proxy-buffer-size: "32k"

docs/external-password-api.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# External Password - API
1+
# External Password API
22

33
Use an external password API when you need FoxIDs to (a) delegate password validation to an existing password store or policy engine, (b) notify an external system about password changes performed in FoxIDs, or (c) handle both scenarios.
44

@@ -11,7 +11,7 @@ If the built-in password policy rejects the password, the external password API
1111
If you require both validation and change notification, and both can be handled by the same system, implement only the validation API.
1212
When you receive a validation request where the password is accepted, perform your notification logic internally. Implement both endpoints only if you must call two different backend systems.
1313

14-
External password APIs are part of the possible password checks for [internal users](users-internal.md).
14+
External password API can be [configured as password check](users-internal.md#password-check) for [internal users](users-internal.md).
1515

1616
## Implement API
1717

docs/users-external.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# External users
2-
An external user is linked to one authentication method and can only be authenticated with that particular authentication method. External users can be linked to the authentication methods: OpenID Connect, SAML 2.0, External Login and Environment Link.
3-
It is optional to use external users; they are not created by default.
2+
You can use just-in-time (JIT) provisioning to create external users and associate them with an external identity.
3+
An external user is associated with one authentication method (OpenID Connect, SAML 2.0, External Login, or Environment Link) and can only be authenticated using that authentication method.
4+
Using external users is optional; they are not created by default.
45

56
All external users grouped under an authentication method are linked with the same claim type (e.g. the `sub` claim type) and the users are separated by unique claim values.
67

src/FoxIDs.Control/FoxIDs.Control.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
<PropertyGroup>
44
<TargetFramework>net9.0</TargetFramework>
5-
<Version>2.2.2</Version>
5+
<Version>2.3.6</Version>
66
<RootNamespace>FoxIDs</RootNamespace>
77
<Authors>Anders Revsgaard</Authors>
88
<Company>FoxIDs</Company>

src/FoxIDs.Control/Infrastructure/Hosting/FoxIDsClientRouteBindingMiddleware.cs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
using FoxIDs.Logic;
2-
using FoxIDs.Logic.Seed;
32
using FoxIDs.Models;
43
using Microsoft.AspNetCore.Http;
5-
using Microsoft.Extensions.DependencyInjection;
64
using System;
75
using System.Threading.Tasks;
86

@@ -18,8 +16,6 @@ protected override bool CheckCustomDomainSupport(string[] route)
1816
throw new NotSupportedException("Host in header not supported in Control Client.");
1917
}
2018

21-
protected override async ValueTask SeedAsync(IServiceProvider requestServices) => await requestServices.GetService<SeedLogic>().SeedAsync();
22-
2319
protected override ValueTask<bool> PreAsync(HttpContext httpContext, string[] route)
2420
{
2521
if (route.Length == 0)
@@ -52,4 +48,4 @@ protected override Track.IdKey GetTrackIdKey(string[] route, bool useCustomDomai
5248
}
5349
}
5450
}
55-
}
51+
}

src/FoxIDs.Control/Infrastructure/Hosting/ServiceCollectionExtensions.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ public static IServiceCollection AddLogic(this IServiceCollection services, FoxI
4040

4141
services.AddTransient<SendEventEmailLogic>();
4242
services.AddTransient<SeedLogic>();
43+
4344
services.AddTransient<MasterTenantDocumentsSeedLogic>();
4445
services.AddTransient<MainTenantDocumentsSeedLogic>();
4546

Lines changed: 74 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,67 +1,113 @@
11
using FoxIDs.Infrastructure;
22
using FoxIDs.Models.Config;
3+
using Microsoft.AspNetCore.DataProtection;
34
using Microsoft.AspNetCore.Http;
5+
using Microsoft.Extensions.DependencyInjection;
46
using System;
5-
using System.Threading.Tasks;
67
using System.Threading;
8+
using System.Threading.Tasks;
79

810
namespace FoxIDs.Logic.Seed
911
{
1012
public class SeedLogic : LogicBase
1113
{
12-
private static SemaphoreSlim signal = new SemaphoreSlim(1, 1);
13-
private static bool isSeeded = false;
1414
private readonly TelemetryLogger logger;
15+
private readonly IServiceProvider serviceProvider;
1516
private readonly FoxIDsControlSettings settings;
1617
private readonly MasterTenantDocumentsSeedLogic masterTenantDocumentsSeedLogic;
1718
private readonly MainTenantDocumentsSeedLogic mainTenantDocumentsSeedLogic;
1819

19-
public SeedLogic(TelemetryLogger logger, FoxIDsControlSettings settings, MasterTenantDocumentsSeedLogic masterTenantDocumentsSeedLogic, MainTenantDocumentsSeedLogic mainTenantDocumentsSeedLogic, IHttpContextAccessor httpContextAccessor) : base(httpContextAccessor)
20+
public SeedLogic(TelemetryLogger logger, IServiceProvider serviceProvider, FoxIDsControlSettings settings, MasterTenantDocumentsSeedLogic masterTenantDocumentsSeedLogic, MainTenantDocumentsSeedLogic mainTenantDocumentsSeedLogic, IHttpContextAccessor httpContextAccessor) : base(httpContextAccessor)
2021
{
2122
this.logger = logger;
23+
this.serviceProvider = serviceProvider;
2224
this.settings = settings;
2325
this.masterTenantDocumentsSeedLogic = masterTenantDocumentsSeedLogic;
2426
this.mainTenantDocumentsSeedLogic = mainTenantDocumentsSeedLogic;
2527
}
2628

27-
public async Task SeedAsync()
29+
public async Task SeedAsync(CancellationToken cancellationToken = default)
30+
{
31+
try
32+
{
33+
await SeedLogAsync(cancellationToken);
34+
DataProtectionCheck();
35+
await SeedDbAsync();
36+
}
37+
catch (OperationCanceledException)
38+
{
39+
throw;
40+
}
41+
catch (ObjectDisposedException)
42+
{
43+
throw;
44+
}
45+
catch (Exception ex)
46+
{
47+
logger.CriticalError(ex);
48+
throw;
49+
}
50+
}
51+
52+
private async Task SeedLogAsync(CancellationToken cancellationToken)
53+
{
54+
if (settings.Options?.Log == LogOptions.OpenSearchAndStdoutErrors)
55+
{
56+
try
57+
{
58+
var openSearchTelemetryLogger = serviceProvider.GetService<OpenSearchTelemetryLogger>();
59+
if (await openSearchTelemetryLogger.SeedAsync(cancellationToken))
60+
{
61+
logger.Trace("OpenSearch log storage seeded on startup.");
62+
}
63+
}
64+
catch (Exception oex)
65+
{
66+
throw new Exception("Error seeding OpenSearch log storage on startup.", oex);
67+
}
68+
}
69+
}
70+
71+
private void DataProtectionCheck()
2872
{
29-
if (isSeeded)
73+
if (!(settings.Options.DataStorage == DataStorageOptions.CosmosDb && settings.Options.Cache == CacheOptions.Redis))
3074
{
31-
return;
75+
try
76+
{
77+
var dataProtection = serviceProvider.GetService<IDataProtectionProvider>();
78+
_ = dataProtection.CreateProtector("seed check protector").Protect("seed check protect data");
79+
}
80+
catch (Exception oex)
81+
{
82+
throw new Exception("Error checking data protection on startup.", oex);
83+
}
3284
}
33-
await signal.WaitAsync();
85+
}
86+
87+
private async Task SeedDbAsync()
88+
{
3489
try
3590
{
36-
if (!isSeeded)
91+
if (settings.MasterSeedEnabled)
3792
{
38-
isSeeded = true;
39-
if (settings.MasterSeedEnabled)
93+
if (await masterTenantDocumentsSeedLogic.SeedAsync())
4094
{
41-
if (await masterTenantDocumentsSeedLogic.SeedAsync())
42-
{
43-
logger.Trace("Document container(s) seeded with master tenant.");
44-
}
95+
logger.Trace("Document container(s) seeded with master tenant on startup.");
96+
}
4597

46-
if (settings.MainTenantSeedEnabled)
98+
if (settings.MainTenantSeedEnabled)
99+
{
100+
if (await mainTenantDocumentsSeedLogic.SeedAsync())
47101
{
48-
if (await mainTenantDocumentsSeedLogic.SeedAsync())
49-
{
50-
logger.Trace("Document container(s) seeded with main tenant.");
51-
}
102+
logger.Trace("Document container(s) seeded with main tenant on startup.");
52103
}
53104
}
54105
}
55106
}
56-
catch (Exception ex)
57-
{
58-
logger.CriticalError(ex, "Error seeding master documents.");
59-
throw;
60-
}
61-
finally
107+
catch (Exception maex)
62108
{
63-
signal.Release(1);
109+
throw new Exception("Error seeding master documents on startup.", maex);
64110
}
65111
}
66112
}
67-
}
113+
}

src/FoxIDs.Control/Program.cs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,24 @@
77
using Microsoft.Extensions.Logging;
88
using Microsoft.Extensions.DependencyInjection;
99
using System;
10+
using FoxIDs.Logic.Seed;
11+
using System.Threading.Tasks;
12+
using System.Threading;
1013

1114
namespace FoxIDs
1215
{
1316
public class Program
1417
{
15-
public static void Main(string[] args)
18+
public static async Task Main(string[] args)
1619
{
17-
CreateWebHostBuilder(args).Build().Run();
20+
var host = CreateWebHostBuilder(args).Build();
21+
22+
using var scope = host.Services.CreateScope();
23+
var seed = scope.ServiceProvider.GetService<SeedLogic>();
24+
var lifetime = scope.ServiceProvider.GetService<IHostApplicationLifetime>();
25+
await seed.SeedAsync(lifetime?.ApplicationStopping ?? CancellationToken.None);
26+
27+
await host.RunAsync();
1828
}
1929

2030
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>

src/FoxIDs.Control/Startup.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
using Microsoft.Extensions.Hosting;
1010
using Microsoft.Net.Http.Headers;
1111
using System.Text.Json.Serialization;
12+
using FoxIDs.Logic.Seed;
1213

1314
namespace FoxIDs
1415
{

0 commit comments

Comments
 (0)