Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
235ff0707f |
@@ -316,8 +316,7 @@ in `bin/state` unless `SWWAF_STATE_DIR` is set, and the default rule file of
|
||||
Each setting is an environment variable, or a file one names (see "Settings
|
||||
given as files" below), and each has a default, so none has to be set. A setting
|
||||
that is set but invalid stops the start with a message naming it, and the
|
||||
effective settings are logged at start, unless `SWWAF_LOG_LEVEL` is `warn` or
|
||||
`error`, which hold that line back.
|
||||
effective settings are logged at start.
|
||||
|
||||
- `SWWAF_LISTEN_ADDR` (default `:8080`): where `smallwebwaf` listens.
|
||||
- `SWWAF_UPSTREAM_URL` (default `http://127.0.0.1:8081`): the app, as `http` or
|
||||
|
||||
@@ -399,25 +399,6 @@ func TestAnswers502WhenTheAppCannotBeReached(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestLogLevelHoldsBackNoRequestLine(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// At error the warning that the request to the app failed is held back,
|
||||
// and is written before the answer is.
|
||||
addr, out := startProxy(t, "http://"+localhost+":1", map[string]string{
|
||||
"SWWAF_LOG_LEVEL": "error",
|
||||
})
|
||||
|
||||
wantStatus(t, get(t, addr, "/"), http.StatusBadGateway)
|
||||
wantLine(t, out.requestLine(t), http.StatusBadGateway, requestlog.ActionUpstreamError)
|
||||
|
||||
for _, line := range out.lines(t) {
|
||||
if line["type"] == "process" {
|
||||
t.Errorf("process line %v, want none at error", line)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestLogsAnAnswerThatBrokeOff(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
||||
@@ -249,16 +249,14 @@ func TestServesUntilToldToStop(t *testing.T) {
|
||||
out.line(t, "msg", "stopped")
|
||||
}
|
||||
|
||||
func TestLogLevelHoldsBackTheLessSevereProcessLines(t *testing.T) {
|
||||
func TestLogLevelHoldsBackProcessLinesAndNoRequestLine(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// A list that cannot be fetched has a warning written once smallwebwaf
|
||||
// serves, after its starting line.
|
||||
lists := httptest.NewServer(http.HandlerFunc(
|
||||
func(w http.ResponseWriter, _ *http.Request) {
|
||||
w.WriteHeader(http.StatusServiceUnavailable)
|
||||
}))
|
||||
t.Cleanup(lists.Close)
|
||||
// At warn no starting line gives the address, so the test picks one.
|
||||
// The app cannot be reached, so that a request has a warning written:
|
||||
// no test can listen on port 1.
|
||||
addr := freeAddress(t)
|
||||
url := "http://" + addr + "/"
|
||||
|
||||
ctx, stop := context.WithCancel(t.Context())
|
||||
out := &output{}
|
||||
@@ -266,15 +264,18 @@ func TestLogLevelHoldsBackTheLessSevereProcessLines(t *testing.T) {
|
||||
|
||||
go func() {
|
||||
exited <- run(ctx, map[string]string{
|
||||
listenAddr: localhost + ":0",
|
||||
stateDir: t.TempDir(),
|
||||
rulesDir: t.TempDir(),
|
||||
"SWWAF_BLOCKLIST_URLS": lists.URL + "/tor.txt",
|
||||
"SWWAF_LOG_LEVEL": "warn",
|
||||
listenAddr: addr,
|
||||
upstreamURL: "http://" + localhost + ":1",
|
||||
stateDir: t.TempDir(),
|
||||
rulesDir: t.TempDir(),
|
||||
"SWWAF_LOG_LEVEL": "warn",
|
||||
}, out)
|
||||
}()
|
||||
|
||||
out.line(t, "msg", "fetching a list failed")
|
||||
waitUntilServing(t, url)
|
||||
wantStatus(t, url, localhost, http.StatusBadGateway)
|
||||
out.line(t, "action", "upstream_error")
|
||||
out.line(t, "msg", "request to the app failed")
|
||||
stop()
|
||||
|
||||
select {
|
||||
@@ -286,7 +287,8 @@ func TestLogLevelHoldsBackTheLessSevereProcessLines(t *testing.T) {
|
||||
t.Fatal("still running after being told to stop")
|
||||
}
|
||||
|
||||
// Not one of the info lines from the start to the stop.
|
||||
// Not one of the info lines from the start to the stop; a request line
|
||||
// has no level.
|
||||
for line := range strings.Lines(out.text()) {
|
||||
var fields map[string]any
|
||||
|
||||
@@ -1145,6 +1147,52 @@ func runUntilStopped(
|
||||
return out
|
||||
}
|
||||
|
||||
// freeAddress returns an address on localhost that nothing listens on as
|
||||
// it returns, for a test that cannot learn smallwebwaf's own address from
|
||||
// its starting line.
|
||||
func freeAddress(t *testing.T) string {
|
||||
t.Helper()
|
||||
|
||||
listener, err := (&net.ListenConfig{}).Listen(t.Context(), "tcp", localhost+":0")
|
||||
if err != nil {
|
||||
t.Fatalf("listen: %v", err)
|
||||
}
|
||||
|
||||
addr := listener.Addr().String()
|
||||
_ = listener.Close()
|
||||
|
||||
return addr
|
||||
}
|
||||
|
||||
// waitUntilServing waits until smallwebwaf at url answers its health
|
||||
// check, for a test that has no starting line to wait for.
|
||||
func waitUntilServing(t *testing.T, url string) {
|
||||
t.Helper()
|
||||
|
||||
transport := &http.Transport{}
|
||||
defer transport.CloseIdleConnections()
|
||||
|
||||
deadline := time.Now().Add(waitLimit)
|
||||
for time.Now().Before(deadline) {
|
||||
req, err := http.NewRequestWithContext(t.Context(), http.MethodGet,
|
||||
url+"_smallwebwaf/healthz", http.NoBody)
|
||||
if err != nil {
|
||||
t.Fatalf("new request: %v", err)
|
||||
}
|
||||
|
||||
res, err := (&http.Client{Transport: transport}).Do(req)
|
||||
if err == nil {
|
||||
_ = res.Body.Close()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
time.Sleep(pollInterval)
|
||||
}
|
||||
|
||||
t.Fatalf("no answer at %s after %s", url, waitLimit)
|
||||
}
|
||||
|
||||
// wantStartingLine checks that the line at start gives the version and
|
||||
// every setting's value.
|
||||
func wantStartingLine(t *testing.T, line map[string]any, appURL, dir string) {
|
||||
|
||||
Reference in New Issue
Block a user