2.3 KiB
Sicheres E2E-Testen der Login-/Lockout-Logik (ohne echten User zu zerstören)
Der Bonuspitfall: Tests der Login-/Brute-Force-Logik dürfen den echten
Benutzeraccount (mehlzoerwer) nicht verändern, sonst ist der echte Login
danach defekt (Skill-Pitfall "E2E-Test mutiert die DB").
Muster (validiert 2026-08-04)
-
IP-Lockout-Zweig testen → mit einem fremden/leeren Benutzernamen laufen lassen. Fremder User trifft nur den In-Memory-
_IP_FAIL-Zähler, KEIN DB-Update auf den echten Account:for i in $(seq 1 6); do curl -sk -X POST https://ssh.<domain>.de/ \ -d "username=foo&password=wrong$i" done tail portal.log # Versuch 6 → "IP-SPERRE aktiv für <ip>"Prüfen, dass der echte User danach
failed=0, lockout_until=0ist. -
DB-User-Lockout-Zweig testen → temporären Test-User in die DB, nach dem Test wieder löschen:
./venv/bin/python -c " import sqlite3 from werkzeug.security import generate_password_hash c=sqlite3.connect('portal.db') c.execute(\"INSERT OR REPLACE INTO users(username,pw_hash,pw_changed,failed,lockout_until)\ VALUES('testuser',?,1,0,0)\", (generate_password_hash('TestPass123!'),)) c.commit(); c.close()"Dann 5x falsches PW für
testuser→ DB zeigtfailed=5, lockout_until=<ts>, Log zeigt "USER-SPERRE aktiv". -
WICHTIG — In-Memory-IP-Sperre leert nur beim Service-Restart: Nach Test 1 ist die Test-IP noch 15 min in
_IP_FAILgesperrt. Vor dem Testen des zweiten Zweigssystemctl restart sshportal(leert den In-Memory-Zähler), sonst kommen die neuen Requests gar nicht bis zur DB. -
Aufräumen (immer, in einer Transaktion committen):
c.execute('DELETE FROM users WHERE username=?', ('testuser',)) c.execute('UPDATE users SET failed=0, lockout_until=0 WHERE username=?', ('mehlzoerwer',)) c.commit()
Fallstricke
sqlite3-CLI fehlt oft auf dem VPS → über das venv-Python lesen (./venv/bin/python -c "..."), nichtsqlite3 portal.db.- DB-Schema kann Alt-Spalten haben →
dict(row)schlägt beim Print fehl ("length 11; 2 is required"); explizite Spalten im SELECT wählen. - Desktop-
dict(rows)-Print ist nur Reporting, nicht Teil des Deletes — ein Traceback dort heißt NICHT, dass der Delete fehlgeschlagen ist.