mirror of
				https://github.com/oarkflow/mq.git
				synced 2025-11-01 02:12:32 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			681 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			681 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package mq
 | |
| 
 | |
| import (
 | |
| 	"context"
 | |
| 	"crypto/rand"
 | |
| 	"crypto/sha256"
 | |
| 	"encoding/hex"
 | |
| 	"fmt"
 | |
| 	"net"
 | |
| 	"strings"
 | |
| 	"sync"
 | |
| 	"time"
 | |
| )
 | |
| 
 | |
| // 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"`
 | |
| 	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 {
 | |
| 	roles       map[string]*Role
 | |
| 	permissions map[string]*Permission
 | |
| 	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)
 | |
| 
 | |
| 	return &SecurityManager{
 | |
| 		authProviders:  make(map[string]AuthProvider),
 | |
| 		roleManager:    NewRoleManager(),
 | |
| 		rateLimiter:    NewSecurityRateLimiter(5, time.Minute*15), // 5 attempts per 15 minutes
 | |
| 		auditLogger:    NewAuditLogger(10000),
 | |
| 		sessionManager: NewSessionManager(time.Hour * 24), // 24 hour sessions
 | |
| 		encryptionKey:  key,
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // NewRoleManager creates a new role manager
 | |
| func NewRoleManager() *RoleManager {
 | |
| 	rm := &RoleManager{
 | |
| 		roles:       make(map[string]*Role),
 | |
| 		permissions: make(map[string]*Permission),
 | |
| 	}
 | |
| 
 | |
| 	// Initialize default permissions
 | |
| 	rm.AddPermission(&Permission{
 | |
| 		Name:        "task.publish",
 | |
| 		Resource:    "task",
 | |
| 		Action:      "publish",
 | |
| 		Description: "Publish tasks to queues",
 | |
| 		CreatedAt:   time.Now(),
 | |
| 	})
 | |
| 
 | |
| 	rm.AddPermission(&Permission{
 | |
| 		Name:        "task.consume",
 | |
| 		Resource:    "task",
 | |
| 		Action:      "consume",
 | |
| 		Description: "Consume tasks from queues",
 | |
| 		CreatedAt:   time.Now(),
 | |
| 	})
 | |
| 
 | |
| 	rm.AddPermission(&Permission{
 | |
| 		Name:        "queue.manage",
 | |
| 		Resource:    "queue",
 | |
| 		Action:      "manage",
 | |
| 		Description: "Manage queues",
 | |
| 		CreatedAt:   time.Now(),
 | |
| 	})
 | |
| 
 | |
| 	rm.AddPermission(&Permission{
 | |
| 		Name:        "admin.system",
 | |
| 		Resource:    "system",
 | |
| 		Action:      "admin",
 | |
| 		Description: "System administration",
 | |
| 		CreatedAt:   time.Now(),
 | |
| 	})
 | |
| 
 | |
| 	// Initialize default roles
 | |
| 	rm.AddRole(&Role{
 | |
| 		Name:        "publisher",
 | |
| 		Description: "Can publish tasks",
 | |
| 		Permissions: []string{"task.publish"},
 | |
| 		CreatedAt:   time.Now(),
 | |
| 	})
 | |
| 
 | |
| 	rm.AddRole(&Role{
 | |
| 		Name:        "consumer",
 | |
| 		Description: "Can consume tasks",
 | |
| 		Permissions: []string{"task.consume"},
 | |
| 		CreatedAt:   time.Now(),
 | |
| 	})
 | |
| 
 | |
| 	rm.AddRole(&Role{
 | |
| 		Name:        "admin",
 | |
| 		Description: "Full system access",
 | |
| 		Permissions: []string{"task.publish", "task.consume", "queue.manage", "admin.system"},
 | |
| 		CreatedAt:   time.Now(),
 | |
| 	})
 | |
| 
 | |
| 	return rm
 | |
| }
 | |
| 
 | |
| // AddPermission adds a permission to the role manager
 | |
| func (rm *RoleManager) AddPermission(perm *Permission) {
 | |
| 	rm.mu.Lock()
 | |
| 	defer rm.mu.Unlock()
 | |
| 	rm.permissions[perm.Name] = perm
 | |
| }
 | |
| 
 | |
| // AddRole adds a role to the role manager
 | |
| func (rm *RoleManager) AddRole(role *Role) {
 | |
| 	rm.mu.Lock()
 | |
| 	defer rm.mu.Unlock()
 | |
| 	rm.roles[role.Name] = 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 {
 | |
| 		if role, exists := rm.roles[roleName]; exists {
 | |
| 			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 {
 | |
| 		if role, exists := rm.roles[roleName]; exists {
 | |
| 			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)
 | |
| }
 | |
| 
 | |
| // 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 {
 | |
| 	users map[string]*User
 | |
| 	mu    sync.RWMutex
 | |
| }
 | |
| 
 | |
| func NewBasicAuthProvider() *BasicAuthProvider {
 | |
| 	return &BasicAuthProvider{
 | |
| 		users: make(map[string]*User),
 | |
| 	}
 | |
| }
 | |
| 
 | |
| 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")
 | |
| 	}
 | |
| 
 | |
| 	bap.mu.RLock()
 | |
| 	user, exists := bap.users[username]
 | |
| 	bap.mu.RUnlock()
 | |
| 
 | |
| 	if !exists {
 | |
| 		return nil, fmt.Errorf("user not found")
 | |
| 	}
 | |
| 
 | |
| 	// In production, compare hashed passwords
 | |
| 	if password != "password" { // Placeholder
 | |
| 		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 {
 | |
| 	bap.mu.Lock()
 | |
| 	defer bap.mu.Unlock()
 | |
| 
 | |
| 	// In production, hash the password
 | |
| 	user.CreatedAt = time.Now()
 | |
| 	bap.users[user.Username] = user
 | |
| 
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // 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
 | |
| }
 | 
