Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.IdentityModel.Tokens;
using Skoruba.AuditLogging.EntityFramework.DbContexts;
using Skoruba.AuditLogging.EntityFramework.Entities;
using Skoruba.AuditLogging.EntityFramework.Extensions;
Expand All @@ -29,7 +28,6 @@
using Skoruba.Duende.IdentityServer.Admin.EntityFramework.Configuration.MySql;
using Skoruba.Duende.IdentityServer.Admin.EntityFramework.Configuration.PostgreSQL;
using Skoruba.Duende.IdentityServer.Admin.EntityFramework.Configuration.SqlServer;
using Skoruba.Duende.IdentityServer.Admin.EntityFramework.Helpers;
using Skoruba.Duende.IdentityServer.Admin.EntityFramework.Interfaces;

namespace Skoruba.Duende.IdentityServer.Admin.Api.Helpers
Expand Down Expand Up @@ -256,88 +254,23 @@ public static void AddAuthorizationPolicies(this IServiceCollection services)
});
}

public static void AddIdSHealthChecks<TConfigurationDbContext, TPersistedGrantDbContext, TIdentityDbContext, TLogDbContext, TAuditLoggingDbContext, TDataProtectionDbContext>(this IServiceCollection services, IConfiguration configuration, AdminApiConfiguration adminApiConfiguration)
public static void AddIdSHealthChecks<TConfigurationDbContext, TPersistedGrantDbContext, TIdentityDbContext, TLogDbContext, TAuditLoggingDbContext, TDataProtectionDbContext, TUser>(this IServiceCollection services, AdminApiConfiguration adminApiConfiguration)
where TConfigurationDbContext : DbContext, IAdminConfigurationDbContext
where TPersistedGrantDbContext : DbContext, IAdminPersistedGrantDbContext
where TIdentityDbContext : DbContext
where TLogDbContext : DbContext, IAdminLogDbContext
where TAuditLoggingDbContext : DbContext, IAuditLoggingDbContext<AuditLog>
where TDataProtectionDbContext : DbContext, IDataProtectionKeyContext
where TUser : class
{
var configurationDbConnectionString = configuration.GetConnectionString(ConfigurationConsts.ConfigurationDbConnectionStringKey);
var persistedGrantsDbConnectionString = configuration.GetConnectionString(ConfigurationConsts.PersistedGrantDbConnectionStringKey);
var identityDbConnectionString = configuration.GetConnectionString(ConfigurationConsts.IdentityDbConnectionStringKey);
var logDbConnectionString = configuration.GetConnectionString(ConfigurationConsts.AdminLogDbConnectionStringKey);
var auditLogDbConnectionString = configuration.GetConnectionString(ConfigurationConsts.AdminAuditLogDbConnectionStringKey);
var dataProtectionDbConnectionString = configuration.GetConnectionString(ConfigurationConsts.DataProtectionDbConnectionStringKey);

var identityServerUri = adminApiConfiguration.IdentityServerBaseUrl;
var healthChecksBuilder = services.AddHealthChecks()
.AddDbContextCheck<TConfigurationDbContext>("ConfigurationDbContext")
.AddDbContextCheck<TPersistedGrantDbContext>("PersistedGrantsDbContext")
.AddDbContextCheck<TIdentityDbContext>("IdentityDbContext")
.AddDbContextCheck<TLogDbContext>("LogDbContext")
.AddDbContextCheck<TAuditLoggingDbContext>("AuditLogDbContext")
.AddDbContextCheck<TDataProtectionDbContext>("DataProtectionDbContext")
.AddIdentityServer(new Uri(identityServerUri), "Identity Server");

var serviceProvider = services.BuildServiceProvider();
var scopeFactory = serviceProvider.GetRequiredService<IServiceScopeFactory>();
using (var scope = scopeFactory.CreateScope())
{
var configurationTableName = DbContextHelpers.GetEntityTable<TConfigurationDbContext>(scope.ServiceProvider);
var persistedGrantTableName = DbContextHelpers.GetEntityTable<TPersistedGrantDbContext>(scope.ServiceProvider);
var identityTableName = DbContextHelpers.GetEntityTable<TIdentityDbContext>(scope.ServiceProvider);
var logTableName = DbContextHelpers.GetEntityTable<TLogDbContext>(scope.ServiceProvider);
var auditLogTableName = DbContextHelpers.GetEntityTable<TAuditLoggingDbContext>(scope.ServiceProvider);
var dataProtectionTableName = DbContextHelpers.GetEntityTable<TDataProtectionDbContext>(scope.ServiceProvider);

var databaseProvider = configuration.GetSection(nameof(DatabaseProviderConfiguration)).Get<DatabaseProviderConfiguration>();
switch (databaseProvider.ProviderType)
{
case DatabaseProviderType.SqlServer:
healthChecksBuilder
.AddSqlServer(configurationDbConnectionString, name: "ConfigurationDb",
healthQuery: $"SELECT TOP 1 * FROM dbo.[{configurationTableName}]")
.AddSqlServer(persistedGrantsDbConnectionString, name: "PersistentGrantsDb",
healthQuery: $"SELECT TOP 1 * FROM dbo.[{persistedGrantTableName}]")
.AddSqlServer(identityDbConnectionString, name: "IdentityDb",
healthQuery: $"SELECT TOP 1 * FROM dbo.[{identityTableName}]")
.AddSqlServer(logDbConnectionString, name: "LogDb",
healthQuery: $"SELECT TOP 1 * FROM dbo.[{logTableName}]")
.AddSqlServer(auditLogDbConnectionString, name: "AuditLogDb",
healthQuery: $"SELECT TOP 1 * FROM dbo.[{auditLogTableName}]")
.AddSqlServer(dataProtectionDbConnectionString, name: "DataProtectionDb",
healthQuery: $"SELECT TOP 1 * FROM dbo.[{dataProtectionTableName}]");
break;
case DatabaseProviderType.PostgreSQL:
healthChecksBuilder
.AddNpgSql(configurationDbConnectionString, name: "ConfigurationDb",
healthQuery: $"SELECT * FROM \"{configurationTableName}\" LIMIT 1")
.AddNpgSql(persistedGrantsDbConnectionString, name: "PersistentGrantsDb",
healthQuery: $"SELECT * FROM \"{persistedGrantTableName}\" LIMIT 1")
.AddNpgSql(identityDbConnectionString, name: "IdentityDb",
healthQuery: $"SELECT * FROM \"{identityTableName}\" LIMIT 1")
.AddNpgSql(logDbConnectionString, name: "LogDb",
healthQuery: $"SELECT * FROM \"{logTableName}\" LIMIT 1")
.AddNpgSql(auditLogDbConnectionString, name: "AuditLogDb",
healthQuery: $"SELECT * FROM \"{auditLogTableName}\" LIMIT 1")
.AddNpgSql(dataProtectionDbConnectionString, name: "DataProtectionDb",
healthQuery: $"SELECT * FROM \"{dataProtectionTableName}\" LIMIT 1");
break;
case DatabaseProviderType.MySql:
healthChecksBuilder
.AddMySql(configurationDbConnectionString, name: "ConfigurationDb")
.AddMySql(persistedGrantsDbConnectionString, name: "PersistentGrantsDb")
.AddMySql(identityDbConnectionString, name: "IdentityDb")
.AddMySql(logDbConnectionString, name: "LogDb")
.AddMySql(auditLogDbConnectionString, name: "AuditLogDb")
.AddMySql(dataProtectionDbConnectionString, name: "DataProtectionDb");
break;
default:
throw new NotImplementedException($"Health checks not defined for database provider {databaseProvider.ProviderType}");
}
}
services.AddHealthChecks()
.AddDbContextCheck<TConfigurationDbContext>(customTestQuery: (context, token) => context.Clients.AnyAsync(token), tags: new[] { "database" })
.AddDbContextCheck<TPersistedGrantDbContext>(customTestQuery: (context, token) => context.Keys.AnyAsync(token), tags: new[] { "database" })
.AddDbContextCheck<TIdentityDbContext>(customTestQuery: (context, token) => context.Set<TUser>().AnyAsync(token), tags: new[] { "database" })
.AddDbContextCheck<TLogDbContext>(customTestQuery: (context, token) => context.Logs.AnyAsync(token), tags: new[] { "database" })
.AddDbContextCheck<TAuditLoggingDbContext>(customTestQuery: (context, token) => context.AuditLog.AnyAsync(token), tags: new[] { "database" })
.AddDbContextCheck<TDataProtectionDbContext>(customTestQuery: (context, token) => context.DataProtectionKeys.AnyAsync(token), tags: new[] { "database" })
.AddIdentityServer(new Uri(adminApiConfiguration.IdentityServerBaseUrl), "Identity Server", tags: new[] { "identity" });
}

public static void AddForwardHeaders(this IApplicationBuilder app)
Expand Down
2 changes: 1 addition & 1 deletion src/Skoruba.Duende.IdentityServer.Admin.Api/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ public void ConfigureServices(IServiceCollection services)

services.AddAuditEventLogging<AdminAuditLogDbContext, AuditLog>(Configuration);

services.AddIdSHealthChecks<IdentityServerConfigurationDbContext, IdentityServerPersistedGrantDbContext, AdminIdentityDbContext, AdminLogDbContext, AdminAuditLogDbContext, IdentityServerDataProtectionDbContext>(Configuration, adminApiConfiguration);
services.AddIdSHealthChecks<IdentityServerConfigurationDbContext, IdentityServerPersistedGrantDbContext, AdminIdentityDbContext, AdminLogDbContext, AdminAuditLogDbContext, IdentityServerDataProtectionDbContext, UserIdentity>(adminApiConfiguration);
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env, AdminApiConfiguration adminApiConfiguration)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ public static IServiceCollection AddIdentityServerAdminUI<TIdentityDbContext, TI
var healthChecksBuilder = options.HealthChecksBuilderFactory?.Invoke(services) ?? services.AddHealthChecks();
healthChecksBuilder.AddIdSHealthChecks<TIdentityServerDbContext, TPersistedGrantDbContext,
TIdentityDbContext, TLogDbContext, TAuditLogDbContext,
TDataProtectionDbContext, TAuditLog>(options.Admin, options.ConnectionStrings, options.DatabaseProvider);
TDataProtectionDbContext, TAuditLog, TUser>(options.Admin);

// Adds a startup filter for further middleware configuration.
services.AddSingleton(options.Testing);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@
using Skoruba.Duende.IdentityServer.Admin.EntityFramework.Configuration.MySql;
using Skoruba.Duende.IdentityServer.Admin.EntityFramework.Configuration.PostgreSQL;
using Skoruba.Duende.IdentityServer.Admin.EntityFramework.Configuration.SqlServer;
using Skoruba.Duende.IdentityServer.Admin.EntityFramework.Helpers;
using Skoruba.Duende.IdentityServer.Admin.EntityFramework.Interfaces;
using Skoruba.Duende.IdentityServer.Admin.EntityFramework.Repositories;
using Skoruba.Duende.IdentityServer.Admin.EntityFramework.Repositories.Interfaces;
Expand Down Expand Up @@ -431,91 +430,26 @@ private static Task OnRedirectToIdentityProvider(RedirectContext context, AdminC
}

public static void AddIdSHealthChecks<TConfigurationDbContext, TPersistedGrantDbContext, TIdentityDbContext,
TLogDbContext, TAuditLoggingDbContext, TDataProtectionDbContext, TAuditLog>
(this IHealthChecksBuilder healthChecksBuilder, AdminConfiguration adminConfiguration,
ConnectionStringsConfiguration connectionStringsConfiguration, DatabaseProviderConfiguration databaseProviderConfiguration)
TLogDbContext, TAuditLoggingDbContext, TDataProtectionDbContext, TAuditLog, TUser>
(this IHealthChecksBuilder healthChecksBuilder, AdminConfiguration adminConfiguration)
where TConfigurationDbContext : DbContext, IAdminConfigurationDbContext
where TPersistedGrantDbContext : DbContext, IAdminPersistedGrantDbContext
where TIdentityDbContext : DbContext
where TLogDbContext : DbContext, IAdminLogDbContext
where TAuditLoggingDbContext : DbContext, IAuditLoggingDbContext<TAuditLog>
where TDataProtectionDbContext : DbContext, IDataProtectionKeyContext
where TAuditLog : AuditLog
where TUser : class
{
var configurationDbConnectionString = connectionStringsConfiguration.ConfigurationDbConnection;
var persistedGrantsDbConnectionString = connectionStringsConfiguration.PersistedGrantDbConnection;
var identityDbConnectionString = connectionStringsConfiguration.IdentityDbConnection;
var logDbConnectionString = connectionStringsConfiguration.AdminLogDbConnection;
var auditLogDbConnectionString = connectionStringsConfiguration.AdminAuditLogDbConnection;
var dataProtectionDbConnectionString = connectionStringsConfiguration.DataProtectionDbConnection;

var identityServerUri = adminConfiguration.IdentityServerBaseUrl;
healthChecksBuilder = healthChecksBuilder
.AddDbContextCheck<TConfigurationDbContext>("ConfigurationDbContext")
.AddDbContextCheck<TPersistedGrantDbContext>("PersistedGrantsDbContext")
.AddDbContextCheck<TIdentityDbContext>("IdentityDbContext")
.AddDbContextCheck<TLogDbContext>("LogDbContext")
.AddDbContextCheck<TAuditLoggingDbContext>("AuditLogDbContext")
.AddDbContextCheck<TDataProtectionDbContext>("DataProtectionDbContext")

.AddIdentityServer(new Uri(identityServerUri), "Identity Server");

var serviceProvider = healthChecksBuilder.Services.BuildServiceProvider();
var scopeFactory = serviceProvider.GetRequiredService<IServiceScopeFactory>();
using (var scope = scopeFactory.CreateScope())
{
var configurationTableName = DbContextHelpers.GetEntityTable<TConfigurationDbContext>(scope.ServiceProvider);
var persistedGrantTableName = DbContextHelpers.GetEntityTable<TPersistedGrantDbContext>(scope.ServiceProvider);
var identityTableName = DbContextHelpers.GetEntityTable<TIdentityDbContext>(scope.ServiceProvider);
var logTableName = DbContextHelpers.GetEntityTable<TLogDbContext>(scope.ServiceProvider);
var auditLogTableName = DbContextHelpers.GetEntityTable<TAuditLoggingDbContext>(scope.ServiceProvider);
var dataProtectionTableName = DbContextHelpers.GetEntityTable<TDataProtectionDbContext>(scope.ServiceProvider);

switch (databaseProviderConfiguration.ProviderType)
{
case DatabaseProviderType.SqlServer:
healthChecksBuilder
.AddSqlServer(configurationDbConnectionString, name: "ConfigurationDb",
healthQuery: $"SELECT TOP 1 * FROM dbo.[{configurationTableName}]")
.AddSqlServer(persistedGrantsDbConnectionString, name: "PersistentGrantsDb",
healthQuery: $"SELECT TOP 1 * FROM dbo.[{persistedGrantTableName}]")
.AddSqlServer(identityDbConnectionString, name: "IdentityDb",
healthQuery: $"SELECT TOP 1 * FROM dbo.[{identityTableName}]")
.AddSqlServer(logDbConnectionString, name: "LogDb",
healthQuery: $"SELECT TOP 1 * FROM dbo.[{logTableName}]")
.AddSqlServer(auditLogDbConnectionString, name: "AuditLogDb",
healthQuery: $"SELECT TOP 1 * FROM dbo.[{auditLogTableName}]")
.AddSqlServer(dataProtectionDbConnectionString, name: "DataProtectionDb",
healthQuery: $"SELECT TOP 1 * FROM dbo.[{dataProtectionTableName}]");
break;
case DatabaseProviderType.PostgreSQL:
healthChecksBuilder
.AddNpgSql(configurationDbConnectionString, name: "ConfigurationDb",
healthQuery: $"SELECT * FROM \"{configurationTableName}\" LIMIT 1")
.AddNpgSql(persistedGrantsDbConnectionString, name: "PersistentGrantsDb",
healthQuery: $"SELECT * FROM \"{persistedGrantTableName}\" LIMIT 1")
.AddNpgSql(identityDbConnectionString, name: "IdentityDb",
healthQuery: $"SELECT * FROM \"{identityTableName}\" LIMIT 1")
.AddNpgSql(logDbConnectionString, name: "LogDb",
healthQuery: $"SELECT * FROM \"{logTableName}\" LIMIT 1")
.AddNpgSql(auditLogDbConnectionString, name: "AuditLogDb",
healthQuery: $"SELECT * FROM \"{auditLogTableName}\" LIMIT 1")
.AddNpgSql(dataProtectionDbConnectionString, name: "DataProtectionDb",
healthQuery: $"SELECT * FROM \"{dataProtectionTableName}\" LIMIT 1");
break;
case DatabaseProviderType.MySql:
healthChecksBuilder
.AddMySql(configurationDbConnectionString, name: "ConfigurationDb")
.AddMySql(persistedGrantsDbConnectionString, name: "PersistentGrantsDb")
.AddMySql(identityDbConnectionString, name: "IdentityDb")
.AddMySql(logDbConnectionString, name: "LogDb")
.AddMySql(auditLogDbConnectionString, name: "AuditLogDb")
.AddMySql(dataProtectionDbConnectionString, name: "DataProtectionDb");
break;
default:
throw new NotImplementedException($"Health checks not defined for database provider {databaseProviderConfiguration.ProviderType}");
}
}
healthChecksBuilder
.AddDbContextCheck<TConfigurationDbContext>(customTestQuery: (context, token) => context.Clients.AnyAsync(token), tags: new []{ "database"} )
.AddDbContextCheck<TPersistedGrantDbContext>(customTestQuery: (context, token) => context.Keys.AnyAsync(token), tags: new[] { "database" })
.AddDbContextCheck<TIdentityDbContext>(customTestQuery: (context, token) => context.Set<TUser>().AnyAsync(token), tags: new[] { "database" })
.AddDbContextCheck<TLogDbContext>(customTestQuery: (context, token) => context.Logs.AnyAsync(token), tags: new[] { "database" })
.AddDbContextCheck<TAuditLoggingDbContext>(customTestQuery: (context, token) => context.AuditLog.AnyAsync(token), tags: new[] { "database" })
.AddDbContextCheck<TDataProtectionDbContext>(customTestQuery: (context, token) => context.DataProtectionKeys.AnyAsync(token), tags: new[] { "database" })
.AddIdentityServer(new Uri(identityServerUri), "Identity Server", tags: new []{ "identity" });
}

/// <summary>
Expand Down
Loading