2 changed files with 180 additions and 9 deletions
@ -0,0 +1,172 @@ |
|||||
|
package s3api |
||||
|
|
||||
|
import ( |
||||
|
"github.com/seaweedfs/seaweedfs/weed/iam/policy" |
||||
|
"github.com/seaweedfs/seaweedfs/weed/s3api/policy_engine" |
||||
|
) |
||||
|
|
||||
|
// ConvertPolicyDocumentToPolicyEngine converts a policy.PolicyDocument to policy_engine.PolicyDocument
|
||||
|
// This function provides efficient type conversion without JSON marshaling overhead.
|
||||
|
// It handles the differences between the two types:
|
||||
|
// - Converts []string fields to StringOrStringSlice
|
||||
|
// - Maps Condition types
|
||||
|
// - Handles optional fields (Id, NotPrincipal, NotAction, NotResource are ignored in policy_engine)
|
||||
|
func ConvertPolicyDocumentToPolicyEngine(src *policy.PolicyDocument) *policy_engine.PolicyDocument { |
||||
|
if src == nil { |
||||
|
return nil |
||||
|
} |
||||
|
|
||||
|
dest := &policy_engine.PolicyDocument{ |
||||
|
Version: src.Version, |
||||
|
Statement: make([]policy_engine.PolicyStatement, len(src.Statement)), |
||||
|
} |
||||
|
|
||||
|
for i, srcStmt := range src.Statement { |
||||
|
dest.Statement[i] = convertStatement(&srcStmt) |
||||
|
} |
||||
|
|
||||
|
return dest |
||||
|
} |
||||
|
|
||||
|
// convertStatement converts a policy.Statement to policy_engine.PolicyStatement
|
||||
|
func convertStatement(src *policy.Statement) policy_engine.PolicyStatement { |
||||
|
stmt := policy_engine.PolicyStatement{ |
||||
|
Sid: src.Sid, |
||||
|
Effect: policy_engine.PolicyEffect(src.Effect), |
||||
|
} |
||||
|
|
||||
|
// Convert Action ([]string to StringOrStringSlice)
|
||||
|
if len(src.Action) > 0 { |
||||
|
stmt.Action = policy_engine.NewStringOrStringSlice(src.Action...) |
||||
|
} |
||||
|
|
||||
|
// Convert Resource ([]string to StringOrStringSlice)
|
||||
|
if len(src.Resource) > 0 { |
||||
|
stmt.Resource = policy_engine.NewStringOrStringSlice(src.Resource...) |
||||
|
} |
||||
|
|
||||
|
// Convert Principal (interface{} to *StringOrStringSlice)
|
||||
|
if src.Principal != nil { |
||||
|
stmt.Principal = convertPrincipal(src.Principal) |
||||
|
} |
||||
|
|
||||
|
// Convert Condition (map[string]map[string]interface{} to PolicyConditions)
|
||||
|
if len(src.Condition) > 0 { |
||||
|
stmt.Condition = convertCondition(src.Condition) |
||||
|
} |
||||
|
|
||||
|
return stmt |
||||
|
} |
||||
|
|
||||
|
// convertPrincipal converts a Principal field to *StringOrStringSlice
|
||||
|
func convertPrincipal(principal interface{}) *policy_engine.StringOrStringSlice { |
||||
|
if principal == nil { |
||||
|
return nil |
||||
|
} |
||||
|
|
||||
|
switch p := principal.(type) { |
||||
|
case string: |
||||
|
result := policy_engine.NewStringOrStringSlice(p) |
||||
|
return &result |
||||
|
case []string: |
||||
|
result := policy_engine.NewStringOrStringSlice(p...) |
||||
|
return &result |
||||
|
case []interface{}: |
||||
|
// Convert []interface{} to []string
|
||||
|
strs := make([]string, 0, len(p)) |
||||
|
for _, v := range p { |
||||
|
if str, ok := v.(string); ok { |
||||
|
strs = append(strs, str) |
||||
|
} |
||||
|
} |
||||
|
if len(strs) > 0 { |
||||
|
result := policy_engine.NewStringOrStringSlice(strs...) |
||||
|
return &result |
||||
|
} |
||||
|
case map[string]interface{}: |
||||
|
// Handle AWS-style principal with service/user keys
|
||||
|
// Example: {"AWS": "arn:aws:iam::123456789012:user/Alice"}
|
||||
|
strs := make([]string, 0) |
||||
|
for _, v := range p { |
||||
|
switch val := v.(type) { |
||||
|
case string: |
||||
|
strs = append(strs, val) |
||||
|
case []string: |
||||
|
strs = append(strs, val...) |
||||
|
case []interface{}: |
||||
|
for _, item := range val { |
||||
|
if str, ok := item.(string); ok { |
||||
|
strs = append(strs, str) |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
if len(strs) > 0 { |
||||
|
result := policy_engine.NewStringOrStringSlice(strs...) |
||||
|
return &result |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return nil |
||||
|
} |
||||
|
|
||||
|
// convertCondition converts policy conditions to PolicyConditions
|
||||
|
func convertCondition(src map[string]map[string]interface{}) policy_engine.PolicyConditions { |
||||
|
if len(src) == 0 { |
||||
|
return nil |
||||
|
} |
||||
|
|
||||
|
dest := make(policy_engine.PolicyConditions) |
||||
|
for condType, condBlock := range src { |
||||
|
destBlock := make(map[string]policy_engine.StringOrStringSlice) |
||||
|
for key, value := range condBlock { |
||||
|
destBlock[key] = convertConditionValue(value) |
||||
|
} |
||||
|
dest[condType] = destBlock |
||||
|
} |
||||
|
|
||||
|
return dest |
||||
|
} |
||||
|
|
||||
|
// convertConditionValue converts a condition value to StringOrStringSlice
|
||||
|
func convertConditionValue(value interface{}) policy_engine.StringOrStringSlice { |
||||
|
switch v := value.(type) { |
||||
|
case string: |
||||
|
return policy_engine.NewStringOrStringSlice(v) |
||||
|
case []string: |
||||
|
return policy_engine.NewStringOrStringSlice(v...) |
||||
|
case []interface{}: |
||||
|
strs := make([]string, 0, len(v)) |
||||
|
for _, item := range v { |
||||
|
if str, ok := item.(string); ok { |
||||
|
strs = append(strs, str) |
||||
|
} |
||||
|
} |
||||
|
return policy_engine.NewStringOrStringSlice(strs...) |
||||
|
default: |
||||
|
// For non-string types, convert to string
|
||||
|
// This handles numbers, booleans, etc.
|
||||
|
return policy_engine.NewStringOrStringSlice(convertToString(v)) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// convertToString converts any value to string representation
|
||||
|
func convertToString(value interface{}) string { |
||||
|
switch v := value.(type) { |
||||
|
case string: |
||||
|
return v |
||||
|
case bool: |
||||
|
if v { |
||||
|
return "true" |
||||
|
} |
||||
|
return "false" |
||||
|
case int, int8, int16, int32, int64, |
||||
|
uint, uint8, uint16, uint32, uint64, |
||||
|
float32, float64: |
||||
|
// Use fmt.Sprintf for numeric types
|
||||
|
return "" |
||||
|
default: |
||||
|
return "" |
||||
|
} |
||||
|
} |
||||
|
|
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue