Files
bzzz/pkg/crypto/access_control.go
anthonyrawlins baac16d372 Fix dependency issues and achieve buildable state
MAJOR BREAKTHROUGH - BZZZ now compiles past structural issues!

DEPENDENCY RESOLUTION:
• Added missing dependencies: bleve, redis, cron, openai packages
• Fixed go.mod/go.sum conflicts with updated crypto packages
• Resolved all golang.org/x package version conflicts

TYPE SYSTEM FIXES:
• Fixed corrupted pkg/agentid/crypto.go (missing package declaration)
• Updated KeyRotationResult types to use slurpRoles.KeyRotationResult
• Fixed AccessControlMatrix field mismatches (roleHierarchy as map vs struct)
• Corrected RoleEncryptionConfig field access (EncryptionKeys not Keys)
• Updated RoleKey types to use proper qualified names

CODE ORGANIZATION:
• Moved test/chat_api_handler.go → cmd/chat-api/main.go (resolved package conflicts)
• Cleaned up unused imports across crypto package files
• Commented out problematic audit logger sections (temporary)
• Fixed brace mismatch in GetSecurityMetrics function

BUILD STATUS IMPROVEMENT:
• BEFORE: Import cycle errors preventing any compilation
• AFTER: Clean compilation through crypto package, now hitting DHT API issues
• This represents moving from structural blockers to routine API compatibility fixes

SIGNIFICANCE:
This commit represents the successful resolution of all major architectural
blocking issues. The codebase now compiles through the core crypto systems
and only has remaining API compatibility issues in peripheral packages.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-17 10:22:03 +10:00

1410 lines
53 KiB
Go

// Package crypto provides sophisticated access control enforcement for role-based encryption.
//
// This module implements enterprise-grade access control with features including:
// - Dynamic access control matrices with real-time policy evaluation
// - Context-aware authorization decisions
// - Hierarchical role inheritance and delegation
// - Attribute-based access control (ABAC) integration
// - Zero-trust security model implementation
// - Real-time access monitoring and enforcement
//
// Security Features:
// - Multi-factor authentication integration
// - Just-in-time (JIT) access provisioning
// - Least privilege principle enforcement
// - Break-glass emergency access procedures
// - Compliance with RBAC, ABAC, and ReBAC models
//
// Cross-references:
// - pkg/crypto/role_crypto.go: Role-based encryption implementation
// - pkg/crypto/audit_logger.go: Access logging and monitoring
// - pkg/slurp/roles/types.go: Role definitions and permissions
package crypto
import (
"context"
"fmt"
"strings"
"sync"
"time"
"chorus.services/bzzz/pkg/config"
"chorus.services/bzzz/pkg/security"
)
// AccessControlMatrix implements sophisticated access control enforcement
type AccessControlMatrix struct {
mu sync.RWMutex
config *config.Config
policyEngine PolicyEngine
roleHierarchy *RoleHierarchy
attributeProvider AttributeProvider
auditLogger AuditLogger
// Legacy fields for compatibility
accessLevels map[string]security.AccessLevel
compartments map[string][]string
// Dynamic policy management
policies map[string]*AccessPolicy
rolePermissions map[string]*RolePermissions
resourcePermissions map[string]*ResourcePermissions
contextualPolicies map[string]*ContextualPolicy
// Enforcement state
activeEnforcement bool
enforcementMode EnforcementMode
bypassTokens map[string]*BypassToken
emergencyAccess *EmergencyAccessManager
// Performance optimization
decisionCache *AccessDecisionCache
policyCache *PolicyCache
evaluationMetrics *EvaluationMetrics
}
// PolicyEngine interface for policy evaluation
type PolicyEngine interface {
EvaluatePolicy(ctx context.Context, request *AccessRequest) (*PolicyDecision, error)
CompilePolicy(policy *AccessPolicy) (*CompiledPolicy, error)
ValidatePolicy(policy *AccessPolicy) (*PolicyValidationResult, error)
LoadPolicies(policies []*AccessPolicy) error
ReloadPolicies() error
}
// AttributeProvider interface for attribute resolution
type AttributeProvider interface {
GetUserAttributes(userID string) (*UserAttributes, error)
GetResourceAttributes(resource string) (*ResourceAttributes, error)
GetEnvironmentAttributes() (*EnvironmentAttributes, error)
GetContextAttributes(ctx context.Context) (*ContextAttributes, error)
}
// RoleHierarchy manages role inheritance and delegation
type RoleHierarchy struct {
mu sync.RWMutex
roles map[string]*Role
hierarchy map[string][]string // Parent -> Children
inheritance map[string][]string // Child -> Parents
delegations map[string]*Delegation
temporaryRoles map[string]*TemporaryRole
roleConstraints map[string]*RoleConstraints
}
// Role represents a role with comprehensive metadata
type Role struct {
ID string `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
Type RoleType `json:"type"`
Status RoleStatus `json:"status"`
// Hierarchy
ParentRoles []string `json:"parent_roles"`
ChildRoles []string `json:"child_roles"`
DelegatedRoles []string `json:"delegated_roles"`
// Permissions
DirectPermissions []string `json:"direct_permissions"`
InheritedPermissions []string `json:"inherited_permissions"`
DeniedPermissions []string `json:"denied_permissions"`
// Constraints
MaxUsers *int `json:"max_users,omitempty"`
RequiresMFA bool `json:"requires_mfa"`
SessionTimeout *time.Duration `json:"session_timeout,omitempty"`
IPRestrictions []string `json:"ip_restrictions"`
TimeRestrictions *TimeRestrictions `json:"time_restrictions,omitempty"`
LocationRestrictions []*LocationRestriction `json:"location_restrictions,omitempty"`
// Lifecycle
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
CreatedBy string `json:"created_by"`
ExpiresAt *time.Time `json:"expires_at,omitempty"`
// Metadata
Tags []string `json:"tags"`
Metadata map[string]interface{} `json:"metadata"`
}
// RoleType represents different types of roles
type RoleType string
const (
RoleTypeStandard RoleType = "standard" // Standard role
RoleTypeService RoleType = "service" // Service account role
RoleTypeTemporary RoleType = "temporary" // Temporary role
RoleTypeDelegated RoleType = "delegated" // Delegated role
RoleTypeEmergency RoleType = "emergency" // Emergency access role
)
// RoleStatus represents the status of a role
type RoleStatus string
const (
RoleStatusActive RoleStatus = "active" // Role is active and usable
RoleStatusInactive RoleStatus = "inactive" // Role is inactive
RoleStatusSuspended RoleStatus = "suspended" // Role is temporarily suspended
RoleStatusRevoked RoleStatus = "revoked" // Role has been revoked
RoleStatusPending RoleStatus = "pending" // Role is pending approval
)
// TimeRestrictions represents time-based access restrictions
type TimeRestrictions struct {
AllowedHours []int `json:"allowed_hours"` // 0-23 allowed hours
AllowedDays []time.Weekday `json:"allowed_days"` // Allowed days of week
AllowedTimeZone string `json:"allowed_timezone"` // Timezone for restrictions
StartDate *time.Time `json:"start_date"` // Role start date
EndDate *time.Time `json:"end_date"` // Role end date
}
// Delegation represents role delegation
type Delegation struct {
DelegationID string `json:"delegation_id"`
DelegatorID string `json:"delegator_id"`
DelegateeID string `json:"delegatee_id"`
DelegatedRoles []string `json:"delegated_roles"`
Permissions []string `json:"permissions"`
Constraints *DelegationConstraints `json:"constraints"`
Status DelegationStatus `json:"status"`
CreatedAt time.Time `json:"created_at"`
ExpiresAt time.Time `json:"expires_at"`
RevokedAt *time.Time `json:"revoked_at,omitempty"`
RevokedBy string `json:"revoked_by,omitempty"`
}
// DelegationStatus represents delegation status
type DelegationStatus string
const (
DelegationStatusActive DelegationStatus = "active"
DelegationStatusExpired DelegationStatus = "expired"
DelegationStatusRevoked DelegationStatus = "revoked"
DelegationStatusSuspended DelegationStatus = "suspended"
)
// DelegationConstraints defines constraints on delegation
type DelegationConstraints struct {
MaxDelegationDepth int `json:"max_delegation_depth"`
RequireApproval bool `json:"require_approval"`
Approvers []string `json:"approvers"`
CanSubDelegate bool `json:"can_sub_delegate"`
UsageLimit *int `json:"usage_limit,omitempty"`
IPRestrictions []string `json:"ip_restrictions"`
TimeRestrictions *TimeRestrictions `json:"time_restrictions,omitempty"`
}
// TemporaryRole represents a temporary role assignment
type TemporaryRole struct {
TemporaryRoleID string `json:"temporary_role_id"`
UserID string `json:"user_id"`
RoleID string `json:"role_id"`
Justification string `json:"justification"`
RequestedBy string `json:"requested_by"`
ApprovedBy string `json:"approved_by"`
GrantedAt time.Time `json:"granted_at"`
ExpiresAt time.Time `json:"expires_at"`
AutoExtend bool `json:"auto_extend"`
MaxExtensions int `json:"max_extensions"`
ExtensionCount int `json:"extension_count"`
Status TemporaryRoleStatus `json:"status"`
UsageTracking *UsageTracking `json:"usage_tracking"`
}
// TemporaryRoleStatus represents temporary role status
type TemporaryRoleStatus string
const (
TemporaryRoleStatusPending TemporaryRoleStatus = "pending"
TemporaryRoleStatusActive TemporaryRoleStatus = "active"
TemporaryRoleStatusExpired TemporaryRoleStatus = "expired"
TemporaryRoleStatusRevoked TemporaryRoleStatus = "revoked"
TemporaryRoleStatusExtended TemporaryRoleStatus = "extended"
)
// UsageTracking tracks usage of temporary roles
type UsageTracking struct {
FirstUsed *time.Time `json:"first_used,omitempty"`
LastUsed *time.Time `json:"last_used,omitempty"`
UsageCount int `json:"usage_count"`
AccessedResources []string `json:"accessed_resources"`
PerformedActions []string `json:"performed_actions"`
UnusualActivity []string `json:"unusual_activity"`
}
// RoleConstraints defines constraints on role usage
type RoleConstraints struct {
RoleID string `json:"role_id"`
ConcurrentSessions *int `json:"concurrent_sessions,omitempty"`
DailyUsageLimit *int `json:"daily_usage_limit,omitempty"`
MonthlyUsageLimit *int `json:"monthly_usage_limit,omitempty"`
ResourceQuotas map[string]int `json:"resource_quotas"`
ActionLimits map[string]int `json:"action_limits"`
RequiredApprovals []*ApprovalRequirement `json:"required_approvals"`
SeparationOfDuties []string `json:"separation_of_duties"`
}
// ApprovalRequirement defines approval requirements
type ApprovalRequirement struct {
Action string `json:"action"`
ResourcePattern string `json:"resource_pattern"`
RequiredApprovers int `json:"required_approvers"`
ApproverRoles []string `json:"approver_roles"`
TimeLimit time.Duration `json:"time_limit"`
AutoApprove bool `json:"auto_approve"`
}
// LocationRestriction defines location-based restrictions
type LocationRestriction struct {
Type string `json:"type"` // allow, deny
Countries []string `json:"countries,omitempty"`
Regions []string `json:"regions,omitempty"`
Cities []string `json:"cities,omitempty"`
IPRanges []string `json:"ip_ranges,omitempty"`
GeofenceRadius *float64 `json:"geofence_radius,omitempty"`
GeofenceCenter *GeoPoint `json:"geofence_center,omitempty"`
}
// GeoPoint represents a geographical point
type GeoPoint struct {
Latitude float64 `json:"latitude"`
Longitude float64 `json:"longitude"`
}
// AccessPolicy represents a comprehensive access policy
type AccessPolicy struct {
PolicyID string `json:"policy_id"`
Name string `json:"name"`
Description string `json:"description"`
Type PolicyType `json:"type"`
Status PolicyStatus `json:"status"`
// Policy structure
Rules []*PolicyRule `json:"rules"`
Conditions []*PolicyCondition `json:"conditions"`
Effects []*PolicyEffect `json:"effects"`
Obligations []*PolicyObligation `json:"obligations"`
// Targeting
Subjects []*PolicySubject `json:"subjects"`
Resources []*PolicyResource `json:"resources"`
Actions []*PolicyAction `json:"actions"`
Environment []*PolicyEnvironment `json:"environment"`
// Metadata
Priority int `json:"priority"`
Version string `json:"version"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
CreatedBy string `json:"created_by"`
ApprovedBy string `json:"approved_by"`
Tags []string `json:"tags"`
Metadata map[string]interface{} `json:"metadata"`
}
// PolicyType represents different types of policies
type PolicyType string
const (
PolicyTypeRBAC PolicyType = "rbac" // Role-based access control
PolicyTypeABAC PolicyType = "abac" // Attribute-based access control
PolicyTypeReBAC PolicyType = "rebac" // Relationship-based access control
PolicyTypeCustom PolicyType = "custom" // Custom policy logic
)
// PolicyStatus represents policy status
type PolicyStatus string
const (
PolicyStatusDraft PolicyStatus = "draft"
PolicyStatusActive PolicyStatus = "active"
PolicyStatusInactive PolicyStatus = "inactive"
PolicyStatusArchived PolicyStatus = "archived"
)
// PolicyRule represents a single policy rule
type PolicyRule struct {
RuleID string `json:"rule_id"`
Name string `json:"name"`
Description string `json:"description"`
Condition string `json:"condition"` // CEL expression
Effect RuleEffect `json:"effect"`
Priority int `json:"priority"`
Enabled bool `json:"enabled"`
Metadata map[string]interface{} `json:"metadata"`
}
// RuleEffect represents the effect of a policy rule
type RuleEffect string
const (
RuleEffectPermit RuleEffect = "permit"
RuleEffectDeny RuleEffect = "deny"
RuleEffectAbstain RuleEffect = "abstain"
)
// PolicyCondition represents a policy condition
type PolicyCondition struct {
ConditionID string `json:"condition_id"`
Type string `json:"type"`
Expression string `json:"expression"`
Parameters map[string]interface{} `json:"parameters"`
Negated bool `json:"negated"`
}
// PolicyEffect represents a policy effect
type PolicyEffect struct {
EffectID string `json:"effect_id"`
Type string `json:"type"`
Action string `json:"action"`
Parameters map[string]interface{} `json:"parameters"`
Required bool `json:"required"`
}
// PolicyObligation represents a policy obligation
type PolicyObligation struct {
ObligationID string `json:"obligation_id"`
Type string `json:"type"`
Action string `json:"action"`
Parameters map[string]interface{} `json:"parameters"`
FulfillmentType string `json:"fulfillment_type"` // before, after, ongoing
Required bool `json:"required"`
}
// PolicySubject represents a policy subject
type PolicySubject struct {
Type string `json:"type"` // user, role, group
Identifier string `json:"identifier"`
Attributes map[string]interface{} `json:"attributes"`
}
// PolicyResource represents a policy resource
type PolicyResource struct {
Type string `json:"type"`
Pattern string `json:"pattern"`
Attributes map[string]interface{} `json:"attributes"`
}
// PolicyAction represents a policy action
type PolicyAction struct {
Type string `json:"type"`
Pattern string `json:"pattern"`
Attributes map[string]interface{} `json:"attributes"`
}
// PolicyEnvironment represents environmental conditions
type PolicyEnvironment struct {
Type string `json:"type"`
Condition string `json:"condition"`
Value interface{} `json:"value"`
}
// ContextualPolicy represents context-aware policies
type ContextualPolicy struct {
PolicyID string `json:"policy_id"`
ContextType string `json:"context_type"`
ContextPattern string `json:"context_pattern"`
AdaptiveRules []*AdaptiveRule `json:"adaptive_rules"`
RiskProfile *RiskProfile `json:"risk_profile"`
LearningEnabled bool `json:"learning_enabled"`
LastUpdated time.Time `json:"last_updated"`
}
// AdaptiveRule represents rules that adapt based on context
type AdaptiveRule struct {
RuleID string `json:"rule_id"`
TriggerCondition string `json:"trigger_condition"`
Adaptation string `json:"adaptation"`
ConfidenceThreshold float64 `json:"confidence_threshold"`
LearningRate float64 `json:"learning_rate"`
RecentAccuracy float64 `json:"recent_accuracy"`
}
// RiskProfile represents a risk profile for contextual decisions
type RiskProfile struct {
ProfileID string `json:"profile_id"`
BaselineRisk float64 `json:"baseline_risk"`
RiskFactors []*RiskFactor `json:"risk_factors"`
MitigationStrategies []*MitigationStrategy `json:"mitigation_strategies"`
UpdatedAt time.Time `json:"updated_at"`
}
// MitigationStrategy represents a risk mitigation strategy
type MitigationStrategy struct {
StrategyID string `json:"strategy_id"`
Type string `json:"type"`
Effectiveness float64 `json:"effectiveness"`
Cost float64 `json:"cost"`
Implementation string `json:"implementation"`
}
// AccessRequest represents a comprehensive access request
type AccessRequest struct {
RequestID string `json:"request_id"`
Timestamp time.Time `json:"timestamp"`
// Subject
UserID string `json:"user_id"`
Roles []string `json:"roles"`
Groups []string `json:"groups"`
UserAttributes *UserAttributes `json:"user_attributes"`
// Resource
Resource string `json:"resource"`
ResourceType string `json:"resource_type"`
ResourceAttributes *ResourceAttributes `json:"resource_attributes"`
// Action
Action string `json:"action"`
ActionType string `json:"action_type"`
ActionAttributes map[string]interface{} `json:"action_attributes"`
// Context
Context context.Context `json:"-"`
ContextAttributes *ContextAttributes `json:"context_attributes"`
EnvironmentAttributes *EnvironmentAttributes `json:"environment_attributes"`
// Security context
SessionID string `json:"session_id"`
IPAddress string `json:"ip_address"`
UserAgent string `json:"user_agent"`
GeoLocation *GeoLocation `json:"geo_location,omitempty"`
ThreatIntelligence *ThreatIntelData `json:"threat_intelligence,omitempty"`
// Request metadata
Priority int `json:"priority"`
Urgency string `json:"urgency"`
Justification string `json:"justification"`
Metadata map[string]interface{} `json:"metadata"`
}
// UserAttributes represents user attributes for ABAC
type UserAttributes struct {
UserID string `json:"user_id"`
Department string `json:"department"`
Title string `json:"title"`
Manager string `json:"manager"`
ClearanceLevel string `json:"clearance_level"`
Certifications []string `json:"certifications"`
Projects []string `json:"projects"`
EmploymentType string `json:"employment_type"`
StartDate time.Time `json:"start_date"`
Location string `json:"location"`
CostCenter string `json:"cost_center"`
CustomAttributes map[string]interface{} `json:"custom_attributes"`
}
// ResourceAttributes represents resource attributes for ABAC
type ResourceAttributes struct {
ResourceID string `json:"resource_id"`
Classification string `json:"classification"`
Owner string `json:"owner"`
DataType string `json:"data_type"`
Sensitivity string `json:"sensitivity"`
Retention string `json:"retention"`
Location string `json:"location"`
Tags []string `json:"tags"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
CustomAttributes map[string]interface{} `json:"custom_attributes"`
}
// ContextAttributes represents contextual attributes
type ContextAttributes struct {
RequestType string `json:"request_type"`
ApplicationContext string `json:"application_context"`
BusinessContext string `json:"business_context"`
TechnicalContext string `json:"technical_context"`
ComplianceContext string `json:"compliance_context"`
RiskContext string `json:"risk_context"`
CustomAttributes map[string]interface{} `json:"custom_attributes"`
}
// EnvironmentAttributes represents environmental attributes
type EnvironmentAttributes struct {
CurrentTime time.Time `json:"current_time"`
BusinessHours bool `json:"business_hours"`
NetworkZone string `json:"network_zone"`
DeviceType string `json:"device_type"`
DeviceTrust string `json:"device_trust"`
ConnectionType string `json:"connection_type"`
ThreatLevel string `json:"threat_level"`
ComplianceMode string `json:"compliance_mode"`
MaintenanceMode bool `json:"maintenance_mode"`
CustomAttributes map[string]interface{} `json:"custom_attributes"`
}
// PolicyDecision represents the result of policy evaluation
type PolicyDecision struct {
RequestID string `json:"request_id"`
Decision DecisionResult `json:"decision"`
Reason string `json:"reason"`
MatchedPolicies []string `json:"matched_policies"`
AppliedRules []string `json:"applied_rules"`
Obligations []*PolicyObligation `json:"obligations"`
Conditions []string `json:"conditions"`
// Decision metadata
ConfidenceScore float64 `json:"confidence_score"`
RiskScore float64 `json:"risk_score"`
EvaluationTime time.Duration `json:"evaluation_time"`
CacheHit bool `json:"cache_hit"`
// Additional information
Advice []string `json:"advice"`
Warnings []string `json:"warnings"`
Recommendations []string `json:"recommendations"`
// Timestamps
EvaluatedAt time.Time `json:"evaluated_at"`
ValidUntil *time.Time `json:"valid_until,omitempty"`
// Metadata
Metadata map[string]interface{} `json:"metadata"`
}
// CompiledPolicy represents a compiled policy for efficient evaluation
type CompiledPolicy struct {
PolicyID string `json:"policy_id"`
CompiledRules []*CompiledRule `json:"compiled_rules"`
OptimizedConditions []*OptimizedCondition `json:"optimized_conditions"`
CompiledAt time.Time `json:"compiled_at"`
CompilerVersion string `json:"compiler_version"`
CacheKey string `json:"cache_key"`
}
// CompiledRule represents a compiled policy rule
type CompiledRule struct {
RuleID string `json:"rule_id"`
CompiledExpression interface{} `json:"compiled_expression"`
Dependencies []string `json:"dependencies"`
EstimatedCost int `json:"estimated_cost"`
}
// OptimizedCondition represents an optimized condition
type OptimizedCondition struct {
ConditionID string `json:"condition_id"`
OptimizedExpression interface{} `json:"optimized_expression"`
IndexHints []string `json:"index_hints"`
ShortCircuit bool `json:"short_circuit"`
}
// PolicyValidationResult represents policy validation results
type PolicyValidationResult struct {
Valid bool `json:"valid"`
Errors []string `json:"errors"`
Warnings []string `json:"warnings"`
Suggestions []string `json:"suggestions"`
ValidatedAt time.Time `json:"validated_at"`
ValidationTime time.Duration `json:"validation_time"`
}
// EnforcementMode represents different enforcement modes
type EnforcementMode string
const (
EnforcementModeStrict EnforcementMode = "strict" // Strict enforcement
EnforcementModeMonitor EnforcementMode = "monitor" // Monitor only
EnforcementModeBypass EnforcementMode = "bypass" // Bypass enforcement
)
// BypassToken represents a temporary bypass token
type BypassToken struct {
TokenID string `json:"token_id"`
CreatedBy string `json:"created_by"`
CreatedAt time.Time `json:"created_at"`
ExpiresAt time.Time `json:"expires_at"`
Reason string `json:"reason"`
Scope []string `json:"scope"`
UsageCount int `json:"usage_count"`
MaxUsage int `json:"max_usage"`
Status BypassTokenStatus `json:"status"`
}
// BypassTokenStatus represents bypass token status
type BypassTokenStatus string
const (
BypassTokenStatusActive BypassTokenStatus = "active"
BypassTokenStatusExpired BypassTokenStatus = "expired"
BypassTokenStatusRevoked BypassTokenStatus = "revoked"
BypassTokenStatusExhausted BypassTokenStatus = "exhausted"
)
// EmergencyAccessManager manages emergency access procedures
type EmergencyAccessManager struct {
mu sync.RWMutex
emergencyProcedures map[string]*EmergencyProcedure
breakGlassAccess map[string]*BreakGlassAccess
emergencyContacts []*EmergencyContact
}
// EmergencyProcedure defines emergency access procedures
type EmergencyProcedure struct {
ProcedureID string `json:"procedure_id"`
Name string `json:"name"`
TriggerConditions []string `json:"trigger_conditions"`
AuthorizedRoles []string `json:"authorized_roles"`
RequiredApprovals int `json:"required_approvals"`
TimeLimit time.Duration `json:"time_limit"`
AutoRevoke bool `json:"auto_revoke"`
NotificationRules []*NotificationRule `json:"notification_rules"`
AuditRequirements *AuditRequirements `json:"audit_requirements"`
}
// BreakGlassAccess represents break-glass emergency access
type BreakGlassAccess struct {
AccessID string `json:"access_id"`
UserID string `json:"user_id"`
ProcedureID string `json:"procedure_id"`
Justification string `json:"justification"`
ActivatedAt time.Time `json:"activated_at"`
ExpiresAt time.Time `json:"expires_at"`
ApprovedBy []string `json:"approved_by"`
Status BreakGlassStatus `json:"status"`
GrantedPermissions []string `json:"granted_permissions"`
UsageLog []*EmergencyUsageEntry `json:"usage_log"`
}
// BreakGlassStatus represents break-glass access status
type BreakGlassStatus string
const (
BreakGlassStatusActive BreakGlassStatus = "active"
BreakGlassStatusExpired BreakGlassStatus = "expired"
BreakGlassStatusRevoked BreakGlassStatus = "revoked"
BreakGlassStatusUsed BreakGlassStatus = "used"
)
// EmergencyUsageEntry represents usage of emergency access
type EmergencyUsageEntry struct {
EntryID string `json:"entry_id"`
Timestamp time.Time `json:"timestamp"`
Action string `json:"action"`
Resource string `json:"resource"`
Result string `json:"result"`
Justification string `json:"justification"`
WitnessedBy string `json:"witnessed_by,omitempty"`
}
// EmergencyContact represents emergency contact information
type EmergencyContact struct {
ContactID string `json:"contact_id"`
Name string `json:"name"`
Role string `json:"role"`
Email string `json:"email"`
Phone string `json:"phone"`
Availability string `json:"availability"`
EscalationLevel int `json:"escalation_level"`
}
// AuditRequirements defines audit requirements for emergency access
type AuditRequirements struct {
RealTimeLogging bool `json:"real_time_logging"`
VideoRecording bool `json:"video_recording"`
WitnessRequired bool `json:"witness_required"`
DetailedJustification bool `json:"detailed_justification"`
PostAccessReview bool `json:"post_access_review"`
RetentionPeriod time.Duration `json:"retention_period"`
}
// AccessDecisionCache provides caching for access decisions
type AccessDecisionCache struct {
mu sync.RWMutex
cache map[string]*CachedDecision
ttl time.Duration
maxSize int
hitCount int64
missCount int64
}
// CachedDecision represents a cached access decision
type CachedDecision struct {
Decision *PolicyDecision `json:"decision"`
CreatedAt time.Time `json:"created_at"`
ExpiresAt time.Time `json:"expires_at"`
AccessCount int `json:"access_count"`
LastAccessed time.Time `json:"last_accessed"`
}
// PolicyCache provides caching for compiled policies
type PolicyCache struct {
mu sync.RWMutex
compiledPolicies map[string]*CompiledPolicy
validationResults map[string]*PolicyValidationResult
lastUpdate time.Time
}
// EvaluationMetrics tracks policy evaluation performance
type EvaluationMetrics struct {
mu sync.RWMutex
totalEvaluations int64
successfulEvaluations int64
failedEvaluations int64
averageLatency time.Duration
peakLatency time.Duration
cacheHitRate float64
policyHitCounts map[string]int64
lastReset time.Time
}
// RolePermissions represents permissions for a specific role
type RolePermissions struct {
RoleID string `json:"role_id"`
DirectPermissions []string `json:"direct_permissions"`
InheritedPermissions []string `json:"inherited_permissions"`
EffectivePermissions []string `json:"effective_permissions"`
DeniedPermissions []string `json:"denied_permissions"`
ComputedAt time.Time `json:"computed_at"`
ValidUntil time.Time `json:"valid_until"`
}
// ResourcePermissions represents permissions for a specific resource
type ResourcePermissions struct {
ResourceID string `json:"resource_id"`
OwnerPermissions []string `json:"owner_permissions"`
RolePermissions map[string][]string `json:"role_permissions"`
UserPermissions map[string][]string `json:"user_permissions"`
PublicPermissions []string `json:"public_permissions"`
InheritedFrom string `json:"inherited_from,omitempty"`
ComputedAt time.Time `json:"computed_at"`
ValidUntil time.Time `json:"valid_until"`
}
// NewAccessControlMatrix creates a new access control matrix
func NewAccessControlMatrix(cfg *config.Config, policyEngine PolicyEngine, attributeProvider AttributeProvider, auditLogger AuditLogger) (*AccessControlMatrix, error) {
acm := &AccessControlMatrix{
config: cfg,
policyEngine: policyEngine,
attributeProvider: attributeProvider,
auditLogger: auditLogger,
policies: make(map[string]*AccessPolicy),
rolePermissions: make(map[string]*RolePermissions),
resourcePermissions: make(map[string]*ResourcePermissions),
contextualPolicies: make(map[string]*ContextualPolicy),
bypassTokens: make(map[string]*BypassToken),
activeEnforcement: true,
enforcementMode: EnforcementModeStrict,
}
// Initialize role hierarchy
roleHierarchy, err := NewRoleHierarchy(cfg)
if err != nil {
return nil, fmt.Errorf("failed to initialize role hierarchy: %w", err)
}
acm.roleHierarchy = roleHierarchy
// Initialize emergency access manager
acm.emergencyAccess = &EmergencyAccessManager{
emergencyProcedures: make(map[string]*EmergencyProcedure),
breakGlassAccess: make(map[string]*BreakGlassAccess),
emergencyContacts: []*EmergencyContact{},
}
// Initialize caches
acm.decisionCache = &AccessDecisionCache{
cache: make(map[string]*CachedDecision),
ttl: 5 * time.Minute,
maxSize: 10000,
}
acm.policyCache = &PolicyCache{
compiledPolicies: make(map[string]*CompiledPolicy),
validationResults: make(map[string]*PolicyValidationResult),
lastUpdate: time.Now(),
}
acm.evaluationMetrics = &EvaluationMetrics{
policyHitCounts: make(map[string]int64),
lastReset: time.Now(),
}
// Load default policies
if err := acm.loadDefaultPolicies(); err != nil {
return nil, fmt.Errorf("failed to load default policies: %w", err)
}
return acm, nil
}
// NewRoleHierarchy creates a new role hierarchy
func NewRoleHierarchy(cfg *config.Config) (*RoleHierarchy, error) {
rh := &RoleHierarchy{
roles: make(map[string]*Role),
hierarchy: make(map[string][]string),
inheritance: make(map[string][]string),
delegations: make(map[string]*Delegation),
temporaryRoles: make(map[string]*TemporaryRole),
roleConstraints: make(map[string]*RoleConstraints),
}
// Load predefined roles from configuration
predefinedRoles := config.GetPredefinedRoles()
for roleID, configRole := range predefinedRoles {
role := &Role{
ID: roleID,
Name: configRole.Name,
Description: configRole.Name, // Use Name as Description since Description field doesn't exist
Type: RoleTypeStandard,
Status: RoleStatusActive,
DirectPermissions: []string{},
InheritedPermissions: []string{},
DeniedPermissions: []string{},
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
Tags: []string{},
Metadata: make(map[string]interface{}),
}
// Convert config permissions to role permissions
for _, permission := range configRole.CanDecrypt {
role.DirectPermissions = append(role.DirectPermissions, fmt.Sprintf("decrypt:%s", permission))
}
rh.roles[roleID] = role
// Set up hierarchy based on CanDecrypt relationships
if len(configRole.CanDecrypt) > 0 {
rh.hierarchy[roleID] = configRole.CanDecrypt
for _, childRole := range configRole.CanDecrypt {
rh.inheritance[childRole] = append(rh.inheritance[childRole], roleID)
}
}
}
return rh, nil
}
// CheckAccess performs comprehensive access control evaluation
func (acm *AccessControlMatrix) CheckAccess(ctx context.Context, request *AccessRequest) (*PolicyDecision, error) {
startTime := time.Now()
acm.evaluationMetrics.mu.Lock()
acm.evaluationMetrics.totalEvaluations++
acm.evaluationMetrics.mu.Unlock()
// Generate cache key
cacheKey := acm.generateCacheKey(request)
// Check decision cache
if cachedDecision := acm.getCachedDecision(cacheKey); cachedDecision != nil {
acm.evaluationMetrics.mu.Lock()
acm.evaluationMetrics.cacheHitRate = float64(acm.decisionCache.hitCount) / float64(acm.evaluationMetrics.totalEvaluations)
acm.evaluationMetrics.mu.Unlock()
cachedDecision.CacheHit = true
return cachedDecision, nil
}
// Check enforcement mode
if acm.enforcementMode == EnforcementModeBypass {
decision := &PolicyDecision{
RequestID: request.RequestID,
Decision: DecisionPermit,
Reason: "Enforcement bypassed",
EvaluationTime: time.Since(startTime),
EvaluatedAt: time.Now(),
}
return decision, nil
}
// Check bypass tokens
if bypassToken := acm.checkBypassToken(request); bypassToken != nil {
decision := &PolicyDecision{
RequestID: request.RequestID,
Decision: DecisionPermit,
Reason: fmt.Sprintf("Bypass token %s used", bypassToken.TokenID),
EvaluationTime: time.Since(startTime),
EvaluatedAt: time.Now(),
}
acm.consumeBypassToken(bypassToken)
return decision, nil
}
// Enrich request with attributes
enrichedRequest, err := acm.enrichRequest(request)
if err != nil {
return nil, fmt.Errorf("failed to enrich request: %w", err)
}
// Evaluate policies
decision, err := acm.policyEngine.EvaluatePolicy(ctx, enrichedRequest)
if err != nil {
acm.evaluationMetrics.mu.Lock()
acm.evaluationMetrics.failedEvaluations++
acm.evaluationMetrics.mu.Unlock()
return nil, fmt.Errorf("policy evaluation failed: %w", err)
}
// Apply contextual policies
decision, err = acm.applyContextualPolicies(ctx, enrichedRequest, decision)
if err != nil {
return nil, fmt.Errorf("contextual policy application failed: %w", err)
}
// Calculate risk score
decision.RiskScore = acm.calculateRiskScore(enrichedRequest, decision)
// Apply additional constraints
decision = acm.applyRoleConstraints(enrichedRequest, decision)
// Finalize decision
decision.EvaluationTime = time.Since(startTime)
decision.EvaluatedAt = time.Now()
// Cache decision
acm.cacheDecision(cacheKey, decision)
// Update metrics
acm.evaluationMetrics.mu.Lock()
acm.evaluationMetrics.successfulEvaluations++
if decision.EvaluationTime > acm.evaluationMetrics.peakLatency {
acm.evaluationMetrics.peakLatency = decision.EvaluationTime
}
acm.evaluationMetrics.averageLatency = ((acm.evaluationMetrics.averageLatency * time.Duration(acm.evaluationMetrics.successfulEvaluations-1)) + decision.EvaluationTime) / time.Duration(acm.evaluationMetrics.successfulEvaluations)
acm.evaluationMetrics.mu.Unlock()
// Log access decision
acm.logAccessDecision(enrichedRequest, decision)
return decision, nil
}
// generateCacheKey generates a cache key for the request
func (acm *AccessControlMatrix) generateCacheKey(request *AccessRequest) string {
key := fmt.Sprintf("%s:%s:%s:%s:%s",
request.UserID,
strings.Join(request.Roles, ","),
request.Resource,
request.Action,
request.IPAddress)
return key
}
// getCachedDecision retrieves a cached decision
func (acm *AccessControlMatrix) getCachedDecision(cacheKey string) *PolicyDecision {
acm.decisionCache.mu.RLock()
defer acm.decisionCache.mu.RUnlock()
cached, exists := acm.decisionCache.cache[cacheKey]
if !exists {
acm.decisionCache.missCount++
return nil
}
if time.Now().After(cached.ExpiresAt) {
delete(acm.decisionCache.cache, cacheKey)
acm.decisionCache.missCount++
return nil
}
cached.AccessCount++
cached.LastAccessed = time.Now()
acm.decisionCache.hitCount++
return cached.Decision
}
// cacheDecision caches an access decision
func (acm *AccessControlMatrix) cacheDecision(cacheKey string, decision *PolicyDecision) {
acm.decisionCache.mu.Lock()
defer acm.decisionCache.mu.Unlock()
// Check cache size limit
if len(acm.decisionCache.cache) >= acm.decisionCache.maxSize {
// Remove oldest entries
acm.evictOldestCacheEntries()
}
expiresAt := time.Now().Add(acm.decisionCache.ttl)
if decision.ValidUntil != nil && decision.ValidUntil.Before(expiresAt) {
expiresAt = *decision.ValidUntil
}
cached := &CachedDecision{
Decision: decision,
CreatedAt: time.Now(),
ExpiresAt: expiresAt,
AccessCount: 1,
LastAccessed: time.Now(),
}
acm.decisionCache.cache[cacheKey] = cached
}
// evictOldestCacheEntries removes the oldest cache entries
func (acm *AccessControlMatrix) evictOldestCacheEntries() {
// Simple LRU eviction - remove 10% of entries
entriesToRemove := acm.decisionCache.maxSize / 10
if entriesToRemove < 1 {
entriesToRemove = 1
}
// Find oldest entries
type cacheEntry struct {
key string
entry *CachedDecision
}
entries := make([]*cacheEntry, 0, len(acm.decisionCache.cache))
for key, entry := range acm.decisionCache.cache {
entries = append(entries, &cacheEntry{key: key, entry: entry})
}
// Sort by last accessed time
for i := 0; i < len(entries)-1; i++ {
for j := i + 1; j < len(entries); j++ {
if entries[i].entry.LastAccessed.After(entries[j].entry.LastAccessed) {
entries[i], entries[j] = entries[j], entries[i]
}
}
}
// Remove oldest entries
for i := 0; i < entriesToRemove && i < len(entries); i++ {
delete(acm.decisionCache.cache, entries[i].key)
}
}
// checkBypassToken checks for valid bypass tokens
func (acm *AccessControlMatrix) checkBypassToken(request *AccessRequest) *BypassToken {
acm.mu.RLock()
defer acm.mu.RUnlock()
// Check for bypass token in request metadata
if tokenID, exists := request.Metadata["bypass_token"].(string); exists {
if token, exists := acm.bypassTokens[tokenID]; exists {
if token.Status == BypassTokenStatusActive && time.Now().Before(token.ExpiresAt) {
if token.UsageCount < token.MaxUsage {
return token
}
}
}
}
return nil
}
// consumeBypassToken consumes a bypass token usage
func (acm *AccessControlMatrix) consumeBypassToken(token *BypassToken) {
acm.mu.Lock()
defer acm.mu.Unlock()
token.UsageCount++
if token.UsageCount >= token.MaxUsage {
token.Status = BypassTokenStatusExhausted
}
}
// enrichRequest enriches the request with additional attributes
func (acm *AccessControlMatrix) enrichRequest(request *AccessRequest) (*AccessRequest, error) {
// Get user attributes
userAttrs, err := acm.attributeProvider.GetUserAttributes(request.UserID)
if err != nil {
return nil, fmt.Errorf("failed to get user attributes: %w", err)
}
request.UserAttributes = userAttrs
// Get resource attributes
resourceAttrs, err := acm.attributeProvider.GetResourceAttributes(request.Resource)
if err != nil {
return nil, fmt.Errorf("failed to get resource attributes: %w", err)
}
request.ResourceAttributes = resourceAttrs
// Get environment attributes
envAttrs, err := acm.attributeProvider.GetEnvironmentAttributes()
if err != nil {
return nil, fmt.Errorf("failed to get environment attributes: %w", err)
}
request.EnvironmentAttributes = envAttrs
// Get context attributes
contextAttrs, err := acm.attributeProvider.GetContextAttributes(request.Context)
if err != nil {
return nil, fmt.Errorf("failed to get context attributes: %w", err)
}
request.ContextAttributes = contextAttrs
return request, nil
}
// applyContextualPolicies applies context-aware policies
func (acm *AccessControlMatrix) applyContextualPolicies(ctx context.Context, request *AccessRequest, baseDecision *PolicyDecision) (*PolicyDecision, error) {
acm.mu.RLock()
contextualPolicies := make([]*ContextualPolicy, 0, len(acm.contextualPolicies))
for _, policy := range acm.contextualPolicies {
contextualPolicies = append(contextualPolicies, policy)
}
acm.mu.RUnlock()
decision := baseDecision
for _, policy := range contextualPolicies {
// Check if policy applies to this request
if acm.policyApplies(policy, request) {
// Apply adaptive rules
for _, rule := range policy.AdaptiveRules {
if acm.evaluateAdaptiveRule(rule, request, decision) {
// Apply adaptation
decision = acm.applyAdaptation(rule, request, decision)
}
}
}
}
return decision, nil
}
// policyApplies checks if a contextual policy applies to the request
func (acm *AccessControlMatrix) policyApplies(policy *ContextualPolicy, request *AccessRequest) bool {
// Simple pattern matching - in production, use more sophisticated matching
return strings.Contains(request.Resource, policy.ContextPattern)
}
// evaluateAdaptiveRule evaluates an adaptive rule
func (acm *AccessControlMatrix) evaluateAdaptiveRule(rule *AdaptiveRule, request *AccessRequest, decision *PolicyDecision) bool {
// Simplified evaluation - in production, use CEL or similar expression engine
return rule.ConfidenceThreshold <= decision.ConfidenceScore
}
// applyAdaptation applies rule adaptation
func (acm *AccessControlMatrix) applyAdaptation(rule *AdaptiveRule, request *AccessRequest, decision *PolicyDecision) *PolicyDecision {
// Apply adaptation based on rule type
switch rule.Adaptation {
case "increase_security":
decision.RiskScore *= 1.2
decision.Obligations = append(decision.Obligations, &PolicyObligation{
ObligationID: "additional_auth",
Type: "authentication",
Action: "require_mfa",
Required: true,
FulfillmentType: "before",
})
case "decrease_security":
decision.RiskScore *= 0.8
}
return decision
}
// calculateRiskScore calculates the risk score for the request
func (acm *AccessControlMatrix) calculateRiskScore(request *AccessRequest, decision *PolicyDecision) float64 {
baseRisk := 0.5
// Risk factors
if request.IPAddress != "" {
// Check for known bad IPs
if acm.isSuspiciousIP(request.IPAddress) {
baseRisk += 0.3
}
}
// Time-based risk
if request.EnvironmentAttributes != nil && !request.EnvironmentAttributes.BusinessHours {
baseRisk += 0.1
}
// Resource sensitivity
if request.ResourceAttributes != nil && request.ResourceAttributes.Sensitivity == "high" {
baseRisk += 0.2
}
// User clearance mismatch
if request.UserAttributes != nil && request.ResourceAttributes != nil {
if request.UserAttributes.ClearanceLevel < request.ResourceAttributes.Classification {
baseRisk += 0.4
}
}
return baseRisk
}
// isSuspiciousIP checks if an IP address is suspicious
func (acm *AccessControlMatrix) isSuspiciousIP(ipAddress string) bool {
// In production, integrate with threat intelligence feeds
return false
}
// applyRoleConstraints applies role-specific constraints
func (acm *AccessControlMatrix) applyRoleConstraints(request *AccessRequest, decision *PolicyDecision) *PolicyDecision {
acm.roleHierarchy.mu.RLock()
defer acm.roleHierarchy.mu.RUnlock()
for _, roleID := range request.Roles {
if constraints, exists := acm.roleHierarchy.roleConstraints[roleID]; exists {
// Apply constraints
for _, approval := range constraints.RequiredApprovals {
if acm.matchesPattern(approval.ResourcePattern, request.Resource) && approval.Action == request.Action {
decision.Obligations = append(decision.Obligations, &PolicyObligation{
ObligationID: fmt.Sprintf("approval_%s", approval.Action),
Type: "approval",
Action: "require_approval",
Required: true,
FulfillmentType: "before",
Parameters: map[string]interface{}{
"required_approvers": approval.RequiredApprovers,
"approver_roles": approval.ApproverRoles,
"time_limit": approval.TimeLimit.String(),
},
})
}
}
}
}
return decision
}
// matchesPattern checks if a resource matches a pattern
func (acm *AccessControlMatrix) matchesPattern(pattern, resource string) bool {
// Simple glob-like matching - in production, use more sophisticated pattern matching
return strings.Contains(resource, strings.TrimSuffix(strings.TrimPrefix(pattern, "*"), "*"))
}
// logAccessDecision logs the access decision for audit purposes
func (acm *AccessControlMatrix) logAccessDecision(request *AccessRequest, decision *PolicyDecision) {
if acm.auditLogger == nil {
return
}
event := &SecurityEvent{
EventID: fmt.Sprintf("access_decision_%s", request.RequestID),
EventType: "access_decision",
Timestamp: time.Now(),
UserID: request.UserID,
Resource: request.Resource,
Action: request.Action,
Outcome: string(decision.Decision),
RiskLevel: acm.getRiskLevelString(decision.RiskScore),
Details: map[string]interface{}{
"request_id": request.RequestID,
"roles": request.Roles,
"decision": decision.Decision,
"reason": decision.Reason,
"matched_policies": decision.MatchedPolicies,
"risk_score": decision.RiskScore,
"evaluation_time": decision.EvaluationTime.String(),
"cache_hit": decision.CacheHit,
},
}
acm.auditLogger.LogSecurityEvent(event)
}
// getRiskLevelString converts risk score to risk level string
func (acm *AccessControlMatrix) getRiskLevelString(riskScore float64) string {
switch {
case riskScore >= 0.8:
return "critical"
case riskScore >= 0.6:
return "high"
case riskScore >= 0.4:
return "medium"
default:
return "low"
}
}
// loadDefaultPolicies loads default access control policies
func (acm *AccessControlMatrix) loadDefaultPolicies() error {
// Create default RBAC policy
defaultPolicy := &AccessPolicy{
PolicyID: "default_rbac",
Name: "Default Role-Based Access Control",
Description: "Default RBAC policy for SLURP system",
Type: PolicyTypeRBAC,
Status: PolicyStatusActive,
Rules: []*PolicyRule{
{
RuleID: "rbac_permit",
Name: "RBAC Permit Rule",
Description: "Permit access based on role permissions",
Condition: "request.roles contains required_role",
Effect: RuleEffectPermit,
Priority: 100,
Enabled: true,
},
},
Priority: 100,
Version: "1.0",
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
CreatedBy: "system",
Tags: []string{"default", "rbac"},
}
acm.mu.Lock()
acm.policies[defaultPolicy.PolicyID] = defaultPolicy
acm.mu.Unlock()
return nil
}
// CreateBypassToken creates a temporary bypass token
func (acm *AccessControlMatrix) CreateBypassToken(createdBy, reason string, scope []string, duration time.Duration, maxUsage int) (*BypassToken, error) {
acm.mu.Lock()
defer acm.mu.Unlock()
tokenID := fmt.Sprintf("bypass_%s_%d", createdBy, time.Now().Unix())
token := &BypassToken{
TokenID: tokenID,
CreatedBy: createdBy,
CreatedAt: time.Now(),
ExpiresAt: time.Now().Add(duration),
Reason: reason,
Scope: scope,
UsageCount: 0,
MaxUsage: maxUsage,
Status: BypassTokenStatusActive,
}
acm.bypassTokens[tokenID] = token
// Log token creation
if acm.auditLogger != nil {
event := &SecurityEvent{
EventID: fmt.Sprintf("bypass_token_created_%s", tokenID),
EventType: "bypass_token_created",
Timestamp: time.Now(),
UserID: createdBy,
Resource: tokenID,
Action: "create_bypass_token",
Outcome: "success",
RiskLevel: "high",
Details: map[string]interface{}{
"token_id": tokenID,
"reason": reason,
"scope": scope,
"duration": duration.String(),
"max_usage": maxUsage,
},
}
acm.auditLogger.LogSecurityEvent(event)
}
return token, nil
}
// GetAccessControlMetrics returns access control metrics
func (acm *AccessControlMatrix) GetAccessControlMetrics() map[string]interface{} {
acm.evaluationMetrics.mu.RLock()
defer acm.evaluationMetrics.mu.RUnlock()
acm.decisionCache.mu.RLock()
cacheHitRate := float64(acm.decisionCache.hitCount) / float64(acm.decisionCache.hitCount+acm.decisionCache.missCount)
acm.decisionCache.mu.RUnlock()
return map[string]interface{}{
"total_evaluations": acm.evaluationMetrics.totalEvaluations,
"successful_evaluations": acm.evaluationMetrics.successfulEvaluations,
"failed_evaluations": acm.evaluationMetrics.failedEvaluations,
"average_latency": acm.evaluationMetrics.averageLatency.String(),
"peak_latency": acm.evaluationMetrics.peakLatency.String(),
"cache_hit_rate": cacheHitRate,
"active_policies": len(acm.policies),
"active_bypass_tokens": len(acm.bypassTokens),
"enforcement_mode": string(acm.enforcementMode),
}
}