lockout

package
v1.0.26 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 4, 2026 License: MIT Imports: 3 Imported by: 0

Documentation

Overview

Package lockout provides the login account-lockout limiter and the admin-API rate limiter. It is a self-contained leaf (stdlib only, no Culvert coupling) extracted from the flat package main per ADR-0002.

Index

Constants

View Source
const (
	// MaxAttempts is the number of consecutive failures that triggers a lock.
	MaxAttempts = 5
	// Window is the span within which failures accumulate toward a lock.
	Window = 10 * time.Minute
	// Duration is how long an account stays locked once tripped.
	Duration = 15 * time.Minute
)
View Source
const (
	// Burst is the max API mutations allowed per window.
	Burst = 60
	// RateWindow is the sliding window width for the API rate limiter.
	RateWindow = 1 * time.Minute
)

Variables

This section is empty.

Functions

func Msg

func Msg(seconds int) string

Msg returns a human-readable lockout error. Exposed in package main as LockoutMsg via the shim alias.

Types

type APIRateLimiter

type APIRateLimiter struct {
	// contains filtered or unexported fields
}

APIRateLimiter limits mutating admin API calls per client IP.

func NewAPIRateLimiter

func NewAPIRateLimiter() *APIRateLimiter

NewAPIRateLimiter returns a ready-to-use APIRateLimiter.

func (*APIRateLimiter) Allow

func (a *APIRateLimiter) Allow(ip string) bool

Allow returns true if the IP is within the rate limit for API mutations.

func (*APIRateLimiter) Cleanup

func (a *APIRateLimiter) Cleanup()

Cleanup removes expired entries.

type LoginLimiter

type LoginLimiter struct {
	// contains filtered or unexported fields
}

LoginLimiter tracks failed login attempts per username.

func NewLoginLimiter

func NewLoginLimiter() *LoginLimiter

NewLoginLimiter returns a ready-to-use LoginLimiter.

func (*LoginLimiter) AttemptsLeft

func (l *LoginLimiter) AttemptsLeft(username string) int

AttemptsLeft returns how many more failures are allowed before lockout.

func (*LoginLimiter) Check

func (l *LoginLimiter) Check(username string) (locked bool, secondsRemaining int)

Check returns (locked bool, secondsRemaining int). A locked account must not be verified further.

func (*LoginLimiter) Cleanup added in v1.0.22

func (l *LoginLimiter) Cleanup()

Cleanup removes entries that can no longer affect a decision, bounding the map against an unbounded-memory DoS: the key is the attacker-controlled username from the unauthenticated login POST, so without a sweep one failed attempt per distinct random username leaks a permanent entry each. An entry is removable when its lock has expired (a future Check would delete it anyway) or when it is unlocked and its failure window has elapsed (a future RecordFailure would reset it to a fresh window). Called periodically by the shared cleanup janitor. Removing a stale entry is behaviorally identical to the lazy reset both hot paths already perform, so it changes no decision.

func (*LoginLimiter) RecordFailure

func (l *LoginLimiter) RecordFailure(username string) bool

RecordFailure registers one failed attempt. Returns true when the account just became locked (so the caller can log the lockout event).

func (*LoginLimiter) RecordSuccess

func (l *LoginLimiter) RecordSuccess(username string)

RecordSuccess clears the failure history for the username.

func (*LoginLimiter) SnapshotAndClear

func (l *LoginLimiter) SnapshotAndClear() func()

SnapshotAndClear captures the current limiter state, replaces it with an empty map, and returns a closure that restores the captured state. It is the exported equivalent of the whitebox snapshot/restore idiom used for test isolation of the package-global limiter: the entries are deep-copied under the mutex and the restore runs under the mutex too, so neither tears against a concurrent reader/writer. Production code never calls this; it exists so package main's test isolation helper does not need access to the unexported entries map across the package boundary (ADR-0002 extraction).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL