feat(auth): cut MxGateway API keys over to ZB.MOM.WW.Auth.ApiKeys 0.1.2; keep constraint enforcement+gRPC+CLI on top (Task 1.3)
This commit is contained in:
+63
-10
@@ -1,27 +1,80 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Options;
|
||||
using ZB.MOM.WW.Auth.Abstractions.ApiKeys;
|
||||
using ZB.MOM.WW.Auth.ApiKeys;
|
||||
using ZB.MOM.WW.Auth.ApiKeys.Admin;
|
||||
using ZB.MOM.WW.Auth.ApiKeys.DependencyInjection;
|
||||
using ZB.MOM.WW.Auth.ApiKeys.Sqlite;
|
||||
|
||||
namespace ZB.MOM.WW.MxGateway.Server.Security.Authentication;
|
||||
|
||||
/// <summary>
|
||||
/// Extension methods for configuring the SQLite authentication store.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The peppered-HMAC API-key pipeline (token format, hashing, constant-time compare, SQLite
|
||||
/// schema, stores, verifier and migration) is provided by the shared
|
||||
/// <c>ZB.MOM.WW.Auth.ApiKeys</c> library, of which this gateway is the donor. This wiring binds
|
||||
/// the library's <see cref="ApiKeyOptions"/> from the gateway's <c>MxGateway:Authentication</c>
|
||||
/// section and layers the gateway-specific constraint enforcement, gRPC interceptor, CLI and
|
||||
/// dashboard on top.
|
||||
/// </remarks>
|
||||
public static class AuthStoreServiceCollectionExtensions
|
||||
{
|
||||
/// <summary>The configuration section the gateway binds API-key options from.</summary>
|
||||
public const string AuthenticationSectionPath = "MxGateway:Authentication";
|
||||
|
||||
/// <summary>The gateway API-key token prefix (token format <c>mxgw_<id>_<secret></c>).</summary>
|
||||
public const string TokenPrefix = "mxgw";
|
||||
|
||||
/// <summary>The configuration key the API-key pepper is resolved from.</summary>
|
||||
public const string PepperSecretName = "MxGateway:ApiKeyPepper";
|
||||
|
||||
/// <summary>
|
||||
/// Adds the SQLite authentication store and related services to the dependency container.
|
||||
/// </summary>
|
||||
/// <param name="services">Service collection to configure.</param>
|
||||
/// <param name="configuration">Application configuration carrying the API-key options.</param>
|
||||
/// <returns>The service collection for chaining.</returns>
|
||||
public static IServiceCollection AddSqliteAuthStore(this IServiceCollection services)
|
||||
public static IServiceCollection AddSqliteAuthStore(
|
||||
this IServiceCollection services,
|
||||
IConfiguration configuration)
|
||||
{
|
||||
services.AddSingleton<IApiKeyParser, ApiKeyParser>();
|
||||
services.AddSingleton<IApiKeySecretHasher, ApiKeySecretHasher>();
|
||||
services.AddSingleton<IApiKeyVerifier, ApiKeyVerifier>();
|
||||
ArgumentNullException.ThrowIfNull(services);
|
||||
ArgumentNullException.ThrowIfNull(configuration);
|
||||
|
||||
// Pin the gateway's API-key contract (token prefix "mxgw"; pepper resolved from
|
||||
// MxGateway:ApiKeyPepper) by layering fallback defaults UNDER the supplied configuration:
|
||||
// an in-memory source provides TokenPrefix/PepperSecretName only when the bound
|
||||
// MxGateway:Authentication section omits them (the section has no TokenPrefix, and the pepper
|
||||
// is intentionally not in appsettings — it is supplied at runtime). Explicit config wins
|
||||
// because it is added last. ApiKeyOptions is an init-only record, so the values must be
|
||||
// present at bind time rather than mutated post-configure.
|
||||
IConfiguration effectiveConfig = new ConfigurationBuilder()
|
||||
.AddInMemoryCollection(new Dictionary<string, string?>
|
||||
{
|
||||
[$"{AuthenticationSectionPath}:TokenPrefix"] = TokenPrefix,
|
||||
[$"{AuthenticationSectionPath}:PepperSecretName"] = PepperSecretName,
|
||||
})
|
||||
.AddConfiguration(configuration)
|
||||
.Build();
|
||||
|
||||
// Register the shared API-key provider: binds ApiKeyOptions from MxGateway:Authentication,
|
||||
// wires up the SQLite stores, the configuration-backed pepper provider, the verifier, the
|
||||
// migrator and the migration hosted service.
|
||||
services.AddZbApiKeyAuth(effectiveConfig, AuthenticationSectionPath);
|
||||
|
||||
// The shared admin command set (create/revoke/rotate/list/init-db with audit) is not
|
||||
// auto-registered by AddZbApiKeyAuth; the gateway CLI and dashboard drive it, so register
|
||||
// it here over the already-wired stores, pepper provider and migrator.
|
||||
services.AddSingleton(sp => new ApiKeyAdminCommands(
|
||||
sp.GetRequiredService<IOptions<ApiKeyOptions>>().Value,
|
||||
sp.GetRequiredService<IApiKeyAdminStore>(),
|
||||
sp.GetRequiredService<IApiKeyAuditStore>(),
|
||||
sp.GetRequiredService<IApiKeyPepperProvider>(),
|
||||
sp.GetRequiredService<SqliteAuthStoreMigrator>()));
|
||||
|
||||
services.AddSingleton<ApiKeyAdminCliRunner>();
|
||||
services.AddSingleton<AuthSqliteConnectionFactory>();
|
||||
services.AddSingleton<IAuthStoreMigrator, SqliteAuthStoreMigrator>();
|
||||
services.AddSingleton<IApiKeyStore, SqliteApiKeyStore>();
|
||||
services.AddSingleton<IApiKeyAdminStore, SqliteApiKeyAdminStore>();
|
||||
services.AddSingleton<IApiKeyAuditStore, SqliteApiKeyAuditStore>();
|
||||
services.AddHostedService<AuthStoreMigrationHostedService>();
|
||||
|
||||
return services;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user