Merge branch 'fix/sec-36-ldap-secret'
ci / windows-x86 (push) Successful in 1m16s
ci / nightly-windev (push) Has been skipped
ci / java (push) Successful in 2m31s
ci / portable (push) Failing after 4m37s

This commit is contained in:
Joseph Doherty
2026-08-07 07:44:43 -04:00
11 changed files with 163 additions and 16 deletions
@@ -145,7 +145,12 @@ public sealed class GatewayOptionsValidator : OptionsValidatorBase<GatewayOption
builder);
AddIfBlank(
options.ServiceAccountPassword,
"MxGateway:Ldap:ServiceAccountPassword is required when LDAP login is enabled.",
"MxGateway:Ldap:ServiceAccountPassword is required when LDAP login is enabled. "
+ "Never commit it: on dev boxes set user-secrets "
+ "(dotnet user-secrets set \"MxGateway:Ldap:ServiceAccountPassword\" <value>); "
+ "on deployed hosts set the environment variable "
+ "MxGateway__Ldap__ServiceAccountPassword. "
+ "(appsettings.json ships the ${secret:ldap/mxgateway/bind} store reference as the default.)",
builder);
AddIfBlank(
options.UserNameAttribute,
@@ -2,6 +2,10 @@
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<!-- Dev-box channel for MxGateway:Ldap:ServiceAccountPassword (SEC-36): user-secrets
are loaded automatically in the Development environment and live under the user
profile, outside the tree, so the shared GLAuth bind credential is never committed. -->
<UserSecretsId>mxaccessgw-server</UserSecretsId>
</PropertyGroup>
<ItemGroup>
@@ -757,9 +757,15 @@ public sealed class GatewayOptionsValidatorTests
new LdapOptions { Enabled = true, ServiceAccountPassword = string.Empty });
ValidateOptionsResult result = new GatewayOptionsValidator().Validate(null, options);
Assert.True(result.Failed);
Assert.Contains(
string failure = Assert.Single(
result.Failures!,
f => f.Contains("MxGateway:Ldap:ServiceAccountPassword is required when LDAP login is enabled."));
// SEC-36: the message must steer the operator to the two supported out-of-band channels
// (dev user-secrets, deployed env var) so a blanked/unresolved credential never gets
// "fixed" by re-committing a value.
Assert.Contains("dotnet user-secrets set", failure);
Assert.Contains("MxGateway__Ldap__ServiceAccountPassword", failure);
}
private static GatewayOptions WithSecurity(SecurityOptions security)