infra(glauth): enable LDAPS on :3894 alongside plain :3893 (#19, mxaccessgw#180)
Self-signed cert (SAN IP 10.100.0.35), public cert checked in, key host-only. Deployed on 10.100.0.35: TLS chain verifies with the cert and fails without it; raw LDAPS simple bind returns 0 for a good password and 49 for a bad one; plain :3893 bind unchanged. README: thumbprint, client config, rotation; also fixes the user-bind DN example (GLAuth puts users under their primary group OU). Claude-Session: https://claude.ai/code/session_01GT67AEHd2Acv1YPwGfXEoV
This commit is contained in:
+25
-3
@@ -2,10 +2,32 @@
|
||||
|
||||
One [GLAuth](https://github.com/glauth/glauth) directory that **all three sister apps use for
|
||||
dev/test auth** — OtOpcUa, MxAccessGateway, ScadaBridge. It runs as a single container on the
|
||||
shared Docker host **`10.100.0.35:3893`** (plaintext LDAP; LDAPS/StartTLS → #19). This is the app-neutral source of
|
||||
shared Docker host **`10.100.0.35`** — plain LDAP on **`:3893`** and LDAPS on **`:3894`** (since 2026-11-10, #19). This is the app-neutral source of
|
||||
truth; each app just points its `…Ldap:Server` at `10.100.0.35`.
|
||||
|
||||
> Open work on this directory is tracked as Gitea issues on `dohertj2/scadaproj` (e.g. #19 LDAPS).
|
||||
> Open work on this directory is tracked as Gitea issues on `dohertj2/scadaproj`.
|
||||
|
||||
## LDAPS (`:3894`)
|
||||
|
||||
LDAPS runs next to plain LDAP; `:3893` is unchanged, so every existing `Transport=None` consumer keeps working.
|
||||
|
||||
- **Cert:** self-signed, `CN=zb-shared-glauth`, SAN `IP:10.100.0.35, DNS:localhost, DNS:zb-shared-glauth`,
|
||||
RSA-3072, valid to **2029-11-09**. The public cert is checked in at [`tls/cert.pem`](tls/cert.pem);
|
||||
the private key exists only on the host (`~/zb-glauth/tls/key.pem`) and is gitignored here.
|
||||
- **SHA-256 thumbprint** (for clients that pin, e.g. mxaccessgw `MxGateway:Ldap` — mxaccessgw#180):
|
||||
`EE:B0:13:70:3F:B8:65:4C:9E:6F:39:0F:22:BE:A1:0B:6D:F5:C6:6E:56:57:84:59:E0:93:C6:07:69:D9:9B:BD`
|
||||
(`openssl x509 -in tls/cert.pem -noout -fingerprint -sha256`).
|
||||
- **Client config:** `Transport=Ldaps`, server `10.100.0.35`, port `3894`. A client must either pin the
|
||||
thumbprint or trust `tls/cert.pem`; it is not in any OS trust store.
|
||||
- **Verify the chain:** `echo | openssl s_client -connect 10.100.0.35:3894 -CAfile tls/cert.pem -verify_return_error -verify_ip 10.100.0.35`
|
||||
→ `Verify return code: 0 (ok)`; without `-CAfile` it must fail with code 18 (self-signed).
|
||||
macOS `ldapsearch` ignores `LDAPTLS_CACERT`, so test binds from the alpine container below with
|
||||
`LDAPTLS_CACERT=/certs/cert.pem` and `-v $PWD/tls:/certs:ro`.
|
||||
- **Rotating:** generate a new pair in `~/zb-glauth/tls/` on the host, copy `cert.pem` back here, update
|
||||
the thumbprint above, `docker compose up -d --force-recreate`. Pinning clients should carry old + new
|
||||
thumbprints across the swap.
|
||||
- **Not covered:** the redundant local pair (`zb-ldap-primary`/`zb-ldap-backup` on the Mac) and each
|
||||
wonder box's own `ScadaBridge-LDAP` GLAuth remain plain-only.
|
||||
|
||||
> Scope: **dev/test only**. Production uses real corporate AD. See
|
||||
> [`../../docs/plans/2026-06-04-shared-glauth-standardization-design.md`](../../docs/plans/2026-06-04-shared-glauth-standardization-design.md).
|
||||
@@ -73,7 +95,7 @@ the search capability, so a successful bind shows `result: 50 Insufficient acces
|
||||
|
||||
```bash
|
||||
ldapsearch -x -H ldap://10.100.0.35:3893 \
|
||||
-D cn=multi-role,dc=zb,dc=local -w password \
|
||||
-D cn=multi-role,ou=SCADA-Admins,dc=zb,dc=local -w password \
|
||||
-b dc=zb,dc=local "(cn=multi-role)" cn
|
||||
```
|
||||
|
||||
|
||||
@@ -3,7 +3,13 @@
|
||||
listen = "0.0.0.0:3893"
|
||||
|
||||
[ldaps]
|
||||
enabled = false
|
||||
# LDAPS on :3894 (mxaccessgw#180), alongside plain :3893, which stays for existing consumers.
|
||||
# Self-signed cert generated on the host; the PUBLIC cert is checked in at tls/cert.pem, the
|
||||
# private key lives only on 10.100.0.35 (~/zb-glauth/tls/key.pem) and is never committed.
|
||||
enabled = true
|
||||
listen = "0.0.0.0:3894"
|
||||
cert = "/app/config/tls/cert.pem"
|
||||
key = "/app/config/tls/key.pem"
|
||||
|
||||
[backend]
|
||||
datastore = "config"
|
||||
|
||||
@@ -11,6 +11,8 @@ services:
|
||||
container_name: zb-shared-glauth
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "3893:3893"
|
||||
- "3893:3893" # plain LDAP (Transport=None)
|
||||
- "3894:3894" # LDAPS (Transport=Ldaps) — mxaccessgw#180
|
||||
volumes:
|
||||
- ./config.toml:/app/config/config.cfg:ro
|
||||
- ./tls:/app/config/tls:ro # cert.pem (public, in repo) + key.pem (host only)
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
key.pem
|
||||
*.key
|
||||
@@ -0,0 +1,26 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIEaTCCAtGgAwIBAgIUFqbnjiomQ8qwlkqc09zz/cz33b0wDQYJKoZIhvcNAQEL
|
||||
BQAwGzEZMBcGA1UEAwwQemItc2hhcmVkLWdsYXV0aDAeFw0yNjExMTAxNjQ1NDJa
|
||||
Fw0yOTExMDkxNjQ1NDJaMBsxGTAXBgNVBAMMEHpiLXNoYXJlZC1nbGF1dGgwggGi
|
||||
MA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQDQCmS7kpTIQQUQW9y4lMSOqNYc
|
||||
t5stvdZf+LlYQYqKydcdgSxJLeA7rIYaC3jGrsFjn/o26BLp0/jQLh5HDjmEwYEF
|
||||
mTqvVdy0ef1AscxJmeCeCAVp5Tm5m5icvN9fLgY/e/mx+G4GJLXGy+xLTffh+dq2
|
||||
nwXq4p7pS8vKlr+y9DGMAIJOJrEp5xTN3l4rTMujdmbiYiC7ymtNpHKgXAJ/zMKY
|
||||
A9woUqD57tAm8w0HpplgSHoLrNMg7uUtan8nJjm355AWqKm4j8wRK6yPXPxPvZuw
|
||||
WAI5wPGH8kjfm1AYFrTuFLZFReX6bbMv2LhQFI9MwBYk6PjCwjyOTjcrK/5xLm86
|
||||
ZUsJ0qCo7Uud/R1kOvOcBp5KBN8Gs31NZx4t6j7brtSQNsZfu9T7x5krUGKVWErr
|
||||
q26mQbf4HN+KORaVNJcW4BI96do1K/uGBUzakilsRh5s3VjkMGqNOCGny0T/vaS5
|
||||
Y29X8CwEW2973MH1HnOJr8fWmKfVwOvhv41MCbkCAwEAAaOBpDCBoTAdBgNVHQ4E
|
||||
FgQUNdXIl0ILdlh3AKXwmJV/KujaaegwHwYDVR0jBBgwFoAUNdXIl0ILdlh3AKXw
|
||||
mJV/KujaaegwDwYDVR0TAQH/BAUwAwEB/zAsBgNVHREEJTAjhwQKZAAjgglsb2Nh
|
||||
bGhvc3SCEHpiLXNoYXJlZC1nbGF1dGgwCwYDVR0PBAQDAgWgMBMGA1UdJQQMMAoG
|
||||
CCsGAQUFBwMBMA0GCSqGSIb3DQEBCwUAA4IBgQAcEVL2fTbwS6T+u/e99fMbgmOm
|
||||
31CefVYjJjjwge1tE4lw56cGygUCQtp90SXHnEXuJbSfTGlWCaXDH4fl064kqcOq
|
||||
WFctP2oxLK1yrrVWNOu0BCi+o2B8P51f5vZt6xMA3nWjs5vPi+ajQ2BBV5cA2o9D
|
||||
4cmOTcVR1ZEb4mSvcO6IZlTP1vT6HL4Sha/rJlWScEUJWUj0g7Tvw97737Ryqh3R
|
||||
XKWW2STTlaYpIBGZGD6TiOjDuLYqZ4nla92yakS9tHrZfQ3LCVdfpnyalEfadkWd
|
||||
lUJ4zK9S0EnbVyy+Wx1i0WZ52gwty09JAaiuNVudyrjLK473wV6kroVO3IzlMkw9
|
||||
Z/kfdjRBfWp8VzwDCgJAUi4T5sp9VsbeeBdzE8twrKZJq5+UgMXH2X42Q0S/9nd2
|
||||
807L00UNOSs8erYgcbpp8Pcs/BPy3SBy6evfmMI7qHQv9/tM1uja74wyqrZgs0Ju
|
||||
FH9zSFseoWjUpdVN54eO74+4XzHFPmWUr4E5mrM=
|
||||
-----END CERTIFICATE-----
|
||||
Reference in New Issue
Block a user