keycloak: coverage tests + dashboard + reword cross-cutting tags

This commit is contained in:
jakman85 committed 2026-08-24 21:07:27 -05:00
1 parent 0cb25c12e3
commit 4bebd4b6d2
10 files changed
+422 -4

No files matched your search

+73
View File
@@ -0,0 +1,73 @@
---
# Keycloak health dashboard (R-OBS-03, docs/10 — "issues and health visible on dashboards"). A
# ConfigMap labelled grafana_dashboard is auto-discovered by the Grafana sidecar (searchNamespace:
# ALL, label grafana_dashboard — see platform/monitoring/kube-prometheus-stack.yaml) and provisioned
# into Grafana. Applied by the `platform` Kustomization (plain ConfigMap, no CRD → no split needed).
apiVersion: v1
kind: ConfigMap
metadata:
name: keycloak-dashboard
namespace: keycloak
labels:
grafana_dashboard: "1"
data:
keycloak-health.json: |
{
"uid": "keycloak-health",
"title": "Keycloak — Identity / SSO health",
"tags": ["keycloak", "identity", "platform-health"],
"timezone": "browser",
"schemaVersion": 39,
"version": 1,
"refresh": "30s",
"time": {"from": "now-6h", "to": "now"},
"panels": [
{
"id": 1,
"type": "stat",
"title": "Keycloak pods ready",
"gridPos": {"h": 6, "w": 8, "x": 0, "y": 0},
"fieldConfig": {"defaults": {"thresholds": {"steps": [{"color": "red", "value": null}, {"color": "green", "value": 1}]}}},
"targets": [
{"expr": "sum(kube_pod_status_ready{namespace=\"keycloak\", pod=~\"keycloak-[0-9]+\", condition=\"true\"})", "legendFormat": "ready"}
]
},
{
"id": 2,
"type": "stat",
"title": "Keycloak DB (CNPG) pods ready",
"gridPos": {"h": 6, "w": 8, "x": 8, "y": 0},
"fieldConfig": {"defaults": {"thresholds": {"steps": [{"color": "red", "value": null}, {"color": "green", "value": 1}]}}},
"targets": [
{"expr": "sum(kube_pod_status_ready{namespace=\"keycloak\", pod=~\"keycloak-db-.*\", condition=\"true\"})", "legendFormat": "db ready"}
]
},
{
"id": 3,
"type": "timeseries",
"title": "Keycloak scrape target up",
"gridPos": {"h": 6, "w": 8, "x": 16, "y": 0},
"targets": [
{"expr": "up{namespace=\"keycloak\"}", "legendFormat": "{{pod}}"}
]
},
{
"id": 4,
"type": "timeseries",
"title": "JVM heap used (Keycloak)",
"gridPos": {"h": 8, "w": 12, "x": 0, "y": 6},
"targets": [
{"expr": "sum by (pod) (jvm_memory_used_bytes{namespace=\"keycloak\", area=\"heap\"})", "legendFormat": "{{pod}}"}
]
},
{
"id": 5,
"type": "timeseries",
"title": "HTTP requests (Keycloak, rate)",
"gridPos": {"h": 8, "w": 12, "x": 12, "y": 6},
"targets": [
{"expr": "sum(rate(http_server_requests_seconds_count{namespace=\"keycloak\"}[5m]))", "legendFormat": "req/s"}
]
}
]
}
@@ -5,7 +5,7 @@
# WHAT THIS IS: the OIDC client secrets for the two confidential clients the realm import
# (keycloak-realm-import.yaml) provisions — grafana and oauth2-proxy. The realm import injects
# these values via spec.placeholders ($(env:GRAFANA_CLIENT_SECRET) / $(env:OAUTH2_PROXY_CLIENT_SECRET)),
# so the client secrets live ONLY here (SOPS-encrypted), never in the realm YAML (R-SEC-01 / R-IDP-04).
# so the client secrets live ONLY here (SOPS-encrypted), never in the realm YAML (R-IDP-04; docs/07).
#
# HAND-OFF STEPS (operator):
# (a) Generate two client secrets:
+1 -1
View File
@@ -4,7 +4,7 @@
# declaratively by the Keycloak Operator; CARRIED BY platform-config (dependsOn platform).
#
# Client secrets are NOT in this file: they are injected from the SOPS-encrypted keycloak-realm-clients
# Secret via spec.placeholders ($(env:...)) — so secrets exist only encrypted (R-SEC-01 / R-IDP-04).
# Secret via spec.placeholders ($(env:...)) — so secrets exist only encrypted (R-IDP-04; SOPS, docs/07).
# Until that Secret is filled (operator hand-off, see keycloak-realm-clients.sops.yaml.example), this
# import stays PENDING on the unresolved placeholder.
apiVersion: k8s.keycloak.org/v2alpha1
+2
View File
@@ -26,3 +26,5 @@ resources:
- https://raw.githubusercontent.com/keycloak/keycloak-k8s-resources/26.0.6/kubernetes/kubernetes.yml
# --- Admin (break-glass) credential — SOPS-encrypted, referenced by name (ADR-0007, R-IDP-04) ---
- keycloak-admin-credentials.sops.yaml
# --- Grafana dashboard for Keycloak health (plain ConfigMap; R-OBS-03) ---
- grafana-dashboard.yaml
+2 -2
View File
@@ -226,7 +226,7 @@ spec:
severity: critical
annotations:
summary: "Egress VPN tunnel down"
description: "The egress-gateway VPN tunnel is down (or its metric is absent) for 5m — outbound traffic could leak or stall (R-SEC-03 leak risk)."
description: "The egress-gateway VPN tunnel is down (or its metric is absent) for 5m — outbound traffic could leak or stall (leak risk, docs/07)."
runbook_url: "https://home.keithjackson.dev/runbooks/vpn-down"
# (ADR-0015) The former `EgressGatewayUnhealthy` pod-readiness alert was REMOVED with the gluetun
# retirement: there is no in-cluster egress-gateway pod anymore (the tunnel is a host systemd
@@ -241,7 +241,7 @@ spec:
severity: warning
annotations:
summary: "Spike in policy-denied network flows"
description: "Policy-denied flow rate is elevated for 10m — a NetworkPolicy regression or an intrusion probe (R-SEC-03)."
description: "Policy-denied flow rate is elevated for 10m — a NetworkPolicy regression or an intrusion probe (security audit, docs/07)."
runbook_url: "https://home.keithjackson.dev/runbooks/denied-flows"
# =====================================================================================