gates / gates (push) Successful in 6m53s
Closed R-1126, R-1125 and R-1129 (not a defect: a misreading of the CI log by the session that filed it); opened R-1135..R-1137; R-1124 noted. 01 §5 [DESIGN]: the tunnel runs before the claim; FileBrowser is published only after its default login is checked. STATUS D10-D12 decided. N100 diary: the 21-minute file-manager gap after 0.327.0. Controller 0.327.1 is the floor since 12:06 UTC. Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
40 lines
3.6 KiB
Bash
Executable File
40 lines
3.6 KiB
Bash
Executable File
#!/bin/bash
|
|
# fbenv-spike.sh — R-1126 Part 1a, inside scratch guest 9202. A THROWAWAY FileBrowser (r1126-fb, its own volume) with
|
|
# FILEBROWSER_ADMIN_PASSWORD from a 0600 env file (generated here, never printed). Prints status codes only.
|
|
set -u
|
|
IMG=gtstef/filebrowser:1.5.6-stable; W=/root/r1126; rm -rf $W; mkdir -m 700 -p $W/srv
|
|
docker rm -f r1126-fb >/dev/null 2>&1; docker volume rm r1126_data >/dev/null 2>&1
|
|
cat > $W/config.yaml <<'C'
|
|
server:
|
|
port: 80
|
|
database: "/home/filebrowser/data/database.db"
|
|
sources:
|
|
- path: "/srv/t"
|
|
name: "T"
|
|
C
|
|
umask 077; printf 'FILEBROWSER_ADMIN_PASSWORD=%s\n' "$(head -c 18 /dev/urandom | base64 | tr -dc A-Za-z0-9 | head -c 16)" > $W/env
|
|
cfgpw() { sed -n 's/^FILEBROWSER_ADMIN_PASSWORD=//p' $W/env; }
|
|
ip() { docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' r1126-fb; }
|
|
login() { printf 'X-Password: %s\n' "$1" | curl -s -o /dev/null -w '%{http_code}' --max-time 5 -X POST -H @- "http://$(ip):80/api/auth/login?username=admin"; }
|
|
token() { printf 'X-Password: %s\n' "$1" | curl -s --max-time 5 -X POST -H @- "http://$(ip):80/api/auth/login?username=admin" | tr -d '"'; }
|
|
start() { docker run -d --name r1126-fb -v r1126_data:/home/filebrowser/data -v $W/config.yaml:/home/filebrowser/config.yaml:ro \
|
|
-v $W/srv:/srv/t -e FILEBROWSER_CONFIG=/home/filebrowser/config.yaml --env-file $W/env $IMG >/dev/null; }
|
|
echo "== 1. a NEW database with the env password: probe the default login from the first answer (1 s apart, 5 answers —"
|
|
echo " FileBrowser 1.5.6 limits login tries: the first run of this spike probed 4/s and was answered 429 after 8 tries)"
|
|
start; seen=""; n=0
|
|
for i in $(seq 1 120); do c=$(login admin 2>/dev/null); if [ -n "$c" ] && [ "$c" != "000" ]; then seen="$seen $c"; n=$((n+1)); [ $n -ge 5 ] && break; sleep 1; else sleep 0.25; fi; done
|
|
echo " default-login answers seen: $(echo $seen | tr ' ' '\n' | sort | uniq -c | tr '\n' ' ')"
|
|
echo " waiting 90 s for FileBrowser's login limiter to clear"; sleep 90
|
|
echo " env password login: $(login "$(cfgpw)")"
|
|
echo "== 2. the household sets its own password in FileBrowser (the API the box uses), then a restart"
|
|
tok=$(token "$(cfgpw)"); own="$(head -c 18 /dev/urandom | base64 | tr -dc A-Za-z0-9 | head -c 16)"
|
|
id=$(curl -s --max-time 5 -H "X-Auth: $tok" -H "Authorization: Bearer $tok" "http://$(ip):80/api/users?id=self" | python3 -c 'import json,sys;d=json.load(sys.stdin);print(d.get("id", ""))')
|
|
body=$(python3 -c 'import json,sys;print(json.dumps({"which":["password"],"data":{"id":int(sys.argv[1]),"username":"admin","password":sys.stdin.read()}}))' "$id" <<< "$own" | sed 's/\\n"/"/')
|
|
code=$(printf 'X-Password: %s\n' "$(cfgpw)" | curl -s -o /dev/null -w '%{http_code}' --max-time 5 -X PUT -H @- -H "X-Auth: $tok" -H "Authorization: Bearer $tok" -H 'Content-Type: application/json' --data "$body" "http://$(ip):80/api/users?id=$id")
|
|
echo " PUT own password: $code; own login: $(login "$own"); env login: $(login "$(cfgpw)")"
|
|
docker restart r1126-fb >/dev/null; for i in $(seq 1 60); do c=$(curl -s -o /dev/null -w '%{http_code}' --max-time 3 "http://$(ip):80/"); [ "$c" != "000" ] && break; sleep 0.5; done
|
|
echo " AFTER RESTART — own login: $(login "$own"); env login: $(login "$(cfgpw)"); default login: $(login admin)"
|
|
docker logs r1126-fb 2>&1 | grep -iE "Resetting admin|admin password from" | sed 's/^/ log: /' | tail -3
|
|
docker rm -f r1126-fb >/dev/null; docker volume rm r1126_data >/dev/null; rm -rf $W
|
|
echo "== cleanup: $(docker ps -a --filter name=r1126 --format '{{.Names}}' | wc -l) containers, $(docker volume ls -q | grep -c r1126) volumes left"
|