feat: add SQLite storage for login attempts and sessions
Adds persistent storage using modernc.org/sqlite (pure Go). Login attempts are deduplicated by (username, password, ip) with counts. Sessions and session logs are tracked with UUID IDs. Includes embedded SQL migrations, configurable retention with background pruning, and an in-memory store for tests. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
63
internal/storage/store.go
Normal file
63
internal/storage/store.go
Normal file
@@ -0,0 +1,63 @@
|
||||
package storage
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
)
|
||||
|
||||
// LoginAttempt represents a deduplicated login attempt.
|
||||
type LoginAttempt struct {
|
||||
ID int64
|
||||
Username string
|
||||
Password string
|
||||
IP string
|
||||
Count int
|
||||
FirstSeen time.Time
|
||||
LastSeen time.Time
|
||||
}
|
||||
|
||||
// Session represents an authenticated SSH session.
|
||||
type Session struct {
|
||||
ID string
|
||||
IP string
|
||||
Username string
|
||||
ShellName string
|
||||
ConnectedAt time.Time
|
||||
DisconnectedAt *time.Time
|
||||
HumanScore *float64
|
||||
}
|
||||
|
||||
// SessionLog represents a single log entry for a session.
|
||||
type SessionLog struct {
|
||||
ID int64
|
||||
SessionID string
|
||||
Timestamp time.Time
|
||||
Input string
|
||||
Output string
|
||||
}
|
||||
|
||||
// Store is the interface for persistent storage of honeypot data.
|
||||
type Store interface {
|
||||
// RecordLoginAttempt upserts a login attempt, incrementing the count
|
||||
// for existing (username, password, ip) combinations.
|
||||
RecordLoginAttempt(ctx context.Context, username, password, ip string) error
|
||||
|
||||
// CreateSession creates a new session record and returns its UUID.
|
||||
CreateSession(ctx context.Context, ip, username, shellName string) (string, error)
|
||||
|
||||
// EndSession sets the disconnected_at timestamp for a session.
|
||||
EndSession(ctx context.Context, sessionID string, disconnectedAt time.Time) error
|
||||
|
||||
// UpdateHumanScore sets the human detection score for a session.
|
||||
UpdateHumanScore(ctx context.Context, sessionID string, score float64) error
|
||||
|
||||
// AppendSessionLog adds a log entry to a session.
|
||||
AppendSessionLog(ctx context.Context, sessionID, input, output string) error
|
||||
|
||||
// DeleteRecordsBefore removes all records older than the given cutoff
|
||||
// and returns the total number of deleted rows.
|
||||
DeleteRecordsBefore(ctx context.Context, cutoff time.Time) (int64, error)
|
||||
|
||||
// Close releases any resources held by the store.
|
||||
Close() error
|
||||
}
|
||||
Reference in New Issue
Block a user