rproxy and servewaf replace the one-process smallwebwaf (closes #172, closes #165)
check / check (push) Failing after 8m17s
check / check (push) Failing after 8m17s
`smallwebwaf` with no command now prints the commands and exits with status 2. The image runs rproxy, or servewaf with SMALLWEBWAF_COMMAND=servewaf. The passing-on code, its settings and its log fields and metric go. internal/proxy keeps the checks, answers, reports and own endpoints; its tests run through the real rproxy. The documents describe the pair. Judgement call: clients.json keeps token_refused, since state files refuse unknown fields. Deviation: script/gitea-requests sets SWWAF_LOG_REQUEST_HEADERS, to label requests. Model: opus-5-5
This commit is contained in:
@@ -84,26 +84,12 @@ func startServeWAFWith(
|
||||
}
|
||||
maps.Copy(settings, env)
|
||||
|
||||
server, out, queue := newServerWith(t, proxy.NewServeWAF,
|
||||
"http://127.0.0.1:8081", geojsURL, clk.Now, settings)
|
||||
server, out, queue := newServeWAF(t, geojsURL, clk.Now, settings)
|
||||
change(server)
|
||||
|
||||
listener, err := (&net.ListenConfig{}).Listen(t.Context(), "tcp", localhost+":0")
|
||||
if err != nil {
|
||||
t.Fatalf("listen: %v", err)
|
||||
}
|
||||
|
||||
go func() {
|
||||
_ = server.Serve(listener)
|
||||
}()
|
||||
|
||||
t.Cleanup(func() {
|
||||
_ = server.Close()
|
||||
})
|
||||
serve(t, server)
|
||||
|
||||
return &serveWAF{
|
||||
t: t, addr: listener.Addr().String(), out: out, server: server,
|
||||
clock: clk, queue: queue,
|
||||
t: t, addr: server.Addr, out: out, server: server, clock: clk, queue: queue,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -626,13 +612,10 @@ func TestQuestionWhoseBodyStopsArrivingGetsNoAnswer(t *testing.T) {
|
||||
wantProcessMessages(t, s, "a question's body stopped arriving", 1)
|
||||
wantNoRequestLines(t, s)
|
||||
|
||||
// The id was not taken, and the metrics count nothing for it.
|
||||
// The id was not taken.
|
||||
again := s.question(siteA, client, "/")
|
||||
again.Header.Set(requestIDHeader, "an-id")
|
||||
wantDisposition(t, do(t, again), http.StatusOK, proxy.DispositionAllow)
|
||||
wantNoSeries(t, s.metrics(),
|
||||
`smallwebwaf_size_and_time_limit_hits_total{instance="`+alertInstance+
|
||||
`",limit="SWWAF_CLIENT_REQUEST_TIMEOUT"}`)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1466,16 +1449,10 @@ func TestOwnEndpointsLinesDoNotSayWhichOfTheTwoTheyAre(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestSettingsOfTheLimitsAndTheProxiesAreIgnored(t *testing.T) {
|
||||
func TestALargeBodyAnnouncedAndLongHeadersAreNoReasonToRefuse(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
s := startServeWAF(t, "", map[string]string{
|
||||
requestMaxBytes: "1",
|
||||
clientHeaderMaxBytes: "5K",
|
||||
clientRequestTimeout: off,
|
||||
clientResponseTimeout: off,
|
||||
trustedProxies: localhost,
|
||||
})
|
||||
s := startServeWAF(t, "", nil)
|
||||
|
||||
req := s.questionWith(http.MethodPost, siteA, client, "/",
|
||||
strings.NewReader("a body"))
|
||||
@@ -1493,33 +1470,23 @@ func TestSettingsOfTheLimitsAndTheProxiesAreIgnored(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestShortClientResponseTimeoutIsIgnored(t *testing.T) {
|
||||
func TestLogLevelHoldsBackNoRequestLine(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// The setting would leave no time to send any answer.
|
||||
s := startServeWAF(t, "", map[string]string{
|
||||
clientResponseTimeout: time.Nanosecond.String(), denyNets: client,
|
||||
})
|
||||
s := startServeWAF(t, "", map[string]string{"SWWAF_LOG_LEVEL": "error"})
|
||||
|
||||
wantDisposition(t, s.ask(client, "/"), http.StatusForbidden, proxy.DispositionDeny)
|
||||
wantStatus(t, get(t, s.addr, proxy.HealthPath), http.StatusOK)
|
||||
}
|
||||
// A refused question would write a process warning, held back at error.
|
||||
req := s.question(siteA, client, "/")
|
||||
req.Header.Del(requestIDHeader)
|
||||
wantStatus(t, do(t, req), http.StatusBadRequest)
|
||||
|
||||
func TestShortClientRequestTimeoutIsIgnored(t *testing.T) {
|
||||
t.Parallel()
|
||||
s.allowed(client)
|
||||
wantLine(t, s.out.requestLine(t), http.StatusOK, requestlog.ActionForward)
|
||||
|
||||
// The setting would have run out while the Core Rule Set read the body. Go's
|
||||
// server would then take the connection for gone, and the line say aborted.
|
||||
s := startServeWAF(t, "", map[string]string{
|
||||
clientRequestTimeout: time.Nanosecond.String(), wafMode: block, wafBodyLimit: "1M",
|
||||
})
|
||||
|
||||
req := s.questionWith(http.MethodPost, siteA, client, "/", strings.NewReader("a=1"))
|
||||
req.Header.Set("Content-Type", formData)
|
||||
wantDisposition(t, do(t, req), http.StatusOK, proxy.DispositionAllow)
|
||||
|
||||
if line := s.out.requestLine(t); line.Aborted {
|
||||
t.Errorf("log line says aborted: %+v", line.Line)
|
||||
for _, line := range s.out.lines(t) {
|
||||
if line["type"] == "process" {
|
||||
t.Errorf("process line %v, want none at error", line)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1573,7 +1540,7 @@ func TestCoreRuleSetReadsTheBodyAQuestionCarries(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
s := startServeWAF(t, "", map[string]string{
|
||||
wafMode: block, wafBodyLimit: "1M",
|
||||
wafMode: block, wafBodyLimit: "64K",
|
||||
})
|
||||
|
||||
ask := func(contentType, body string) answer {
|
||||
|
||||
Reference in New Issue
Block a user