keycloak: coverage tests + dashboard + reword cross-cutting tags
This commit is contained in:
10 files changed
+422
-4
No files matched your search
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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"
|
||||
|
||||
# =====================================================================================
|
||||
|
||||
Reference in new issue
Block a user