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, "Port": 3893,
"Transport": "None", "Transport": "None",
"AllowInsecure": true, "AllowInsecure": true,
"SearchBase": "dc=scadabridge,dc=local", "SearchBase": "dc=zb,dc=local",
"ServiceAccountDn": "cn=admin,dc=scadabridge,dc=local", "ServiceAccountDn": "cn=admin,dc=zb,dc=local",
"ServiceAccountPassword": "password" "ServiceAccountPassword": "password"
}, },
"JwtSigningKey": "scadabridge-env2-dev-jwt-signing-key-must-be-at-least-32-characters-long", "JwtSigningKey": "scadabridge-env2-dev-jwt-signing-key-must-be-at-least-32-characters-long",
@@ -27,8 +27,8 @@
"Port": 3893, "Port": 3893,
"Transport": "None", "Transport": "None",
"AllowInsecure": true, "AllowInsecure": true,
"SearchBase": "dc=scadabridge,dc=local", "SearchBase": "dc=zb,dc=local",
"ServiceAccountDn": "cn=admin,dc=scadabridge,dc=local", "ServiceAccountDn": "cn=admin,dc=zb,dc=local",
"ServiceAccountPassword": "password" "ServiceAccountPassword": "password"
}, },
"JwtSigningKey": "scadabridge-env2-dev-jwt-signing-key-must-be-at-least-32-characters-long", "JwtSigningKey": "scadabridge-env2-dev-jwt-signing-key-must-be-at-least-32-characters-long",
@@ -27,8 +27,8 @@
"Port": 3893, "Port": 3893,
"Transport": "None", "Transport": "None",
"AllowInsecure": true, "AllowInsecure": true,
"SearchBase": "dc=scadabridge,dc=local", "SearchBase": "dc=zb,dc=local",
"ServiceAccountDn": "cn=admin,dc=scadabridge,dc=local", "ServiceAccountDn": "cn=admin,dc=zb,dc=local",
"ServiceAccountPassword": "password" "ServiceAccountPassword": "password"
}, },
"JwtSigningKey": "scadabridge-dev-jwt-signing-key-must-be-at-least-32-characters-long", "JwtSigningKey": "scadabridge-dev-jwt-signing-key-must-be-at-least-32-characters-long",
@@ -27,8 +27,8 @@
"Port": 3893, "Port": 3893,
"Transport": "None", "Transport": "None",
"AllowInsecure": true, "AllowInsecure": true,
"SearchBase": "dc=scadabridge,dc=local", "SearchBase": "dc=zb,dc=local",
"ServiceAccountDn": "cn=admin,dc=scadabridge,dc=local", "ServiceAccountDn": "cn=admin,dc=zb,dc=local",
"ServiceAccountPassword": "password" "ServiceAccountPassword": "password"
}, },
"JwtSigningKey": "scadabridge-dev-jwt-signing-key-must-be-at-least-32-characters-long", "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": { "Ldap": {
"Server": "localhost", "Server": "localhost",
"Port": 3893, "Port": 3893,
"BaseDN": "dc=scadabridge,dc=local", "BaseDN": "dc=zb,dc=local",
"UseSsl": false "UseSsl": false
}, },
"OpcUa": { "OpcUa": {
+12 -12
View File
@@ -12,7 +12,7 @@ The test LDAP server uses [GLAuth](https://glauth.github.io/), a lightweight LDA
## Base DN ## Base DN
``` ```
dc=scadabridge,dc=local dc=zb,dc=local
``` ```
## Test Users ## 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: 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: The full DNs for all test users:
| Username | Full DN | | Username | Full DN |
|----------|---------| |----------|---------|
| `admin` | `cn=admin,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=scadabridge,dc=local` | | `designer` | `cn=designer,ou=SCADA-Designers,ou=users,dc=zb,dc=local` |
| `deployer` | `cn=deployer,ou=SCADA-Deploy-All,ou=users,dc=scadabridge,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=scadabridge,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=scadabridge,dc=local` | | `multi-role` | `cn=multi-role,ou=SCADA-Admins,ou=users,dc=zb,dc=local` |
## Verification ## Verification
@@ -68,9 +68,9 @@ docker ps --filter name=scadabridge-ldap
```bash ```bash
ldapsearch -H ldap://localhost:3893 \ 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 \ -w password \
-b "dc=scadabridge,dc=local" \ -b "dc=zb,dc=local" \
"(objectClass=*)" "(objectClass=*)"
``` ```
@@ -78,9 +78,9 @@ ldapsearch -H ldap://localhost:3893 \
```bash ```bash
ldapsearch -H ldap://localhost:3893 \ 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 \ -w password \
-b "dc=scadabridge,dc=local" \ -b "dc=zb,dc=local" \
"(cn=multi-role)" "(cn=multi-role)"
``` ```
+1 -1
View File
@@ -7,7 +7,7 @@
[backend] [backend]
datastore = "config" datastore = "config"
baseDN = "dc=scadabridge,dc=local" baseDN = "dc=zb,dc=local"
# ── Groups ────────────────────────────────────────────────────────── # ── Groups ──────────────────────────────────────────────────────────
+3 -3
View File
@@ -9,10 +9,10 @@ from ldap3 import Server, Connection, NONE, SUBTREE, SIMPLE
DEFAULT_HOST = "localhost" DEFAULT_HOST = "localhost"
DEFAULT_PORT = 3893 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=... # GLAuth places users under ou=<PrimaryGroupName>,ou=users,dc=...
# The admin user (primarygroup SCADA-Admins) needs search capabilities in config. # 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" DEFAULT_BIND_PASSWORD = "password"
@@ -48,7 +48,7 @@ def cmd_check(args):
def cmd_bind(args): def cmd_bind(args):
"""Test user authentication via bind. """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 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. to discover the full DN, then rebind with that DN.
""" """
@@ -28,8 +28,8 @@
"Port": 3893, "Port": 3893,
"Transport": "None", "Transport": "None",
"AllowInsecure": true, "AllowInsecure": true,
"SearchBase": "dc=scadabridge,dc=local", "SearchBase": "dc=zb,dc=local",
"ServiceAccountDn": "cn=admin,dc=scadabridge,dc=local", "ServiceAccountDn": "cn=admin,dc=zb,dc=local",
"ServiceAccountPassword": "${SCADABRIDGE_LDAP_SERVICE_ACCOUNT_PASSWORD}" "ServiceAccountPassword": "${SCADABRIDGE_LDAP_SERVICE_ACCOUNT_PASSWORD}"
}, },
"JwtSigningKey": "${SCADABRIDGE_JWT_SIGNING_KEY}", "JwtSigningKey": "${SCADABRIDGE_JWT_SIGNING_KEY}",
@@ -57,8 +57,8 @@ public class CentralActorPathTests : IAsyncLifetime
["ScadaBridge:Security:Ldap:Port"] = "3893", ["ScadaBridge:Security:Ldap:Port"] = "3893",
["ScadaBridge:Security:Ldap:Transport"] = "None", ["ScadaBridge:Security:Ldap:Transport"] = "None",
["ScadaBridge:Security:Ldap:AllowInsecure"] = "true", ["ScadaBridge:Security:Ldap:AllowInsecure"] = "true",
["ScadaBridge:Security:Ldap:SearchBase"] = "dc=scadabridge,dc=local", ["ScadaBridge:Security:Ldap:SearchBase"] = "dc=zb,dc=local",
["ScadaBridge:Security:Ldap:ServiceAccountDn"] = "cn=admin,dc=scadabridge,dc=local", ["ScadaBridge:Security:Ldap:ServiceAccountDn"] = "cn=admin,dc=zb,dc=local",
}); });
}); });
builder.UseSetting("ScadaBridge:Node:Role", "Central"); builder.UseSetting("ScadaBridge:Node:Role", "Central");
@@ -121,8 +121,8 @@ public class CentralAuditWiringTests : IDisposable
["ScadaBridge:Security:Ldap:Port"] = "3893", ["ScadaBridge:Security:Ldap:Port"] = "3893",
["ScadaBridge:Security:Ldap:Transport"] = "None", ["ScadaBridge:Security:Ldap:Transport"] = "None",
["ScadaBridge:Security:Ldap:AllowInsecure"] = "true", ["ScadaBridge:Security:Ldap:AllowInsecure"] = "true",
["ScadaBridge:Security:Ldap:SearchBase"] = "dc=scadabridge,dc=local", ["ScadaBridge:Security:Ldap:SearchBase"] = "dc=zb,dc=local",
["ScadaBridge:Security:Ldap:ServiceAccountDn"] = "cn=admin,dc=scadabridge,dc=local", ["ScadaBridge:Security:Ldap:ServiceAccountDn"] = "cn=admin,dc=zb,dc=local",
["ScadaBridge:InboundApi:ApiKeyPepper"] = "test-inbound-api-key-pepper-at-least-32-chars!", ["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:Port"] = "3893",
["ScadaBridge:Security:Ldap:Transport"] = "None", ["ScadaBridge:Security:Ldap:Transport"] = "None",
["ScadaBridge:Security:Ldap:AllowInsecure"] = "true", ["ScadaBridge:Security:Ldap:AllowInsecure"] = "true",
["ScadaBridge:Security:Ldap:SearchBase"] = "dc=scadabridge,dc=local", ["ScadaBridge:Security:Ldap:SearchBase"] = "dc=zb,dc=local",
["ScadaBridge:Security:Ldap:ServiceAccountDn"] = "cn=admin,dc=scadabridge,dc=local", ["ScadaBridge:Security:Ldap:ServiceAccountDn"] = "cn=admin,dc=zb,dc=local",
// Auth re-arch (C5): inbound-API keys live in the shared // Auth re-arch (C5): inbound-API keys live in the shared
// ZB.MOM.WW.Auth.ApiKeys SQLite store. The verifier reuses // ZB.MOM.WW.Auth.ApiKeys SQLite store. The verifier reuses
// this same config key as its pepper secret (PepperSecretName), // this same config key as its pepper secret (PepperSecretName),
@@ -107,7 +107,7 @@ public class AuthFlowTests : IClassFixture<ScadaBridgeWebApplicationFactory>
public async Task LoginEndpoint_WithValidLdapCredentials_SetsCookieAndRedirects() public async Task LoginEndpoint_WithValidLdapCredentials_SetsCookieAndRedirects()
{ {
// Requires GLAuth test LDAP server: docker compose -f infra/docker-compose.yml up -d glauth // 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()) if (!await IsLdapAvailableAsync())
{ {
// Skip gracefully if GLAuth not running — not a test failure // 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__Port"] = "3893",
["ScadaBridge__Security__Ldap__Transport"] = "None", ["ScadaBridge__Security__Ldap__Transport"] = "None",
["ScadaBridge__Security__Ldap__AllowInsecure"] = "true", ["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 // 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: // 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. // 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", ["ScadaBridge__Security__Ldap__ServiceAccountPassword"] = "password",
}; };