diff options
| -rw-r--r-- | weed/s3api/policy_engine/conditions.go | 56 | ||||
| -rw-r--r-- | weed/s3api/policy_engine/engine.go | 2 | ||||
| -rw-r--r-- | weed/s3api/policy_engine/types.go | 5 |
3 files changed, 54 insertions, 9 deletions
diff --git a/weed/s3api/policy_engine/conditions.go b/weed/s3api/policy_engine/conditions.go index fc8005fd0..feb582e89 100644 --- a/weed/s3api/policy_engine/conditions.go +++ b/weed/s3api/policy_engine/conditions.go @@ -705,8 +705,15 @@ func GetConditionEvaluator(operator string) (ConditionEvaluator, error) { } } +// ExistingObjectTagPrefix is the prefix for object tag condition keys +const ExistingObjectTagPrefix = "s3:ExistingObjectTag/" + +// ObjectTagMetadataPrefix is the prefix used to store tags in entry.Extended +const ObjectTagMetadataPrefix = "X-Amz-Tagging-" + // EvaluateConditions evaluates all conditions in a policy statement -func EvaluateConditions(conditions PolicyConditions, contextValues map[string][]string) bool { +// objectEntry is the object's metadata from entry.Extended (can be nil) +func EvaluateConditions(conditions PolicyConditions, contextValues map[string][]string, objectEntry map[string][]byte) bool { if len(conditions) == 0 { return true // No conditions means always true } @@ -719,9 +726,27 @@ func EvaluateConditions(conditions PolicyConditions, contextValues map[string][] } for key, value := range conditionMap { - contextVals, exists := contextValues[key] - if !exists { - contextVals = []string{} + var contextVals []string + + // Handle s3:ExistingObjectTag/<tag-key> condition keys + // These refer to tags that already exist on the object + if strings.HasPrefix(key, ExistingObjectTagPrefix) { + // Extract tag value from entry.Extended using the tag prefix + tagKey := key[len(ExistingObjectTagPrefix):] + metadataKey := ObjectTagMetadataPrefix + tagKey + if objectEntry != nil { + if tagValue, exists := objectEntry[metadataKey]; exists { + contextVals = []string{string(tagValue)} + } + } + // If tag doesn't exist, contextVals remains empty + } else { + // Regular condition key lookup + var exists bool + contextVals, exists = contextValues[key] + if !exists { + contextVals = []string{} + } } if !conditionEvaluator.Evaluate(value.Strings(), contextVals) { @@ -734,7 +759,8 @@ func EvaluateConditions(conditions PolicyConditions, contextValues map[string][] } // EvaluateConditionsLegacy evaluates conditions using the old interface{} format for backward compatibility -func EvaluateConditionsLegacy(conditions map[string]interface{}, contextValues map[string][]string) bool { +// objectEntry is the object's metadata from entry.Extended (can be nil) +func EvaluateConditionsLegacy(conditions map[string]interface{}, contextValues map[string][]string, objectEntry map[string][]byte) bool { if len(conditions) == 0 { return true // No conditions means always true } @@ -753,9 +779,23 @@ func EvaluateConditionsLegacy(conditions map[string]interface{}, contextValues m } for key, value := range conditionMapTyped { - contextVals, exists := contextValues[key] - if !exists { - contextVals = []string{} + var contextVals []string + + // Handle s3:ExistingObjectTag/<tag-key> condition keys + if strings.HasPrefix(key, ExistingObjectTagPrefix) { + tagKey := key[len(ExistingObjectTagPrefix):] + metadataKey := ObjectTagMetadataPrefix + tagKey + if objectEntry != nil { + if tagValue, exists := objectEntry[metadataKey]; exists { + contextVals = []string{string(tagValue)} + } + } + } else { + var exists bool + contextVals, exists = contextValues[key] + if !exists { + contextVals = []string{} + } } if !conditionEvaluator.Evaluate(value, contextVals) { diff --git a/weed/s3api/policy_engine/engine.go b/weed/s3api/policy_engine/engine.go index 01af3c240..57a13881c 100644 --- a/weed/s3api/policy_engine/engine.go +++ b/weed/s3api/policy_engine/engine.go @@ -154,7 +154,7 @@ func (engine *PolicyEngine) evaluateStatement(stmt *CompiledStatement, args *Pol // Check conditions if len(stmt.Statement.Condition) > 0 { - if !EvaluateConditions(stmt.Statement.Condition, args.Conditions) { + if !EvaluateConditions(stmt.Statement.Condition, args.Conditions, args.ObjectEntry) { return false } } diff --git a/weed/s3api/policy_engine/types.go b/weed/s3api/policy_engine/types.go index d68b1f297..a8f822fb8 100644 --- a/weed/s3api/policy_engine/types.go +++ b/weed/s3api/policy_engine/types.go @@ -106,6 +106,11 @@ type PolicyEvaluationArgs struct { Resource string Principal string Conditions map[string][]string + // ObjectEntry is the object's metadata from entry.Extended. + // Used for evaluating conditions like s3:ExistingObjectTag/<tag-key>. + // Tags are stored as "X-Amz-Tagging-<key>" -> value. + // Can be nil for bucket-level operations or when object doesn't exist. + ObjectEntry map[string][]byte } // PolicyCache for caching compiled policies |
