diff options
Diffstat (limited to 'cmd/dashboard')
| -rw-r--r-- | cmd/dashboard/main.go | 59 |
1 files changed, 44 insertions, 15 deletions
diff --git a/cmd/dashboard/main.go b/cmd/dashboard/main.go index c648ede..596932a 100644 --- a/cmd/dashboard/main.go +++ b/cmd/dashboard/main.go @@ -163,8 +163,29 @@ func main() { r.Use(appmiddleware.SecurityHeaders(cfg.Debug)) // Security headers r.Use(sessionManager.LoadAndSave) // Session middleware must be applied globally - // Initialize Claudomator reverse proxy - claudomatorProxy := handlers.NewClaudomatorProxy(cfg.ClaudomatorURL, cfg.WebAuthnOrigin) + // Service gateway — upstream services proxied through doot's auth + SSL layer. + // Each mount registers a path prefix, upstream URL, and any public webhook paths. + type serviceMount struct { + name string + upstream string + prefix string + webhookPaths []string // POST paths that bypass session auth (e.g. HMAC-signed webhooks) + } + mounts := []serviceMount{ + { + name: "claudomator", + upstream: cfg.ClaudomatorURL, + prefix: "/claudomator", + webhookPaths: []string{"/claudomator/api/webhooks/github"}, + }, + } + if cfg.PlaygroundURL != "" { + mounts = append(mounts, serviceMount{ + name: "playground", + upstream: cfg.PlaygroundURL, + prefix: "/playground", + }) + } // Rate limiter for auth endpoints authRateLimiter := appmiddleware.NewRateLimiter(config.AuthRateLimitRequests, config.AuthRateLimitWindow) @@ -225,21 +246,29 @@ func main() { }) }) - // Claudomator proxy routes - // /claudomator (no trailing slash) -> 301 redirect - r.Get("/claudomator", func(w http.ResponseWriter, r *http.Request) { - http.Redirect(w, r, "/claudomator/", http.StatusMovedPermanently) - }) + // Register service gateway mounts — each upstream proxied behind doot's auth layer. + for _, m := range mounts { + proxy := handlers.NewServiceProxy(m.upstream, cfg.WebAuthnOrigin, m.prefix) - // GitHub webhook: no auth (GitHub POSTs with HMAC, no session) - r.Post("/claudomator/api/webhooks/github", claudomatorProxy.ServeHTTP) + // Bare prefix → redirect to prefix/ + prefix := m.prefix + r.Get(prefix, func(w http.ResponseWriter, r *http.Request) { + http.Redirect(w, r, prefix+"/", http.StatusMovedPermanently) + }) + + // Public webhook paths bypass session auth (rely on service-level HMAC/token) + for _, wp := range m.webhookPaths { + r.Post(wp, proxy.ServeHTTP) + } + + // All other routes require auth + origin check (CSRF protection for proxy) + r.Group(func(r chi.Router) { + r.Use(authHandlers.Middleware().RequireAuth) + r.Use(auth.OriginCheck(cfg.WebAuthnOrigin)) + r.Handle(prefix+"/*", proxy) + }) + } - // All other Claudomator routes: RequireAuth + origin check (CSRF protection for proxy) - r.Group(func(r chi.Router) { - r.Use(authHandlers.Middleware().RequireAuth) - r.Use(auth.OriginCheck(cfg.WebAuthnOrigin)) - r.Handle("/claudomator/*", claudomatorProxy) - }) // Protected routes (auth required) r.Group(func(r chi.Router) { |
