fix(harness): swap retired bitnami/openldap for GLAuth in the Host real-LDAP mode
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:
@@ -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<Program></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);
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
#
|
||||
# 1. EF behaviors that diverge between provider implementations — index uniqueness,
|
||||
# RowVersion concurrency, JSON column round-trips, EF migration application.
|
||||
# 2. Real LDAP binds against an OpenLDAP server with the dev users from
|
||||
# C:\publish\glauth\auth.md.
|
||||
# 2. Real LDAP binds against a GLAuth server (./glauth/config.toml) with dev users
|
||||
# alice (full access) / bob (read-only) and the cn=serviceaccount bind account.
|
||||
#
|
||||
# Activate by setting these env vars before running the suite:
|
||||
#
|
||||
@@ -43,15 +43,13 @@ services:
|
||||
retries: 20
|
||||
|
||||
ldap:
|
||||
# OpenLDAP image — same one docker-dev/ uses, just on a different port. Dev users
|
||||
# alice/bob match the GLAuth fixtures so AuthEndpoints contract tests share creds.
|
||||
image: bitnami/openldap:2.6
|
||||
environment:
|
||||
LDAP_ROOT: "dc=zb,dc=local"
|
||||
LDAP_ADMIN_USERNAME: "admin"
|
||||
LDAP_ADMIN_PASSWORD: "ldapadmin"
|
||||
LDAP_USERS: "alice,bob"
|
||||
LDAP_PASSWORDS: "alice123,bob123"
|
||||
LDAP_USER_DC: "ou=FleetAdmin"
|
||||
# GLAuth — the same LDAP server the rest of the project uses (docker-dev + the live
|
||||
# OPC UA data-plane auth, both against the shared GLAuth on :3893). Replaced the retired
|
||||
# bitnami/openldap:2.6 (Bitnami deprecated their free catalog in 2025). Seeded by
|
||||
# ./glauth/config.toml with a search-capable serviceaccount + dev users alice/bob.
|
||||
# Listens on :3893 in-container; mapped to host :3894 to run beside docker-dev's :3893.
|
||||
image: glauth/glauth:latest
|
||||
volumes:
|
||||
- ./glauth/config.toml:/app/config/config.cfg:ro
|
||||
ports:
|
||||
- "3894:1389"
|
||||
- "3894:3893"
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
# GLAuth config for the Host.IntegrationTests real-LDAP mode (OTOPCUA_HARNESS_USE_LDAP=1).
|
||||
#
|
||||
# Replaces the retired bitnami/openldap:2.6 image (Bitnami deprecated their free catalog
|
||||
# in 2025) with GLAuth — the same LDAP server the rest of the project uses (docker-dev +
|
||||
# the live OPC UA data-plane auth, both against the shared GLAuth on 10.100.0.35:3893).
|
||||
# Unifying on GLAuth removes the lone OpenLDAP outlier and the gone-image breakage.
|
||||
#
|
||||
# Mirrors scadaproj/infra/glauth/config.toml (source of truth) but trimmed to the harness's
|
||||
# needs: baseDN dc=zb,dc=local, a search-capable service account, and two dev users
|
||||
# (alice = full-access, bob = read-only). Bind DN form is GLAuth's cn=<name>,dc=zb,dc=local.
|
||||
#
|
||||
# Listens on :3893 inside the container; the compose maps host :3894 -> :3893 so this runs
|
||||
# side-by-side with docker-dev's shared GLAuth (:3893) without a port clash.
|
||||
|
||||
[ldap]
|
||||
enabled = true
|
||||
listen = "0.0.0.0:3893"
|
||||
|
||||
[ldaps]
|
||||
enabled = false
|
||||
|
||||
[backend]
|
||||
datastore = "config"
|
||||
baseDN = "dc=zb,dc=local"
|
||||
|
||||
[behaviors]
|
||||
# Tests may bind bad passwords on purpose (outage / wrong-cred paths) — don't lock out.
|
||||
LimitFailedBinds = false
|
||||
|
||||
# ── Groups (gidnumbers match scadaproj/infra/glauth so GroupToRole maps identically) ──
|
||||
[[groups]]
|
||||
name = "ReadOnly"
|
||||
gidnumber = 5601
|
||||
[[groups]]
|
||||
name = "WriteOperate"
|
||||
gidnumber = 5602
|
||||
[[groups]]
|
||||
name = "WriteTune"
|
||||
gidnumber = 5603
|
||||
[[groups]]
|
||||
name = "WriteConfigure"
|
||||
gidnumber = 5604
|
||||
[[groups]]
|
||||
name = "AlarmAck"
|
||||
gidnumber = 5605
|
||||
|
||||
# ── Users ─────────────────────────────────────────────────────────────
|
||||
# Service account the harness binds first to search for the user entry.
|
||||
# DN: cn=serviceaccount,dc=zb,dc=local password: serviceaccount123
|
||||
[[users]]
|
||||
name = "serviceaccount"
|
||||
uidnumber = 5999
|
||||
primarygroup = 5601
|
||||
passsha256 = "af29d0e5c9801ae98a999ed3915e1cf428a64b4b62b3cf221b6336cce0398419"
|
||||
[[users.capabilities]]
|
||||
action = "search"
|
||||
object = "*"
|
||||
|
||||
# alice — full access (member of every write/ack role group). password: alice123
|
||||
[[users]]
|
||||
name = "alice"
|
||||
givenname = "Alice"
|
||||
sn = "Admin"
|
||||
mail = "alice@zb.local"
|
||||
uidnumber = 5010
|
||||
primarygroup = 5604
|
||||
othergroups = [5601, 5602, 5603, 5605]
|
||||
passsha256 = "4e40e8ffe0ee32fa53e139147ed559229a5930f89c2204706fc174beb36210b3"
|
||||
|
||||
# bob — read-only. password: bob123
|
||||
[[users]]
|
||||
name = "bob"
|
||||
givenname = "Bob"
|
||||
sn = "Reader"
|
||||
mail = "bob@zb.local"
|
||||
uidnumber = 5011
|
||||
primarygroup = 5601
|
||||
passsha256 = "8d059c3640b97180dd2ee453e20d34ab0cb0f2eccbe87d01915a8e578a202b11"
|
||||
Reference in New Issue
Block a user