Documentation
¶
Overview ¶
Package auth provides authentication and authorization for Wormhole.
The auth package implements team-based authentication using HMAC-SHA256 tokens and role-based access control for multi-user scenarios.
Features ¶
- Team token generation with HMAC-SHA256 signing
- Token validation (signature + expiration)
- Role-based permissions (admin, member, viewer)
- Simple pre-shared token mode for quick setup
- In-memory team management
Token Modes ¶
Two modes are supported:
- HMAC Mode: Tokens are signed with a secret key and include team, role, issued-at, expiration, and a random nonce.
- Simple Mode: Tokens are plain strings compared against a whitelist. All matched tokens get "default" team + "member" role.
Usage ¶
// HMAC mode
a, err := auth.New(auth.Config{
Secret: []byte("your-secret-key-at-least-16-bytes"),
TokenExpiry: 24 * time.Hour,
})
// Generate team token
token, err := a.GenerateTeamToken("team-name", auth.RoleMember)
// Validate token
claims, err := a.ValidateToken(token)
if err != nil {
return err
}
// Check permission
if !auth.HasPermission(claims, auth.PermissionWrite) {
return auth.ErrForbidden
}
// Simple mode
a := auth.NewSimple([]string{"token-abc", "token-xyz"})
claims, err := a.ValidateToken("token-abc") // returns default/member claims.
Index ¶
- Variables
- func DefaultSQLiteStorePath() string
- func HasPermission(claims *Claims, perm Permission) bool
- type AuditEvent
- type AuditEventType
- type AuditLogger
- func (l *AuditLogger) IsEnabled() bool
- func (l *AuditLogger) Log(event AuditEvent)
- func (l *AuditLogger) LogAuthFailure(ip, reason string)
- func (l *AuditLogger) LogAuthSuccess(ip, teamName string, role Role, sessionID, subdomain string)
- func (l *AuditLogger) LogClientConnected(ip, sessionID, subdomain, teamName string, role Role)
- func (l *AuditLogger) LogClientDisconnected(sessionID, subdomain string, duration time.Duration)
- func (l *AuditLogger) LogIPBlocked(ip string, failureCount int)
- func (l *AuditLogger) LogIPUnblocked(ip string, manual bool)
- func (l *AuditLogger) LogTokenGenerated(teamName string, role Role)
- func (l *AuditLogger) SetEnabled(enabled bool)
- type AuditLoggerConfig
- type Auth
- func (a *Auth) CleanupRevokedTokens() int
- func (a *Auth) Close() error
- func (a *Auth) ExtendTokenExpiry(token string, extension time.Duration) (string, error)
- func (a *Auth) GenerateTeamToken(teamName string, role Role) (string, error)
- func (a *Auth) GetTeam(name string) (*TeamInfo, error)
- func (a *Auth) IsRevoked(tokenID string) bool
- func (a *Auth) ListTeams() []TeamInfo
- func (a *Auth) RefreshAndRevokeToken(oldToken string) (string, error)
- func (a *Auth) RefreshToken(token string) (string, error)
- func (a *Auth) RegisterTeam(name string) error
- func (a *Auth) RevokeAllTeamTokens(_ string) error
- func (a *Auth) RevokeToken(tokenID string, expiresAt time.Time) error
- func (a *Auth) RevokeTokenByString(token string) error
- func (a *Auth) RevokedTokenCount() int
- func (a *Auth) Store() Store
- func (a *Auth) UnrevokeToken(tokenID string)
- func (a *Auth) ValidateToken(token string) (*Claims, error)
- type Claims
- type Config
- type MemoryStore
- func (s *MemoryStore) CleanupExpiredRevocations() (int, error)
- func (s *MemoryStore) Close() error
- func (s *MemoryStore) CountRevokedTokens() (int, error)
- func (s *MemoryStore) DeleteTeam(name string) error
- func (s *MemoryStore) GetTeam(name string) (*TeamInfo, error)
- func (s *MemoryStore) IsTokenRevoked(tokenID string) (bool, error)
- func (s *MemoryStore) ListTeams() ([]TeamInfo, error)
- func (s *MemoryStore) RemoveRevokedToken(tokenID string) error
- func (s *MemoryStore) SaveRevokedToken(tokenID string, expiresAt time.Time) error
- func (s *MemoryStore) SaveTeam(team *TeamInfo) error
- type Permission
- type RateLimitConfig
- type RateLimiter
- func (rl *RateLimiter) Close()
- func (rl *RateLimiter) GetBlockedIPs() []string
- func (rl *RateLimiter) IsBlocked(ip string) bool
- func (rl *RateLimiter) RecordFailure(ip string) bool
- func (rl *RateLimiter) RecordSuccess(ip string)
- func (rl *RateLimiter) Stats() RateLimiterStats
- func (rl *RateLimiter) Unblock(ip string)
- type RateLimiterStats
- type Role
- type SQLiteStore
- func (s *SQLiteStore) CleanupExpiredRevocations() (int, error)
- func (s *SQLiteStore) Close() error
- func (s *SQLiteStore) CountRevokedTokens() (int, error)
- func (s *SQLiteStore) DeleteTeam(name string) error
- func (s *SQLiteStore) GetTeam(name string) (*TeamInfo, error)
- func (s *SQLiteStore) IsTokenRevoked(tokenID string) (bool, error)
- func (s *SQLiteStore) ListTeams() ([]TeamInfo, error)
- func (s *SQLiteStore) RemoveRevokedToken(tokenID string) error
- func (s *SQLiteStore) SaveRevokedToken(tokenID string, expiresAt time.Time) error
- func (s *SQLiteStore) SaveTeam(team *TeamInfo) error
- type SQLiteStoreConfig
- type Store
- type TeamInfo
Constants ¶
This section is empty.
Variables ¶
var ( ErrInvalidToken = errors.New("invalid token") ErrTokenExpired = errors.New("token expired") ErrTokenRevoked = errors.New("token revoked") ErrForbidden = errors.New("forbidden") ErrTeamNotFound = errors.New("team not found") ErrInvalidSecret = errors.New("secret must be at least 16 bytes") ErrDuplicateTeam = errors.New("team already exists") ErrInvalidTeamName = errors.New("invalid team name") )
Sentinel errors for authentication.
Functions ¶
func DefaultSQLiteStorePath ¶
func DefaultSQLiteStorePath() string
DefaultSQLiteStorePath returns the default path for the SQLite database.
func HasPermission ¶
func HasPermission(claims *Claims, perm Permission) bool
HasPermission checks if the claims grant the specified permission.
Types ¶
type AuditEvent ¶
type AuditEvent struct {
Timestamp time.Time `json:"timestamp"`
Type AuditEventType `json:"type"`
IP string `json:"ip,omitempty"`
TeamName string `json:"team,omitempty"`
Role string `json:"role,omitempty"`
SessionID string `json:"session_id,omitempty"`
Subdomain string `json:"subdomain,omitempty"`
Error string `json:"error,omitempty"`
Details map[string]interface{} `json:"details,omitempty"`
}
AuditEvent represents a single audit log entry.
type AuditEventType ¶
type AuditEventType string
AuditEventType represents the type of audit event.
const ( // EventAuthSuccess indicates successful authentication. EventAuthSuccess AuditEventType = "auth_success" // EventAuthFailure indicates failed authentication. EventAuthFailure AuditEventType = "auth_failure" // EventIPBlocked indicates an IP was blocked due to failures. EventIPBlocked AuditEventType = "ip_blocked" // EventIPUnblocked indicates an IP was manually unblocked. EventIPUnblocked AuditEventType = "ip_unblocked" // EventTokenGenerated indicates a new token was generated. EventTokenGenerated AuditEventType = "token_generated" // EventClientConnected indicates a client connected. EventClientConnected AuditEventType = "client_connected" // EventClientDisconnected indicates a client disconnected. EventClientDisconnected AuditEventType = "client_disconnected" )
type AuditLogger ¶
type AuditLogger struct {
// contains filtered or unexported fields
}
AuditLogger logs authentication and authorization events.
func NewAuditLogger ¶
func NewAuditLogger(config AuditLoggerConfig) *AuditLogger
NewAuditLogger creates a new audit logger.
func (*AuditLogger) IsEnabled ¶
func (l *AuditLogger) IsEnabled() bool
IsEnabled returns whether audit logging is enabled.
func (*AuditLogger) Log ¶
func (l *AuditLogger) Log(event AuditEvent)
Log writes an audit event to the log.
func (*AuditLogger) LogAuthFailure ¶
func (l *AuditLogger) LogAuthFailure(ip, reason string)
LogAuthFailure logs a failed authentication event.
func (*AuditLogger) LogAuthSuccess ¶
func (l *AuditLogger) LogAuthSuccess(ip, teamName string, role Role, sessionID, subdomain string)
LogAuthSuccess logs a successful authentication event.
func (*AuditLogger) LogClientConnected ¶
func (l *AuditLogger) LogClientConnected(ip, sessionID, subdomain, teamName string, role Role)
LogClientConnected logs a client connection event.
func (*AuditLogger) LogClientDisconnected ¶
func (l *AuditLogger) LogClientDisconnected(sessionID, subdomain string, duration time.Duration)
LogClientDisconnected logs a client disconnection event.
func (*AuditLogger) LogIPBlocked ¶
func (l *AuditLogger) LogIPBlocked(ip string, failureCount int)
LogIPBlocked logs an IP blocking event.
func (*AuditLogger) LogIPUnblocked ¶
func (l *AuditLogger) LogIPUnblocked(ip string, manual bool)
LogIPUnblocked logs an IP unblocking event.
func (*AuditLogger) LogTokenGenerated ¶
func (l *AuditLogger) LogTokenGenerated(teamName string, role Role)
LogTokenGenerated logs a token generation event.
func (*AuditLogger) SetEnabled ¶
func (l *AuditLogger) SetEnabled(enabled bool)
SetEnabled enables or disables audit logging.
type AuditLoggerConfig ¶
type AuditLoggerConfig struct {
// Enabled turns audit logging on or off.
Enabled bool
// Writer is the destination for audit logs (defaults to os.Stdout).
Writer io.Writer
}
AuditLoggerConfig configures the audit logger.
type Auth ¶
type Auth struct {
// contains filtered or unexported fields
}
Auth provides token-based authentication and authorization.
func NewSimple ¶
NewSimple creates an Auth instance for simple pre-shared token mode. In this mode, tokens are compared directly against the allowed list.
func (*Auth) CleanupRevokedTokens ¶
CleanupRevokedTokens removes expired entries from the revocation blacklist. This should be called periodically to prevent the blacklist from growing unbounded.
func (*Auth) Close ¶
Close releases any resources held by the Auth instance. This should be called when the Auth instance is no longer needed.
func (*Auth) ExtendTokenExpiry ¶
ExtendTokenExpiry creates a new token with an extended expiry time. The original token is NOT revoked.
func (*Auth) GenerateTeamToken ¶
GenerateTeamToken generates a new signed token for the given team and role.
func (*Auth) RefreshAndRevokeToken ¶
RefreshAndRevokeToken generates a new token and revokes the old one atomically. This is the recommended way to refresh tokens when rotation is desired.
func (*Auth) RefreshToken ¶
RefreshToken generates a new token with the same claims as the original, but with a fresh issuance time and expiry. The original token is NOT revoked. Use RevokeToken to invalidate the old token if desired.
func (*Auth) RegisterTeam ¶
RegisterTeam registers a team in the store.
func (*Auth) RevokeAllTeamTokens ¶
RevokeAllTeamTokens marks a team as fully revoked by incrementing a version. This is a placeholder for a more sophisticated team-level revocation. For now, it's not implemented as it would require version tracking in tokens. Use RevokeToken for individual token revocation.
func (*Auth) RevokeToken ¶
RevokeToken adds a token ID to the revocation blacklist. The expiresAt parameter indicates when the token would have expired; after that time, the revocation entry can be cleaned up. If expiresAt is zero, the revocation is permanent until manually cleared.
func (*Auth) RevokeTokenByString ¶
RevokeTokenByString parses a token string and revokes it by ID. Returns ErrInvalidToken if the token cannot be parsed or has no ID.
func (*Auth) RevokedTokenCount ¶
RevokedTokenCount returns the number of tokens in the revocation blacklist.
func (*Auth) Store ¶
Store returns the underlying storage backend. This is useful for advanced operations or testing.
func (*Auth) UnrevokeToken ¶
UnrevokeToken removes a token ID from the revocation blacklist.
type Claims ¶
type Claims struct {
// TokenID is the unique identifier for this token.
TokenID string `json:"jti,omitempty"`
// TeamName is the team this token belongs to.
TeamName string `json:"team"`
// Role is the role assigned to this token.
Role Role `json:"role"`
// IssuedAt is when the token was issued.
IssuedAt time.Time `json:"iat"`
// ExpiresAt is when the token expires (zero means no expiry).
ExpiresAt time.Time `json:"exp,omitempty"`
}
Claims contains the validated token information.
type Config ¶
type Config struct {
// Secret is the HMAC signing key (must be at least 16 bytes).
Secret []byte
// TokenExpiry is the default expiry duration for new tokens.
TokenExpiry time.Duration
// AllowedTokens is a list of pre-shared plain tokens (simple mode).
// When set, these tokens bypass HMAC validation entirely.
AllowedTokens []string
// Store is the storage backend for teams and revoked tokens.
// If nil, a MemoryStore is used (no persistence).
Store Store
}
Config holds the authentication configuration.
type MemoryStore ¶
type MemoryStore struct {
// contains filtered or unexported fields
}
MemoryStore implements Store using in-memory maps. This is the default, zero-persistence backend.
func NewMemoryStore ¶
func NewMemoryStore() *MemoryStore
NewMemoryStore creates a new in-memory store.
func (*MemoryStore) CleanupExpiredRevocations ¶
func (s *MemoryStore) CleanupExpiredRevocations() (int, error)
CleanupExpiredRevocations removes expired revocation entries.
func (*MemoryStore) CountRevokedTokens ¶
func (s *MemoryStore) CountRevokedTokens() (int, error)
CountRevokedTokens returns the number of revoked tokens.
func (*MemoryStore) DeleteTeam ¶
func (s *MemoryStore) DeleteTeam(name string) error
DeleteTeam removes a team from memory.
func (*MemoryStore) GetTeam ¶
func (s *MemoryStore) GetTeam(name string) (*TeamInfo, error)
GetTeam retrieves a team from memory.
func (*MemoryStore) IsTokenRevoked ¶
func (s *MemoryStore) IsTokenRevoked(tokenID string) (bool, error)
IsTokenRevoked checks if a token is revoked.
func (*MemoryStore) ListTeams ¶
func (s *MemoryStore) ListTeams() ([]TeamInfo, error)
ListTeams returns all teams from memory.
func (*MemoryStore) RemoveRevokedToken ¶
func (s *MemoryStore) RemoveRevokedToken(tokenID string) error
RemoveRevokedToken removes a token from the revocation list.
func (*MemoryStore) SaveRevokedToken ¶
func (s *MemoryStore) SaveRevokedToken(tokenID string, expiresAt time.Time) error
SaveRevokedToken saves a revoked token to memory.
func (*MemoryStore) SaveTeam ¶
func (s *MemoryStore) SaveTeam(team *TeamInfo) error
SaveTeam saves a team to memory.
type Permission ¶
type Permission string
Permission represents an action that can be authorized.
const ( // PermissionConnect allows establishing a tunnel connection. PermissionConnect Permission = "connect" // PermissionWrite allows creating and managing tunnels. PermissionWrite Permission = "write" // PermissionRead allows viewing tunnels and statistics. PermissionRead Permission = "read" // PermissionAdmin allows administrative operations. PermissionAdmin Permission = "admin" )
type RateLimitConfig ¶
type RateLimitConfig struct {
// MaxFailures is the maximum number of auth failures before blocking.
MaxFailures int
// Window is the time window for counting failures.
Window time.Duration
// BlockDuration is how long to block after exceeding MaxFailures.
BlockDuration time.Duration
// CleanupInterval is how often to clean up expired entries.
CleanupInterval time.Duration
}
RateLimitConfig configures the rate limiter behavior.
func DefaultRateLimitConfig ¶
func DefaultRateLimitConfig() RateLimitConfig
DefaultRateLimitConfig returns sensible defaults for rate limiting.
type RateLimiter ¶
type RateLimiter struct {
// contains filtered or unexported fields
}
RateLimiter tracks authentication failures and blocks IPs.
func NewRateLimiter ¶
func NewRateLimiter(config RateLimitConfig) *RateLimiter
NewRateLimiter creates a new rate limiter with the given config.
func (*RateLimiter) Close ¶
func (rl *RateLimiter) Close()
Close stops the rate limiter and its cleanup goroutine.
func (*RateLimiter) GetBlockedIPs ¶
func (rl *RateLimiter) GetBlockedIPs() []string
GetBlockedIPs returns a list of currently blocked IP addresses.
func (*RateLimiter) IsBlocked ¶
func (rl *RateLimiter) IsBlocked(ip string) bool
IsBlocked checks if the given IP is currently blocked.
func (*RateLimiter) RecordFailure ¶
func (rl *RateLimiter) RecordFailure(ip string) bool
RecordFailure records an authentication failure for the given IP. Returns true if the IP is now blocked.
func (*RateLimiter) RecordSuccess ¶
func (rl *RateLimiter) RecordSuccess(ip string)
RecordSuccess records a successful authentication, clearing failure count.
func (*RateLimiter) Stats ¶
func (rl *RateLimiter) Stats() RateLimiterStats
Stats returns current rate limiter statistics.
func (*RateLimiter) Unblock ¶
func (rl *RateLimiter) Unblock(ip string)
Unblock manually unblocks an IP address.
type RateLimiterStats ¶
type RateLimiterStats struct {
TrackedIPs int `json:"tracked_ips"`
BlockedIPs int `json:"blocked_ips"`
}
Stats returns rate limiter statistics.
type SQLiteStore ¶
type SQLiteStore struct {
// contains filtered or unexported fields
}
SQLiteStore implements Store using SQLite for persistence.
func NewSQLiteStore ¶
func NewSQLiteStore(config SQLiteStoreConfig) (*SQLiteStore, error)
NewSQLiteStore creates a new SQLite-backed store.
func (*SQLiteStore) CleanupExpiredRevocations ¶
func (s *SQLiteStore) CleanupExpiredRevocations() (int, error)
CleanupExpiredRevocations removes expired revocation entries.
func (*SQLiteStore) Close ¶
func (s *SQLiteStore) Close() error
Close closes the database connection.
func (*SQLiteStore) CountRevokedTokens ¶
func (s *SQLiteStore) CountRevokedTokens() (int, error)
CountRevokedTokens returns the number of revoked tokens.
func (*SQLiteStore) DeleteTeam ¶
func (s *SQLiteStore) DeleteTeam(name string) error
DeleteTeam removes a team from SQLite.
func (*SQLiteStore) GetTeam ¶
func (s *SQLiteStore) GetTeam(name string) (*TeamInfo, error)
GetTeam retrieves a team from SQLite.
func (*SQLiteStore) IsTokenRevoked ¶
func (s *SQLiteStore) IsTokenRevoked(tokenID string) (bool, error)
IsTokenRevoked checks if a token is revoked.
func (*SQLiteStore) ListTeams ¶
func (s *SQLiteStore) ListTeams() ([]TeamInfo, error)
ListTeams returns all teams from SQLite.
func (*SQLiteStore) RemoveRevokedToken ¶
func (s *SQLiteStore) RemoveRevokedToken(tokenID string) error
RemoveRevokedToken removes a token from the revocation list.
func (*SQLiteStore) SaveRevokedToken ¶
func (s *SQLiteStore) SaveRevokedToken(tokenID string, expiresAt time.Time) error
SaveRevokedToken saves a revoked token to SQLite.
func (*SQLiteStore) SaveTeam ¶
func (s *SQLiteStore) SaveTeam(team *TeamInfo) error
SaveTeam saves a team to SQLite.
type SQLiteStoreConfig ¶
type SQLiteStoreConfig struct {
// Path is the path to the SQLite database file.
// If empty, defaults to ~/.wormhole/wormhole.db
Path string
// CreateDir creates the parent directory if it doesn't exist.
CreateDir bool
}
SQLiteStoreConfig configures the SQLite store.
type Store ¶
type Store interface {
// Team operations.
SaveTeam(team *TeamInfo) error
GetTeam(name string) (*TeamInfo, error)
ListTeams() ([]TeamInfo, error)
DeleteTeam(name string) error
// Token revocation operations.
SaveRevokedToken(tokenID string, expiresAt time.Time) error
IsTokenRevoked(tokenID string) (bool, error)
RemoveRevokedToken(tokenID string) error
CleanupExpiredRevocations() (int, error)
CountRevokedTokens() (int, error)
// Close releases any resources held by the store.
Close() error
}
Store defines the interface for persisting authentication data. Implementations can be in-memory (default) or persistent (SQLite).