feat(auth): cut ScadaBridge over to ZB.MOM.WW.Auth.Ldap; nest+rename Ldap config; roles+sitescope via IGroupRoleMapper (Task 1.2/1.4)
This commit is contained in:
@@ -1,21 +1,44 @@
|
||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using ZB.MOM.WW.Auth.Abstractions.Roles;
|
||||
using ZB.MOM.WW.Auth.AspNetCore;
|
||||
|
||||
namespace ZB.MOM.WW.ScadaBridge.Security;
|
||||
|
||||
public static class ServiceCollectionExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Registers LDAP authentication, JWT token service, role mapper, cookie authentication, and authorization policies.
|
||||
/// The configuration section bound to the shared LDAP <c>LdapOptions</c>. Nested
|
||||
/// under the existing <c>ScadaBridge:Security</c> section as a <c>Ldap</c> sub-section
|
||||
/// (Task 1.4 config rename) so the non-LDAP <see cref="SecurityOptions"/> fields stay
|
||||
/// where they are while the LDAP connection settings bind to the shared library.
|
||||
/// </summary>
|
||||
public const string LdapSectionPath = "ScadaBridge:Security:Ldap";
|
||||
|
||||
/// <summary>
|
||||
/// Registers LDAP authentication (shared <c>ZB.MOM.WW.Auth.Ldap</c>), JWT token service,
|
||||
/// role mapper, cookie authentication, and authorization policies.
|
||||
/// </summary>
|
||||
/// <param name="services">The service collection to register into.</param>
|
||||
public static IServiceCollection AddSecurity(this IServiceCollection services)
|
||||
/// <param name="configuration">
|
||||
/// Application configuration, read for the nested <see cref="LdapSectionPath"/> LDAP
|
||||
/// options bound + validated by <c>AddZbLdapAuth</c>.
|
||||
/// </param>
|
||||
public static IServiceCollection AddSecurity(this IServiceCollection services, IConfiguration configuration)
|
||||
{
|
||||
services.AddScoped<LdapAuthService>();
|
||||
// Task 1.2 cutover: replace ScadaBridge's bespoke LdapAuthService with the shared
|
||||
// ZB.MOM.WW.Auth.Ldap implementation (ScadaBridge was the donor for its hardened
|
||||
// bind-then-search / escaping / fail-closed semantics, so this is a behaviour-
|
||||
// equivalent re-point). AddZbLdapAuth binds LdapOptions from the nested Ldap
|
||||
// sub-section, registers IValidateOptions<LdapOptions> with ValidateOnStart (so a
|
||||
// misconfigured directory fails fast at boot — superseding the old
|
||||
// SecurityOptionsValidator LDAP checks), and registers ILdapAuthService as a
|
||||
// stateless singleton.
|
||||
services.AddZbLdapAuth(configuration, LdapSectionPath);
|
||||
|
||||
services.AddScoped<JwtTokenService>();
|
||||
services.AddScoped<RoleMapper>();
|
||||
|
||||
@@ -27,16 +50,11 @@ public static class ServiceCollectionExtensions
|
||||
// to consume this seam in a later task.
|
||||
services.AddScoped<IGroupRoleMapper<string>, ScadaBridgeGroupRoleMapper>();
|
||||
|
||||
// Security-020: register the IValidateOptions<SecurityOptions> so a
|
||||
// missing/empty LdapServer or LdapSearchBase fails fast at startup
|
||||
// with a clear, key-naming message rather than a generic LDAP error
|
||||
// on the first real login. ValidateOnStart() forces the validation to
|
||||
// run during host startup rather than lazily on the first
|
||||
// IOptions<SecurityOptions> resolve. TryAddEnumerable so multiple
|
||||
// AddSecurity calls (or future additional validators) don't pile up.
|
||||
services.AddOptions<SecurityOptions>().ValidateOnStart();
|
||||
services.TryAddEnumerable(
|
||||
ServiceDescriptor.Singleton<IValidateOptions<SecurityOptions>, SecurityOptionsValidator>());
|
||||
// Note: the old SecurityOptionsValidator (which fail-fast-validated LdapServer +
|
||||
// LdapSearchBase) is gone — those keys moved into the shared LdapOptions, whose
|
||||
// LdapOptionsValidator (registered with ValidateOnStart by AddZbLdapAuth above)
|
||||
// now enforces Server + SearchBase + ServiceAccountDn + transport at startup. The
|
||||
// JWT signing key continues to fail-fast at JwtTokenService construction.
|
||||
|
||||
// Register ASP.NET Core authentication with cookie scheme
|
||||
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
|
||||
|
||||
Reference in New Issue
Block a user