54 lines
2.3 KiB
Markdown
54 lines
2.3 KiB
Markdown
# 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)
|
|
|
|
1. **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:
|
|
```bash
|
|
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=0` ist.
|
|
|
|
2. **DB-User-Lockout-Zweig testen** → **temporären Test-User** in die DB,
|
|
nach dem Test wieder löschen:
|
|
```bash
|
|
./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 zeigt `failed=5, lockout_until=<ts>`,
|
|
Log zeigt "USER-SPERRE aktiv".
|
|
|
|
3. **WICHTIG — In-Memory-IP-Sperre leert nur beim Service-Restart**:
|
|
Nach Test 1 ist die Test-IP noch 15 min in `_IP_FAIL` gesperrt. Vor dem
|
|
Testen des zweiten Zweigs `systemctl restart sshportal` (leert den
|
|
In-Memory-Zähler), sonst kommen die neuen Requests gar nicht bis zur DB.
|
|
|
|
4. **Aufräumen** (immer, in einer Transaktion committen):
|
|
```bash
|
|
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 "..."`), nicht `sqlite3 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.
|