You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							768 lines
						
					
					
						
							21 KiB
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							768 lines
						
					
					
						
							21 KiB
						
					
					
				
								package policy_engine
							 | 
						|
								
							 | 
						|
								import (
							 | 
						|
									"fmt"
							 | 
						|
									"net"
							 | 
						|
									"reflect"
							 | 
						|
									"strconv"
							 | 
						|
									"strings"
							 | 
						|
									"sync"
							 | 
						|
									"time"
							 | 
						|
								
							 | 
						|
									"github.com/seaweedfs/seaweedfs/weed/glog"
							 | 
						|
								)
							 | 
						|
								
							 | 
						|
								// LRUNode represents a node in the doubly-linked list for efficient LRU operations
							 | 
						|
								type LRUNode struct {
							 | 
						|
									key   string
							 | 
						|
									value []string
							 | 
						|
									prev  *LRUNode
							 | 
						|
									next  *LRUNode
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// NormalizedValueCache provides size-limited caching for normalized values with efficient LRU eviction
							 | 
						|
								type NormalizedValueCache struct {
							 | 
						|
									mu      sync.RWMutex
							 | 
						|
									cache   map[string]*LRUNode
							 | 
						|
									maxSize int
							 | 
						|
									head    *LRUNode // Most recently used
							 | 
						|
									tail    *LRUNode // Least recently used
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// NewNormalizedValueCache creates a new normalized value cache with configurable size
							 | 
						|
								func NewNormalizedValueCache(maxSize int) *NormalizedValueCache {
							 | 
						|
									if maxSize <= 0 {
							 | 
						|
										maxSize = 1000 // Default size
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									// Create dummy head and tail nodes for easier list manipulation
							 | 
						|
									head := &LRUNode{}
							 | 
						|
									tail := &LRUNode{}
							 | 
						|
									head.next = tail
							 | 
						|
									tail.prev = head
							 | 
						|
								
							 | 
						|
									return &NormalizedValueCache{
							 | 
						|
										cache:   make(map[string]*LRUNode),
							 | 
						|
										maxSize: maxSize,
							 | 
						|
										head:    head,
							 | 
						|
										tail:    tail,
							 | 
						|
									}
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// Get retrieves a cached value and updates access order in O(1) time
							 | 
						|
								func (c *NormalizedValueCache) Get(key string) ([]string, bool) {
							 | 
						|
									c.mu.Lock()
							 | 
						|
									defer c.mu.Unlock()
							 | 
						|
								
							 | 
						|
									if node, exists := c.cache[key]; exists {
							 | 
						|
										// Move to head (most recently used) - O(1) operation
							 | 
						|
										c.moveToHead(node)
							 | 
						|
										return node.value, true
							 | 
						|
									}
							 | 
						|
									return nil, false
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// Set stores a value in the cache with size limit enforcement in O(1) time
							 | 
						|
								func (c *NormalizedValueCache) Set(key string, value []string) {
							 | 
						|
									c.mu.Lock()
							 | 
						|
									defer c.mu.Unlock()
							 | 
						|
								
							 | 
						|
									if node, exists := c.cache[key]; exists {
							 | 
						|
										// Update existing node and move to head
							 | 
						|
										node.value = value
							 | 
						|
										c.moveToHead(node)
							 | 
						|
										return
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									// Create new node
							 | 
						|
									newNode := &LRUNode{
							 | 
						|
										key:   key,
							 | 
						|
										value: value,
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									// If at max size, evict least recently used
							 | 
						|
									if len(c.cache) >= c.maxSize {
							 | 
						|
										c.evictLeastRecentlyUsed()
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									// Add to cache and move to head
							 | 
						|
									c.cache[key] = newNode
							 | 
						|
									c.addToHead(newNode)
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// moveToHead moves a node to the head of the list (most recently used) - O(1)
							 | 
						|
								func (c *NormalizedValueCache) moveToHead(node *LRUNode) {
							 | 
						|
									c.removeNode(node)
							 | 
						|
									c.addToHead(node)
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// addToHead adds a node right after the head - O(1)
							 | 
						|
								func (c *NormalizedValueCache) addToHead(node *LRUNode) {
							 | 
						|
									node.prev = c.head
							 | 
						|
									node.next = c.head.next
							 | 
						|
									c.head.next.prev = node
							 | 
						|
									c.head.next = node
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// removeNode removes a node from the list - O(1)
							 | 
						|
								func (c *NormalizedValueCache) removeNode(node *LRUNode) {
							 | 
						|
									node.prev.next = node.next
							 | 
						|
									node.next.prev = node.prev
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// removeTail removes the last node before tail (least recently used) - O(1)
							 | 
						|
								func (c *NormalizedValueCache) removeTail() *LRUNode {
							 | 
						|
									lastNode := c.tail.prev
							 | 
						|
									c.removeNode(lastNode)
							 | 
						|
									return lastNode
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// evictLeastRecentlyUsed removes the least recently used item in O(1) time
							 | 
						|
								func (c *NormalizedValueCache) evictLeastRecentlyUsed() {
							 | 
						|
									tail := c.removeTail()
							 | 
						|
									delete(c.cache, tail.key)
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// Clear clears all cached values
							 | 
						|
								func (c *NormalizedValueCache) Clear() {
							 | 
						|
									c.mu.Lock()
							 | 
						|
									defer c.mu.Unlock()
							 | 
						|
									c.cache = make(map[string]*LRUNode)
							 | 
						|
									c.head.next = c.tail
							 | 
						|
									c.tail.prev = c.head
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// GetStats returns cache statistics
							 | 
						|
								func (c *NormalizedValueCache) GetStats() (size int, maxSize int) {
							 | 
						|
									c.mu.RLock()
							 | 
						|
									defer c.mu.RUnlock()
							 | 
						|
									return len(c.cache), c.maxSize
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// Global cache instance with size limit
							 | 
						|
								var normalizedValueCache = NewNormalizedValueCache(1000)
							 | 
						|
								
							 | 
						|
								// getCachedNormalizedValues returns cached normalized values or caches new ones
							 | 
						|
								func getCachedNormalizedValues(value interface{}) []string {
							 | 
						|
									// Create a string key for caching - more efficient than fmt.Sprintf
							 | 
						|
									typeStr := reflect.TypeOf(value).String()
							 | 
						|
									cacheKey := typeStr + ":" + fmt.Sprint(value)
							 | 
						|
								
							 | 
						|
									// Try to get from cache
							 | 
						|
									if cached, exists := normalizedValueCache.Get(cacheKey); exists {
							 | 
						|
										return cached
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									// Not in cache, normalize and store
							 | 
						|
									// Use the error-handling version for better error reporting
							 | 
						|
									normalized, err := normalizeToStringSliceWithError(value)
							 | 
						|
									if err != nil {
							 | 
						|
										glog.Warningf("Failed to normalize policy value %v: %v", value, err)
							 | 
						|
										// Fallback to string conversion for backward compatibility
							 | 
						|
										normalized = []string{fmt.Sprintf("%v", value)}
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									normalizedValueCache.Set(cacheKey, normalized)
							 | 
						|
								
							 | 
						|
									return normalized
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// ConditionEvaluator evaluates policy conditions
							 | 
						|
								type ConditionEvaluator interface {
							 | 
						|
									Evaluate(conditionValue interface{}, contextValues []string) bool
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// StringEqualsEvaluator evaluates StringEquals conditions
							 | 
						|
								type StringEqualsEvaluator struct{}
							 | 
						|
								
							 | 
						|
								func (e *StringEqualsEvaluator) Evaluate(conditionValue interface{}, contextValues []string) bool {
							 | 
						|
									expectedValues := getCachedNormalizedValues(conditionValue)
							 | 
						|
									for _, expected := range expectedValues {
							 | 
						|
										for _, contextValue := range contextValues {
							 | 
						|
											if expected == contextValue {
							 | 
						|
												return true
							 | 
						|
											}
							 | 
						|
										}
							 | 
						|
									}
							 | 
						|
									return false
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// StringNotEqualsEvaluator evaluates StringNotEquals conditions
							 | 
						|
								type StringNotEqualsEvaluator struct{}
							 | 
						|
								
							 | 
						|
								func (e *StringNotEqualsEvaluator) Evaluate(conditionValue interface{}, contextValues []string) bool {
							 | 
						|
									expectedValues := getCachedNormalizedValues(conditionValue)
							 | 
						|
									for _, expected := range expectedValues {
							 | 
						|
										for _, contextValue := range contextValues {
							 | 
						|
											if expected == contextValue {
							 | 
						|
												return false
							 | 
						|
											}
							 | 
						|
										}
							 | 
						|
									}
							 | 
						|
									return true
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// StringLikeEvaluator evaluates StringLike conditions (supports wildcards)
							 | 
						|
								type StringLikeEvaluator struct{}
							 | 
						|
								
							 | 
						|
								func (e *StringLikeEvaluator) Evaluate(conditionValue interface{}, contextValues []string) bool {
							 | 
						|
									patterns := getCachedNormalizedValues(conditionValue)
							 | 
						|
									for _, pattern := range patterns {
							 | 
						|
										for _, contextValue := range contextValues {
							 | 
						|
											if MatchesWildcard(pattern, contextValue) {
							 | 
						|
												return true
							 | 
						|
											}
							 | 
						|
										}
							 | 
						|
									}
							 | 
						|
									return false
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// StringNotLikeEvaluator evaluates StringNotLike conditions
							 | 
						|
								type StringNotLikeEvaluator struct{}
							 | 
						|
								
							 | 
						|
								func (e *StringNotLikeEvaluator) Evaluate(conditionValue interface{}, contextValues []string) bool {
							 | 
						|
									patterns := getCachedNormalizedValues(conditionValue)
							 | 
						|
									for _, pattern := range patterns {
							 | 
						|
										for _, contextValue := range contextValues {
							 | 
						|
											if MatchesWildcard(pattern, contextValue) {
							 | 
						|
												return false
							 | 
						|
											}
							 | 
						|
										}
							 | 
						|
									}
							 | 
						|
									return true
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// NumericEqualsEvaluator evaluates NumericEquals conditions
							 | 
						|
								type NumericEqualsEvaluator struct{}
							 | 
						|
								
							 | 
						|
								func (e *NumericEqualsEvaluator) Evaluate(conditionValue interface{}, contextValues []string) bool {
							 | 
						|
									expectedValues := getCachedNormalizedValues(conditionValue)
							 | 
						|
									for _, expected := range expectedValues {
							 | 
						|
										expectedFloat, err := strconv.ParseFloat(expected, 64)
							 | 
						|
										if err != nil {
							 | 
						|
											continue
							 | 
						|
										}
							 | 
						|
										for _, contextValue := range contextValues {
							 | 
						|
											contextFloat, err := strconv.ParseFloat(contextValue, 64)
							 | 
						|
											if err != nil {
							 | 
						|
												continue
							 | 
						|
											}
							 | 
						|
											if expectedFloat == contextFloat {
							 | 
						|
												return true
							 | 
						|
											}
							 | 
						|
										}
							 | 
						|
									}
							 | 
						|
									return false
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// NumericNotEqualsEvaluator evaluates NumericNotEquals conditions
							 | 
						|
								type NumericNotEqualsEvaluator struct{}
							 | 
						|
								
							 | 
						|
								func (e *NumericNotEqualsEvaluator) Evaluate(conditionValue interface{}, contextValues []string) bool {
							 | 
						|
									expectedValues := getCachedNormalizedValues(conditionValue)
							 | 
						|
									for _, expected := range expectedValues {
							 | 
						|
										expectedFloat, err := strconv.ParseFloat(expected, 64)
							 | 
						|
										if err != nil {
							 | 
						|
											continue
							 | 
						|
										}
							 | 
						|
										for _, contextValue := range contextValues {
							 | 
						|
											contextFloat, err := strconv.ParseFloat(contextValue, 64)
							 | 
						|
											if err != nil {
							 | 
						|
												continue
							 | 
						|
											}
							 | 
						|
											if expectedFloat == contextFloat {
							 | 
						|
												return false
							 | 
						|
											}
							 | 
						|
										}
							 | 
						|
									}
							 | 
						|
									return true
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// NumericLessThanEvaluator evaluates NumericLessThan conditions
							 | 
						|
								type NumericLessThanEvaluator struct{}
							 | 
						|
								
							 | 
						|
								func (e *NumericLessThanEvaluator) Evaluate(conditionValue interface{}, contextValues []string) bool {
							 | 
						|
									expectedValues := getCachedNormalizedValues(conditionValue)
							 | 
						|
									for _, expected := range expectedValues {
							 | 
						|
										expectedFloat, err := strconv.ParseFloat(expected, 64)
							 | 
						|
										if err != nil {
							 | 
						|
											continue
							 | 
						|
										}
							 | 
						|
										for _, contextValue := range contextValues {
							 | 
						|
											contextFloat, err := strconv.ParseFloat(contextValue, 64)
							 | 
						|
											if err != nil {
							 | 
						|
												continue
							 | 
						|
											}
							 | 
						|
											if contextFloat < expectedFloat {
							 | 
						|
												return true
							 | 
						|
											}
							 | 
						|
										}
							 | 
						|
									}
							 | 
						|
									return false
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// NumericLessThanEqualsEvaluator evaluates NumericLessThanEquals conditions
							 | 
						|
								type NumericLessThanEqualsEvaluator struct{}
							 | 
						|
								
							 | 
						|
								func (e *NumericLessThanEqualsEvaluator) Evaluate(conditionValue interface{}, contextValues []string) bool {
							 | 
						|
									expectedValues := getCachedNormalizedValues(conditionValue)
							 | 
						|
									for _, expected := range expectedValues {
							 | 
						|
										expectedFloat, err := strconv.ParseFloat(expected, 64)
							 | 
						|
										if err != nil {
							 | 
						|
											continue
							 | 
						|
										}
							 | 
						|
										for _, contextValue := range contextValues {
							 | 
						|
											contextFloat, err := strconv.ParseFloat(contextValue, 64)
							 | 
						|
											if err != nil {
							 | 
						|
												continue
							 | 
						|
											}
							 | 
						|
											if contextFloat <= expectedFloat {
							 | 
						|
												return true
							 | 
						|
											}
							 | 
						|
										}
							 | 
						|
									}
							 | 
						|
									return false
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// NumericGreaterThanEvaluator evaluates NumericGreaterThan conditions
							 | 
						|
								type NumericGreaterThanEvaluator struct{}
							 | 
						|
								
							 | 
						|
								func (e *NumericGreaterThanEvaluator) Evaluate(conditionValue interface{}, contextValues []string) bool {
							 | 
						|
									expectedValues := getCachedNormalizedValues(conditionValue)
							 | 
						|
									for _, expected := range expectedValues {
							 | 
						|
										expectedFloat, err := strconv.ParseFloat(expected, 64)
							 | 
						|
										if err != nil {
							 | 
						|
											continue
							 | 
						|
										}
							 | 
						|
										for _, contextValue := range contextValues {
							 | 
						|
											contextFloat, err := strconv.ParseFloat(contextValue, 64)
							 | 
						|
											if err != nil {
							 | 
						|
												continue
							 | 
						|
											}
							 | 
						|
											if contextFloat > expectedFloat {
							 | 
						|
												return true
							 | 
						|
											}
							 | 
						|
										}
							 | 
						|
									}
							 | 
						|
									return false
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// NumericGreaterThanEqualsEvaluator evaluates NumericGreaterThanEquals conditions
							 | 
						|
								type NumericGreaterThanEqualsEvaluator struct{}
							 | 
						|
								
							 | 
						|
								func (e *NumericGreaterThanEqualsEvaluator) Evaluate(conditionValue interface{}, contextValues []string) bool {
							 | 
						|
									expectedValues := getCachedNormalizedValues(conditionValue)
							 | 
						|
									for _, expected := range expectedValues {
							 | 
						|
										expectedFloat, err := strconv.ParseFloat(expected, 64)
							 | 
						|
										if err != nil {
							 | 
						|
											continue
							 | 
						|
										}
							 | 
						|
										for _, contextValue := range contextValues {
							 | 
						|
											contextFloat, err := strconv.ParseFloat(contextValue, 64)
							 | 
						|
											if err != nil {
							 | 
						|
												continue
							 | 
						|
											}
							 | 
						|
											if contextFloat >= expectedFloat {
							 | 
						|
												return true
							 | 
						|
											}
							 | 
						|
										}
							 | 
						|
									}
							 | 
						|
									return false
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// DateEqualsEvaluator evaluates DateEquals conditions
							 | 
						|
								type DateEqualsEvaluator struct{}
							 | 
						|
								
							 | 
						|
								func (e *DateEqualsEvaluator) Evaluate(conditionValue interface{}, contextValues []string) bool {
							 | 
						|
									expectedValues := getCachedNormalizedValues(conditionValue)
							 | 
						|
									for _, expected := range expectedValues {
							 | 
						|
										expectedTime, err := time.Parse(time.RFC3339, expected)
							 | 
						|
										if err != nil {
							 | 
						|
											continue
							 | 
						|
										}
							 | 
						|
										for _, contextValue := range contextValues {
							 | 
						|
											contextTime, err := time.Parse(time.RFC3339, contextValue)
							 | 
						|
											if err != nil {
							 | 
						|
												continue
							 | 
						|
											}
							 | 
						|
											if expectedTime.Equal(contextTime) {
							 | 
						|
												return true
							 | 
						|
											}
							 | 
						|
										}
							 | 
						|
									}
							 | 
						|
									return false
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// DateNotEqualsEvaluator evaluates DateNotEquals conditions
							 | 
						|
								type DateNotEqualsEvaluator struct{}
							 | 
						|
								
							 | 
						|
								func (e *DateNotEqualsEvaluator) Evaluate(conditionValue interface{}, contextValues []string) bool {
							 | 
						|
									expectedValues := getCachedNormalizedValues(conditionValue)
							 | 
						|
									for _, expected := range expectedValues {
							 | 
						|
										expectedTime, err := time.Parse(time.RFC3339, expected)
							 | 
						|
										if err != nil {
							 | 
						|
											continue
							 | 
						|
										}
							 | 
						|
										for _, contextValue := range contextValues {
							 | 
						|
											contextTime, err := time.Parse(time.RFC3339, contextValue)
							 | 
						|
											if err != nil {
							 | 
						|
												continue
							 | 
						|
											}
							 | 
						|
											if expectedTime.Equal(contextTime) {
							 | 
						|
												return false
							 | 
						|
											}
							 | 
						|
										}
							 | 
						|
									}
							 | 
						|
									return true
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// DateLessThanEvaluator evaluates DateLessThan conditions
							 | 
						|
								type DateLessThanEvaluator struct{}
							 | 
						|
								
							 | 
						|
								func (e *DateLessThanEvaluator) Evaluate(conditionValue interface{}, contextValues []string) bool {
							 | 
						|
									expectedValues := getCachedNormalizedValues(conditionValue)
							 | 
						|
									for _, expected := range expectedValues {
							 | 
						|
										expectedTime, err := time.Parse(time.RFC3339, expected)
							 | 
						|
										if err != nil {
							 | 
						|
											continue
							 | 
						|
										}
							 | 
						|
										for _, contextValue := range contextValues {
							 | 
						|
											contextTime, err := time.Parse(time.RFC3339, contextValue)
							 | 
						|
											if err != nil {
							 | 
						|
												continue
							 | 
						|
											}
							 | 
						|
											if contextTime.Before(expectedTime) {
							 | 
						|
												return true
							 | 
						|
											}
							 | 
						|
										}
							 | 
						|
									}
							 | 
						|
									return false
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// DateLessThanEqualsEvaluator evaluates DateLessThanEquals conditions
							 | 
						|
								type DateLessThanEqualsEvaluator struct{}
							 | 
						|
								
							 | 
						|
								func (e *DateLessThanEqualsEvaluator) Evaluate(conditionValue interface{}, contextValues []string) bool {
							 | 
						|
									expectedValues := getCachedNormalizedValues(conditionValue)
							 | 
						|
									for _, expected := range expectedValues {
							 | 
						|
										expectedTime, err := time.Parse(time.RFC3339, expected)
							 | 
						|
										if err != nil {
							 | 
						|
											continue
							 | 
						|
										}
							 | 
						|
										for _, contextValue := range contextValues {
							 | 
						|
											contextTime, err := time.Parse(time.RFC3339, contextValue)
							 | 
						|
											if err != nil {
							 | 
						|
												continue
							 | 
						|
											}
							 | 
						|
											if contextTime.Before(expectedTime) || contextTime.Equal(expectedTime) {
							 | 
						|
												return true
							 | 
						|
											}
							 | 
						|
										}
							 | 
						|
									}
							 | 
						|
									return false
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// DateGreaterThanEvaluator evaluates DateGreaterThan conditions
							 | 
						|
								type DateGreaterThanEvaluator struct{}
							 | 
						|
								
							 | 
						|
								func (e *DateGreaterThanEvaluator) Evaluate(conditionValue interface{}, contextValues []string) bool {
							 | 
						|
									expectedValues := getCachedNormalizedValues(conditionValue)
							 | 
						|
									for _, expected := range expectedValues {
							 | 
						|
										expectedTime, err := time.Parse(time.RFC3339, expected)
							 | 
						|
										if err != nil {
							 | 
						|
											continue
							 | 
						|
										}
							 | 
						|
										for _, contextValue := range contextValues {
							 | 
						|
											contextTime, err := time.Parse(time.RFC3339, contextValue)
							 | 
						|
											if err != nil {
							 | 
						|
												continue
							 | 
						|
											}
							 | 
						|
											if contextTime.After(expectedTime) {
							 | 
						|
												return true
							 | 
						|
											}
							 | 
						|
										}
							 | 
						|
									}
							 | 
						|
									return false
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// DateGreaterThanEqualsEvaluator evaluates DateGreaterThanEquals conditions
							 | 
						|
								type DateGreaterThanEqualsEvaluator struct{}
							 | 
						|
								
							 | 
						|
								func (e *DateGreaterThanEqualsEvaluator) Evaluate(conditionValue interface{}, contextValues []string) bool {
							 | 
						|
									expectedValues := getCachedNormalizedValues(conditionValue)
							 | 
						|
									for _, expected := range expectedValues {
							 | 
						|
										expectedTime, err := time.Parse(time.RFC3339, expected)
							 | 
						|
										if err != nil {
							 | 
						|
											continue
							 | 
						|
										}
							 | 
						|
										for _, contextValue := range contextValues {
							 | 
						|
											contextTime, err := time.Parse(time.RFC3339, contextValue)
							 | 
						|
											if err != nil {
							 | 
						|
												continue
							 | 
						|
											}
							 | 
						|
											if contextTime.After(expectedTime) || contextTime.Equal(expectedTime) {
							 | 
						|
												return true
							 | 
						|
											}
							 | 
						|
										}
							 | 
						|
									}
							 | 
						|
									return false
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// BoolEvaluator evaluates Bool conditions
							 | 
						|
								type BoolEvaluator struct{}
							 | 
						|
								
							 | 
						|
								func (e *BoolEvaluator) Evaluate(conditionValue interface{}, contextValues []string) bool {
							 | 
						|
									expectedValues := getCachedNormalizedValues(conditionValue)
							 | 
						|
									for _, expected := range expectedValues {
							 | 
						|
										for _, contextValue := range contextValues {
							 | 
						|
											if strings.ToLower(expected) == strings.ToLower(contextValue) {
							 | 
						|
												return true
							 | 
						|
											}
							 | 
						|
										}
							 | 
						|
									}
							 | 
						|
									return false
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// IpAddressEvaluator evaluates IpAddress conditions
							 | 
						|
								type IpAddressEvaluator struct{}
							 | 
						|
								
							 | 
						|
								func (e *IpAddressEvaluator) Evaluate(conditionValue interface{}, contextValues []string) bool {
							 | 
						|
									expectedValues := getCachedNormalizedValues(conditionValue)
							 | 
						|
									for _, expected := range expectedValues {
							 | 
						|
										_, expectedNet, err := net.ParseCIDR(expected)
							 | 
						|
										if err != nil {
							 | 
						|
											// Try parsing as single IP
							 | 
						|
											expectedIP := net.ParseIP(expected)
							 | 
						|
											if expectedIP == nil {
							 | 
						|
												glog.V(3).Infof("Failed to parse expected IP address: %s", expected)
							 | 
						|
												continue
							 | 
						|
											}
							 | 
						|
											for _, contextValue := range contextValues {
							 | 
						|
												contextIP := net.ParseIP(contextValue)
							 | 
						|
												if contextIP == nil {
							 | 
						|
													glog.V(3).Infof("Failed to parse IP address: %s", contextValue)
							 | 
						|
													continue
							 | 
						|
												}
							 | 
						|
												if contextIP.Equal(expectedIP) {
							 | 
						|
													return true
							 | 
						|
												}
							 | 
						|
											}
							 | 
						|
										} else {
							 | 
						|
											// CIDR network
							 | 
						|
											for _, contextValue := range contextValues {
							 | 
						|
												contextIP := net.ParseIP(contextValue)
							 | 
						|
												if contextIP == nil {
							 | 
						|
													glog.V(3).Infof("Failed to parse IP address: %s", contextValue)
							 | 
						|
													continue
							 | 
						|
												}
							 | 
						|
												if expectedNet.Contains(contextIP) {
							 | 
						|
													return true
							 | 
						|
												}
							 | 
						|
											}
							 | 
						|
										}
							 | 
						|
									}
							 | 
						|
									return false
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// NotIpAddressEvaluator evaluates NotIpAddress conditions
							 | 
						|
								type NotIpAddressEvaluator struct{}
							 | 
						|
								
							 | 
						|
								func (e *NotIpAddressEvaluator) Evaluate(conditionValue interface{}, contextValues []string) bool {
							 | 
						|
									expectedValues := getCachedNormalizedValues(conditionValue)
							 | 
						|
									for _, expected := range expectedValues {
							 | 
						|
										_, expectedNet, err := net.ParseCIDR(expected)
							 | 
						|
										if err != nil {
							 | 
						|
											// Try parsing as single IP
							 | 
						|
											expectedIP := net.ParseIP(expected)
							 | 
						|
											if expectedIP == nil {
							 | 
						|
												glog.V(3).Infof("Failed to parse expected IP address: %s", expected)
							 | 
						|
												continue
							 | 
						|
											}
							 | 
						|
											for _, contextValue := range contextValues {
							 | 
						|
												contextIP := net.ParseIP(contextValue)
							 | 
						|
												if contextIP == nil {
							 | 
						|
													glog.V(3).Infof("Failed to parse IP address: %s", contextValue)
							 | 
						|
													continue
							 | 
						|
												}
							 | 
						|
												if contextIP.Equal(expectedIP) {
							 | 
						|
													return false
							 | 
						|
												}
							 | 
						|
											}
							 | 
						|
										} else {
							 | 
						|
											// CIDR network
							 | 
						|
											for _, contextValue := range contextValues {
							 | 
						|
												contextIP := net.ParseIP(contextValue)
							 | 
						|
												if contextIP == nil {
							 | 
						|
													glog.V(3).Infof("Failed to parse IP address: %s", contextValue)
							 | 
						|
													continue
							 | 
						|
												}
							 | 
						|
												if expectedNet.Contains(contextIP) {
							 | 
						|
													return false
							 | 
						|
												}
							 | 
						|
											}
							 | 
						|
										}
							 | 
						|
									}
							 | 
						|
									return true
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// ArnEqualsEvaluator evaluates ArnEquals conditions
							 | 
						|
								type ArnEqualsEvaluator struct{}
							 | 
						|
								
							 | 
						|
								func (e *ArnEqualsEvaluator) Evaluate(conditionValue interface{}, contextValues []string) bool {
							 | 
						|
									expectedValues := getCachedNormalizedValues(conditionValue)
							 | 
						|
									for _, expected := range expectedValues {
							 | 
						|
										for _, contextValue := range contextValues {
							 | 
						|
											if expected == contextValue {
							 | 
						|
												return true
							 | 
						|
											}
							 | 
						|
										}
							 | 
						|
									}
							 | 
						|
									return false
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// ArnLikeEvaluator evaluates ArnLike conditions
							 | 
						|
								type ArnLikeEvaluator struct{}
							 | 
						|
								
							 | 
						|
								func (e *ArnLikeEvaluator) Evaluate(conditionValue interface{}, contextValues []string) bool {
							 | 
						|
									patterns := getCachedNormalizedValues(conditionValue)
							 | 
						|
									for _, pattern := range patterns {
							 | 
						|
										for _, contextValue := range contextValues {
							 | 
						|
											if MatchesWildcard(pattern, contextValue) {
							 | 
						|
												return true
							 | 
						|
											}
							 | 
						|
										}
							 | 
						|
									}
							 | 
						|
									return false
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// NullEvaluator evaluates Null conditions
							 | 
						|
								type NullEvaluator struct{}
							 | 
						|
								
							 | 
						|
								func (e *NullEvaluator) Evaluate(conditionValue interface{}, contextValues []string) bool {
							 | 
						|
									expectedValues := getCachedNormalizedValues(conditionValue)
							 | 
						|
									for _, expected := range expectedValues {
							 | 
						|
										expectedBool := strings.ToLower(expected) == "true"
							 | 
						|
										contextExists := len(contextValues) > 0
							 | 
						|
										if expectedBool && !contextExists {
							 | 
						|
											return true // Key should be null and it is
							 | 
						|
										}
							 | 
						|
										if !expectedBool && contextExists {
							 | 
						|
											return true // Key should not be null and it isn't
							 | 
						|
										}
							 | 
						|
									}
							 | 
						|
									return false
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// GetConditionEvaluator returns the appropriate evaluator for a condition operator
							 | 
						|
								func GetConditionEvaluator(operator string) (ConditionEvaluator, error) {
							 | 
						|
									switch operator {
							 | 
						|
									case "StringEquals":
							 | 
						|
										return &StringEqualsEvaluator{}, nil
							 | 
						|
									case "StringNotEquals":
							 | 
						|
										return &StringNotEqualsEvaluator{}, nil
							 | 
						|
									case "StringLike":
							 | 
						|
										return &StringLikeEvaluator{}, nil
							 | 
						|
									case "StringNotLike":
							 | 
						|
										return &StringNotLikeEvaluator{}, nil
							 | 
						|
									case "NumericEquals":
							 | 
						|
										return &NumericEqualsEvaluator{}, nil
							 | 
						|
									case "NumericNotEquals":
							 | 
						|
										return &NumericNotEqualsEvaluator{}, nil
							 | 
						|
									case "NumericLessThan":
							 | 
						|
										return &NumericLessThanEvaluator{}, nil
							 | 
						|
									case "NumericLessThanEquals":
							 | 
						|
										return &NumericLessThanEqualsEvaluator{}, nil
							 | 
						|
									case "NumericGreaterThan":
							 | 
						|
										return &NumericGreaterThanEvaluator{}, nil
							 | 
						|
									case "NumericGreaterThanEquals":
							 | 
						|
										return &NumericGreaterThanEqualsEvaluator{}, nil
							 | 
						|
									case "DateEquals":
							 | 
						|
										return &DateEqualsEvaluator{}, nil
							 | 
						|
									case "DateNotEquals":
							 | 
						|
										return &DateNotEqualsEvaluator{}, nil
							 | 
						|
									case "DateLessThan":
							 | 
						|
										return &DateLessThanEvaluator{}, nil
							 | 
						|
									case "DateLessThanEquals":
							 | 
						|
										return &DateLessThanEqualsEvaluator{}, nil
							 | 
						|
									case "DateGreaterThan":
							 | 
						|
										return &DateGreaterThanEvaluator{}, nil
							 | 
						|
									case "DateGreaterThanEquals":
							 | 
						|
										return &DateGreaterThanEqualsEvaluator{}, nil
							 | 
						|
									case "Bool":
							 | 
						|
										return &BoolEvaluator{}, nil
							 | 
						|
									case "IpAddress":
							 | 
						|
										return &IpAddressEvaluator{}, nil
							 | 
						|
									case "NotIpAddress":
							 | 
						|
										return &NotIpAddressEvaluator{}, nil
							 | 
						|
									case "ArnEquals":
							 | 
						|
										return &ArnEqualsEvaluator{}, nil
							 | 
						|
									case "ArnLike":
							 | 
						|
										return &ArnLikeEvaluator{}, nil
							 | 
						|
									case "Null":
							 | 
						|
										return &NullEvaluator{}, nil
							 | 
						|
									default:
							 | 
						|
										return nil, fmt.Errorf("unsupported condition operator: %s", operator)
							 | 
						|
									}
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// EvaluateConditions evaluates all conditions in a policy statement
							 | 
						|
								func EvaluateConditions(conditions PolicyConditions, contextValues map[string][]string) bool {
							 | 
						|
									if len(conditions) == 0 {
							 | 
						|
										return true // No conditions means always true
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									for operator, conditionMap := range conditions {
							 | 
						|
										conditionEvaluator, err := GetConditionEvaluator(operator)
							 | 
						|
										if err != nil {
							 | 
						|
											glog.Warningf("Unsupported condition operator: %s", operator)
							 | 
						|
											continue
							 | 
						|
										}
							 | 
						|
								
							 | 
						|
										for key, value := range conditionMap {
							 | 
						|
											contextVals, exists := contextValues[key]
							 | 
						|
											if !exists {
							 | 
						|
												contextVals = []string{}
							 | 
						|
											}
							 | 
						|
								
							 | 
						|
											if !conditionEvaluator.Evaluate(value.Strings(), contextVals) {
							 | 
						|
												return false // If any condition fails, the whole condition block fails
							 | 
						|
											}
							 | 
						|
										}
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									return true
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// EvaluateConditionsLegacy evaluates conditions using the old interface{} format for backward compatibility
							 | 
						|
								func EvaluateConditionsLegacy(conditions map[string]interface{}, contextValues map[string][]string) bool {
							 | 
						|
									if len(conditions) == 0 {
							 | 
						|
										return true // No conditions means always true
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									for operator, conditionMap := range conditions {
							 | 
						|
										conditionEvaluator, err := GetConditionEvaluator(operator)
							 | 
						|
										if err != nil {
							 | 
						|
											glog.Warningf("Unsupported condition operator: %s", operator)
							 | 
						|
											continue
							 | 
						|
										}
							 | 
						|
								
							 | 
						|
										conditionMapTyped, ok := conditionMap.(map[string]interface{})
							 | 
						|
										if !ok {
							 | 
						|
											glog.Warningf("Invalid condition format for operator: %s", operator)
							 | 
						|
											continue
							 | 
						|
										}
							 | 
						|
								
							 | 
						|
										for key, value := range conditionMapTyped {
							 | 
						|
											contextVals, exists := contextValues[key]
							 | 
						|
											if !exists {
							 | 
						|
												contextVals = []string{}
							 | 
						|
											}
							 | 
						|
								
							 | 
						|
											if !conditionEvaluator.Evaluate(value, contextVals) {
							 | 
						|
												return false // If any condition fails, the whole condition block fails
							 | 
						|
											}
							 | 
						|
										}
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									return true
							 | 
						|
								}
							 |