rproxy and servewaf replace the one-process smallwebwaf (closes #172, closes #165)
check / check (push) Failing after 14m44s
check / check (push) Failing after 14m44s
`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. Partially verified: make example-app and make gitea-requests never built the image, as Ubuntu's snapshot service answered 5xx. Model: opus-5-5
This commit was merged in pull request #184.
This commit is contained in:
@@ -47,8 +47,6 @@ const (
|
||||
func TestEachByteLimitBansOnceTheResponseHasEnded(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
const scraper = "192.0.2.200"
|
||||
|
||||
for _, tc := range []struct {
|
||||
setting, window string
|
||||
// apart is the time between the two requests, which the window
|
||||
@@ -94,7 +92,7 @@ func TestEachByteLimitBansOnceTheResponseHasEnded(t *testing.T) {
|
||||
|
||||
s.get(client, http.StatusForbidden, requestlog.ActionBanned)
|
||||
|
||||
wantMetric(t, s.scrape(scraper), `smallwebwaf_rate_limit_hits_total{`+
|
||||
wantMetric(t, s.scrape(), `smallwebwaf_rate_limit_hits_total{`+
|
||||
`instance="`+alertInstance+`",kind="bytes",window="`+tc.window+`"}`, 1)
|
||||
})
|
||||
}
|
||||
@@ -126,7 +124,7 @@ func TestBytesOfAnAnswerThatBreaksOffAreCounted(t *testing.T) {
|
||||
// The 70 bytes passed on before the app broke off are over the limit of
|
||||
// 50, and ban the client for an hour.
|
||||
line, got := s.requestWithBody(http.MethodGet, client, "/", "", "", http.StatusOK,
|
||||
requestlog.ActionUpstreamError)
|
||||
requestlog.ActionForward)
|
||||
if len(got.body) != answerBytes || line.LimitHit != minuteBytes ||
|
||||
line.BanExpires != expires {
|
||||
t.Errorf("got %d bytes, and the log line has limit_hit %q and ban_expires %q, "+
|
||||
@@ -168,39 +166,6 @@ func TestWebSocketBytesAreCountedOnceItCloses(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestWebSocketPassesTheAnswerAfterTheClientStopsSending(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
app := startApp(t, echoOnceTheClientStops)
|
||||
addr, out := startProxy(t, app.URL,
|
||||
map[string]string{trustedProxies: trustLocalhost})
|
||||
s := &sender{t: t, addr: addr, out: out}
|
||||
|
||||
conn, reader := s.openWebSocket()
|
||||
send(t, conn, uploadBody)
|
||||
|
||||
// The client closes its sending side and waits for the answer, which the
|
||||
// app sends only once it has seen the client stop. smallwebwaf passes the
|
||||
// close on to the app through CloseWrite on upgradedConn; without that,
|
||||
// it closes both connections, and the answer is lost.
|
||||
tcp, ok := conn.(*net.TCPConn)
|
||||
if !ok {
|
||||
t.Fatalf("connection is a %T, want a *net.TCPConn", conn)
|
||||
}
|
||||
|
||||
err := tcp.CloseWrite()
|
||||
if err != nil {
|
||||
t.Fatalf("close the sending side: %v", err)
|
||||
}
|
||||
|
||||
got, err := io.ReadAll(reader)
|
||||
if err != nil || string(got) != uploadBody {
|
||||
t.Errorf("got %q (%v), want %q", got, err, uploadBody)
|
||||
}
|
||||
|
||||
s.closeWebSocket(conn)
|
||||
}
|
||||
|
||||
func TestBytesCountSaysWhichBytesCount(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -465,28 +430,6 @@ func answerAfterUpgrade(w http.ResponseWriter, _ *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
// echoOnceTheClientStops is an app that switches protocols, as for a
|
||||
// WebSocket, reads what the client sends until the client stops sending,
|
||||
// and then sends it all back.
|
||||
func echoOnceTheClientStops(w http.ResponseWriter, _ *http.Request) {
|
||||
conn, buffered, err := http.NewResponseController(w).Hijack()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
defer func() {
|
||||
_ = conn.Close()
|
||||
}()
|
||||
|
||||
_, _ = buffered.WriteString("HTTP/1.1 101 Switching Protocols\r\n" +
|
||||
"Connection: Upgrade\r\nUpgrade: websocket\r\n\r\n")
|
||||
_ = buffered.Flush()
|
||||
|
||||
received, _ := io.ReadAll(buffered)
|
||||
_, _ = buffered.Write(received)
|
||||
_ = buffered.Flush()
|
||||
}
|
||||
|
||||
// webSocket opens a WebSocket from client to answerAfterUpgrade, sends a
|
||||
// line of bodyBytes on it, reads the answer, and closes it. It checks the
|
||||
// answer, and the log line as request does, and returns the log line.
|
||||
@@ -543,7 +486,7 @@ func (s *sender) closeWebSocket(conn net.Conn) logLine {
|
||||
|
||||
_ = conn.Close()
|
||||
|
||||
line := s.out.requestLines(s.t, s.sent+1)[s.sent]
|
||||
line := s.out.endedLines(s.t, s.sent+1)[s.sent]
|
||||
s.sent++
|
||||
wantLine(s.t, line, http.StatusSwitchingProtocols, requestlog.ActionForward)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user