# Plattformaufgaben — kube-bot Spur

Stand: 2026-06-11
Status: Entwurf / read-only / keine Umsetzung

## Fokus kube-bot

- K3s Plattform-Runtime
- Argo CD / GitOps
- Namespaces / Mandantentrennung
- Ingress / DMZ-Exposure
- NetworkPolicies
- Cluster-/Storage-Risiken aus Kubernetes-Sicht

## P0 — Sofort zu klärende Plattformrisiken

### 1. DMZ-Exposure administrativer Dienste prüfen

Bekannte/zu prüfende Dienste:
- Argo CD: `argocd.cattaro.eu` -> K3s/Ingress
- Kubernetes Dashboard: Namespace `kubernetes-dashboard`, NodePort sichtbar in Inventur
- Portainer: Namespace `portainer`, NodePort/ServiceLB sichtbar
- Longhorn UI: Namespace `longhorn-system`
- Nginx Proxy Manager UI auf Reverse Proxy `192.168.20.20:81`
- später Infisical: bevorzugt nicht in DMZ, sondern Synology/Intranet-Pilot

Ziel:
- keine breit öffentliche Admin-UI
- Zugriff nur Intranet/VPN/ZTNA/IP-Allowlist
- dokumentierte Proxy-/Firewall-Regeln
- klare Owner je Admin-Dienst

### 2. Argo CD Risikostand

Ist-Zustand aus Inventur:
- Argo CD läuft in `infra-argocd`
- mehrere Applications nutzen Project `default`
- einige Apps melden `Unknown`, u.a. wegen Git-Auth-Problemen
- Mandantentrennung über AppProjects noch nicht sauber sichtbar

Risiko:
- Default-Project kann zu breit sein
- Mandanten-Apps und Platform-Apps sind nicht ausreichend getrennt
- Git-Auth/Token-Thema passt direkt zur Infisical-/Secrets-Roadmap

Ziel:
- `platform-*` AppProjects
- `tenant-cattaro`
- `tenant-pidoka` / `tenant-heckenfels` oder sauberer Firmen-/Mandantenname festlegen
- keine Mandantenproduktion im Argo-CD-Default-Project

### 3. K3s / Node / Longhorn Risiken

Bekannt:
- 2 Nodes: `192.168.20.40` control-plane, `192.168.20.45` worker
- K3s-Versionen uneinheitlich: v1.28.4 vs v1.29.3
- Longhorn 3 Replicas bei nur 2 Nodes -> dauerhaft degraded
- Backup Target für Longhorn war leer/nicht verfügbar

Ziel:
- Backup/Restore vor Storage-Änderungen klären
- K3s Upgrade-Pfad definieren
- Longhorn Replica-Konzept festlegen
- dritter Node bzw. Intranet-Management-Node planen

## P1 — Zielstruktur GitOps / Mandanten

### Namespaces Zielbild

Platform:
- `platform-argocd`
- `platform-ingress`
- `platform-secrets`
- `platform-monitoring`
- `platform-logging`
- `platform-backup`
- `platform-storage`

Mandanten:
- `tenant-cattaro-stage`
- `tenant-cattaro-prod`
- `tenant-pidoka-stage` oder `tenant-heckenfels-stage`
- `tenant-pidoka-prod` oder `tenant-heckenfels-prod`

Offene Entscheidung:
- Mandantenname für heckenfels.com/Pidoka sauber festlegen: `pidoka` vs `heckenfels`.

### Argo CD AppProjects Zielbild

Platform:
- `platform-core`
- `platform-network`
- `platform-security`
- `platform-observability`

Tenant:
- `tenant-cattaro`
- `tenant-pidoka` / `tenant-heckenfels`

Grundregeln:
- Tenant-Projekte dürfen nur eigene Namespaces deployen.
- Cluster-scoped Ressourcen nur Platform-Projekten erlauben.
- Repos pro Projekt begrenzen.
- Produktionssyncs mit klarer Approval-Regel.

### GitOps Repo-Struktur — Vorschlag

Variante A: ein Plattform-Repo mit klaren Verzeichnissen

```text
platform-gitops/
  clusters/
    dmz-k3s/
      platform/
      tenants/
        cattaro/
        pidoka/
  projects/
    platform-core/
    tenant-cattaro/
    tenant-pidoka/
  apps/
    platform/
    tenants/
  charts/
  docs/
```

Variante B: getrennte Repos

```text
platform-gitops-infra/
tenant-cattaro-gitops/
tenant-pidoka-gitops/
```

Empfehlung:
- Kurzfristig Variante A wegen kleiner Umgebung und besserer Übersicht.
- Später bei echten DevSecOps-Teams ggf. Mandanten-/Team-Repos trennen.

## P1 — DevSecOps Request Templates

Benötigte Templates:
- Service-Onboarding
- Namespace/AppProject Request
- Secret/Infisical Request
- Ingress/DNS Request
- Storage/PVC Request
- Backup/Restore Request
- Production Change Request
- Incident Report / Post-Incident Review

## Nächste kube-bot Schritte

1. DMZ-Exposure-Matrix aus vorhandener Inventur detaillieren.
2. Argo-CD-AppProject-Zieldefinition ausarbeiten.
3. GitOps-Repo-Struktur als konkreten Vorschlag formulieren.
4. Request-Templates als Markdown-Entwürfe erstellen.

Keine Umsetzung ohne explizites OK.

## Entscheidung — Mandantenname Pidoka

Entscheidung durch Mislav am 2026-06-11:
- Für heckenfels.com/Pidoka-Bereich wird `pidoka` als Mandantenname verwendet.

Standard:
- Namespaces: `tenant-pidoka-stage`, `tenant-pidoka-prod`
- Argo-CD-AppProject: `tenant-pidoka`
- Infisical-Projekt: `tenant-pidoka`
- Labels: `tenant: pidoka`, `owner: pidoka`

Begründung:
- Pidoka ist die organisatorische/rechtliche Einheit; heckenfels.com ist Domain-/Service-Kontext.

## P0.1 Ergebnis — DMZ-Exposure administrativer Dienste

Stand: 2026-06-11, read-only geprüft durch kube-bot.

### Befund

Administrativ relevante Dienste sind innerhalb der DMZ direkt über NodePorts/LoadBalancer-Ports auf beiden K3s-Nodes erreichbar:

- Portainer UI
  - Service: `portainer/portainer`
  - Type: `LoadBalancer`
  - IPs: `192.168.20.40`, `192.168.20.45`
  - Ports: `30777/http`, `30779/https`, `30776/edge`
  - Test: Ports offen, UI liefert HTTP 200

- Kubernetes Dashboard
  - Service: `kubernetes-dashboard/kubernetes-dashboard`
  - Type: `NodePort`
  - Port: `31351/https`
  - Test: Port offen, UI liefert HTTP 200

- Keycloak
  - Service: `keycloak/keycloak`
  - Type: `LoadBalancer`, EXTERNAL-IP pending, aber NodePort `32184/http`
  - Test: Port offen, UI liefert HTTP 200
  - Zusätzlich `svclb-keycloak` war in früherer Inventur auffällig/pending.

- Argo CD
  - Service: `infra-argocd/argocd-server` ClusterIP
  - Ingress: `argocd.cattaro.eu` über Traefik
  - Traefik LoadBalancer: `192.168.20.40/45`, NodePorts `31797/http`, `30508/https`
  - Extern über `https://argocd.cattaro.eu` erreichbar, HTTP 200.

- Longhorn UI
  - Service: `longhorn-system/longhorn-frontend`
  - Type: ClusterIP
  - Kein direkter NodePort/Ingress gefunden.
  - Bewertung: besser als Portainer/Dashboard; weiterhin intern schützen.

### Risiko

In einer DMZ sind direkt erreichbare Admin-UIs riskant, selbst wenn sie nur intern/über Firewall erreichbar sind. Besonders kritisch:

1. Portainer: Container-/Kubernetes-Verwaltung, potentiell hoher Impact.
2. Kubernetes Dashboard: direkter Cluster-Admin-/Token-Bezug möglich.
3. Argo CD: Deployment-Kontrolle; sollte langfristig Management-Zone/Intranet werden.
4. Keycloak: Identitätsdienst, öffentlich/interner Scope muss geklärt werden.

### Empfohlene Maßnahmen ohne direkte Umsetzung

P0-a:
- Mit OPNsense/Nginx Proxy Manager abgleichen, welche dieser Ports aus welchen Netzen erreichbar sind.
- Extern/Internet darf kein direkter Zugriff auf NodePorts bestehen.

P0-b:
- Kubernetes Dashboard nicht per NodePort offen halten; bevorzugt nur temporär via `kubectl proxy`/Port-forward/VPN oder intern streng begrenzt.

P0-c:
- Portainer Zugriff auf VPN/ZTNA/Intranet/IP-Allowlist begrenzen; Edge-Port 30776 prüfen, ob benötigt.

P0-d:
- Argo CD UI/API Zugriff einschränken; langfristig in Intranet/Management-Zone ziehen.

P0-e:
- Keycloak Scope klären: produktiver IdP vs Legacy/Test. Falls nicht benötigt, Exposition reduzieren.

### Keine Änderungen durchgeführt

Alle Checks waren read-only. Keine Services, Ingresses, Firewall-Regeln oder Deployments wurden geändert.

## P0.2 Ergebnis — Proxy-/DMZ-Sicht und Backup-/Intranet-Grenze

Stand: 2026-06-11, read-only geprüft.

### Proxy Host 192.168.20.20 / raspi

Host-/Port-Sicht:
- `80/tcp`, `443/tcp`: Nginx Proxy Manager Frontend
- `81/tcp`: Nginx Proxy Manager Management UI
- `8000/tcp`, `9000/tcp`: Portainer/Portainer Agent Docker-Ports auf dem Proxyhost

Risiko:
- Nginx Proxy Manager UI (`81`) und Portainer (`9000/8000`) sind Management-Oberflächen auf dem Reverse-Proxy-Host.
- Diese sollten nicht öffentlich erreichbar sein und möglichst nur über Intranet/VPN/ZTNA/IP-Allowlist zugänglich sein.

Live Docker/NPM-DB-Auslese war mit `kube-bot` auf dem Proxy wegen fehlender Docker-Socket-Berechtigung nicht möglich. Die vorhandene Inventur enthält jedoch aktive Proxy-Hosts.

### Bekannte Proxy Hosts aus Inventur

Cattaro:
- `argocd.cattaro.eu` -> `http://192.168.20.40:31797`
- `bitwarden.cattaro.eu` -> `http://192.168.20.20:8080`
- `nextcloud.cattaro.eu` -> `http://192.168.20.30:80`
- `office.cattaro.eu` -> `http://192.168.188.40:80`
- `meshcentral.cattaro.eu` -> `http://192.168.188.42:2087`

Pidoka:
- `matomo.heckenfels.com` -> `http://192.168.20.40:80`
- `mautic.heckenfels.com` -> `http://192.168.20.40:31797`
- `crm.heckenfels.com` -> `http://192.168.20.40:31797`
- `suitecrm.heckenfels.com` -> `http://192.168.20.40:31797`
- `n8n.heckenfels.com` -> `https://192.168.20.40:443`
- `dashboard.heckenfels.com` -> `http://192.168.20.40:30718`
- `service.heckenfels.com` -> `http://192.168.20.40:8080`

### Backup-/Intranet-Grenze

Konsens mit diskstation-bot:
- Produktive Secret-Migration ist blockiert, bis die Exposure-Sicht sauber geklärt ist.
- DMZ darf keine breiten Zugriffe auf DiskStation, Backup-Freigaben, DSM, Admin-UIs oder später Infisical erhalten.
- Falls DMZ -> Intranet technisch nötig ist, dann nur explizit, minimal, protokolliert und auditierbar.

Zu prüfen/dokumentieren:
- OPNsense NAT/Firewall: Sind NodePorts/Management-Ports aus Internet oder nur internen Netzen erreichbar?
- Gibt es DMZ -> DiskStation SMB/NFS/WebDAV-Freigaben?
- Gibt es bestehende NFS/Longhorn-Stagingpfade zur DiskStation oder Pull-Pfade von DiskStation zur DMZ?
- Sind NPM UI 81 und Proxy-Portainer 9000/8000 extern erreichbar?
- Ist `dashboard.heckenfels.com` ein Admin-Dashboard oder Anwender-Dashboard?
- Was ist `service.heckenfels.com` auf Port 8080?

### Bewertung

P0.2 ist teilweise abgeschlossen:
- K3s- und Proxy-Port-Sicht ist dokumentiert.
- Öffentliche/Firewall-Sicht über OPNsense ist noch offen.
- NPM-DB Live-Auslese vom Proxy ist wegen fehlender Docker-Rechte für `kube-bot` blockiert; vorhandene Inventur wurde genutzt.

### Empfehlung

Vor produktiver Infisical-/Secret-Migration:
1. OPNsense-Regeln/NAT für Admin-Ports prüfen.
2. NPM UI und Portainer Proxyhost absichern.
3. K3s Admin-NodePorts reduzieren oder auf Management-Netz begrenzen.
4. DMZ -> Intranet Regeln explizit dokumentieren und minimieren.
5. DiskStation-Zugriffe aus DMZ nur für genau definierte Backup-/Restore-Flüsse zulassen.

## OPNsense API Zugriff — Test 2026-06-11

Ergebnis:
- OPNsense Web/API Port erkannt: `https://192.168.20.1:8443`
- `https://192.168.20.1:443` läuft in Timeout; HTTP `80` leitet auf `8443` um.
- Temporärer API-Key aus DM wurde getestet, aber Authentifizierung schlägt fehl.
- API antwortet auf read-only Testendpunkte mit `401 Authentication Failed`.
- Keine Secrets ausgegeben oder gespeichert.

Bewertung:
- Netzwerkpfad zur OPNsense API funktioniert grundsätzlich über Port `8443`.
- Credentials oder API-Key-/User-Konfiguration sind noch nicht korrekt nutzbar.

Nächste Prüfung durch Owner:
- API-Key/Secret vollständig kopiert?
- API-Key für richtigen User aktiv?
- User hat API-Zugriff/effective privileges?
- Temporärer User nicht deaktiviert/gesperrt?
- API-Zugriff auf WebGUI-Port `8443` erlaubt?
