Keep the bans, the clients and GeoJS's answers in state files (closes #17)
check / check (push) Successful in 3m24s
check / check (push) Successful in 3m24s
smallwebwaf now copies its state to bans.json, clients.json and lookups.json in SWWAF_STATE_DIR, as "Persistent state" in SPEC.md describes, and reads them back at start, so a restart lifts no ban and gives no client a fresh allowance. Each client gains a history, and a ban's notes count the netblock's requests. bans.json is written SWWAF_STATE_WRITE_DELAY after a ban, and every file every SWWAF_STATE_COUNTER_INTERVAL and at the stop. A ban read back is masked to its netblock and refuses every client in it. A file that does not parse, an unknown version, an entry without a field it needs, or an unwritable directory stops the start. Deviation: no AS number or name, and no ban cause, reason or lifting yet. Model: opus-5-5
This commit was merged in pull request #72.
This commit is contained in:
+44
-11
@@ -1,12 +1,14 @@
|
||||
#!/bin/sh
|
||||
# script/example-app: build the image, and on it the example app in
|
||||
# deploy/example-app, then run the app's container and check that the
|
||||
# health check passes, that a request is served through smallwebwaf,
|
||||
# that `sv stop` stops smallwebwaf in order, and that `docker stop`
|
||||
# stops the container without having to kill it. The container and both
|
||||
# images are removed however the script ends. Building the app needs
|
||||
# network access, for nixpkgs' binary cache. script/check does not run
|
||||
# this.
|
||||
# deploy/example-app, then run the app's container with a volume for the
|
||||
# state files and check that the health check passes, that a request is
|
||||
# served through smallwebwaf, that a second one in a minute bans the
|
||||
# client, that `sv stop` stops smallwebwaf in order, that `docker stop`
|
||||
# stops the container without having to kill it, and that a new
|
||||
# container on the same volume still refuses the banned client. The
|
||||
# containers, the volume and both images are removed however the script
|
||||
# ends. Building the app needs network access, for nixpkgs' binary cache.
|
||||
# script/check does not run this.
|
||||
set -eu
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd -P)"
|
||||
@@ -18,9 +20,11 @@ NAME="$("$SCRIPT_DIR/projectname")-example-$$"
|
||||
IMAGE="$NAME-base"
|
||||
APP_IMAGE="$NAME-app"
|
||||
CONTAINER="$NAME"
|
||||
VOLUME="$NAME-state"
|
||||
|
||||
cleanup() {
|
||||
docker rm --force "$CONTAINER" >/dev/null 2>&1 || true
|
||||
docker volume rm --force "$VOLUME" >/dev/null 2>&1 || true
|
||||
docker rmi --force "$APP_IMAGE" "$IMAGE" >/dev/null 2>&1 || true
|
||||
}
|
||||
|
||||
@@ -53,6 +57,26 @@ logged() {
|
||||
docker logs "$CONTAINER" 2>&1 | grep -qF "$1"
|
||||
}
|
||||
|
||||
# start_container: run the app's container, with the state files on the
|
||||
# volume and a rate limit of one request a minute, and wait until it is
|
||||
# healthy.
|
||||
start_container() {
|
||||
docker run --detach --name "$CONTAINER" --publish 127.0.0.1::8080 \
|
||||
--volume "$VOLUME:/var/lib/smallwebwaf" \
|
||||
--env SWWAF_RATE_LIMIT_PER_MINUTE=1 \
|
||||
"$APP_IMAGE" >/dev/null
|
||||
wait_for "the health check did not pass" healthy
|
||||
address="$(docker port "$CONTAINER" 8080/tcp)"
|
||||
}
|
||||
|
||||
# refused: a request to the container gets 403, SWWAF_BAN_RESPONSE's
|
||||
# default.
|
||||
refused() {
|
||||
code="$(curl --silent --output /dev/null --write-out '%{http_code}' \
|
||||
--max-time 10 "http://$address/")" || true
|
||||
[ "$code" = 403 ]
|
||||
}
|
||||
|
||||
main() {
|
||||
cd "$ROOT"
|
||||
trap cleanup EXIT
|
||||
@@ -62,18 +86,20 @@ main() {
|
||||
docker build --no-cache --build-arg SMALLWEBWAF_IMAGE="$IMAGE" \
|
||||
-t "$APP_IMAGE" deploy/example-app
|
||||
|
||||
docker run --detach --name "$CONTAINER" --publish 127.0.0.1::8080 \
|
||||
"$APP_IMAGE" >/dev/null
|
||||
wait_for "the health check did not pass" healthy
|
||||
docker volume create "$VOLUME" >/dev/null
|
||||
start_container
|
||||
echo "example-app: the health check passes"
|
||||
|
||||
address="$(docker port "$CONTAINER" 8080/tcp)"
|
||||
page="$(curl --fail --silent --show-error --max-time 10 "http://$address/")" ||
|
||||
fail "no answer on port 8080"
|
||||
[ "$page" = "hello from the example app" ] || fail "port 8080 answered $page"
|
||||
wait_for "smallwebwaf logged no request it forwarded" logged '"action":"forward"'
|
||||
echo "example-app: smallwebwaf passes a request to the app and its answer back"
|
||||
|
||||
refused || fail "a second request in a minute was not refused"
|
||||
wait_for "smallwebwaf logged no ban" logged '"action":"rate_limited"'
|
||||
echo "example-app: a second request in a minute bans the client"
|
||||
|
||||
docker exec "$CONTAINER" sv stop smallwebwaf >/dev/null ||
|
||||
fail "sv stop smallwebwaf failed"
|
||||
wait_for "smallwebwaf did not stop in order" logged '"msg":"stopped"'
|
||||
@@ -83,6 +109,13 @@ main() {
|
||||
status="$(docker inspect --format '{{.State.ExitCode}}' "$CONTAINER")"
|
||||
[ "$status" = 0 ] || fail "docker stop left exit status $status"
|
||||
echo "example-app: docker stop stops the container in order"
|
||||
|
||||
docker rm "$CONTAINER" >/dev/null
|
||||
start_container
|
||||
refused || fail "the new container let the banned client through"
|
||||
wait_for "smallwebwaf logged no request refused under the ban" \
|
||||
logged '"action":"banned"'
|
||||
echo "example-app: a new container on the same volume keeps the ban"
|
||||
}
|
||||
|
||||
main "$@"
|
||||
|
||||
+7
-1
@@ -1,6 +1,7 @@
|
||||
#!/bin/sh
|
||||
# script/run: build bin/smallwebwaf with script/build and run it, with
|
||||
# the settings in the environment.
|
||||
# the settings in the environment. Unless SWWAF_STATE_DIR is set, the
|
||||
# state files go in bin/state, beside the binary.
|
||||
set -eu
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd -P)"
|
||||
@@ -8,6 +9,11 @@ ROOT="$(cd "$SCRIPT_DIR/.." && pwd -P)"
|
||||
|
||||
main() {
|
||||
"$SCRIPT_DIR/build"
|
||||
if [ -z "${SWWAF_STATE_DIR+set}" ]; then
|
||||
SWWAF_STATE_DIR="$ROOT/bin/state"
|
||||
export SWWAF_STATE_DIR
|
||||
mkdir -p "$SWWAF_STATE_DIR"
|
||||
fi
|
||||
exec "$ROOT/bin/smallwebwaf"
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user