docs(ldap): NAM AD setup notes + live TLS probe results; backup-DC failover design (Auth 0.2.0)
This commit is contained in:
+104
@@ -0,0 +1,104 @@
|
||||
# Zimmer NAM — LDAP / Active Directory Auth Setup
|
||||
|
||||
Reference for configuring services to authenticate against the Zimmer NAM domain.
|
||||
Extracted from the production Ignition 8.1 gateway `Ignition-IGNTN-APP-VP01`
|
||||
(`config.idb`, `NAM` AD-Hybrid user source), audited 2026-08-05. Full audit:
|
||||
`~/Desktop/config-idb-users-groups.md`.
|
||||
|
||||
## Directory / connection
|
||||
|
||||
| Setting | Value |
|
||||
|---------|-------|
|
||||
| Domain | `nam.zimmer.com` |
|
||||
| Primary DC | `uswap-vdc-nam1:389` |
|
||||
| Secondary DC | `uswap-vdc-nam2:389` |
|
||||
| Encryption | **None** — plain LDAP on 389 (no LDAPS/StartTLS in the Ignition config) |
|
||||
| SASL | `DIGEST-MD5`, `CRAM-MD5` offered; QoP `auth-conf,auth-int,auth`; strength `high,medium,low`; no mutual auth |
|
||||
| Referrals | FOLLOW |
|
||||
| Read timeout | 60 000 ms |
|
||||
| Paging | 1000 entries/page |
|
||||
| Anonymous bind | Disallowed |
|
||||
|
||||
## Bind identity (UPN, not DN)
|
||||
|
||||
- Service account: `svc_igntnapp`
|
||||
- Binds by **UPN**: `svc_igntnapp@nam.zimmer.com` — there is no bind DN/CN anywhere
|
||||
in the working config; end users also authenticate as `<sAMAccountName>@nam.zimmer.com`
|
||||
(automatic suffix).
|
||||
- Password: held encrypted by the gateway; obtain from the credential owner — never
|
||||
commit it (in this repo's services use a `${secret:NAME}` reference).
|
||||
|
||||
## User lookup
|
||||
|
||||
| Setting | Value |
|
||||
|---------|-------|
|
||||
| Search base | domain root `DC=nam,DC=zimmer,DC=com` (Ignition field left empty) |
|
||||
| User search filter | `(&(objectClass=user)(sAMAccountName={0}))` |
|
||||
| User enumeration filter | `(&(objectClass=user)(!(objectClass=computer)))` |
|
||||
| Username attribute | `sAMAccountName` |
|
||||
| Display name | `name` |
|
||||
| Email | `mail` |
|
||||
| Phone / SMS | `telephoneNumber` / `mobile` |
|
||||
|
||||
## Groups / roles
|
||||
|
||||
**The working setup does not use LDAP groups at all.** The Ignition profile is
|
||||
AD-Hybrid: AD answers *who you are*, while *what you may do* (roles
|
||||
Administrator, Designer, Engineer, Maintenance, Management, Mfg_Tech, Operator)
|
||||
is assigned manually per user inside the application. AD security-group
|
||||
membership grants nothing.
|
||||
|
||||
Implication for new services: don't assume a `memberOf`-based authorization
|
||||
scheme exists to mirror — there is no established group→role convention in this
|
||||
domain's SCADA stack. Either keep app-local role assignment (matching the
|
||||
existing pattern) or define new AD groups deliberately; standard AD attributes
|
||||
(`memberOf`, filter `(&(objectClass=group)(member={0}))`) are available if we
|
||||
choose to.
|
||||
|
||||
## Behavioral notes from the working config
|
||||
|
||||
- Users are **populated on demand**: a local record is created on first
|
||||
successful AD login (with no roles until granted).
|
||||
- Failover: soft failover to the local internal user source, 60 s credential-cache
|
||||
validation — cached logins keep working through a DC outage.
|
||||
- Lockout: 5 failed attempts / 15-minute window.
|
||||
|
||||
## Cautions
|
||||
|
||||
- Port 389 without TLS means simple binds transit cleartext unless SASL
|
||||
confidentiality is negotiated — for new .NET services prefer LDAPS (636) or
|
||||
StartTLS against the same DCs.
|
||||
|
||||
## TLS probe results (verified 2026-08-10, from the dev Mac)
|
||||
|
||||
Both DCs were live-probed; **LDAPS and StartTLS both work on both DCs.**
|
||||
|
||||
| Check | uswap-vdc-nam1 | uswap-vdc-nam2 |
|
||||
|---|---|---|
|
||||
| Ports open | 389, 636, 3268, 3269 | 389, 636, 3268, 3269 |
|
||||
| LDAPS (636) handshake | TLSv1.3 OK | TLSv1.3 OK |
|
||||
| StartTLS on 389 | OK | OK |
|
||||
| Anonymous rootDSE over LDAPS | `result: 0 Success` | `result: 0 Success` |
|
||||
| Cert subject/SAN | `USWAP-VDC-NAM1.nam.zimmer.com` (matches FQDN) | `USWAP-VDC-NAM2.nam.zimmer.com` (matches FQDN) |
|
||||
| Cert validity | 2026-03-21 → 2027-03-21 | 2026-03-20 → 2027-03-20 |
|
||||
| Chain | leaf ← `zimmer-issueca1` ← `zimmer-rootca` (intermediate served, root not) | same |
|
||||
| **Key size** | **RSA 1024-bit** (sha256 sig) | **RSA 1024-bit** (sha256 sig) |
|
||||
|
||||
Implications for new .NET services:
|
||||
|
||||
- **Use LDAPS 636** (or StartTLS) — no reason to accept cleartext binds.
|
||||
- **Trust:** `zimmer-rootca` is an internal CA, not in default OS/container trust
|
||||
stores. Either install the root (+ intermediate) into the host/container trust
|
||||
store, or pin the chain via `LdapOptions.ServerCertificateValidationCallback`
|
||||
(code-only seam in `ZB.MOM.WW.Auth.Ldap`).
|
||||
- **⚠️ RSA 1024-bit DC certs:** OpenSSL at default security level (SECLEVEL=2 —
|
||||
what Debian-based .NET containers ship) **rejects 1024-bit keys**
|
||||
(`EE certificate key too weak`, observed in this probe), so a Linux/container
|
||||
client may fail the TLS handshake even with the CA trusted. Windows/Schannel
|
||||
hosts accept them. Options: get the DC cert template reissued at 2048+ (right
|
||||
fix, needs AD PKI owner), or lower SECLEVEL / use a custom validation callback
|
||||
in affected containers (workaround). Certs expire 2027-03 — a reissue
|
||||
opportunity.
|
||||
- Hostnames resolve from the dev network: nam1 = `10.201.216.2`,
|
||||
nam2 = `10.201.138.78`.
|
||||
|
||||
Reference in New Issue
Block a user