mirror of
https://github.com/minio/minio.git
synced 2024-12-24 22:25:54 -05:00
starts-with policy condition support issue (#7937)
This commit is contained in:
parent
26985ac632
commit
dbf7b1e573
@ -315,6 +315,7 @@ const (
|
|||||||
ErrAdminProfilerNotEnabled
|
ErrAdminProfilerNotEnabled
|
||||||
ErrInvalidDecompressedSize
|
ErrInvalidDecompressedSize
|
||||||
ErrAddUserInvalidArgument
|
ErrAddUserInvalidArgument
|
||||||
|
ErrPostPolicyConditionInvalidFormat
|
||||||
)
|
)
|
||||||
|
|
||||||
type errorCodeMap map[APIErrorCode]APIError
|
type errorCodeMap map[APIErrorCode]APIError
|
||||||
@ -1496,6 +1497,11 @@ var errorCodes = errorCodeMap{
|
|||||||
Description: "User is not allowed to be same as admin access key",
|
Description: "User is not allowed to be same as admin access key",
|
||||||
HTTPStatusCode: http.StatusConflict,
|
HTTPStatusCode: http.StatusConflict,
|
||||||
},
|
},
|
||||||
|
ErrPostPolicyConditionInvalidFormat: {
|
||||||
|
Code: "PostPolicyInvalidKeyName",
|
||||||
|
Description: "Invalid according to Policy: Policy Condition failed",
|
||||||
|
HTTPStatusCode: http.StatusForbidden,
|
||||||
|
},
|
||||||
// Add your error structure here.
|
// Add your error structure here.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -656,9 +656,10 @@ func (api objectAPIHandlers) PostPolicyBucketHandler(w http.ResponseWriter, r *h
|
|||||||
|
|
||||||
// Handle policy if it is set.
|
// Handle policy if it is set.
|
||||||
if len(policyBytes) > 0 {
|
if len(policyBytes) > 0 {
|
||||||
|
|
||||||
postPolicyForm, err := parsePostPolicyForm(string(policyBytes))
|
postPolicyForm, err := parsePostPolicyForm(string(policyBytes))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrMalformedPOSTRequest), r.URL, guessIsBrowserReq(r))
|
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrPostPolicyConditionInvalidFormat), r.URL, guessIsBrowserReq(r))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -314,7 +314,7 @@ func testPostPolicyBucketHandler(obj ObjectLayer, instanceType string, t TestErr
|
|||||||
{
|
{
|
||||||
objectName: "test",
|
objectName: "test",
|
||||||
data: []byte("Hello, World"),
|
data: []byte("Hello, World"),
|
||||||
expectedRespStatus: http.StatusBadRequest,
|
expectedRespStatus: http.StatusForbidden,
|
||||||
accessKey: credentials.AccessKey,
|
accessKey: credentials.AccessKey,
|
||||||
secretKey: credentials.SecretKey,
|
secretKey: credentials.SecretKey,
|
||||||
dates: []interface{}{curTimePlus5Min.Format(expirationDateFormat), curTime.Format(iso8601DateFormat), curTime.Format(yyyymmdd)},
|
dates: []interface{}{curTimePlus5Min.Format(expirationDateFormat), curTime.Format(iso8601DateFormat), curTime.Format(yyyymmdd)},
|
||||||
|
@ -101,8 +101,9 @@ type contentLengthRange struct {
|
|||||||
type PostPolicyForm struct {
|
type PostPolicyForm struct {
|
||||||
Expiration time.Time // Expiration date and time of the POST policy.
|
Expiration time.Time // Expiration date and time of the POST policy.
|
||||||
Conditions struct { // Conditional policy structure.
|
Conditions struct { // Conditional policy structure.
|
||||||
Policies map[string]struct {
|
Policies []struct {
|
||||||
Operator string
|
Operator string
|
||||||
|
Key string
|
||||||
Value string
|
Value string
|
||||||
}
|
}
|
||||||
ContentLengthRange contentLengthRange
|
ContentLengthRange contentLengthRange
|
||||||
@ -130,10 +131,6 @@ func parsePostPolicyForm(policy string) (ppf PostPolicyForm, e error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return ppf, err
|
return ppf, err
|
||||||
}
|
}
|
||||||
parsedPolicy.Conditions.Policies = make(map[string]struct {
|
|
||||||
Operator string
|
|
||||||
Value string
|
|
||||||
})
|
|
||||||
|
|
||||||
// Parse conditions.
|
// Parse conditions.
|
||||||
for _, val := range rawPolicy.Conditions {
|
for _, val := range rawPolicy.Conditions {
|
||||||
@ -146,13 +143,13 @@ func parsePostPolicyForm(policy string) (ppf PostPolicyForm, e error) {
|
|||||||
}
|
}
|
||||||
// {"acl": "public-read" } is an alternate way to indicate - [ "eq", "$acl", "public-read" ]
|
// {"acl": "public-read" } is an alternate way to indicate - [ "eq", "$acl", "public-read" ]
|
||||||
// In this case we will just collapse this into "eq" for all use cases.
|
// In this case we will just collapse this into "eq" for all use cases.
|
||||||
parsedPolicy.Conditions.Policies["$"+strings.ToLower(k)] = struct {
|
parsedPolicy.Conditions.Policies = append(parsedPolicy.Conditions.Policies, struct {
|
||||||
Operator string
|
Operator string
|
||||||
|
Key string
|
||||||
Value string
|
Value string
|
||||||
}{
|
}{
|
||||||
Operator: policyCondEqual,
|
policyCondEqual, "$" + strings.ToLower(k), toString(v),
|
||||||
Value: toString(v),
|
})
|
||||||
}
|
|
||||||
}
|
}
|
||||||
case []interface{}: // Handle array types.
|
case []interface{}: // Handle array types.
|
||||||
if len(condt) != 3 { // Return error if we have insufficient elements.
|
if len(condt) != 3 { // Return error if we have insufficient elements.
|
||||||
@ -167,13 +164,16 @@ func parsePostPolicyForm(policy string) (ppf PostPolicyForm, e error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
operator, matchType, value := toLowerString(condt[0]), toLowerString(condt[1]), toString(condt[2])
|
operator, matchType, value := toLowerString(condt[0]), toLowerString(condt[1]), toString(condt[2])
|
||||||
parsedPolicy.Conditions.Policies[matchType] = struct {
|
if !strings.HasPrefix(matchType, "$") {
|
||||||
|
return parsedPolicy, fmt.Errorf("Invalid according to Policy: Policy Condition failed: [%s, %s, %s]", operator, matchType, value)
|
||||||
|
}
|
||||||
|
parsedPolicy.Conditions.Policies = append(parsedPolicy.Conditions.Policies, struct {
|
||||||
Operator string
|
Operator string
|
||||||
|
Key string
|
||||||
Value string
|
Value string
|
||||||
}{
|
}{
|
||||||
Operator: operator,
|
operator, matchType, value,
|
||||||
Value: value,
|
})
|
||||||
}
|
|
||||||
case policyCondContentLength:
|
case policyCondContentLength:
|
||||||
min, err := toInteger(condt[1])
|
min, err := toInteger(condt[1])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -224,10 +224,10 @@ func checkPostPolicy(formValues http.Header, postPolicyForm PostPolicyForm) erro
|
|||||||
}
|
}
|
||||||
// map to store the metadata
|
// map to store the metadata
|
||||||
metaMap := make(map[string]string)
|
metaMap := make(map[string]string)
|
||||||
for cond, v := range postPolicyForm.Conditions.Policies {
|
for _, policy := range postPolicyForm.Conditions.Policies {
|
||||||
if strings.HasPrefix(cond, "$x-amz-meta-") {
|
if strings.HasPrefix(policy.Key, "$x-amz-meta-") {
|
||||||
formCanonicalName := http.CanonicalHeaderKey(strings.TrimPrefix(cond, "$"))
|
formCanonicalName := http.CanonicalHeaderKey(strings.TrimPrefix(policy.Key, "$"))
|
||||||
metaMap[formCanonicalName] = v.Value
|
metaMap[formCanonicalName] = policy.Value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Check if any extra metadata field is passed as input
|
// Check if any extra metadata field is passed as input
|
||||||
@ -243,30 +243,30 @@ func checkPostPolicy(formValues http.Header, postPolicyForm PostPolicyForm) erro
|
|||||||
condPassed := true
|
condPassed := true
|
||||||
|
|
||||||
// Iterate over policy conditions and check them against received form fields
|
// Iterate over policy conditions and check them against received form fields
|
||||||
for cond, v := range postPolicyForm.Conditions.Policies {
|
for _, policy := range postPolicyForm.Conditions.Policies {
|
||||||
// Form fields names are in canonical format, convert conditions names
|
// Form fields names are in canonical format, convert conditions names
|
||||||
// to canonical for simplification purpose, so `$key` will become `Key`
|
// to canonical for simplification purpose, so `$key` will become `Key`
|
||||||
formCanonicalName := http.CanonicalHeaderKey(strings.TrimPrefix(cond, "$"))
|
formCanonicalName := http.CanonicalHeaderKey(strings.TrimPrefix(policy.Key, "$"))
|
||||||
// Operator for the current policy condition
|
// Operator for the current policy condition
|
||||||
op := v.Operator
|
op := policy.Operator
|
||||||
// If the current policy condition is known
|
// If the current policy condition is known
|
||||||
if startsWithSupported, condFound := startsWithConds[cond]; condFound {
|
if startsWithSupported, condFound := startsWithConds[policy.Key]; condFound {
|
||||||
// Check if the current condition supports starts-with operator
|
// Check if the current condition supports starts-with operator
|
||||||
if op == policyCondStartsWith && !startsWithSupported {
|
if op == policyCondStartsWith && !startsWithSupported {
|
||||||
return fmt.Errorf("Invalid according to Policy: Policy Condition failed")
|
return fmt.Errorf("Invalid according to Policy: Policy Condition failed")
|
||||||
}
|
}
|
||||||
// Check if current policy condition is satisfied
|
// Check if current policy condition is satisfied
|
||||||
condPassed = checkPolicyCond(op, formValues.Get(formCanonicalName), v.Value)
|
condPassed = checkPolicyCond(op, formValues.Get(formCanonicalName), policy.Value)
|
||||||
if !condPassed {
|
if !condPassed {
|
||||||
return fmt.Errorf("Invalid according to Policy: Policy Condition failed")
|
return fmt.Errorf("Invalid according to Policy: Policy Condition failed")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// This covers all conditions X-Amz-Meta-* and X-Amz-*
|
// This covers all conditions X-Amz-Meta-* and X-Amz-*
|
||||||
if strings.HasPrefix(cond, "$x-amz-meta-") || strings.HasPrefix(cond, "$x-amz-") {
|
if strings.HasPrefix(policy.Key, "$x-amz-meta-") || strings.HasPrefix(policy.Key, "$x-amz-") {
|
||||||
// Check if policy condition is satisfied
|
// Check if policy condition is satisfied
|
||||||
condPassed = checkPolicyCond(op, formValues.Get(formCanonicalName), v.Value)
|
condPassed = checkPolicyCond(op, formValues.Get(formCanonicalName), policy.Value)
|
||||||
if !condPassed {
|
if !condPassed {
|
||||||
return fmt.Errorf("Invalid according to Policy: Policy Condition failed: [%s, %s, %s]", op, cond, v.Value)
|
return fmt.Errorf("Invalid according to Policy: Policy Condition failed: [%s, %s, %s]", op, policy.Key, policy.Value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user