Compare commits
2
Commits
e3b159db07
..
next
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8632da556a | ||
|
|
344ce13c96 |
@@ -1575,12 +1575,13 @@ It sets no `ENTRYPOINT` or `USER` of its own. The container must start
|
||||
writes. `runsvinit` starts runit's `runsvdir`, which runs the `run` script of
|
||||
each directory under `/etc/service`. Ubuntu's `sv` looks for services there
|
||||
too.
|
||||
- The image's `run` script, `/etc/service/smallwebwaf/run`, starts the command
|
||||
`SMALLWEBWAF_COMMAND` names, `rproxy` when it is unset or empty, as the
|
||||
`smallwebwaf` user (uid and gid 65532) with runit's `chpst`. For `servewaf`,
|
||||
it first makes `SWWAF_STATE_DIR` and every file in it belong to that user. For
|
||||
`rproxy` it changes no owner. With any other value, it starts nothing, and
|
||||
stops with a message naming `SMALLWEBWAF_COMMAND` and its value.
|
||||
- The image's `run` script is `/etc/service/smallwebwaf/run`. It starts
|
||||
`servewaf` when `SMALLWEBWAF_COMMAND` is `servewaf`, and `rproxy` when it is
|
||||
`rproxy`, unset or empty. It runs either as the `smallwebwaf` user (uid and
|
||||
gid 65532), with runit's `chpst`. For `servewaf`, it first makes
|
||||
`SWWAF_STATE_DIR` and every file in it belong to that user. For `rproxy` it
|
||||
changes no owner. With any other value, it starts nothing, and stops with a
|
||||
message naming `SMALLWEBWAF_COMMAND` and its value.
|
||||
|
||||
Every `run` script, the app's included, is a bash script. It starts with
|
||||
`#!/usr/bin/env bash` and `set -euo pipefail`, and puts its code in a `main`
|
||||
@@ -1700,15 +1701,14 @@ ranges traefik is on.
|
||||
|
||||
### upaas
|
||||
|
||||
An app deployed by upaas, which rebuilds and restarts an app's Docker container
|
||||
when its repository changes, takes the shape of "`rproxy` in the app's
|
||||
container" with no change to upaas. upaas builds the app's Dockerfile and runs
|
||||
the one container as it runs any app. The traefik labels route to port 8080, and
|
||||
the `SWRP_` settings go with the app's environment variables. `servewaf` runs in
|
||||
a container of its own, on a network the app's container can reach, with its
|
||||
state volume and the directory of any token file. `docs/gitea.md` records what
|
||||
the defaults do in front of gitea, and `script/gitea-requests` checks those
|
||||
notes.
|
||||
upaas rebuilds and restarts an app's Docker container when its repository
|
||||
changes. An app it deploys takes the shape of "`rproxy` in the app's container"
|
||||
with no change to upaas. upaas builds the app's Dockerfile and runs the one
|
||||
container as it runs any app. The traefik labels route to port 8080, and the
|
||||
`SWRP_` settings go with the app's environment variables. `servewaf` runs in a
|
||||
container of its own, on a network the app's container can reach, with its state
|
||||
volume and the directory of any token file. `docs/gitea.md` records what the
|
||||
defaults do in front of gitea, and `script/gitea-requests` checks those notes.
|
||||
|
||||
## Planned, not built
|
||||
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package rproxy_test
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
"log/slog"
|
||||
"net"
|
||||
@@ -602,10 +604,12 @@ func TestAnAppTooSlowToAnswerIsAnswered504(t *testing.T) {
|
||||
func TestAnAppTooSlowToFinishItsAnswerIsCutOff(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
const start = "the start"
|
||||
|
||||
release := make(chan struct{})
|
||||
servewaf := startServeWAF(t, allow)
|
||||
app := startApp(t, func(w http.ResponseWriter, _ *http.Request) {
|
||||
_, _ = io.WriteString(w, "the start")
|
||||
_, _ = io.WriteString(w, start)
|
||||
_ = http.NewResponseController(w).Flush()
|
||||
|
||||
<-release
|
||||
@@ -613,17 +617,29 @@ func TestAnAppTooSlowToFinishItsAnswerIsCutOff(t *testing.T) {
|
||||
|
||||
t.Cleanup(func() { close(release) })
|
||||
|
||||
// The time limit is long enough for a loaded host to pass on the start of the
|
||||
// answer before it runs out.
|
||||
addr, _ := startRProxy(t, servewaf.URL, app.URL, map[string]string{
|
||||
maxResponseTime: "300",
|
||||
maxResponseTime: "3000",
|
||||
})
|
||||
|
||||
conn := dial(t, addr)
|
||||
send(t, conn, "GET / HTTP/1.1\r\nHost: site.example\r\n\r\n")
|
||||
|
||||
// dial's deadline ends this read with an error if the connection stays open.
|
||||
_, err := io.ReadAll(conn)
|
||||
res, err := http.ReadResponse(bufio.NewReader(conn), nil)
|
||||
if err != nil {
|
||||
t.Errorf("read: %v, want the connection closed", err)
|
||||
t.Fatalf("read the answer: %v", err)
|
||||
}
|
||||
|
||||
// The body breaks off when rproxy closes the connection. If the connection
|
||||
// stays open, dial's deadline ends this read with a timeout instead.
|
||||
body, err := io.ReadAll(res.Body)
|
||||
_ = res.Body.Close()
|
||||
|
||||
if res.StatusCode != http.StatusOK || string(body) != start ||
|
||||
!errors.Is(err, io.ErrUnexpectedEOF) {
|
||||
t.Errorf("answered %d %q (%v), want the app's 200 %q, then the connection closed",
|
||||
res.StatusCode, body, err, start)
|
||||
}
|
||||
|
||||
if report := servewaf.report(t); report.Status != http.StatusOK {
|
||||
@@ -651,8 +667,10 @@ func TestAVisitorTooSlowToTakeTheAnswerIsCutOff(t *testing.T) {
|
||||
}
|
||||
}
|
||||
})
|
||||
// The time limit is long enough for a loaded host to start passing on the
|
||||
// answer before it runs out.
|
||||
addr, out := startRProxy(t, servewaf.URL, app.URL, map[string]string{
|
||||
maxResponseTime: "500",
|
||||
maxResponseTime: "3000",
|
||||
})
|
||||
|
||||
// The visitor asks, and never reads the answer.
|
||||
@@ -793,8 +811,10 @@ func TestAVisitorThatStopsSendingGetsAnAnswerRProxyGivesByTheDeadline(t *testing
|
||||
|
||||
servewaf := startServeWAF(t, deny)
|
||||
app := startApp(t, greet)
|
||||
// The time limit is long enough for a loaded host to read the first part of
|
||||
// the body before it runs out.
|
||||
addr, _ := startRProxy(t, servewaf.URL, app.URL, map[string]string{
|
||||
maxRequestTime: "500",
|
||||
maxRequestTime: "3000",
|
||||
})
|
||||
|
||||
// Go's server waits for a little of the body left before it sends an answer,
|
||||
|
||||
@@ -1353,8 +1353,10 @@ func TestAReportServeWAFLeavesUnansweredIsDroppedAtTheTimeLimit(t *testing.T) {
|
||||
})
|
||||
|
||||
app := startApp(t, greet)
|
||||
// The time limit is long enough for a loaded host to answer the question before
|
||||
// it runs out.
|
||||
addr, out := startRProxy(t, backend, app.URL, map[string]string{
|
||||
timeoutSetting: "1000",
|
||||
timeoutSetting: "3000",
|
||||
})
|
||||
|
||||
t.Cleanup(func() { close(release) })
|
||||
|
||||
Reference in New Issue
Block a user