From db04f6f1c35ab87342725a793ce3729be379e6d7 Mon Sep 17 00:00:00 2001 From: Claude Bot Date: Tue, 14 Jul 2026 20:21:56 +0200 Subject: [PATCH] fix(gatus): trim public status page to stop internal topology disclosure (#206) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit status.renner.uno / status.k.renner.uno is a public, unauthenticated gatus page. Its endpoints named the internal service estate (Authentik, Gitea, Immich, Grafana, HA, Paperless, Proxmox, PBS, UDM DNS, Mosquitto) and gatus exposed each check's target hostname/URL/port — and on failure the error text (e.g. mosquitto.home-assistant.svc.cluster.local, 10.2.40.1) — via the public results and /api/v1/endpoints/statuses API (all hide-* default false). Per owner decision keep the page public (not Authentik-gated) but scrub the disclosure: - rename every endpoint to an opaque label (Web Service N / Infrastructure N), removing product/vendor/hostname identifiers from the public `name` - add a per-endpoint ui block with hide-hostname/hide-url/hide-port/ hide-conditions/hide-errors: true so gatus scrubs targets server-side All checks keep running unchanged (real targets stay in `url`, visible only to git/cluster operators). Public page now shows group + opaque label + up/down + response time only. Maintainer opaque->real map kept as a comment. Fixes #206 Co-Authored-By: Claude Opus 4.8 --- kubernetes/apps/gatus/configmap.yaml | 130 ++++++++++++++++++++++++--- 1 file changed, 116 insertions(+), 14 deletions(-) diff --git a/kubernetes/apps/gatus/configmap.yaml b/kubernetes/apps/gatus/configmap.yaml index 565ba190..97e87283 100644 --- a/kubernetes/apps/gatus/configmap.yaml +++ b/kubernetes/apps/gatus/configmap.yaml @@ -3,6 +3,30 @@ kind: ConfigMap metadata: name: gatus-config namespace: apps +# SECURITY (issue #206): status.renner.uno / status.k.renner.uno is PUBLIC and +# unauthenticated by design (kept public per owner decision — not Authentik-gated). +# To stop it disclosing the internal service estate, every endpoint below: +# * uses an OPAQUE display name (no product/vendor/hostname in `name`), and +# * sets `ui.hide-hostname/hide-url/hide-port/hide-conditions/hide-errors: true` +# so gatus scrubs the target hostname, URL, port, condition strings, and (on +# failure) error text — which would otherwise leak internal FQDNs/IPs such as +# mosquitto.home-assistant.svc.cluster.local or 10.2.40.1 — from the public +# results and the /api/v1/endpoints/statuses API. +# The public page therefore shows only: group, opaque label, up/down, response +# time. The real targets stay in `url` below (visible only to git/cluster- +# privileged operators) so every health check still runs unchanged. +# +# Opaque-label map (maintainer reference only — NOT served publicly): +# services group infrastructure group +# Web Service 1 = Authentik Infrastructure 1 = PBS 2 (pbs2.renner.uno) +# Web Service 2 = Gitea Infrastructure 2 = Proxmox VE (pve.renner.uno) +# Web Service 3 = Immich Infrastructure 3 = UDM DNS (10.2.40.1) +# Web Service 4 = Woodpecker CI Infrastructure 4 = Mosquitto MQTT broker +# Web Service 5 = Grafana +# Web Service 6 = Home Assistant +# Web Service 7 = Paperless +# Web Service 8 = Audiobookshelf +# Web Service 9 = Music Assistant data: config.yaml: | storage: @@ -11,74 +35,128 @@ data: ui: title: Homelab Status - description: Service health monitoring for renner.uno + description: Service health monitoring endpoints: # Web Services - - name: Authentik + - name: Web Service 1 group: services url: https://auth.renner.uno/-/health/ready/ interval: 60s + ui: + hide-hostname: true + hide-url: true + hide-port: true + hide-conditions: true + hide-errors: true conditions: - "[STATUS] == 200" - "[RESPONSE_TIME] < 2000" - - name: Gitea + - name: Web Service 2 group: services url: https://gitea.renner.uno/api/v1/settings/api interval: 60s + ui: + hide-hostname: true + hide-url: true + hide-port: true + hide-conditions: true + hide-errors: true conditions: - "[STATUS] == 200" - "[RESPONSE_TIME] < 2000" - - name: Immich + - name: Web Service 3 group: services url: https://immich.renner.uno/api/server/ping interval: 60s + ui: + hide-hostname: true + hide-url: true + hide-port: true + hide-conditions: true + hide-errors: true conditions: - "[STATUS] == 200" - "[BODY].res == pong" - - name: Woodpecker CI + - name: Web Service 4 group: services url: https://ci.renner.uno/healthz interval: 60s + ui: + hide-hostname: true + hide-url: true + hide-port: true + hide-conditions: true + hide-errors: true conditions: - "[STATUS] == any(200, 204)" - - name: Grafana + - name: Web Service 5 group: services url: https://dash.renner.uno/api/health interval: 60s + ui: + hide-hostname: true + hide-url: true + hide-port: true + hide-conditions: true + hide-errors: true conditions: - "[STATUS] == 200" - "[BODY].database == ok" - - name: Home Assistant + - name: Web Service 6 group: services url: https://home.renner.uno interval: 60s + ui: + hide-hostname: true + hide-url: true + hide-port: true + hide-conditions: true + hide-errors: true conditions: - "[STATUS] == any(200, 301, 302)" - - name: Paperless + - name: Web Service 7 group: services url: https://file.renner.uno interval: 60s + ui: + hide-hostname: true + hide-url: true + hide-port: true + hide-conditions: true + hide-errors: true conditions: - "[STATUS] == any(200, 301, 302)" - - name: Audiobookshelf + - name: Web Service 8 group: services url: https://audiobooks.renner.uno/healthcheck interval: 60s + ui: + hide-hostname: true + hide-url: true + hide-port: true + hide-conditions: true + hide-errors: true conditions: - "[STATUS] == 200" - - name: Music Assistant + - name: Web Service 9 group: services url: https://music.renner.uno interval: 60s + ui: + hide-hostname: true + hide-url: true + hide-port: true + hide-conditions: true + hide-errors: true conditions: - "[STATUS] == any(200, 301, 302)" @@ -95,31 +173,49 @@ data: # NoData). Monitor the offsite PBS from the offsite side or via a # check that doesn't depend on this cluster's DNS path. - - name: PBS 2 (pbs2.renner.uno) + - name: Infrastructure 1 group: infrastructure url: https://pbs2.renner.uno:8007 interval: 60s client: insecure-skip-verify: true + ui: + hide-hostname: true + hide-url: true + hide-port: true + hide-conditions: true + hide-errors: true conditions: - "[STATUS] == any(200, 301, 302)" - - name: Proxmox VE + - name: Infrastructure 2 group: infrastructure url: https://pve.renner.uno interval: 60s client: insecure-skip-verify: true + ui: + hide-hostname: true + hide-url: true + hide-port: true + hide-conditions: true + hide-errors: true conditions: - "[STATUS] == any(200, 301, 302)" - - name: UDM DNS (renner.uno) + - name: Infrastructure 3 group: infrastructure url: 10.2.40.1 interval: 30s dns: query-name: udm.renner.uno query-type: A + ui: + hide-hostname: true + hide-url: true + hide-port: true + hide-conditions: true + hide-errors: true conditions: - "[DNS_RCODE] == NOERROR" - "[RESPONSE_TIME] < 500" @@ -129,10 +225,16 @@ data: # image-automation straight to master (no CI gate), and the deployment # is a single Recreate/rolling pod, so a bad bump that fails to come up # would otherwise be silent. This turns that into an alert. - - name: Mosquitto (MQTT broker) + - name: Infrastructure 4 group: infrastructure url: tcp://mosquitto.home-assistant.svc.cluster.local:1883 interval: 60s + ui: + hide-hostname: true + hide-url: true + hide-port: true + hide-conditions: true + hide-errors: true conditions: - "[CONNECTED] == true" -- 2.54.0