544a6ddb77
Resolves the 35 findings from the 2026-06-01 baseline (commit 26ba1c7),
test-first for every behavioral change. +51 tests (331 -> 382 passing, 0 failed).
- Telemetry-001 (HIGH): RedactionEnricher now honours property removal, so a
redactor that drops a key actually scrubs the secret from the event.
- Auth: LDAP validator ValidateOnStart; API-key verify no longer fails on a
best-effort MarkUsed write or a corrupt scopes column (fail-closed); LDAP cert
validation hook; KeyPrefix persistence aligned; README algorithm corrected.
- Health: Akka checks return Degraded (not throw) when the cluster isn't up yet;
GrpcDependencyHealthCheck catch-all; null 'description' rendered; composite
endpoint builder; XML docs shipped.
- Audit: CompositeAuditWriter no longer re-throws OperationCanceledException;
TruncatingAuditRedactor over-redact scrubs Target + safe negative max; options
record; XML docs shipped.
- Configuration: TryAddEnumerable idempotent registration; consistent port
quoting; strict invariant port parsing; XML docs + README packaged.
- Theme: mobile toggle is now CSS-only (no Bootstrap JS); token/CSS hygiene;
XML docs on the public parameter surface.
Shared-contract/spec docs updated where the code was the source of truth
(observability service.instance.id, MapZbMetrics, redactor reach). All changes
additive/back-compatible at v0.1.0. code-reviews bookkeeping follows separately.
61 lines
3.0 KiB
C#
61 lines
3.0 KiB
C#
using Microsoft.Extensions.Configuration;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using Microsoft.Extensions.DependencyInjection.Extensions;
|
|
using Microsoft.Extensions.Options;
|
|
using ZB.MOM.WW.Auth.Abstractions.Ldap;
|
|
using ZB.MOM.WW.Auth.Ldap;
|
|
|
|
namespace ZB.MOM.WW.Auth.AspNetCore;
|
|
|
|
/// <summary>
|
|
/// Dependency-injection helpers that wire up the ZB.MOM.WW LDAP authentication provider
|
|
/// from configuration. Composes the concrete implementation living in the
|
|
/// <c>ZB.MOM.WW.Auth.Ldap</c> package so consuming apps register a provider with a single call.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// API-key DI wiring lives in <c>ZB.MOM.WW.Auth.ApiKeys</c>
|
|
/// (<c>ZB.MOM.WW.Auth.ApiKeys.DependencyInjection.ApiKeyServiceCollectionExtensions.AddZbApiKeyAuth</c>)
|
|
/// so that an LDAP-only consumer can reference this package without pulling in SQLite.
|
|
/// </remarks>
|
|
public static class ServiceCollectionExtensions
|
|
{
|
|
/// <summary>
|
|
/// Registers LDAP authentication: binds and validates <see cref="LdapOptions"/> from the
|
|
/// configuration section at <paramref name="sectionPath"/>, and registers
|
|
/// <see cref="ILdapAuthService"/>.
|
|
/// </summary>
|
|
/// <param name="services">The service collection to add to.</param>
|
|
/// <param name="config">The application configuration.</param>
|
|
/// <param name="sectionPath">Path of the configuration section holding the LDAP options.</param>
|
|
/// <returns>The same <paramref name="services"/> instance, for chaining.</returns>
|
|
public static IServiceCollection AddZbLdapAuth(
|
|
this IServiceCollection services,
|
|
IConfiguration config,
|
|
string sectionPath)
|
|
{
|
|
ArgumentNullException.ThrowIfNull(services);
|
|
ArgumentNullException.ThrowIfNull(config);
|
|
ArgumentException.ThrowIfNullOrWhiteSpace(sectionPath);
|
|
|
|
// Bind via the options builder and opt into start-time validation. An IValidateOptions<T>
|
|
// otherwise only runs when the options are first materialized (IOptions<T>.Value) — which
|
|
// here is the first login (ILdapAuthService factory below), not boot. ValidateOnStart hooks
|
|
// the host's start-time options validation so a misconfigured directory (e.g. insecure
|
|
// transport without AllowInsecure) fails fast at startup rather than on first login.
|
|
services.AddOptions<LdapOptions>()
|
|
.Bind(config.GetSection(sectionPath))
|
|
.ValidateOnStart();
|
|
|
|
// Fail fast at startup on a misconfigured directory rather than on first login.
|
|
services.AddSingleton<IValidateOptions<LdapOptions>, LdapOptionsValidator>();
|
|
|
|
// LdapAuthService is stateless: it holds only a snapshot of LdapOptions and a stateless
|
|
// connection factory, and opens/disposes a connection per call. It is not IDisposable.
|
|
// Singleton is correct; TryAdd mirrors the pattern in AddZbApiKeyAuth (idempotency).
|
|
services.TryAddSingleton<ILdapAuthService>(sp =>
|
|
new LdapAuthService(sp.GetRequiredService<IOptions<LdapOptions>>().Value));
|
|
|
|
return services;
|
|
}
|
|
}
|