reconcile-lldap-resolver-live.sh had never completed a run. Four defects,
found by running it on 2026-08-27:
1. request() set Content-Type: application/json on every call, including
bodyless GETs. Werkzeug 3.x rejects those in front of privacyIDEA, so
every GET returned an HTML 400 while POSTs succeeded — the resolver
write landed and the lookup immediately after it did not.
bootstrap-realm.sh already fixed this in pi_api and said why; this
script was written later and did not inherit it.
2. GET /user/ returns result.value as a list of user objects, not a dict
carrying "users". With the 400 fixed, the lookup finally reached the
parse and raised AttributeError past the except clause, so the run
died as a traceback instead of a receipt. Both shapes now accepted,
and the except clause catches parse errors so a failed run still
names the phase it died in.
3. A resolver write replaces the whole object, so TIMEOUT,
CACHE_TIMEOUT and SIZELIMIT were dropped by every --apply. A resolver
with them unset still resolves users, but the WebUI refuses to save
or test it — so the script silently un-repaired a resolver an
operator had fixed by hand. Now sent, defaulting to the verified
5/120/500 and overridable per run. Same omission fixed in
bootstrap-realm.sh, which created the resolver that way originally.
4. The predecessor prompt could not be left empty, so an operator who
had lost the exposed credential had to type a placeholder — which
also fails the bind and was recorded as a PASSING denial proof.
--predecessor-unavailable skips the bind and records NOT-PROVEN.
--note carries operator context into the receipt line itself, so the
claim and its caveat travel together.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 3377672@bnt-lap001
Assistant-Session: 15463ccf-238f-4e13-b163-93aa25c6d166
Once any admin policy exists, PI enforces it for all admins. Without an
explicit policy, pi-admin is locked out of the REST API after trigger-admin-rights
is created. Add pi-admin-all-rights (scope=admin, action=*) via pi-manage
(in-pod) as step 5, before the REST-based trigger-admin-rights step.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
PI_NO_RESPONSE_SIGN=True works around Werkzeug 3.x crash where request.json
raises BadRequest on GET requests with empty bodies (sign_response path).
Rate limit raised from 20/5 to 200/100 req/min to allow the AngularJS UI's
burst of ~50 parallel static asset requests on each page load without being
throttled by Traefik. TODO: split tight /auth+/validate vs loose /static limits.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
gpappsoft entrypoint requires PI_ADDRESS and PI_PORT env vars to build
the gunicorn bind argument. Without them the container crashes immediately.
/token/ returns 401 for unauthenticated GET requests so the httpGet
readiness probe was permanently failing. Switch to tcpSocket to match
the startup and liveness probes.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
gpappsoft image sets PRIVACYIDEA_CONFIGFILE=/privacyidea/etc/pi.cfg
internally, causing it to ignore our mounted configmap at
/etc/privacyidea/pi.cfg and fall back to SQLite.
Override the env var so the entrypoint reads our pi.cfg, which points
to PostgreSQL via PI_SQLALCHEMY_DATABASE_URI from the secret.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
privacyidea/privacyidea:3.12 and privacyidea/otpserver:3.12.2 do not
exist on Docker Hub. Correct image is ghcr.io/gpappsoft/privacyidea-docker:3.12.2
which listens on port 8080.
Update all port references: deployment, service, ingress, netpol-mfa,
netpol-sso (keycape→privacyIDEA egress rule).
Also: creds-bootstrap-agent.sh — restart privacyIDEA deployment after
applying new secrets so the pod picks up updated env vars.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
privacyidea/privacyidea:3.12 does not exist on Docker Hub.
Correct image: privacyidea/otpserver:3.12.2 (port 5001).
Updated files:
- deployment.yaml: image, containerPort, probes, service port
- ingress.yaml: backend service port
- netpol-mfa.yaml: ingress port + keycloak → keycape label
- netpol-sso.yaml: KeyCape egress port to privacyIDEA
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Traefik 2.10 (K3s 1.30 bundle) requires ipWhiteList, not ipAllowList.
Updated both middleware files and clarified comments to match cluster version.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>