chore(auth): ScadaBridge unify dev LDAP base DN to dc=zb,dc=local (Task 1.6)

Replace dc=scadabridge,dc=local with dc=zb,dc=local in all dev/test LDAP
references — app config, docker test-cluster node configs (docker/ and
docker-env2/), GLAuth fixture, dev tooling, Host.Tests fixtures,
IntegrationTests factory, and operational test_infra docs. OU structure
(ou=SCADA-Admins,ou=users,etc.) preserved throughout. Email domains
(@scadabridge.local), hostnames, and container names are untouched.
Historical plan docs (2026-05-24-second-environment.md,
2026-05-31-folder-repo-rename-scadabridge-design.md) excluded as
point-in-time records. No synthetic dc=example,dc=com placeholders touched.
This commit is contained in:
Joseph Doherty
2026-06-02 06:54:14 -04:00
parent c185a567f5
commit 6ae605160c
14 changed files with 36 additions and 36 deletions
@@ -27,8 +27,8 @@
"Port": 3893,
"Transport": "None",
"AllowInsecure": true,
"SearchBase": "dc=scadabridge,dc=local",
"ServiceAccountDn": "cn=admin,dc=scadabridge,dc=local",
"SearchBase": "dc=zb,dc=local",
"ServiceAccountDn": "cn=admin,dc=zb,dc=local",
"ServiceAccountPassword": "password"
},
"JwtSigningKey": "scadabridge-env2-dev-jwt-signing-key-must-be-at-least-32-characters-long",
@@ -27,8 +27,8 @@
"Port": 3893,
"Transport": "None",
"AllowInsecure": true,
"SearchBase": "dc=scadabridge,dc=local",
"ServiceAccountDn": "cn=admin,dc=scadabridge,dc=local",
"SearchBase": "dc=zb,dc=local",
"ServiceAccountDn": "cn=admin,dc=zb,dc=local",
"ServiceAccountPassword": "password"
},
"JwtSigningKey": "scadabridge-env2-dev-jwt-signing-key-must-be-at-least-32-characters-long",
@@ -27,8 +27,8 @@
"Port": 3893,
"Transport": "None",
"AllowInsecure": true,
"SearchBase": "dc=scadabridge,dc=local",
"ServiceAccountDn": "cn=admin,dc=scadabridge,dc=local",
"SearchBase": "dc=zb,dc=local",
"ServiceAccountDn": "cn=admin,dc=zb,dc=local",
"ServiceAccountPassword": "password"
},
"JwtSigningKey": "scadabridge-dev-jwt-signing-key-must-be-at-least-32-characters-long",
@@ -27,8 +27,8 @@
"Port": 3893,
"Transport": "None",
"AllowInsecure": true,
"SearchBase": "dc=scadabridge,dc=local",
"ServiceAccountDn": "cn=admin,dc=scadabridge,dc=local",
"SearchBase": "dc=zb,dc=local",
"ServiceAccountDn": "cn=admin,dc=zb,dc=local",
"ServiceAccountPassword": "password"
},
"JwtSigningKey": "scadabridge-dev-jwt-signing-key-must-be-at-least-32-characters-long",
+1 -1
View File
@@ -67,7 +67,7 @@ For use in `appsettings.Development.json`:
"Ldap": {
"Server": "localhost",
"Port": 3893,
"BaseDN": "dc=scadabridge,dc=local",
"BaseDN": "dc=zb,dc=local",
"UseSsl": false
},
"OpcUa": {
+12 -12
View File
@@ -12,7 +12,7 @@ The test LDAP server uses [GLAuth](https://glauth.github.io/), a lightweight LDA
## Base DN
```
dc=scadabridge,dc=local
dc=zb,dc=local
```
## Test Users
@@ -41,20 +41,20 @@ All users have the password `password`.
Users bind with their full DN, which includes the primary group as an OU:
```
cn=<username>,ou=<PrimaryGroupName>,ou=users,dc=scadabridge,dc=local
cn=<username>,ou=<PrimaryGroupName>,ou=users,dc=zb,dc=local
```
For example: `cn=admin,ou=SCADA-Admins,ou=users,dc=scadabridge,dc=local`
For example: `cn=admin,ou=SCADA-Admins,ou=users,dc=zb,dc=local`
The full DNs for all test users:
| Username | Full DN |
|----------|---------|
| `admin` | `cn=admin,ou=SCADA-Admins,ou=users,dc=scadabridge,dc=local` |
| `designer` | `cn=designer,ou=SCADA-Designers,ou=users,dc=scadabridge,dc=local` |
| `deployer` | `cn=deployer,ou=SCADA-Deploy-All,ou=users,dc=scadabridge,dc=local` |
| `site-deployer` | `cn=site-deployer,ou=SCADA-Deploy-SiteA,ou=users,dc=scadabridge,dc=local` |
| `multi-role` | `cn=multi-role,ou=SCADA-Admins,ou=users,dc=scadabridge,dc=local` |
| `admin` | `cn=admin,ou=SCADA-Admins,ou=users,dc=zb,dc=local` |
| `designer` | `cn=designer,ou=SCADA-Designers,ou=users,dc=zb,dc=local` |
| `deployer` | `cn=deployer,ou=SCADA-Deploy-All,ou=users,dc=zb,dc=local` |
| `site-deployer` | `cn=site-deployer,ou=SCADA-Deploy-SiteA,ou=users,dc=zb,dc=local` |
| `multi-role` | `cn=multi-role,ou=SCADA-Admins,ou=users,dc=zb,dc=local` |
## Verification
@@ -68,9 +68,9 @@ docker ps --filter name=scadabridge-ldap
```bash
ldapsearch -H ldap://localhost:3893 \
-D "cn=admin,ou=SCADA-Admins,ou=users,dc=scadabridge,dc=local" \
-D "cn=admin,ou=SCADA-Admins,ou=users,dc=zb,dc=local" \
-w password \
-b "dc=scadabridge,dc=local" \
-b "dc=zb,dc=local" \
"(objectClass=*)"
```
@@ -78,9 +78,9 @@ ldapsearch -H ldap://localhost:3893 \
```bash
ldapsearch -H ldap://localhost:3893 \
-D "cn=admin,ou=SCADA-Admins,ou=users,dc=scadabridge,dc=local" \
-D "cn=admin,ou=SCADA-Admins,ou=users,dc=zb,dc=local" \
-w password \
-b "dc=scadabridge,dc=local" \
-b "dc=zb,dc=local" \
"(cn=multi-role)"
```
+1 -1
View File
@@ -7,7 +7,7 @@
[backend]
datastore = "config"
baseDN = "dc=scadabridge,dc=local"
baseDN = "dc=zb,dc=local"
# ── Groups ──────────────────────────────────────────────────────────
+3 -3
View File
@@ -9,10 +9,10 @@ from ldap3 import Server, Connection, NONE, SUBTREE, SIMPLE
DEFAULT_HOST = "localhost"
DEFAULT_PORT = 3893
DEFAULT_BASE_DN = "dc=scadabridge,dc=local"
DEFAULT_BASE_DN = "dc=zb,dc=local"
# GLAuth places users under ou=<PrimaryGroupName>,ou=users,dc=...
# The admin user (primarygroup SCADA-Admins) needs search capabilities in config.
DEFAULT_BIND_DN = "cn=admin,ou=SCADA-Admins,ou=users,dc=scadabridge,dc=local"
DEFAULT_BIND_DN = "cn=admin,ou=SCADA-Admins,ou=users,dc=zb,dc=local"
DEFAULT_BIND_PASSWORD = "password"
@@ -48,7 +48,7 @@ def cmd_check(args):
def cmd_bind(args):
"""Test user authentication via bind.
GLAuth DN format: cn=<user>,ou=<PrimaryGroup>,ou=users,dc=scadabridge,dc=local
GLAuth DN format: cn=<user>,ou=<PrimaryGroup>,ou=users,dc=zb,dc=local
Since we don't know the user's primary group upfront, we search for the user first
to discover the full DN, then rebind with that DN.
"""
@@ -28,8 +28,8 @@
"Port": 3893,
"Transport": "None",
"AllowInsecure": true,
"SearchBase": "dc=scadabridge,dc=local",
"ServiceAccountDn": "cn=admin,dc=scadabridge,dc=local",
"SearchBase": "dc=zb,dc=local",
"ServiceAccountDn": "cn=admin,dc=zb,dc=local",
"ServiceAccountPassword": "${SCADABRIDGE_LDAP_SERVICE_ACCOUNT_PASSWORD}"
},
"JwtSigningKey": "${SCADABRIDGE_JWT_SIGNING_KEY}",
@@ -57,8 +57,8 @@ public class CentralActorPathTests : IAsyncLifetime
["ScadaBridge:Security:Ldap:Port"] = "3893",
["ScadaBridge:Security:Ldap:Transport"] = "None",
["ScadaBridge:Security:Ldap:AllowInsecure"] = "true",
["ScadaBridge:Security:Ldap:SearchBase"] = "dc=scadabridge,dc=local",
["ScadaBridge:Security:Ldap:ServiceAccountDn"] = "cn=admin,dc=scadabridge,dc=local",
["ScadaBridge:Security:Ldap:SearchBase"] = "dc=zb,dc=local",
["ScadaBridge:Security:Ldap:ServiceAccountDn"] = "cn=admin,dc=zb,dc=local",
});
});
builder.UseSetting("ScadaBridge:Node:Role", "Central");
@@ -121,8 +121,8 @@ public class CentralAuditWiringTests : IDisposable
["ScadaBridge:Security:Ldap:Port"] = "3893",
["ScadaBridge:Security:Ldap:Transport"] = "None",
["ScadaBridge:Security:Ldap:AllowInsecure"] = "true",
["ScadaBridge:Security:Ldap:SearchBase"] = "dc=scadabridge,dc=local",
["ScadaBridge:Security:Ldap:ServiceAccountDn"] = "cn=admin,dc=scadabridge,dc=local",
["ScadaBridge:Security:Ldap:SearchBase"] = "dc=zb,dc=local",
["ScadaBridge:Security:Ldap:ServiceAccountDn"] = "cn=admin,dc=zb,dc=local",
["ScadaBridge:InboundApi:ApiKeyPepper"] = "test-inbound-api-key-pepper-at-least-32-chars!",
});
});
@@ -116,8 +116,8 @@ public class CentralCompositionRootTests : IDisposable
["ScadaBridge:Security:Ldap:Port"] = "3893",
["ScadaBridge:Security:Ldap:Transport"] = "None",
["ScadaBridge:Security:Ldap:AllowInsecure"] = "true",
["ScadaBridge:Security:Ldap:SearchBase"] = "dc=scadabridge,dc=local",
["ScadaBridge:Security:Ldap:ServiceAccountDn"] = "cn=admin,dc=scadabridge,dc=local",
["ScadaBridge:Security:Ldap:SearchBase"] = "dc=zb,dc=local",
["ScadaBridge:Security:Ldap:ServiceAccountDn"] = "cn=admin,dc=zb,dc=local",
// Auth re-arch (C5): inbound-API keys live in the shared
// ZB.MOM.WW.Auth.ApiKeys SQLite store. The verifier reuses
// this same config key as its pepper secret (PepperSecretName),
@@ -107,7 +107,7 @@ public class AuthFlowTests : IClassFixture<ScadaBridgeWebApplicationFactory>
public async Task LoginEndpoint_WithValidLdapCredentials_SetsCookieAndRedirects()
{
// Requires GLAuth test LDAP server: docker compose -f infra/docker-compose.yml up -d glauth
// GLAuth runs on localhost:3893, baseDN dc=scadabridge,dc=local, all passwords "password"
// GLAuth runs on localhost:3893, baseDN dc=zb,dc=local, all passwords "password"
if (!await IsLdapAvailableAsync())
{
// Skip gracefully if GLAuth not running — not a test failure
@@ -45,11 +45,11 @@ public class ScadaBridgeWebApplicationFactory : WebApplicationFactory<Program>
["ScadaBridge__Security__Ldap__Port"] = "3893",
["ScadaBridge__Security__Ldap__Transport"] = "None",
["ScadaBridge__Security__Ldap__AllowInsecure"] = "true",
["ScadaBridge__Security__Ldap__SearchBase"] = "dc=scadabridge,dc=local",
["ScadaBridge__Security__Ldap__SearchBase"] = "dc=zb,dc=local",
// GLAuth places users at cn=<name>,ou=<group>,ou=users,dc=... — a service
// account is configured to enable the shared service's search-then-bind:
// resolve the user's real DN by (UserNameAttribute=<name>) lookup, then bind it.
["ScadaBridge__Security__Ldap__ServiceAccountDn"] = "cn=admin,ou=SCADA-Admins,ou=users,dc=scadabridge,dc=local",
["ScadaBridge__Security__Ldap__ServiceAccountDn"] = "cn=admin,ou=SCADA-Admins,ou=users,dc=zb,dc=local",
["ScadaBridge__Security__Ldap__ServiceAccountPassword"] = "password",
};