From bd929d98fc7df7535c9de57b106d49aa0f3b98b1 Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Thu, 13 Aug 2026 09:17:42 -0400 Subject: [PATCH] docs(ldap): e2e NAM AD login verified via HG docker -- svc_igntadmin, stage diagnostics --- ldap_setup.md | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/ldap_setup.md b/ldap_setup.md index 238478d..38474c2 100644 --- a/ldap_setup.md +++ b/ldap_setup.md @@ -142,6 +142,40 @@ Two refinements to the TLS notes above, from the actual chain a .NET client sees Cert observed on nam1: `CN=USWAP-VDC-NAM1.nam.zimmer.com`, SAN matches, sha256RSA, valid 2026-03-20 → 2027-03-20, chain `leaf ← zimmer-issueca1 ← zimmer-rootca`. +### End-to-end app login verified 2026-08-13 (HistorianGateway docker → real NAM AD) + +A real ZB.MOM.WW app authenticated a real user against the production directory for the +first time: the local HistorianGateway container (Auth `0.2.1`) with its dashboard LDAP +temporarily flipped from the glauth-redundant pair to the two NAM DCs — LDAPS 636, +`AllowInsecure` (the container trust store lacks `zimmer-rootca`), domain-root +`SearchBase`, `sAMAccountName` login, `memberOf` → bare-CN `UG_WW_*` keys in +`Dashboard:GroupToRole`. Login succeeded and the group mapping resolved to a dashboard +role. The flip is an **uncommitted working-tree change** in +`HistorianGateway/docker/docker-compose.yml` (revert: `git checkout -- docker/docker-compose.yml` ++ remove the `Ldap__ServiceAccountPassword` line from `histgw.secrets.env`). + +Three findings worth keeping: + +- **The service account for our use is `svc_igntadmin@nam.zimmer.com` — not + `svc_igntnapp`.** `svc_igntnapp` is *Ignition's* account (the "Bind identity" section + above describes Ignition's config); binding it with our held password fails + `data 52e` (bad credential). ldapprobe's built-in default is `svc_igntnapp` — pass + `--svc svc_igntadmin@nam.zimmer.com` when probing with the held password. +- **The failover log's failure *stage* is a precise diagnostic.** Seen live: + `failed system-side at search` on both DCs = the service password is **empty** + (AD treats a passwordless simple bind as anonymous, accepts it, then refuses the + search); `failed system-side at service-bind` = the credential is **wrong** (52e); + a clean "invalid or not authorized" with **no** WRN lines = the directory answered + and the user is unknown or matched zero mapped groups (fail-closed). +- **Failed logins double against lockout policy** (5 attempts / 15 min): a bad + *service* credential costs one failed bind on **each** DC per attempt, because the + endpoint walk retries system-side failures on the fallback. Validate a candidate + service password with a single `ldapsearch -H ldaps://uswap-vdc-nam1… -x -D -W` + before letting an app loop on it. + +The Debian-based .NET 10 container handshook LDAPS 636 to both DCs without the +`SECLEVEL` workaround mentioned above being needed. + ### `UG_WW_*` — an existing Wonderware group convention (observed 2026-08-12) **This partly overturns the "Groups / roles" section above.** That section is accurate