Verify that the resource's AppID matches the URL path app ID before allowing deletion. Without this check, any authenticated user could delete resources belonging to any app by providing the target resource's ID in the URL regardless of the app ID in the path (IDOR vulnerability). Closes #19
108 lines
3.5 KiB
Go
108 lines
3.5 KiB
Go
package server
|
|
|
|
import (
|
|
"net/http"
|
|
"time"
|
|
|
|
"github.com/go-chi/chi/v5"
|
|
chimw "github.com/go-chi/chi/v5/middleware"
|
|
"github.com/prometheus/client_golang/prometheus/promhttp"
|
|
|
|
"git.eeqj.de/sneak/upaas/static"
|
|
)
|
|
|
|
// requestTimeout is the maximum duration for handling a request.
|
|
const requestTimeout = 60 * time.Second
|
|
|
|
// SetupRoutes configures all HTTP routes.
|
|
//
|
|
//nolint:funlen // route configuration is inherently long but straightforward
|
|
func (s *Server) SetupRoutes() {
|
|
s.router = chi.NewRouter()
|
|
|
|
// Global middleware
|
|
s.router.Use(chimw.Recoverer)
|
|
s.router.Use(chimw.RequestID)
|
|
s.router.Use(s.mw.Logging())
|
|
s.router.Use(s.mw.CORS())
|
|
s.router.Use(chimw.Timeout(requestTimeout))
|
|
s.router.Use(s.mw.SetupRequired())
|
|
|
|
// Health check (no auth required)
|
|
s.router.Get("/health", s.handlers.HandleHealthCheck())
|
|
|
|
// Static files
|
|
s.router.Handle("/s/*", http.StripPrefix(
|
|
"/s/",
|
|
http.FileServer(http.FS(static.Static)),
|
|
))
|
|
|
|
// Webhook endpoint (uses secret for auth, not session — no CSRF)
|
|
s.router.Post("/webhook/{secret}", s.handlers.HandleWebhook())
|
|
|
|
// All HTML-serving routes get CSRF protection
|
|
s.router.Group(func(r chi.Router) {
|
|
r.Use(s.mw.CSRF())
|
|
|
|
// Public routes
|
|
r.Get("/login", s.handlers.HandleLoginGET())
|
|
r.Post("/login", s.handlers.HandleLoginPOST())
|
|
r.Get("/setup", s.handlers.HandleSetupGET())
|
|
r.Post("/setup", s.handlers.HandleSetupPOST())
|
|
|
|
// Protected routes (require session auth)
|
|
r.Group(func(r chi.Router) {
|
|
r.Use(s.mw.SessionAuth())
|
|
|
|
// Dashboard
|
|
r.Get("/", s.handlers.HandleDashboard())
|
|
|
|
// Logout
|
|
r.Post("/logout", s.handlers.HandleLogout())
|
|
|
|
// App routes
|
|
r.Get("/apps/new", s.handlers.HandleAppNew())
|
|
r.Post("/apps", s.handlers.HandleAppCreate())
|
|
r.Get("/apps/{id}", s.handlers.HandleAppDetail())
|
|
r.Get("/apps/{id}/edit", s.handlers.HandleAppEdit())
|
|
r.Post("/apps/{id}", s.handlers.HandleAppUpdate())
|
|
r.Post("/apps/{id}/delete", s.handlers.HandleAppDelete())
|
|
r.Post("/apps/{id}/deploy", s.handlers.HandleAppDeploy())
|
|
r.Get("/apps/{id}/deployments", s.handlers.HandleAppDeployments())
|
|
r.Get("/apps/{id}/deployments/{deploymentID}/logs", s.handlers.HandleDeploymentLogsAPI())
|
|
r.Get("/apps/{id}/deployments/{deploymentID}/download", s.handlers.HandleDeploymentLogDownload())
|
|
r.Get("/apps/{id}/logs", s.handlers.HandleAppLogs())
|
|
r.Get("/apps/{id}/container-logs", s.handlers.HandleContainerLogsAPI())
|
|
r.Get("/apps/{id}/status", s.handlers.HandleAppStatusAPI())
|
|
r.Get("/apps/{id}/recent-deployments", s.handlers.HandleRecentDeploymentsAPI())
|
|
r.Post("/apps/{id}/restart", s.handlers.HandleAppRestart())
|
|
r.Post("/apps/{id}/stop", s.handlers.HandleAppStop())
|
|
r.Post("/apps/{id}/start", s.handlers.HandleAppStart())
|
|
|
|
// Environment variables
|
|
r.Post("/apps/{id}/env-vars", s.handlers.HandleEnvVarAdd())
|
|
r.Post("/apps/{id}/env-vars/{varID}/delete", s.handlers.HandleEnvVarDelete())
|
|
|
|
// Labels
|
|
r.Post("/apps/{id}/labels", s.handlers.HandleLabelAdd())
|
|
r.Post("/apps/{id}/labels/{labelID}/delete", s.handlers.HandleLabelDelete())
|
|
|
|
// Volumes
|
|
r.Post("/apps/{id}/volumes", s.handlers.HandleVolumeAdd())
|
|
r.Post("/apps/{id}/volumes/{volumeID}/delete", s.handlers.HandleVolumeDelete())
|
|
|
|
// Ports
|
|
r.Post("/apps/{id}/ports", s.handlers.HandlePortAdd())
|
|
r.Post("/apps/{id}/ports/{portID}/delete", s.handlers.HandlePortDelete())
|
|
})
|
|
})
|
|
|
|
// Metrics endpoint (optional, with basic auth)
|
|
if s.params.Config.MetricsUsername != "" {
|
|
s.router.Group(func(r chi.Router) {
|
|
r.Use(s.mw.MetricsAuth())
|
|
r.Get("/metrics", promhttp.Handler().ServeHTTP)
|
|
})
|
|
}
|
|
}
|