mirror of
https://blitiri.com.ar/repos/chasquid
synced 2026-10-29 15:02:30 +00:00
monitoring: Use method-based routing and CSRF for http requests
The monitoring http server is mostly read-only but shows sensitive data, and also has one mutating endpoint, /exit. This patch updates the routing to use method-based routing, and also wraps it on CSRF to reject cross-origin requests from browsers. Note that does not affect direct POST /exit requests via tools like curl or wget, which continue to work just like today. This is exercised in the (unchanged) integration tests.
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"blitiri.com.ar/go/chasquid/internal/config"
|
||||
)
|
||||
|
||||
func TestMonitoringHandler(t *testing.T) {
|
||||
conf := &config.Config{Hostname: "testhost"}
|
||||
h := monitoringHandler(http.NewServeMux(), &http.Server{}, conf)
|
||||
|
||||
cases := []struct {
|
||||
method string
|
||||
path string
|
||||
header map[string]string
|
||||
want int
|
||||
}{
|
||||
{"GET", "/", nil, http.StatusOK},
|
||||
{"HEAD", "/", nil, http.StatusOK},
|
||||
{"POST", "/", nil, http.StatusMethodNotAllowed},
|
||||
{"GET", "/doesnotexist", nil, http.StatusNotFound},
|
||||
{"GET", "/metrics", nil, http.StatusOK},
|
||||
{"GET", "/debug/flags", nil, http.StatusOK},
|
||||
{"GET", "/debug/config", nil, http.StatusOK},
|
||||
{"POST", "/debug/config", nil, http.StatusMethodNotAllowed},
|
||||
{"GET", "/debug/traces", nil, http.StatusOK},
|
||||
|
||||
// /exit is only allowed via POST.
|
||||
{"GET", "/exit", nil, http.StatusMethodNotAllowed},
|
||||
|
||||
// Cross-origin requests from browsers must be rejected, to prevent
|
||||
// CSRF. They must not reach the handler, which would exit.
|
||||
{"POST", "/exit",
|
||||
map[string]string{"Sec-Fetch-Site": "cross-site"},
|
||||
http.StatusForbidden},
|
||||
{"POST", "/exit",
|
||||
map[string]string{"Origin": "https://evil.example"},
|
||||
http.StatusForbidden},
|
||||
}
|
||||
for _, c := range cases {
|
||||
req := httptest.NewRequest(c.method, c.path, nil)
|
||||
for k, v := range c.header {
|
||||
req.Header.Set(k, v)
|
||||
}
|
||||
rec := httptest.NewRecorder()
|
||||
h.ServeHTTP(rec, req)
|
||||
if rec.Code != c.want {
|
||||
t.Errorf("%s %s %v: got status %d, expected %d",
|
||||
c.method, c.path, c.header, rec.Code, c.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user