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(teamName 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 invalidates all existing tokens for a team by incrementing the team's revoked version. Any token whose version is less than or equal to the new revoked version will be rejected during validation. Returns ErrTeamNotFound if the team does not exist.
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).