Files
mq/security.go
2025-09-24 16:01:07 +05:45

995 lines
25 KiB
Go

package mq
import (
"context"
"crypto/rand"
"crypto/sha256"
"encoding/hex"
"fmt"
"net"
"strings"
"sync"
"time"
"github.com/oarkflow/squealx"
)
// Storage interfaces for persistence
type UserStorage interface {
GetUser(username string) (*User, error)
GetPassword(username string) (string, error)
SaveUser(user *User, password string) error
ListUsers() ([]*User, error)
DeleteUser(username string) error
}
type RoleStorage interface {
GetRole(name string) (*Role, error)
SaveRole(role *Role) error
ListRoles() ([]*Role, error)
DeleteRole(name string) error
}
type PermissionStorage interface {
GetPermission(name string) (*Permission, error)
SavePermission(perm *Permission) error
ListPermissions() ([]*Permission, error)
DeletePermission(name string) error
}
// MemoryUserStorage implements UserStorage using in-memory storage
type MemoryUserStorage struct {
users map[string]*User
passwords map[string]string
mu sync.RWMutex
}
func NewMemoryUserStorage() *MemoryUserStorage {
return &MemoryUserStorage{
users: make(map[string]*User),
passwords: make(map[string]string),
}
}
func (mus *MemoryUserStorage) GetUser(username string) (*User, error) {
mus.mu.RLock()
defer mus.mu.RUnlock()
user, exists := mus.users[username]
if !exists {
return nil, fmt.Errorf("user not found")
}
return user, nil
}
func (mus *MemoryUserStorage) SaveUser(user *User, password string) error {
mus.mu.Lock()
defer mus.mu.Unlock()
mus.users[user.Username] = user
mus.passwords[user.Username] = password
return nil
}
func (mus *MemoryUserStorage) ListUsers() ([]*User, error) {
mus.mu.RLock()
defer mus.mu.RUnlock()
users := make([]*User, 0, len(mus.users))
for _, user := range mus.users {
users = append(users, user)
}
return users, nil
}
func (mus *MemoryUserStorage) GetPassword(username string) (string, error) {
mus.mu.RLock()
defer mus.mu.RUnlock()
password, exists := mus.passwords[username]
if !exists {
return "", fmt.Errorf("password not found")
}
return password, nil
}
func (mus *MemoryUserStorage) DeleteUser(username string) error {
mus.mu.Lock()
defer mus.mu.Unlock()
delete(mus.users, username)
delete(mus.passwords, username)
return nil
}
// MemoryRoleStorage implements RoleStorage using in-memory storage
type MemoryRoleStorage struct {
roles map[string]*Role
mu sync.RWMutex
}
func NewMemoryRoleStorage() *MemoryRoleStorage {
return &MemoryRoleStorage{
roles: make(map[string]*Role),
}
}
func (mrs *MemoryRoleStorage) GetRole(name string) (*Role, error) {
mrs.mu.RLock()
defer mrs.mu.RUnlock()
role, exists := mrs.roles[name]
if !exists {
return nil, fmt.Errorf("role not found")
}
return role, nil
}
func (mrs *MemoryRoleStorage) SaveRole(role *Role) error {
mrs.mu.Lock()
defer mrs.mu.Unlock()
mrs.roles[role.Name] = role
return nil
}
func (mrs *MemoryRoleStorage) ListRoles() ([]*Role, error) {
mrs.mu.RLock()
defer mrs.mu.RUnlock()
roles := make([]*Role, 0, len(mrs.roles))
for _, role := range mrs.roles {
roles = append(roles, role)
}
return roles, nil
}
func (mrs *MemoryRoleStorage) DeleteRole(name string) error {
mrs.mu.Lock()
defer mrs.mu.Unlock()
delete(mrs.roles, name)
return nil
}
// MemoryPermissionStorage implements PermissionStorage using in-memory storage
type MemoryPermissionStorage struct {
permissions map[string]*Permission
mu sync.RWMutex
}
func NewMemoryPermissionStorage() *MemoryPermissionStorage {
return &MemoryPermissionStorage{
permissions: make(map[string]*Permission),
}
}
func (mps *MemoryPermissionStorage) GetPermission(name string) (*Permission, error) {
mps.mu.RLock()
defer mps.mu.RUnlock()
perm, exists := mps.permissions[name]
if !exists {
return nil, fmt.Errorf("permission not found")
}
return perm, nil
}
func (mps *MemoryPermissionStorage) SavePermission(perm *Permission) error {
mps.mu.Lock()
defer mps.mu.Unlock()
mps.permissions[perm.Name] = perm
return nil
}
func (mps *MemoryPermissionStorage) ListPermissions() ([]*Permission, error) {
mps.mu.RLock()
defer mps.mu.RUnlock()
perms := make([]*Permission, 0, len(mps.permissions))
for _, perm := range mps.permissions {
perms = append(perms, perm)
}
return perms, nil
}
func (mps *MemoryPermissionStorage) DeletePermission(name string) error {
mps.mu.Lock()
defer mps.mu.Unlock()
delete(mps.permissions, name)
return nil
}
// SQLUserStorage implements UserStorage using SQL database
type SQLUserStorage struct {
db *squealx.DB
}
func NewSQLUserStorage(db *squealx.DB) *SQLUserStorage {
return &SQLUserStorage{db: db}
}
func (sus *SQLUserStorage) GetUser(username string) (*User, error) {
var user User
err := sus.db.Get(&user, "SELECT id, username, roles, permissions, metadata, created_at, last_login_at FROM users WHERE username = $1", username)
if err != nil {
return nil, err
}
return &user, nil
}
func (sus *SQLUserStorage) GetPassword(username string) (string, error) {
var password string
err := sus.db.Get(&password, "SELECT password FROM users WHERE username = $1", username)
if err != nil {
return "", err
}
return password, nil
}
func (sus *SQLUserStorage) SaveUser(user *User, password string) error {
_, err := sus.db.Exec(`
INSERT INTO users (id, username, password, roles, permissions, metadata, created_at, last_login_at)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
ON CONFLICT (username) DO UPDATE SET
password = EXCLUDED.password,
roles = EXCLUDED.roles,
permissions = EXCLUDED.permissions,
metadata = EXCLUDED.metadata,
last_login_at = EXCLUDED.last_login_at`,
user.ID, user.Username, password, user.Roles, user.Permissions, user.Metadata, user.CreatedAt, user.LastLoginAt)
return err
}
func (sus *SQLUserStorage) ListUsers() ([]*User, error) {
var users []*User
err := sus.db.Select(&users, "SELECT id, username, roles, permissions, metadata, created_at, last_login_at FROM users")
return users, err
}
func (sus *SQLUserStorage) DeleteUser(username string) error {
_, err := sus.db.Exec("DELETE FROM users WHERE username = $1", username)
return err
}
// SQLRoleStorage implements RoleStorage using SQL database
type SQLRoleStorage struct {
db *squealx.DB
}
func NewSQLRoleStorage(db *squealx.DB) *SQLRoleStorage {
return &SQLRoleStorage{db: db}
}
func (srs *SQLRoleStorage) GetRole(name string) (*Role, error) {
var role Role
err := srs.db.Get(&role, "SELECT name, description, permissions, created_at FROM roles WHERE name = $1", name)
if err != nil {
return nil, err
}
return &role, nil
}
func (srs *SQLRoleStorage) SaveRole(role *Role) error {
_, err := srs.db.Exec(`
INSERT INTO roles (name, description, permissions, created_at)
VALUES ($1, $2, $3, $4)
ON CONFLICT (name) DO UPDATE SET
description = EXCLUDED.description,
permissions = EXCLUDED.permissions`,
role.Name, role.Description, role.Permissions, role.CreatedAt)
return err
}
func (srs *SQLRoleStorage) ListRoles() ([]*Role, error) {
var roles []*Role
err := srs.db.Select(&roles, "SELECT name, description, permissions, created_at FROM roles")
return roles, err
}
func (srs *SQLRoleStorage) DeleteRole(name string) error {
_, err := srs.db.Exec("DELETE FROM roles WHERE name = $1", name)
return err
}
// SQLPermissionStorage implements PermissionStorage using SQL database
type SQLPermissionStorage struct {
db *squealx.DB
}
func NewSQLPermissionStorage(db *squealx.DB) *SQLPermissionStorage {
return &SQLPermissionStorage{db: db}
}
func (sps *SQLPermissionStorage) GetPermission(name string) (*Permission, error) {
var perm Permission
err := sps.db.Get(&perm, "SELECT name, resource, action, description, created_at FROM permissions WHERE name = $1", name)
if err != nil {
return nil, err
}
return &perm, nil
}
func (sps *SQLPermissionStorage) SavePermission(perm *Permission) error {
_, err := sps.db.Exec(`
INSERT INTO permissions (name, resource, action, description, created_at)
VALUES ($1, $2, $3, $4, $5)
ON CONFLICT (name) DO UPDATE SET
resource = EXCLUDED.resource,
action = EXCLUDED.action,
description = EXCLUDED.description`,
perm.Name, perm.Resource, perm.Action, perm.Description, perm.CreatedAt)
return err
}
func (sps *SQLPermissionStorage) ListPermissions() ([]*Permission, error) {
var perms []*Permission
err := sps.db.Select(&perms, "SELECT name, resource, action, description, created_at FROM permissions")
return perms, err
}
func (sps *SQLPermissionStorage) DeletePermission(name string) error {
_, err := sps.db.Exec("DELETE FROM permissions WHERE name = $1", name)
return err
}
// SecurityManager handles authentication, authorization, and security policies
type SecurityManager struct {
authProviders map[string]AuthProvider
roleManager *RoleManager
rateLimiter *SecurityRateLimiter
auditLogger *AuditLogger
sessionManager *SessionManager
encryptionKey []byte
mu sync.RWMutex
}
// AuthProvider interface for different authentication methods
type AuthProvider interface {
Name() string
Authenticate(ctx context.Context, credentials map[string]any) (*User, error)
ValidateToken(token string) (*User, error)
}
// User represents an authenticated user
type User struct {
ID string `json:"id"`
Username string `json:"username"`
Password string `json:"-"`
Roles []string `json:"roles"`
Permissions []string `json:"permissions"`
Metadata map[string]any `json:"metadata,omitempty"`
CreatedAt time.Time `json:"created_at"`
LastLoginAt *time.Time `json:"last_login_at,omitempty"`
}
// RoleManager manages user roles and permissions
type RoleManager struct {
roleStorage RoleStorage
permissionStorage PermissionStorage
mu sync.RWMutex
}
// Role represents a user role with associated permissions
type Role struct {
Name string `json:"name"`
Description string `json:"description"`
Permissions []string `json:"permissions"`
CreatedAt time.Time `json:"created_at"`
}
// Permission represents a specific permission
type Permission struct {
Name string `json:"name"`
Resource string `json:"resource"`
Action string `json:"action"`
Description string `json:"description"`
CreatedAt time.Time `json:"created_at"`
}
// SecurityRateLimiter implements rate limiting for security operations
type SecurityRateLimiter struct {
attempts map[string]*RateLimitEntry
maxAttempts int
window time.Duration
mu sync.RWMutex
}
// RateLimitEntry tracks rate limiting for a specific key
type RateLimitEntry struct {
Count int
WindowStart time.Time
}
// AuditLogger logs security-related events
type AuditLogger struct {
events []AuditEvent
maxEvents int
mu sync.RWMutex
}
// AuditEvent represents a security audit event
type AuditEvent struct {
ID string `json:"id"`
Timestamp time.Time `json:"timestamp"`
EventType string `json:"event_type"`
UserID string `json:"user_id,omitempty"`
Resource string `json:"resource"`
Action string `json:"action"`
IPAddress string `json:"ip_address,omitempty"`
UserAgent string `json:"user_agent,omitempty"`
Success bool `json:"success"`
Details map[string]any `json:"details,omitempty"`
}
// SessionManager manages user sessions
type SessionManager struct {
sessions map[string]*Session
maxAge time.Duration
mu sync.RWMutex
}
// Session represents a user session
type Session struct {
ID string `json:"id"`
UserID string `json:"user_id"`
CreatedAt time.Time `json:"created_at"`
ExpiresAt time.Time `json:"expires_at"`
IPAddress string `json:"ip_address"`
UserAgent string `json:"user_agent"`
Data map[string]any `json:"data,omitempty"`
}
// NewSecurityManager creates a new security manager
func NewSecurityManager() *SecurityManager {
key := make([]byte, 32)
rand.Read(key)
// Create memory storages by default
userStorage := NewMemoryUserStorage()
roleStorage := NewMemoryRoleStorage()
permissionStorage := NewMemoryPermissionStorage()
sm := &SecurityManager{
authProviders: make(map[string]AuthProvider),
roleManager: NewRoleManager(roleStorage, permissionStorage),
rateLimiter: NewSecurityRateLimiter(5, time.Minute*15), // 5 attempts per 15 minutes
auditLogger: NewAuditLogger(10000),
sessionManager: NewSessionManager(time.Hour * 24), // 24 hour sessions
encryptionKey: key,
}
// Add default basic auth provider
basicProvider := NewBasicAuthProvider(userStorage)
sm.AddAuthProvider(basicProvider)
return sm
}
// NewRoleManager creates a new role manager
func NewRoleManager(roleStorage RoleStorage, permissionStorage PermissionStorage) *RoleManager {
return &RoleManager{
roleStorage: roleStorage,
permissionStorage: permissionStorage,
}
}
// AddPermission adds a permission to the role manager
func (rm *RoleManager) AddPermission(perm *Permission) error {
rm.mu.Lock()
defer rm.mu.Unlock()
return rm.permissionStorage.SavePermission(perm)
}
// AddRole adds a role to the role manager
func (rm *RoleManager) AddRole(role *Role) error {
rm.mu.Lock()
defer rm.mu.Unlock()
return rm.roleStorage.SaveRole(role)
}
// HasPermission checks if a user has a specific permission
func (rm *RoleManager) HasPermission(user *User, permission string) bool {
rm.mu.RLock()
defer rm.mu.RUnlock()
for _, roleName := range user.Roles {
role, err := rm.roleStorage.GetRole(roleName)
if err != nil {
continue
}
for _, perm := range role.Permissions {
if perm == permission {
return true
}
}
}
return false
}
// GetUserPermissions returns all permissions for a user
func (rm *RoleManager) GetUserPermissions(user *User) []string {
rm.mu.RLock()
defer rm.mu.RUnlock()
permissions := make(map[string]bool)
for _, roleName := range user.Roles {
role, err := rm.roleStorage.GetRole(roleName)
if err != nil {
continue
}
for _, perm := range role.Permissions {
permissions[perm] = true
}
}
result := make([]string, 0, len(permissions))
for perm := range permissions {
result = append(result, perm)
}
return result
}
// NewSecurityRateLimiter creates a new security rate limiter
func NewSecurityRateLimiter(maxAttempts int, window time.Duration) *SecurityRateLimiter {
return &SecurityRateLimiter{
attempts: make(map[string]*RateLimitEntry),
maxAttempts: maxAttempts,
window: window,
}
}
// IsAllowed checks if an action is allowed based on rate limiting
func (rl *SecurityRateLimiter) IsAllowed(key string) bool {
rl.mu.Lock()
defer rl.mu.Unlock()
now := time.Now()
entry, exists := rl.attempts[key]
if !exists {
rl.attempts[key] = &RateLimitEntry{
Count: 1,
WindowStart: now,
}
return true
}
// Check if we're in a new window
if now.Sub(entry.WindowStart) >= rl.window {
entry.Count = 1
entry.WindowStart = now
return true
}
// Check if we've exceeded the limit
if entry.Count >= rl.maxAttempts {
return false
}
entry.Count++
return true
}
// Reset resets the rate limit for a key
func (rl *SecurityRateLimiter) Reset(key string) {
rl.mu.Lock()
defer rl.mu.Unlock()
delete(rl.attempts, key)
}
// NewAuditLogger creates a new audit logger
func NewAuditLogger(maxEvents int) *AuditLogger {
return &AuditLogger{
events: make([]AuditEvent, 0),
maxEvents: maxEvents,
}
}
// LogEvent logs a security event
func (al *AuditLogger) LogEvent(event AuditEvent) {
al.mu.Lock()
defer al.mu.Unlock()
event.ID = generateID()
event.Timestamp = time.Now()
al.events = append(al.events, event)
// Keep only the most recent events
if len(al.events) > al.maxEvents {
al.events = al.events[len(al.events)-al.maxEvents:]
}
}
// GetEvents returns audit events with optional filtering
func (al *AuditLogger) GetEvents(userID, eventType string, limit int) []AuditEvent {
al.mu.RLock()
defer al.mu.RUnlock()
var filtered []AuditEvent
for _, event := range al.events {
if (userID == "" || event.UserID == userID) &&
(eventType == "" || event.EventType == eventType) {
filtered = append(filtered, event)
}
}
// Return most recent events
if len(filtered) > limit && limit > 0 {
start := len(filtered) - limit
return filtered[start:]
}
return filtered
}
// NewSessionManager creates a new session manager
func NewSessionManager(maxAge time.Duration) *SessionManager {
sm := &SessionManager{
sessions: make(map[string]*Session),
maxAge: maxAge,
}
// Start cleanup routine
go sm.cleanupRoutine()
return sm
}
// CreateSession creates a new session for a user
func (sm *SessionManager) CreateSession(userID, ipAddress, userAgent string) *Session {
sm.mu.Lock()
defer sm.mu.Unlock()
session := &Session{
ID: generateID(),
UserID: userID,
CreatedAt: time.Now(),
ExpiresAt: time.Now().Add(sm.maxAge),
IPAddress: ipAddress,
UserAgent: userAgent,
Data: make(map[string]any),
}
sm.sessions[session.ID] = session
return session
}
// GetSession retrieves a session by ID
func (sm *SessionManager) GetSession(sessionID string) (*Session, bool) {
sm.mu.RLock()
defer sm.mu.RUnlock()
session, exists := sm.sessions[sessionID]
if !exists {
return nil, false
}
// Check if session has expired
if time.Now().After(session.ExpiresAt) {
return nil, false
}
return session, true
}
// DeleteSession deletes a session
func (sm *SessionManager) DeleteSession(sessionID string) {
sm.mu.Lock()
defer sm.mu.Unlock()
delete(sm.sessions, sessionID)
}
// cleanupRoutine periodically cleans up expired sessions
func (sm *SessionManager) cleanupRoutine() {
ticker := time.NewTicker(time.Hour)
defer ticker.Stop()
for range ticker.C {
sm.mu.Lock()
now := time.Now()
for id, session := range sm.sessions {
if now.After(session.ExpiresAt) {
delete(sm.sessions, id)
}
}
sm.mu.Unlock()
}
}
// AddAuthProvider adds an authentication provider
func (sm *SecurityManager) AddAuthProvider(provider AuthProvider) {
sm.mu.Lock()
defer sm.mu.Unlock()
sm.authProviders[provider.Name()] = provider
}
// Authenticate authenticates a user using available providers
func (sm *SecurityManager) Authenticate(ctx context.Context, credentials map[string]any) (*User, error) {
sm.mu.RLock()
providers := make(map[string]AuthProvider)
for name, provider := range sm.authProviders {
providers[name] = provider
}
sm.mu.RUnlock()
var lastErr error
for _, provider := range providers {
user, err := provider.Authenticate(ctx, credentials)
if err == nil {
// Log successful authentication
sm.auditLogger.LogEvent(AuditEvent{
EventType: "authentication",
UserID: user.ID,
Action: "login",
Success: true,
Details: map[string]any{
"provider": provider.Name(),
},
})
// Update user permissions
user.Permissions = sm.roleManager.GetUserPermissions(user)
return user, nil
}
lastErr = err
}
// Log failed authentication
sm.auditLogger.LogEvent(AuditEvent{
EventType: "authentication",
Action: "login",
Success: false,
Details: map[string]any{
"error": lastErr.Error(),
},
})
return nil, fmt.Errorf("authentication failed: %w", lastErr)
}
func (sm *SecurityManager) AddPermission(perm *Permission) error {
if perm == nil || (perm.Name == "" && (perm.Resource == "" || perm.Action == "")) {
return fmt.Errorf("invalid permission")
}
return sm.roleManager.AddPermission(perm)
}
func (sm *SecurityManager) AddRole(role *Role) error {
if role == nil || role.Name == "" {
return fmt.Errorf("invalid role")
}
return sm.roleManager.AddRole(role)
}
func (sm *SecurityManager) AddUsers(users ...*User) error {
for _, user := range users {
if user == nil || user.Username == "" || user.Password == "" {
return fmt.Errorf("invalid user")
}
if err := sm.AddUser(user); err != nil {
return err
}
}
return nil
}
func (sm *SecurityManager) AddRoles(roles ...*Role) error {
for _, role := range roles {
if err := sm.AddRole(role); err != nil {
return err
}
}
return nil
}
func (sm *SecurityManager) AddPermissions(perms ...*Permission) error {
for _, perm := range perms {
if err := sm.AddPermission(perm); err != nil {
return err
}
}
return nil
}
// AddUser adds a user to the system
func (sm *SecurityManager) AddUser(user *User) error {
for _, provider := range sm.authProviders {
if bap, ok := provider.(*BasicAuthProvider); ok {
return bap.AddUser(user, user.Password)
}
}
return fmt.Errorf("no suitable auth provider found")
}
// Authorize checks if a user is authorized for an action
func (sm *SecurityManager) Authorize(user *User, resource, action string) error {
permission := fmt.Sprintf("%s.%s", resource, action)
if !sm.roleManager.HasPermission(user, permission) {
// Log authorization failure
sm.auditLogger.LogEvent(AuditEvent{
EventType: "authorization",
UserID: user.ID,
Resource: resource,
Action: action,
Success: false,
})
return fmt.Errorf("user %s does not have permission %s", user.Username, permission)
}
// Log successful authorization
sm.auditLogger.LogEvent(AuditEvent{
EventType: "authorization",
UserID: user.ID,
Resource: resource,
Action: action,
Success: true,
})
return nil
}
// ValidateSession validates a session token
func (sm *SecurityManager) ValidateSession(sessionID string) (*User, error) {
session, exists := sm.sessionManager.GetSession(sessionID)
if !exists {
return nil, fmt.Errorf("invalid session")
}
// Create a user object from session data
user := &User{
ID: session.UserID,
Username: session.UserID, // In a real implementation, you'd fetch from database
}
// Update user permissions
user.Permissions = sm.roleManager.GetUserPermissions(user)
return user, nil
}
// CheckRateLimit checks if an action is rate limited
func (sm *SecurityManager) CheckRateLimit(key string) error {
if !sm.rateLimiter.IsAllowed(key) {
sm.auditLogger.LogEvent(AuditEvent{
EventType: "rate_limit",
Action: "exceeded",
Success: false,
Details: map[string]any{
"key": key,
},
})
return fmt.Errorf("rate limit exceeded for key: %s", key)
}
return nil
}
// Encrypt encrypts data using the security manager's key
func (sm *SecurityManager) Encrypt(data []byte) ([]byte, error) {
// Simple encryption using SHA256 hash of key + data
// In production, use proper encryption like AES
hash := sha256.Sum256(append(sm.encryptionKey, data...))
return hash[:], nil
}
// Decrypt decrypts data (placeholder for proper decryption)
func (sm *SecurityManager) Decrypt(data []byte) ([]byte, error) {
// Placeholder - in production, implement proper decryption
return data, nil
}
// BasicAuthProvider implements basic username/password authentication
type BasicAuthProvider struct {
userStorage UserStorage
}
func NewBasicAuthProvider(userStorage UserStorage) *BasicAuthProvider {
return &BasicAuthProvider{
userStorage: userStorage,
}
}
func (bap *BasicAuthProvider) Name() string {
return "basic"
}
func (bap *BasicAuthProvider) Authenticate(ctx context.Context, credentials map[string]any) (*User, error) {
username, ok := credentials["username"].(string)
if !ok {
return nil, fmt.Errorf("username required")
}
password, ok := credentials["password"].(string)
if !ok {
return nil, fmt.Errorf("password required")
}
user, err := bap.userStorage.GetUser(username)
if err != nil {
return nil, fmt.Errorf("user not found")
}
storedPassword, err := bap.userStorage.GetPassword(username)
if err != nil || storedPassword != password {
return nil, fmt.Errorf("invalid password")
}
// Update last login
now := time.Now()
user.LastLoginAt = &now
return user, nil
}
func (bap *BasicAuthProvider) ValidateToken(token string) (*User, error) {
// Basic token validation - in production, use JWT or similar
parts := strings.Split(token, ":")
if len(parts) != 2 {
return nil, fmt.Errorf("invalid token format")
}
username := parts[0]
return bap.Authenticate(context.Background(), map[string]any{
"username": username,
"password": "token", // Placeholder
})
}
func (bap *BasicAuthProvider) AddUser(user *User, password string) error {
// In production, hash the password
user.CreatedAt = time.Now()
return bap.userStorage.SaveUser(user, password)
}
// generateID generates a random ID
func generateID() string {
bytes := make([]byte, 16)
rand.Read(bytes)
return hex.EncodeToString(bytes)
}
// SecurityMiddleware provides security middleware for HTTP handlers
type SecurityMiddleware struct {
securityManager *SecurityManager
}
// NewSecurityMiddleware creates a new security middleware
func NewSecurityMiddleware(sm *SecurityManager) *SecurityMiddleware {
return &SecurityMiddleware{
securityManager: sm,
}
}
// AuthenticateRequest authenticates a request with credentials
func (sm *SecurityMiddleware) AuthenticateRequest(credentials map[string]any, ipAddress string) (*User, error) {
user, err := sm.securityManager.Authenticate(context.Background(), credentials)
if err != nil {
// Log failed authentication attempt
sm.securityManager.auditLogger.LogEvent(AuditEvent{
EventType: "authentication",
Action: "login",
Success: false,
Details: map[string]any{
"ip_address": ipAddress,
"error": err.Error(),
},
})
return nil, err
}
return user, nil
}
// AuthorizeRequest authorizes a request
func (sm *SecurityMiddleware) AuthorizeRequest(user *User, resource, action string) error {
return sm.securityManager.Authorize(user, resource, action)
}
// GetClientIP gets the real client IP from a network connection
func GetClientIP(conn net.Conn) string {
if conn == nil {
return ""
}
host, _, err := net.SplitHostPort(conn.RemoteAddr().String())
if err != nil {
return conn.RemoteAddr().String()
}
return host
}