mirror of
https://blitiri.com.ar/repos/chasquid
synced 2026-10-29 15:02:30 +00:00
b23047aa83
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.
56 lines
1.5 KiB
Go
56 lines
1.5 KiB
Go
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)
|
|
}
|
|
}
|
|
}
|