fix(secrets): honor env-supplied LDAP bind password in live LDAP integration suite; clarify pre-host migration
ci / nightly-windev (push) Has been skipped
ci / windows-x86 (push) Successful in 1m12s
ci / java (push) Successful in 2m0s
ci / portable (push) Successful in 6m51s

This commit is contained in:
Joseph Doherty
2026-07-16 11:24:23 -04:00
parent 2e7245dd55
commit e088dfabf7
3 changed files with 33 additions and 1 deletions
+9
View File
@@ -236,10 +236,19 @@ LDAP groups resolve to the `Admin` role succeeds and emits the role claim;
the password into `FailureMessage`; an unknown username fails authentication; and
an unreachable LDAP server is absorbed into a failed result rather than throwing.
`appsettings.json` now ships the LDAP bind password as the unexpanded
`${secret:ldap/mxgateway/bind}` token (resolved at gateway startup by the
pre-host secrets expander, which this suite's bare `ConfigurationBuilder`
does not run). Before running the live LDAP suite, set
`MxGateway__Ldap__ServiceAccountPassword` to the real GLAuth service-account
password (dev value `serviceaccount123` for the shared GLAuth) so the suite
binds with the real password instead of the literal token.
Run the LDAP live tests explicitly:
```bash
$env:MXGATEWAY_RUN_LIVE_LDAP_TESTS = "1"
$env:MxGateway__Ldap__ServiceAccountPassword = "serviceaccount123"
dotnet test src/ZB.MOM.WW.MxGateway.IntegrationTests/ZB.MOM.WW.MxGateway.IntegrationTests.csproj --filter FullyQualifiedName~DashboardLdapLiveTests
```
@@ -161,12 +161,32 @@ public sealed class DashboardLdapLiveTests
IConfiguration configuration = new ConfigurationBuilder()
.AddJsonFile(appSettingsPath, optional: false)
.AddEnvironmentVariables()
.Build();
// Same section production binds in AddZbLdapAuth(configuration, "MxGateway:Ldap").
// Get<T> returns null only when the section is absent; appsettings.json always
// carries it, so fall back to shared defaults defensively rather than throw.
return configuration.GetSection("MxGateway:Ldap").Get<LibraryLdapOptions>()
LibraryLdapOptions options = configuration.GetSection("MxGateway:Ldap").Get<LibraryLdapOptions>()
?? new LibraryLdapOptions();
// appsettings.json now ships the bind password as the unexpanded
// "${secret:ldap/mxgateway/bind}" token (resolved at gateway startup by the
// pre-host secrets expander, which this bare ConfigurationBuilder does not run).
// AddEnvironmentVariables() above lets MxGateway__Ldap__ServiceAccountPassword
// override the token with the real password. Fail loud rather than silently
// binding with the literal token string, which would make every live test in
// this file fail with a confusing LDAP bind error instead of an actionable one.
if (string.IsNullOrEmpty(options.ServiceAccountPassword)
|| options.ServiceAccountPassword.StartsWith("${secret:", StringComparison.Ordinal))
{
throw new InvalidOperationException(
"Live LDAP tests require the real bind password via the "
+ "MxGateway__Ldap__ServiceAccountPassword environment variable "
+ "(appsettings now ships a ${secret:} token that this suite does not expand). "
+ "Set it before running.");
}
return options;
}
}
@@ -82,6 +82,9 @@ public static class GatewayApplication
.BuildServiceProvider())
#pragma warning restore ASP0000
{
// Intentionally unconditional: the pre-host expander below needs the secrets
// store schema to exist before the first ${secret:} resolve. Secrets:RunMigrationsOnStartup
// governs only the runtime SecretsMigrationHostedService, not this bootstrap path.
secretsProvider.GetRequiredService<SqliteSecretsStoreMigrator>()
.MigrateAsync(default).GetAwaiter().GetResult();
var resolver = secretsProvider.GetRequiredService<ISecretResolver>();