diff --git a/keycloak.md b/keycloak.md index 5150ba8..6890dfb 100644 --- a/keycloak.md +++ b/keycloak.md @@ -211,7 +211,7 @@ Three practical consequences: | `keycloak.livenessProbe` | object | `httpGet /health/live` on `management`, period 10s, timeout 5s, 3 failures | **Deliberately not `/health` or `/health/ready`** — see [the probes](#the-three-probes-use-three-different-paths-on-purpose). | | `keycloak.readinessProbe` | object | `httpGet /health/ready` on `management`, period 10s, timeout 5s, 3 failures | Includes the database, and must. | | `keycloak.startupProbe` | object | `httpGet /health/started` on `management`, period 10s, 60 failures (= **600s**) | Gates liveness and readiness. The budget covers a **first** start, which creates the whole schema through Liquibase while the second replica waits on the migration lock. The Quarkus augmentation is **not** inside it — that runs in an init container, which has no probe and no deadline. | -| `keycloak.securityContext.pod` | object | non-root **1000**, `runAsGroup` **0**, `fsGroup` `1000`, `fsGroupChangePolicy: Always`, `seccompProfile: RuntimeDefault` | **uid 1000 / gid 0 is the image's requirement, not a free choice**: it declares `keycloak:x:1000:0` in `/etc/passwd`, puts that user in the **root group**, and copies the install tree with `--chown=1000:0`. The mounted build volume has to be writable by the same pair. | +| `keycloak.securityContext.pod` | object | non-root **1000**, `runAsGroup` **1000**, `fsGroup` `1000`, `fsGroupChangePolicy: Always`, `seccompProfile: RuntimeDefault` | **uid 1000 is the image's requirement**: it declares `keycloak:x:1000:0` in `/etc/passwd` and copies the install tree with `--chown=1000:0`, so 1000 **owns** everything the process reads. The **group is 1000 and not the image's own 0**, which is a deliberate divergence: upstream puts the user in the root group and makes the tree group-writable, which is the OpenShift arbitrary-uid pattern — it lets *any* uid in group 0 write. Counted across the image layer, 521 of 522 entries are owned by `1000:0` with every mode granting the owner full access, so pinning the owning uid makes group 0 unnecessary. What that buys: **no root GID in this pod**, hence no `AVD-KSV-0116` finding and no suppression for it — a suppression would have had to cover the serving container too. | | `keycloak.securityContext.container` | object | `readOnlyRootFilesystem: true`, all caps dropped, no privilege escalation, non-root | Applied to **every** container in the pod, both init containers included. No capability is added and none is needed: 8080, 9000 and 7800 are all above 1024 and the entrypoint is a shell script calling `java`. | | `keycloak.podDisruptionBudget.enabled` | bool | `true` | | | `keycloak.podDisruptionBudget.minAvailable` | int | `1` | **Rendered only while the computed replica count is `>= 2`** — see [the PDB trap](#a-pdb-with-one-replica-blocks-every-drain). |