From 1e8a6c22cdefac18f3864c7688fa1540c76541f9 Mon Sep 17 00:00:00 2001 From: sysops Date: Sun, 30 Aug 2026 23:54:07 +0200 Subject: [PATCH] API-12: kek-bezugsdienst-starten - cmd/kek-api: startet internal/kek.Handler.TenantKEKHandler (API-10), tenantResolverAdapter bildet tenant.Registry.GetBySlug auf kek.TenantResolver ab (nur Signatur-Anpassung) - reines Wiring, kein Diff an internal/kek|moduleregistry|tenant (verifiziert) - real deployed auf 131, end-zu-ende bewiesen: echtes Modul registriert+provisioniert, echter Tenant-KEK erzeugt, curl gegen laufenden Dienst liefert exakt denselben KEK zurueck (byte-fuer-byte verglichen), falsches Credential -> 403 - reale Grant-Luecke gefunden und behoben (nexarch_core auf tenant_keks), verifiziert Pruefungen siehe docs/API-12-PRUEFPROTOKOLL.md --- cmd/kek-api/main.go | 82 +++++++++++++++++++++ deploy/systemd/nexarch-kek-api.service.tmpl | 14 ++++ docs/API-12-PRUEFPROTOKOLL.md | 61 +++++++++++++++ 3 files changed, 157 insertions(+) create mode 100644 cmd/kek-api/main.go create mode 100644 deploy/systemd/nexarch-kek-api.service.tmpl create mode 100644 docs/API-12-PRUEFPROTOKOLL.md diff --git a/cmd/kek-api/main.go b/cmd/kek-api/main.go new file mode 100644 index 0000000..1e73503 --- /dev/null +++ b/cmd/kek-api/main.go @@ -0,0 +1,82 @@ +// kek-api ist der Aufrufpunkt fuer API-12: startet den bereits fertigen +// API-10-Handler (internal/kek) als eigenstaendigen HTTP-Dienst. +// REINES WIRING — keine Aenderung an internal/kek/, internal/moduleregistry/ +// oder internal/tenant/. +package main + +import ( + "context" + "log" + "net/http" + "os" + "time" + + "github.com/jackc/pgx/v5/pgxpool" + + "gitea.perlbach24.de/scripte/nexarch/internal/flag" + "gitea.perlbach24.de/scripte/nexarch/internal/kek" + "gitea.perlbach24.de/scripte/nexarch/internal/moduleregistry" + "gitea.perlbach24.de/scripte/nexarch/internal/tenant" +) + +// tenantResolverAdapter erfüllt kek.TenantResolver über den bestehenden +// tenant.Registry.GetBySlug-Zugriff — kein neuer Tenant-Code, nur +// Signatur-Anpassung. +type tenantResolverAdapter struct{ registry *tenant.Registry } + +func (a tenantResolverAdapter) ResolveTenantID(ctx context.Context, tenantSlug string) (string, error) { + t, err := a.registry.GetBySlug(ctx, tenantSlug) + if err != nil { + return "", err + } + return t.ID, nil +} + +func requireEnv(name string) string { + v := os.Getenv(name) + if v == "" { + log.Fatalf("%s muss gesetzt sein", name) + } + return v +} + +func main() { + registryDSN := requireEnv("NEXARCH_KEK_REGISTRY_DSN") + masterKeyEnvVar := os.Getenv("NEXARCH_KEK_MASTER_KEY_ENV") + if masterKeyEnvVar == "" { + masterKeyEnvVar = "NEXARCH_KEK_MASTER_KEY" + } + addr := os.Getenv("NEXARCH_KEK_API_LISTEN_ADDR") + if addr == "" { + addr = "127.0.0.1:8102" + } + + masterKey, err := kek.LoadMasterKeyFromEnv(masterKeyEnvVar) + if err != nil { + log.Fatalf("master-key laden: %v", err) + } + + ctx := context.Background() + pool, err := pgxpool.New(ctx, registryDSN) + if err != nil { + log.Fatalf("datenbankverbindung: %v", err) + } + defer pool.Close() + + flagStore := flag.NewStore(pool) + flagService := flag.NewService(flagStore, 30*time.Second) + registry := moduleregistry.NewRegistry(pool, flagService) + tenantRegistry := tenant.NewRegistry(pool) + store := kek.NewStore(pool) + + handler := kek.NewHandler(store, masterKey, registry, registry, tenantResolverAdapter{registry: tenantRegistry}) + + mux := http.NewServeMux() + mux.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) }) + mux.HandleFunc("/internal/kek/tenant", handler.TenantKEKHandler) + + log.Printf("kek-api: listening on %s", addr) + if err := http.ListenAndServe(addr, mux); err != nil { + log.Fatalf("http server: %v", err) + } +} diff --git a/deploy/systemd/nexarch-kek-api.service.tmpl b/deploy/systemd/nexarch-kek-api.service.tmpl new file mode 100644 index 0000000..a3d304b --- /dev/null +++ b/deploy/systemd/nexarch-kek-api.service.tmpl @@ -0,0 +1,14 @@ +[Unit] +Description=NEXARCH Core - KEK-Bezugsdienst (API-10/API-12) +After=network.target postgresql.service + +[Service] +Type=simple +User=nexarch +EnvironmentFile=/etc/nexarch/kek-api.env +ExecStart=__INSTALL_DIR__/bin/kek-api +Restart=on-failure +StandardOutput=journal + +[Install] +WantedBy=multi-user.target diff --git a/docs/API-12-PRUEFPROTOKOLL.md b/docs/API-12-PRUEFPROTOKOLL.md new file mode 100644 index 0000000..68d1d3b --- /dev/null +++ b/docs/API-12-PRUEFPROTOKOLL.md @@ -0,0 +1,61 @@ +# API-12 – Prüfprotokoll: KEK-Bezugsdienst starten (API-10 als laufender Dienst) + +Voraussetzung API-10 – bereits Fertig, hier UNVERÄNDERT. + +## Reines Wiring, keine neue Logik + +`git diff --stat internal/kek/ internal/moduleregistry/ internal/tenant/` +liefert KEINEN Diff. `cmd/kek-api/main.go` setzt ausschließlich +bestehende Konstruktoren zusammen; `tenantResolverAdapter` bildet nur +`tenant.Registry.GetBySlug` auf `kek.TenantResolver` ab (Signatur- +Anpassung, kein neuer Fachcode). + +## Umsetzung + +- `cmd/kek-api/main.go` – `POST /internal/kek/tenant?tenant=`, + authentifiziert über dasselbe Service-Credential-Verfahren wie jeder + andere Modul-Core-Aufruf (API-02), zusätzlich Tenant-Aktivierungs- + prüfung (identisches Muster wie in `internal/kek.Handler` bereits + vorgesehen). +- `deploy/systemd/nexarch-kek-api.service.tmpl`. + +## Prüfungen + +| # | Prüfung | Ergebnis | +|---|---|---| +| 1 | Dienst startet und bleibt stabil (systemctl status aktiv) | **bestanden** – real auf 131: `nexarch-kek-api.service` aktiv | +| 2 | Realer Aufruf mit gültigem Service-Credential liefert den erwarteten Tenant-KEK, ohne/mit falschem Credential wird abgelehnt | **bestanden** – real per `curl`: echtes Modul registriert+provisioniert, echter Tenant-KEK über `kek.Store.CreateForTenant` erzeugt (Klartext-Hex zum Vergleich notiert) — Aufruf mit korrektem Credential liefert exakt denselben KEK (Base64-dekodiert übereinstimmend mit dem erzeugten Hex-Wert verifiziert); Aufruf mit falschem Credential → 403 | +| 3 | Code-Review: keine Änderung an internal/kek/ selbst, nur main.go+systemd neu | **bestanden** – `git diff --stat` bestätigt: `internal/kek/`, `internal/moduleregistry/`, `internal/tenant/` unverändert | + +## Echte Verdrahtung auf 192.168.1.131 + +- `kek-api` gebaut nach `/opt/nexarch-core/bin/`, + `/etc/nexarch/kek-api.env` (0600, echter zufälliger 32-Byte- + Master-Key), Dienst installiert/aktiviert. +- Reale Grant-Lücke gefunden und behoben (gleiches Muster wie zuvor): + `nexarch_core` hatte keine Rechte auf `tenant_keks` — `GRANT` + nachgezogen und über `information_schema.role_table_grants` + verifiziert. +- End-zu-Ende-Beweis: echtes Modul registriert, Service-Credential + provisioniert, echter Tenant + Tenant-KEK real erzeugt, `curl` gegen + den laufenden Dienst liefert exakt diesen KEK zurück (Byte-für-Byte + verglichen), falsches Credential real abgelehnt. Testdaten + anschließend entfernt. + +## Build/Test-Ergebnis (192.168.1.131) + +``` +go build ./... -> clean +go vet ./... -> clean +golangci-lint run ./cmd/kek-api/... -> 0 issues +``` + +Keine neuen Go-Tests nötig (kein neuer Fachcode außer main.go/Adapter, +die eigentliche Logik ist bereits durch API-10s eigene Tests +abgedeckt). + +## Gesamtergebnis + +**Bestanden.** API-10 ist jetzt ein real laufender, über systemd +verwalteter Dienst — Voraussetzung für Mail ARC-02 und künftig DMS +FDN-09-Nachnutzung.