feat(admin-console): Stage 1 — pipe + skeleton behind the gateway
Tests · Go / test (push) Successful in 2m0s
Tests · Go / test (push) Successful in 2m0s
Add the server-rendered operator console at /_gm, exposed publicly through the gateway behind the existing admin_accounts Basic Auth. Backend: - new internal/adminconsole package (html/template Renderer, stateless HMAC CSRF signer, embedded stylesheet) - /_gm route group reusing basicauth.Middleware(admin.Service) + a CSRF guard (per-operator token + same-origin check); dashboard landing page - BACKEND_ADMIN_CONSOLE_CSRF_KEY config (per-process random fallback) Gateway: - new "admin" public route class (per-IP rate limit, body + GET/HEAD/POST method limits) classifying /_gm traffic - reverse proxy to the backend /_gm surface, preserving Host and relaying the backend 401 Basic Auth challenge; 502 when the backend is unreachable - GATEWAY_PUBLIC_HTTP_ANTI_ABUSE_ADMIN_* config dev-deploy: - Caddy routes /_gm/* to the gateway - bootstrap admin + stable CSRF key; enable Prometheus /metrics exporters on backend and gateway (forward-compat for a future Prometheus/Grafana stack) Docs: ARCHITECTURE 14.1/16, FUNCTIONAL 10.2.1 (+ru mirror), backend and gateway READMEs, new backend/docs/admin-console.md. Tests: renderer + CSRF unit tests; backend router auth/render/asset/CSRF; gateway classifier, proxy forwarding/Host/401/405/413/429/502.
This commit is contained in:
@@ -55,6 +55,8 @@ const (
|
||||
envAdminBootstrapUser = "BACKEND_ADMIN_BOOTSTRAP_USER"
|
||||
envAdminBootstrapPassword = "BACKEND_ADMIN_BOOTSTRAP_PASSWORD"
|
||||
|
||||
envAdminConsoleCSRFKey = "BACKEND_ADMIN_CONSOLE_CSRF_KEY"
|
||||
|
||||
envGeoIPDBPath = "BACKEND_GEOIP_DB_PATH"
|
||||
|
||||
envOTelTracesExporter = "BACKEND_OTEL_TRACES_EXPORTER"
|
||||
@@ -208,6 +210,7 @@ type Config struct {
|
||||
Docker DockerConfig
|
||||
Game GameConfig
|
||||
Admin AdminBootstrapConfig
|
||||
AdminConsole AdminConsoleConfig
|
||||
GeoIP GeoIPConfig
|
||||
Telemetry TelemetryConfig
|
||||
Auth AuthConfig
|
||||
@@ -308,6 +311,15 @@ type AdminBootstrapConfig struct {
|
||||
Password string
|
||||
}
|
||||
|
||||
// AdminConsoleConfig configures the server-rendered operator console.
|
||||
// CSRFKey is the secret keying the console's stateless anti-CSRF token.
|
||||
// When empty the console falls back to a per-process random key, which is
|
||||
// secure but means forms do not survive a restart and do not validate across
|
||||
// replicas; set a shared key when running more than one backend instance.
|
||||
type AdminConsoleConfig struct {
|
||||
CSRFKey string
|
||||
}
|
||||
|
||||
// GeoIPConfig configures the GeoLite2 country database used by geo lookups.
|
||||
type GeoIPConfig struct {
|
||||
DBPath string
|
||||
@@ -644,6 +656,8 @@ func LoadFromEnv() (Config, error) {
|
||||
cfg.Admin.User = loadString(envAdminBootstrapUser, cfg.Admin.User)
|
||||
cfg.Admin.Password = loadString(envAdminBootstrapPassword, cfg.Admin.Password)
|
||||
|
||||
cfg.AdminConsole.CSRFKey = loadString(envAdminConsoleCSRFKey, cfg.AdminConsole.CSRFKey)
|
||||
|
||||
cfg.GeoIP.DBPath = loadString(envGeoIPDBPath, cfg.GeoIP.DBPath)
|
||||
|
||||
cfg.Telemetry.TracesExporter = strings.ToLower(loadString(envOTelTracesExporter, cfg.Telemetry.TracesExporter))
|
||||
|
||||
Reference in New Issue
Block a user