aboutsummaryrefslogtreecommitdiff
path: root/internal/server/server.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/server/server.go')
-rw-r--r--internal/server/server.go51
1 files changed, 48 insertions, 3 deletions
diff --git a/internal/server/server.go b/internal/server/server.go
index 92b0f09..b0192a4 100644
--- a/internal/server/server.go
+++ b/internal/server/server.go
@@ -65,9 +65,11 @@ func New(cfg *config.Config, store *storage.Storage, sched *monitor.Scheduler, l
// Pages
mux.HandleFunc("GET /", s.handleIndex)
- mux.HandleFunc("GET /api/status", s.handleAPIStatus)
- mux.HandleFunc("GET /api/monitor/{name}", s.handleAPIMonitor)
- mux.HandleFunc("GET /api/history/{name}", s.handleAPIHistory)
+
+ // API endpoints (protected by API access control)
+ mux.HandleFunc("GET /api/status", s.withAPIAuth(s.handleAPIStatus))
+ mux.HandleFunc("GET /api/monitor/{name}", s.withAPIAuth(s.handleAPIMonitor))
+ mux.HandleFunc("GET /api/history/{name}", s.withAPIAuth(s.handleAPIHistory))
// Create HTTP server
s.server = &http.Server{
@@ -115,6 +117,49 @@ func (s *Server) withMiddleware(next http.Handler) http.Handler {
})
}
+// withAPIAuth wraps an API handler with access control based on config.API.Access
+func (s *Server) withAPIAuth(handler http.HandlerFunc) http.HandlerFunc {
+ return func(w http.ResponseWriter, r *http.Request) {
+ switch s.config.API.Access {
+ case "private":
+ // API is disabled
+ s.jsonError(w, "API access is disabled", http.StatusForbidden)
+ return
+
+ case "authenticated":
+ // Check for API key in header or query param
+ apiKey := r.Header.Get("X-API-Key")
+ if apiKey == "" {
+ apiKey = r.URL.Query().Get("api_key")
+ }
+
+ if apiKey == "" {
+ w.Header().Set("WWW-Authenticate", "API-Key")
+ s.jsonError(w, "API key required", http.StatusUnauthorized)
+ return
+ }
+
+ // Check if key is valid
+ valid := false
+ for _, key := range s.config.API.Keys {
+ if key == apiKey {
+ valid = true
+ break
+ }
+ }
+
+ if !valid {
+ s.jsonError(w, "Invalid API key", http.StatusUnauthorized)
+ return
+ }
+
+ // case "public" or default: allow access
+ }
+
+ handler(w, r)
+ }
+}
+
// PageData contains data for rendering the status page
type PageData struct {
Site config.SiteConfig