fix(harness): swap retired bitnami/openldap for GLAuth in the Host real-LDAP mode
v2-ci / build (pull_request) Successful in 4m13s
v2-ci / unit-tests (pull_request) Failing after 10m18s

The Host.IntegrationTests opt-in real-LDAP mode (OTOPCUA_HARNESS_USE_LDAP=1)
used bitnami/openldap:2.6, gone since Bitnami deprecated their free image
catalog in 2025. Replaced it with GLAuth — the same LDAP server the rest of
the project already uses (docker-dev + the live OPC UA data-plane auth, both
against the shared GLAuth on :3893) — removing the lone OpenLDAP outlier and
the gone-image breakage.

- Added tests/.../Host.IntegrationTests/glauth/config.toml: baseDN dc=zb,dc=local,
  a search-capable serviceaccount, dev users alice (full access) / bob (read-only),
  and role groups with the same gidnumbers as scadaproj/infra/glauth so GroupToRole
  maps identically.
- Compose ldap service -> glauth/glauth:latest, mounting the config, host :3894 -> :3893.
- Repointed the harness real-LDAP override from the OpenLDAP cn=admin/ldapadmin to
  GLAuth's cn=serviceaccount/serviceaccount123.

Live-verified against a deployed container on :3894: the serviceaccount bind
searches and returns alice + her 5 memberOf groups; alice/bob bind with the
correct password; a wrong password yields Invalid credentials (49) — exactly the
OtOpcUaLdapAuthService flow (proven identical to the data-plane's shared-GLAuth path).

NB: real-LDAP mode is opt-in; the default Host run uses StubLdapAuthService, so
this never blocked the default suite. Integration-sweep follow-up #6 (LDAP leg);
the amd64-emulated-SQL deadline leg remains open.
This commit is contained in:
Joseph Doherty
2026-07-15 06:03:50 -04:00
parent 18481f3d11
commit 3a48eb0c70
5 changed files with 125 additions and 31 deletions
@@ -38,7 +38,7 @@ namespace ZB.MOM.WW.OtOpcUa.Host.IntegrationTests;
/// database name (<c>OtOpcUa_Harness_{guid}</c>) created via <c>EnsureCreated</c>
/// and dropped via <c>EnsureDeleted</c> on dispose.</item>
/// <item><c>OTOPCUA_HARNESS_USE_LDAP=1</c> → drop the stub and point <c>LdapAuthService</c>
/// at OpenLDAP on <c>localhost:3894</c>.</item>
/// at the GLAuth container on <c>localhost:3894</c> (see Docker/glauth/config.toml).</item>
/// </list>
///
/// <para>Why not <c>WebApplicationFactory&lt;Program&gt;</c>? Program.cs reads <c>OTOPCUA_ROLES</c>
@@ -300,8 +300,10 @@ public sealed class TwoNodeClusterHarness : IAsyncDisposable
configOverrides["Security:Ldap:Transport"] = "None";
configOverrides["Security:Ldap:AllowInsecure"] = "true";
configOverrides["Security:Ldap:SearchBase"] = "dc=zb,dc=local";
configOverrides["Security:Ldap:ServiceAccountDn"] = "cn=admin,dc=zb,dc=local";
configOverrides["Security:Ldap:ServiceAccountPassword"] = "ldapadmin";
// GLAuth's search-capable bind account (see Docker/glauth/config.toml) — matches the
// shared GLAuth the data-plane binds against. Replaced the retired OpenLDAP cn=admin.
configOverrides["Security:Ldap:ServiceAccountDn"] = "cn=serviceaccount,dc=zb,dc=local";
configOverrides["Security:Ldap:ServiceAccountPassword"] = "serviceaccount123";
}
builder.Configuration.AddInMemoryCollection(configOverrides);