IAM-07: account-lockout-login-rate-limiting
internal/lockout: Store.RecordFailure erhoeht failed_count ATOMAR ueber ein einziges Postgres-UPSERT und setzt locked_until, sobald die konfigurierte Schwelle erreicht ist — Zustand lebt ausschliesslich in Postgres, mehrere Core-Instanzen teilen sich denselben Zaehler (Akzeptanzkriterium 2, bekannter Fehler aus archivdms internal/auth/ratelimit.go vermieden: kein In-Process-Zaehler). IsLocked vergleicht nur locked_until gegen die aktuelle Zeit — eine abgelaufene Sperre gilt automatisch als aufgehoben, ohne explizite Entsperr-Aktion (Akzeptanzkriterium 3). Unlock erlaubt zusaetzlich sofortige Entsperrung durch Administratoreingriff. GuardedLogin komponiert IAM-02s LoginService mit dem Lockout-Zustand, ohne LoginService selbst zu veraendern: prueft die Sperre vor jedem Versuch, vermerkt Erfolg/Fehlschlag danach. Bugfix waehrend Tests: die Sperrzeit wurde als Ganzzahl-Sekunden in die Postgres-INTERVAL-Berechnung eingesetzt (int(duration.Seconds())), wodurch Sperrzeiten unter 1 Sekunde (z.B. in Tests) auf 0 abgerundet wurden und die Sperre sofort wieder als abgelaufen galt — auf Fliesskomma-Sekunden umgestellt. Pruefungen (ausgefuehrt auf root@192.168.1.131, go build/vet/test PASS): 1. Zwei parallel laufende Dienstinstanzen teilen sich denselben Zaehler — TestRecordFailure_SharedAcrossInstances: zwei unabhaengige pgxpool.Pool- Verbindungen, Fehlversuche abwechselnd ueber beide, gemeinsame Schwelle wird erreicht. PASS. 2. Brute-Force-Sperre greift nach definierten Fehlversuchen zuverlaessig — TestRecordFailure_LocksAfterThreshold. PASS. 3. Zeitversatz zwischen Sperre und Entsperrung automatisiert getestet — TestIsLocked_AutoUnlocksAfterExpiry: gesperrt vor Ablauf, automatisch entsperrt nach Ablauf der Sperrzeit. PASS. Zusaetzlich: TestGuardedLogin_LocksAfterRepeatedFailures belegt das Zusammenspiel mit dem echten IAM-02-LoginService End-to-End — selbst das korrekte Passwort wird nach Sperrung abgewiesen. PASS. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
3d20d86a4f
commit
ac070c160a
@@ -0,0 +1 @@
|
||||
DROP TABLE IF EXISTS login_attempts;
|
||||
@@ -0,0 +1,10 @@
|
||||
-- Account-Lockout & Login-Rate-Limiting (IAM-07, siehe
|
||||
-- core-kanban/tickets/IAM-07.md). Geteilter, externer Zustand in Postgres —
|
||||
-- kein In-Process-Zaehler (bekannter Fehler aus archivdms
|
||||
-- internal/auth/ratelimit.go), gilt korrekt ueber mehrere Core-Instanzen.
|
||||
CREATE TABLE login_attempts (
|
||||
email TEXT PRIMARY KEY,
|
||||
failed_count INT NOT NULL DEFAULT 0,
|
||||
locked_until TIMESTAMPTZ,
|
||||
last_attempt_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
Reference in New Issue
Block a user