#!/usr/bin/env python3 """R-752 wger on 9202. argv[1] = control | fix. control: the LIVE template (axes keyed on ip_address, 10 failures, 30 min). fix: the drill template (AXES_LOCKOUT_PARAMETERS=username, AXES_COOLOFF_TIME=15). Both: install, a SECOND household member made with wger's own Django (manage.py shell — seeding, not a login), positive controls, 10 wrong REST logins for the public name `admin` as a stranger, then admin's and the second member's RIGHT passwords. fix only: one right-password try at +8 min (a try DURING the lock — does it extend it?), then single tries at +16, +24, +32 min until it works; a wrong one after.""" import sys, time import walk as w import lk MODE = sys.argv[1] SUB = "fitness" w.login() lk.p(f"##### wger {MODE} — controller {w.guest('docker inspect felhom-controller --format {{.Config.Image}}').strip()}") if MODE == "fix": for _ in range(12): w.sync_rescan() cat = w.guest("grep -rh AXES_LOCKOUT_PARAMETERS /var/lib/docker/volumes/felhom-controller-data/_data/ --include=docker-compose.yml 2>/dev/null | sort -u").strip() if "COOLOFF_TIME=5" in w.guest("grep -rh AXES_COOLOFF_TIME /var/lib/docker/volumes/felhom-controller-data/_data/ --include=docker-compose.yml 2>/dev/null"): break time.sleep(15) lk.p("the box's catalog copy:", cat) lk.p("deploy:", w.deploy("wger", SUB)) for _ in range(120): time.sleep(5) if "hold OPENED" in w.guest("docker logs --since 20m felhom-controller 2>&1 | grep 'wger: install hold OPENED'"): break w.wait_app(SUB, "/en/user/login", want=("200",), tries=72) lk.p("axes settings inside the app:", w.guest("""cat > /tmp/axs.py <<'PY' import os, sys sys.path.insert(0, '/home/wger/src'); os.chdir('/home/wger/src') os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'settings.main') import django; django.setup() from django.conf import settings as s print(s.AXES_LOCKOUT_PARAMETERS, s.AXES_FAILURE_LIMIT, s.AXES_COOLOFF_TIME, s.AXES_RESET_COOL_OFF_ON_FAILURE_DURING_LOCKOUT, s.AXES_HANDLER, s.CACHES['default']['BACKEND']) PY docker cp /tmp/axs.py wger:/tmp/axs.py && docker exec wger python3 /tmp/axs.py 2>&1 | tail -1; docker exec wger sh -c 'ps -eo args' | grep -E '[g]unicorn|[r]unserver|[u]vicorn' | head -3""").strip()) pw = (w.GENERATED.get("wger") or {}).get("ADMIN_PASSWORD", "") pw2 = "Second-" + str(int(time.time())) lk.p("second member:", w.guest( "docker exec wger python3 -c \"import os,sys; sys.path.insert(0,'/home/wger/src'); os.chdir('/home/wger/src'); " "os.environ.setdefault('DJANGO_SETTINGS_MODULE','settings.main'); import django; django.setup(); " "from django.contrib.auth.models import User; u=User.objects.create_user('second', 'second@gate.invalid', sys.argv[1]); print('made', u.username)\" " + pw2).strip()) lk.p("positive controls — admin:", lk.wger("admin", pw), "| second:", lk.wger("second", pw2)) for i in range(1, 12): lk.p(f"stranger wrong try {i} (admin):", lk.wger("admin", f"wrong-{i}-{time.time()}")) t0 = time.time() lk.p("household — admin RIGHT password:", lk.wger("admin", pw), "| second member RIGHT password:", lk.wger("second", pw2)) if MODE == "fix": def at(minutes, label, who="admin", p=None): while time.time() - t0 < minutes * 60: time.sleep(10) r = lk.wger(who, p or pw) lk.p(f"+{(time.time() - t0) / 60:.1f} min {label}:", r) return r sched = [float(x) for x in (sys.argv[2].split(",") if len(sys.argv) > 2 else ["8", "16", "24", "32", "40"])] at(sched[0], "admin RIGHT password DURING the lock (does it restart the cool-off?)") lk.p("second member, same moment:", lk.wger("second", pw2)) for m in sched[1:]: if at(m, "admin RIGHT password") == "ok": break lk.p("a wrong one after:", lk.wger("admin", "wrong-after"), "| right again:", lk.wger("admin", pw)) lk.p(w.guest("docker logs --since 60m wger 2>&1 | grep -i -E 'axes|lock' | tail -6 | cut -c1-220").strip()) w.remove("wger") lk.p("removed; deployed =", w.stack("wger").get("deployed"))