Rename discriminator to waf everywhere (closes #312)
check / check (push) Successful in 5m7s
check / check (push) Successful in 5m7s
The command is now `sww waf`, and the package is `internal/waf`. Types, functions, files, tests, comments, docs, the Dockerfile, the runit script, `script/`, compose examples, the log field `waf_line` and the `X-From-Waf` test header follow. No behaviour changes, and no setting changes name: rproxy already finds the waf through `SWRP_WAF_BACKEND`. Done with one `sed -i` (Discriminator and DISCRIMINATOR to WAF, discriminator to waf) over the files `git grep -i discriminator` listed, as sneak allowed for this rename, then `git mv` for the package and files. Model: opus-5-5
This commit is contained in:
1 parent
ad36dd1775
commit
3fc63a1e40
89 files changed
+1454
-1489
No files matched your search
+53
-53
@@ -19,18 +19,18 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"sneak.berlin/go/smallwebwaf/internal/discriminator"
|
||||
"sneak.berlin/go/smallwebwaf/internal/sww"
|
||||
"sneak.berlin/go/smallwebwaf/internal/waf"
|
||||
)
|
||||
|
||||
const (
|
||||
// wafBackend is the setting that names discriminator to rproxy.
|
||||
// wafBackend is the setting that names waf to rproxy.
|
||||
wafBackend = "SWRP_WAF_BACKEND"
|
||||
// rproxyListenAddr is the setting that says where rproxy listens.
|
||||
rproxyListenAddr = "SWRP_LISTEN_ADDR"
|
||||
// rproxyUpstreamURL is the setting that says where the app is.
|
||||
rproxyUpstreamURL = "SWRP_UPSTREAM_URL"
|
||||
// rproxyTimeout is the setting that says how long rproxy waits for discriminator.
|
||||
// rproxyTimeout is the setting that says how long rproxy waits for waf.
|
||||
rproxyTimeout = "SWRP_TIMEOUT_MS"
|
||||
// bannedProbe is a path the default rule file bans a client for.
|
||||
bannedProbe = "/.env"
|
||||
@@ -52,7 +52,7 @@ func runRProxy(ctx context.Context, env map[string]string, out *output) int {
|
||||
})
|
||||
}
|
||||
|
||||
// startRProxy runs rproxy with discriminator at backend and the app at appURL, and
|
||||
// startRProxy runs rproxy with waf at backend and the app at appURL, and
|
||||
// returns its URL and what it writes. It believes X-Forwarded-For from the
|
||||
// tests. It stops as the test ends, and that it stopped in order is checked.
|
||||
func startRProxy(t *testing.T, backend, appURL string) (string, *output) {
|
||||
@@ -91,10 +91,10 @@ func startRProxy(t *testing.T, backend, appURL string) (string, *output) {
|
||||
return "http://" + addr, out
|
||||
}
|
||||
|
||||
// startDiscriminator runs discriminator with the settings in env, and returns
|
||||
// startWAF runs waf with the settings in env, and returns
|
||||
// its address and URL, what it writes, and what stops it, which checks that it
|
||||
// stopped in order.
|
||||
func startDiscriminator(t *testing.T, env map[string]string) (string, *output, func()) {
|
||||
func startWAF(t *testing.T, env map[string]string) (string, *output, func()) {
|
||||
t.Helper()
|
||||
|
||||
ctx, stop := context.WithCancel(t.Context())
|
||||
@@ -113,17 +113,17 @@ func startDiscriminator(t *testing.T, env map[string]string) (string, *output, f
|
||||
select {
|
||||
case status := <-exited:
|
||||
if status != 0 {
|
||||
t.Fatalf("discriminator's exit status %d, want 0; output:\n%s", status, out.text())
|
||||
t.Fatalf("waf's exit status %d, want 0; output:\n%s", status, out.text())
|
||||
}
|
||||
case <-time.After(waitLimit):
|
||||
t.Fatal("discriminator still running after being told to stop")
|
||||
t.Fatal("waf still running after being told to stop")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// discriminatorSettings are discriminator's settings with the default rule
|
||||
// wafSettings are waf's settings with the default rule
|
||||
// file, to listen at any free port.
|
||||
func discriminatorSettings(t *testing.T) map[string]string {
|
||||
func wafSettings(t *testing.T) map[string]string {
|
||||
t.Helper()
|
||||
|
||||
return map[string]string{
|
||||
@@ -136,7 +136,7 @@ func discriminatorSettings(t *testing.T) map[string]string {
|
||||
func TestABanThroughOneSiteRefusesTheClientOnTheOther(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
addr, discriminatorOut, stop := startDiscriminator(t, discriminatorSettings(t))
|
||||
addr, wafOut, stop := startWAF(t, wafSettings(t))
|
||||
defer stop()
|
||||
|
||||
backend := "http://" + addr
|
||||
@@ -151,32 +151,32 @@ func TestABanThroughOneSiteRefusesTheClientOnTheOther(t *testing.T) {
|
||||
wantStatus(t, second+"/", placed, http.StatusForbidden)
|
||||
wantStatus(t, second+"/", otherClient, http.StatusOK)
|
||||
|
||||
// One request's three lines carry one id, rproxy's with discriminator's answer.
|
||||
// One request's three lines carry one id, rproxy's with waf's answer.
|
||||
line := firstOut.line(t, "path", bannedProbe)
|
||||
if line["disposition"] != discriminator.DispositionDeny ||
|
||||
if line["disposition"] != waf.DispositionDeny ||
|
||||
line["client_ip"] != placed {
|
||||
t.Errorf("rproxy's line is %v", line)
|
||||
}
|
||||
|
||||
id, _ := line["request_id"].(string)
|
||||
decision := discriminatorLine(t, discriminatorOut, id, "decision")
|
||||
report := discriminatorLine(t, discriminatorOut, id, "report")
|
||||
decision := wafLine(t, wafOut, id, "decision")
|
||||
report := wafLine(t, wafOut, id, "report")
|
||||
|
||||
if decision["host"] != line["host"] || decision["client_ip"] != placed ||
|
||||
report["status"] != float64(http.StatusForbidden) {
|
||||
t.Errorf("discriminator's lines are %v and %v", decision, report)
|
||||
t.Errorf("waf's lines are %v and %v", decision, report)
|
||||
}
|
||||
}
|
||||
|
||||
// discriminatorLine waits for discriminator's line with request id and
|
||||
// discriminator_line kind.
|
||||
func discriminatorLine(t *testing.T, out *output, id, kind string) map[string]any {
|
||||
// wafLine waits for waf's line with request id and
|
||||
// waf_line kind.
|
||||
func wafLine(t *testing.T, out *output, id, kind string) map[string]any {
|
||||
t.Helper()
|
||||
|
||||
deadline := time.Now().Add(waitLimit)
|
||||
for time.Now().Before(deadline) {
|
||||
line := out.findLine(t, func(fields map[string]any) bool {
|
||||
return fields["request_id"] == id && fields["discriminator_line"] == kind
|
||||
return fields["request_id"] == id && fields["waf_line"] == kind
|
||||
})
|
||||
if line != nil {
|
||||
return line
|
||||
@@ -190,14 +190,14 @@ func discriminatorLine(t *testing.T, out *output, id, kind string) map[string]an
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestTheSiteAnswersWhileDiscriminatorIsStoppedAndStartedAgain(t *testing.T) {
|
||||
func TestTheSiteAnswersWhileWAFIsStoppedAndStartedAgain(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
env := discriminatorSettings(t)
|
||||
addr, _, stop := startDiscriminator(t, env)
|
||||
env := wafSettings(t)
|
||||
addr, _, stop := startWAF(t, env)
|
||||
|
||||
// rproxy asks discriminator through an address the test holds throughout,
|
||||
// so no other test can take it while discriminator is stopped.
|
||||
// rproxy asks waf through an address the test holds throughout,
|
||||
// so no other test can take it while waf is stopped.
|
||||
backend, forwardTo := startForwarder(t)
|
||||
forwardTo(addr)
|
||||
|
||||
@@ -228,22 +228,22 @@ func TestTheSiteAnswersWhileDiscriminatorIsStoppedAndStartedAgain(t *testing.T)
|
||||
wantStatus(t, site+bannedProbe, placed, http.StatusForbidden)
|
||||
wantStatus(t, site+"/", placed, http.StatusForbidden)
|
||||
|
||||
// rproxy's connections are closed at once from here, before discriminator
|
||||
// rproxy's connections are closed at once from here, before waf
|
||||
// stops and frees its port.
|
||||
forwardTo("")
|
||||
stop()
|
||||
|
||||
// With discriminator down, the site answers, and rproxy says the default did it.
|
||||
// With waf down, the site answers, and rproxy says the default did it.
|
||||
wantStatus(t, site+"/after-stop", placed, http.StatusOK)
|
||||
|
||||
line := out.line(t, "path", "/after-stop")
|
||||
if line["disposition"] != discriminator.DispositionAllow ||
|
||||
if line["disposition"] != waf.DispositionAllow ||
|
||||
line["default_disposition"] != true {
|
||||
t.Errorf("rproxy's line is %v", line)
|
||||
}
|
||||
|
||||
// Started again with its state files, it applies the ban again.
|
||||
addr, _, stop = startDiscriminator(t, env)
|
||||
addr, _, stop = startWAF(t, env)
|
||||
forwardTo(addr)
|
||||
|
||||
defer func() {
|
||||
@@ -397,10 +397,10 @@ func sendRaw(t *testing.T, site, request string) int {
|
||||
return res.StatusCode
|
||||
}
|
||||
|
||||
func TestAChunkedBodyStaysABodyAtDiscriminator(t *testing.T) {
|
||||
func TestAChunkedBodyStaysABodyAtWAF(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
addr, discriminatorOut, stop := startDiscriminator(t, discriminatorSettings(t))
|
||||
addr, wafOut, stop := startWAF(t, wafSettings(t))
|
||||
defer stop()
|
||||
|
||||
site, _ := startRProxy(t, "http://"+addr, startApp(t))
|
||||
@@ -409,7 +409,7 @@ func TestAChunkedBodyStaysABodyAtDiscriminator(t *testing.T) {
|
||||
const smuggledID = "smuggled-request"
|
||||
|
||||
smuggled := "GET " + bannedProbe + " HTTP/1.1\r\nHost: site.example\r\n" +
|
||||
discriminator.ClientHeader + ": " + otherClient + "\r\n" +
|
||||
waf.ClientHeader + ": " + otherClient + "\r\n" +
|
||||
"X-Request-ID: " + smuggledID + "\r\n\r\n"
|
||||
|
||||
status := sendRaw(t, site, "POST /upload HTTP/1.1\r\nHost: site.example\r\n"+
|
||||
@@ -425,18 +425,18 @@ func TestAChunkedBodyStaysABodyAtDiscriminator(t *testing.T) {
|
||||
time.Sleep(pollInterval)
|
||||
}
|
||||
|
||||
line := discriminatorOut.findLine(t, func(fields map[string]any) bool {
|
||||
line := wafOut.findLine(t, func(fields map[string]any) bool {
|
||||
return fields["request_id"] == smuggledID
|
||||
})
|
||||
if line != nil {
|
||||
t.Errorf("discriminator read the body as a request: %v", line)
|
||||
t.Errorf("waf read the body as a request: %v", line)
|
||||
}
|
||||
}
|
||||
|
||||
func TestATargetThatCannotGoToDiscriminatorIsRefusedForABannedClient(t *testing.T) {
|
||||
func TestATargetThatCannotGoToWAFIsRefusedForABannedClient(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
addr, _, stop := startDiscriminator(t, discriminatorSettings(t))
|
||||
addr, _, stop := startWAF(t, wafSettings(t))
|
||||
defer stop()
|
||||
|
||||
site, out := startRProxy(t, "http://"+addr, startApp(t))
|
||||
@@ -460,7 +460,7 @@ func TestAClientWithAZoneIsTheClientWithout(t *testing.T) {
|
||||
|
||||
const zoned = "2001:db8::1%eth0"
|
||||
|
||||
addr, _, stop := startDiscriminator(t, discriminatorSettings(t))
|
||||
addr, _, stop := startWAF(t, wafSettings(t))
|
||||
defer stop()
|
||||
|
||||
site, out := startRProxy(t, "http://"+addr, startApp(t))
|
||||
@@ -475,7 +475,7 @@ func TestAClientWithAZoneIsTheClientWithout(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestAStatusDiscriminatorDoesNotTakeIsReportedAs599(t *testing.T) {
|
||||
func TestAStatusWAFDoesNotTakeIsReportedAs599(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
const status = 799
|
||||
@@ -486,7 +486,7 @@ func TestAStatusDiscriminatorDoesNotTakeIsReportedAs599(t *testing.T) {
|
||||
}))
|
||||
t.Cleanup(app.Close)
|
||||
|
||||
addr, discriminatorOut, stop := startDiscriminator(t, discriminatorSettings(t))
|
||||
addr, wafOut, stop := startWAF(t, wafSettings(t))
|
||||
defer stop()
|
||||
|
||||
site, out := startRProxy(t, "http://"+addr, app.URL)
|
||||
@@ -500,9 +500,9 @@ func TestAStatusDiscriminatorDoesNotTakeIsReportedAs599(t *testing.T) {
|
||||
|
||||
id, _ := line["request_id"].(string)
|
||||
|
||||
report := discriminatorLine(t, discriminatorOut, id, "report")
|
||||
report := wafLine(t, wafOut, id, "report")
|
||||
if report["status"] != 599.0 {
|
||||
t.Errorf("discriminator's line is %v, want status 599", report)
|
||||
t.Errorf("waf's line is %v, want status 599", report)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -544,16 +544,16 @@ func startRProxyProcess(t *testing.T, env ...string) (string, *exec.Cmd, *output
|
||||
return addr, cmd, out
|
||||
}
|
||||
|
||||
func TestRProxyAsksADiscriminatorThatSpeaksHTTP2OverHTTP1(t *testing.T) {
|
||||
func TestRProxyAsksAWAFThatSpeaksHTTP2OverHTTP1(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
protocols := make(chan string, 10)
|
||||
backend := httptest.NewUnstartedServer(http.HandlerFunc(
|
||||
func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Header.Get(discriminator.ClientHeader) != "" {
|
||||
if r.Header.Get(waf.ClientHeader) != "" {
|
||||
protocols <- r.Proto
|
||||
|
||||
w.Header().Set(discriminator.DispositionHeader, discriminator.DispositionDeny)
|
||||
w.Header().Set(waf.DispositionHeader, waf.DispositionDeny)
|
||||
w.WriteHeader(http.StatusForbidden)
|
||||
}
|
||||
}))
|
||||
@@ -563,7 +563,7 @@ func TestRProxyAsksADiscriminatorThatSpeaksHTTP2OverHTTP1(t *testing.T) {
|
||||
|
||||
// rproxy has no setting for the certificates it trusts, so it is told of this
|
||||
// one as Go's client is told of any, in a process of its own.
|
||||
certificates := filepath.Join(t.TempDir(), "discriminator.pem")
|
||||
certificates := filepath.Join(t.TempDir(), "waf.pem")
|
||||
|
||||
err := os.WriteFile(certificates, pem.EncodeToMemory(&pem.Block{
|
||||
Type: "CERTIFICATE", Bytes: backend.Certificate().Raw,
|
||||
@@ -585,7 +585,7 @@ func TestRProxyAsksADiscriminatorThatSpeaksHTTP2OverHTTP1(t *testing.T) {
|
||||
} {
|
||||
status := sendRaw(t, addr, "GET / HTTP/1.1\r\nHost: site.example\r\n"+headers+"\r\n")
|
||||
if status != http.StatusForbidden {
|
||||
t.Errorf("with %s: status %d, want discriminator's 403", name, status)
|
||||
t.Errorf("with %s: status %d, want waf's 403", name, status)
|
||||
}
|
||||
|
||||
select {
|
||||
@@ -594,7 +594,7 @@ func TestRProxyAsksADiscriminatorThatSpeaksHTTP2OverHTTP1(t *testing.T) {
|
||||
t.Errorf("with %s: asked over %s, want HTTP/1.1", name, protocol)
|
||||
}
|
||||
case <-time.After(waitLimit):
|
||||
t.Errorf("with %s: discriminator was not asked", name)
|
||||
t.Errorf("with %s: waf was not asked", name)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -623,8 +623,8 @@ func TestRProxyStoppingWaitsForAReportBeingSent(t *testing.T) {
|
||||
release := make(chan struct{})
|
||||
backend := httptest.NewServer(http.HandlerFunc(
|
||||
func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Header.Get(discriminator.ClientHeader) != "" {
|
||||
w.Header().Set(discriminator.DispositionHeader, discriminator.DispositionAllow)
|
||||
if r.Header.Get(waf.ClientHeader) != "" {
|
||||
w.Header().Set(waf.DispositionHeader, waf.DispositionAllow)
|
||||
|
||||
return
|
||||
}
|
||||
@@ -731,7 +731,7 @@ func TestRProxyStoppingCutsOffARequestAfterFiveSeconds(t *testing.T) {
|
||||
|
||||
backend := httptest.NewServer(http.HandlerFunc(
|
||||
func(w http.ResponseWriter, _ *http.Request) {
|
||||
w.Header().Set(discriminator.DispositionHeader, discriminator.DispositionAllow)
|
||||
w.Header().Set(waf.DispositionHeader, waf.DispositionAllow)
|
||||
}))
|
||||
t.Cleanup(backend.Close)
|
||||
|
||||
@@ -794,7 +794,7 @@ func TestRProxyInvalidSettingStopsTheStart(t *testing.T) {
|
||||
{"no backend", wafBackend, nil},
|
||||
{
|
||||
"another invalid", rproxyTimeout,
|
||||
map[string]string{wafBackend: "http://discriminator:8080", rproxyTimeout: "soon"},
|
||||
map[string]string{wafBackend: "http://waf:8080", rproxyTimeout: "soon"},
|
||||
},
|
||||
} {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
@@ -831,7 +831,7 @@ func TestRProxyAddressInUseStopsTheStart(t *testing.T) {
|
||||
out := &output{}
|
||||
|
||||
status := runRProxy(t.Context(), map[string]string{
|
||||
wafBackend: "http://discriminator:8080",
|
||||
wafBackend: "http://waf:8080",
|
||||
rproxyListenAddr: taken.Addr().String(),
|
||||
}, out)
|
||||
if status != 1 {
|
||||
@@ -848,7 +848,7 @@ func TestMainRunsRProxy(t *testing.T) {
|
||||
addr, cmd, out := startRProxyProcess(t, wafBackend+"=http://127.0.0.1:9")
|
||||
|
||||
req, err := http.NewRequestWithContext(t.Context(), http.MethodGet,
|
||||
"http://"+addr+discriminator.HealthPath, http.NoBody)
|
||||
"http://"+addr+waf.HealthPath, http.NoBody)
|
||||
if err != nil {
|
||||
t.Fatalf("new request: %v", err)
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user