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
This commit is contained in:
@@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
|
||||||
@@ -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=<slug>`,
|
||||||
|
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.
|
||||||
Reference in New Issue
Block a user