Merge chore/shared-lib-latest-pins: every ZB.MOM.WW pin to newest published; Auth 0.2.0 obliged the LdapOptions shadow mirror
ci / nightly-windev (push) Has been skipped
ci / windows-x86 (push) Successful in 1m13s
ci / java (push) Successful in 2m24s
ci / portable (push) Successful in 9m24s

This commit is contained in:
Joseph Doherty
2026-08-12 04:17:34 -04:00
7 changed files with 45 additions and 12 deletions
+1
View File
@@ -254,6 +254,7 @@ dev/test GLAuth posture (`glauth.md`), not a production posture.
| `MxGateway:Ldap:UserNameAttribute` | `cn` | LDAP attribute holding the login user name. |
| `MxGateway:Ldap:DisplayNameAttribute` | `cn` | LDAP attribute holding the display name. |
| `MxGateway:Ldap:GroupAttribute` | `memberOf` | LDAP attribute enumerating group membership (mapped to dashboard roles via `MxGateway:Dashboard:GroupToRole`). |
| `MxGateway:Ldap:FallbackServers` | *(empty)* | Ordered backup LDAP endpoints tried when the primary fails with a system-side error (connect/TLS, service-account bind, or search) — **not** when a user's credentials are simply wrong. Each entry is `host` (adopting `Port`) or `host:port`. Empty leaves single-endpoint behaviour exactly as before. Endpoint preference is sticky: the last endpoint that answered keeps being used until it fails. The `Transport` / `AllowInsecure` policy applies to every endpoint — a fallback is not a way to downgrade TLS. Entries are parsed at startup and a malformed one fails the boot, so a typo'd backup DC cannot lie dormant until the outage it exists to survive. Requires ZB.MOM.WW.Auth 0.2.0+. |
When LDAP is enabled, `Server`, `SearchBase`, `ServiceAccountDn`,
`ServiceAccountPassword`, and the attribute names must be non-blank, and `Port`
@@ -22,8 +22,8 @@
(IntegrationTests-028).
-->
<ItemGroup>
<PackageReference Include="ZB.MOM.WW.Auth.Abstractions" Version="0.1.5" />
<PackageReference Include="ZB.MOM.WW.Auth.Ldap" Version="0.1.5" />
<PackageReference Include="ZB.MOM.WW.Auth.Abstractions" Version="0.2.0" />
<PackageReference Include="ZB.MOM.WW.Auth.Ldap" Version="0.2.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="10.0.7" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="10.0.7" />
</ItemGroup>
@@ -11,4 +11,5 @@ public sealed record EffectiveLdapConfiguration(
string ServiceAccountPassword,
string UserNameAttribute,
string DisplayNameAttribute,
string GroupAttribute);
string GroupAttribute,
IReadOnlyList<string> FallbackServers);
@@ -30,7 +30,8 @@ public sealed class GatewayConfigurationProvider(IOptions<GatewayOptions> option
ServiceAccountPassword: RedactedValue,
UserNameAttribute: value.Ldap.UserNameAttribute,
DisplayNameAttribute: value.Ldap.DisplayNameAttribute,
GroupAttribute: value.Ldap.GroupAttribute),
GroupAttribute: value.Ldap.GroupAttribute,
FallbackServers: value.Ldap.FallbackServers),
Worker: new EffectiveWorkerConfiguration(
ExecutablePath: value.Worker.ExecutablePath,
WorkingDirectory: value.Worker.WorkingDirectory,
@@ -68,4 +68,19 @@ public sealed class LdapOptions
/// <summary>Gets the LDAP attribute name for group membership.</summary>
public string GroupAttribute { get; init; } = "memberOf";
/// <summary>
/// Gets the ordered fallback LDAP endpoints (<c>"host"</c> or <c>"host:port"</c>) the shared
/// provider walks when the primary fails with a system-side error. Empty (the default) leaves
/// single-endpoint behaviour unchanged. Mirrors
/// <see cref="ZB.MOM.WW.Auth.Abstractions.Ldap.LdapOptions.FallbackServers"/>, added in
/// ZB.MOM.WW.Auth 0.2.0.
/// <para>
/// Carried here only so the effective-config display does not hide a configured backup DC —
/// nothing on the gateway side reads it. Entry syntax is validated at boot by the shared
/// <c>LdapOptionsValidator</c>, which owns the (internal) parser; re-validating here would
/// mean a second, drifting copy of that grammar.
/// </para>
/// </summary>
public IReadOnlyList<string> FallbackServers { get; init; } = [];
}
@@ -26,6 +26,21 @@ else
<tr><th scope="row">Run migrations</th><td>@Snapshot.Configuration.Authentication.RunMigrationsOnStartup</td></tr>
<tr><th scope="row">LDAP enabled</th><td>@Snapshot.Configuration.Ldap.Enabled</td></tr>
<tr><th scope="row">LDAP server</th><td>@Snapshot.Configuration.Ldap.Server:@Snapshot.Configuration.Ldap.Port</td></tr>
<tr>
<th scope="row">LDAP fallback servers</th>
@* Rendered even when empty: "none" is the operationally interesting answer
on a host someone believes has a backup DC configured. *@
<td>
@if (Snapshot.Configuration.Ldap.FallbackServers.Count == 0)
{
<span class="text-muted">none</span>
}
else
{
<code>@string.Join(", ", Snapshot.Configuration.Ldap.FallbackServers)</code>
}
</td>
</tr>
<tr><th scope="row">LDAP transport</th><td>@Snapshot.Configuration.Ldap.Transport</td></tr>
<tr><th scope="row">LDAP search base</th><td><code>@Snapshot.Configuration.Ldap.SearchBase</code></td></tr>
<tr><th scope="row">LDAP service account</th><td><code>@Snapshot.Configuration.Ldap.ServiceAccountDn</code></td></tr>
@@ -10,20 +10,20 @@
<ItemGroup>
<PackageReference Include="Grpc.AspNetCore" Version="2.76.0" />
<PackageReference Include="ZB.MOM.WW.Auth.Abstractions" Version="0.1.5" />
<PackageReference Include="ZB.MOM.WW.Auth.Ldap" Version="0.1.5" />
<PackageReference Include="ZB.MOM.WW.Auth.ApiKeys" Version="0.1.5" />
<PackageReference Include="ZB.MOM.WW.Auth.AspNetCore" Version="0.1.5" />
<PackageReference Include="ZB.MOM.WW.Auth.Abstractions" Version="0.2.0" />
<PackageReference Include="ZB.MOM.WW.Auth.Ldap" Version="0.2.0" />
<PackageReference Include="ZB.MOM.WW.Auth.ApiKeys" Version="0.2.0" />
<PackageReference Include="ZB.MOM.WW.Auth.AspNetCore" Version="0.2.0" />
<PackageReference Include="ZB.MOM.WW.Audit" Version="0.1.0" />
<PackageReference Include="ZB.MOM.WW.Theme" Version="0.4.1" />
<PackageReference Include="ZB.MOM.WW.Configuration" Version="0.1.0" />
<PackageReference Include="ZB.MOM.WW.Health" Version="0.2.0" />
<PackageReference Include="ZB.MOM.WW.Health" Version="0.3.0" />
<PackageReference Include="ZB.MOM.WW.Telemetry" Version="0.1.0" />
<PackageReference Include="ZB.MOM.WW.Telemetry.Serilog" Version="0.1.0" />
<PackageReference Include="ZB.MOM.WW.GalaxyRepository" Version="0.2.0" />
<PackageReference Include="ZB.MOM.WW.Secrets" Version="0.6.1" />
<PackageReference Include="ZB.MOM.WW.Secrets.Abstractions" Version="0.6.1" />
<PackageReference Include="ZB.MOM.WW.Secrets.Ui" Version="0.6.1" />
<PackageReference Include="ZB.MOM.WW.Secrets" Version="0.6.2" />
<PackageReference Include="ZB.MOM.WW.Secrets.Abstractions" Version="0.6.2" />
<PackageReference Include="ZB.MOM.WW.Secrets.Ui" Version="0.6.2" />
<PackageReference Include="Serilog.AspNetCore" Version="10.0.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="6.1.1" />
<PackageReference Include="Serilog.Sinks.File" Version="7.0.0" />