This comprehensive refactoring addresses critical architectural issues: IMPORT CYCLE RESOLUTION: • pkg/crypto ↔ pkg/slurp/roles: Created pkg/security/access_levels.go • pkg/ucxl → pkg/dht: Created pkg/storage/interfaces.go • pkg/slurp/leader → pkg/election → pkg/slurp/storage: Moved types to pkg/election/interfaces.go MODULE PATH MIGRATION: • Changed from github.com/anthonyrawlins/bzzz to chorus.services/bzzz • Updated all import statements across 115+ files • Maintains compatibility while removing personal GitHub account dependency TYPE SYSTEM IMPROVEMENTS: • Resolved duplicate type declarations in crypto package • Added missing type definitions (RoleStatus, TimeRestrictions, KeyStatus, KeyRotationResult) • Proper interface segregation to prevent future cycles ARCHITECTURAL BENEFITS: • Build now progresses past structural issues to normal dependency resolution • Cleaner separation of concerns between packages • Eliminates circular dependencies that prevented compilation • Establishes foundation for scalable codebase growth 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1409 lines
53 KiB
Go
1409 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"
|
|
"encoding/json"
|
|
"fmt"
|
|
"strings"
|
|
"sync"
|
|
"time"
|
|
|
|
"chorus.services/bzzz/pkg/config"
|
|
"chorus.services/bzzz/pkg/security"
|
|
"chorus.services/bzzz/pkg/ucxl"
|
|
"chorus.services/bzzz/pkg/slurp/roles"
|
|
)
|
|
|
|
// AccessControlMatrix implements sophisticated access control enforcement
|
|
type AccessControlMatrix struct {
|
|
mu sync.RWMutex
|
|
config *config.Config
|
|
policyEngine PolicyEngine
|
|
roleHierarchy *RoleHierarchy
|
|
attributeProvider AttributeProvider
|
|
auditLogger AuditLogger
|
|
|
|
// 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),
|
|
}
|
|
} |