Fix: Allow deleting multiple objects anonymously if policy supports it (#7439)

Fixes #5683
master
kannappanr 6 years ago committed by Nitish Tiwari
parent 188cf1d5ce
commit 0c75395abe
  1. 39
      cmd/bucket-handlers.go
  2. 41
      cmd/web-handlers.go

@ -263,16 +263,6 @@ func (api objectAPIHandlers) DeleteMultipleObjectsHandler(w http.ResponseWriter,
return
}
var s3Error APIErrorCode
if s3Error = checkRequestAuthType(ctx, r, policy.DeleteObjectAction, bucket, ""); s3Error != ErrNone {
// In the event access is denied, a 200 response should still be returned
// http://docs.aws.amazon.com/AmazonS3/latest/API/multiobjectdeleteapi.html
if s3Error != ErrAccessDenied {
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(s3Error), r.URL, guessIsBrowserReq(r))
return
}
}
// Content-Length is required and should be non-zero
// http://docs.aws.amazon.com/AmazonS3/latest/API/multiobjectdeleteapi.html
if r.ContentLength <= 0 {
@ -324,37 +314,32 @@ func (api objectAPIHandlers) DeleteMultipleObjectsHandler(w http.ResponseWriter,
deleteObject = api.CacheAPI().DeleteObject
}
var dErrs = make([]error, len(deleteObjects.Objects))
var dErrs = make([]APIErrorCode, len(deleteObjects.Objects))
for index, object := range deleteObjects.Objects {
// If the request is denied access, each item
// should be marked as 'AccessDenied'
if s3Error == ErrAccessDenied {
dErrs[index] = PrefixAccessDenied{
Bucket: bucket,
Object: object.ObjectName,
if dErrs[index] = checkRequestAuthType(ctx, r, policy.DeleteObjectAction, bucket, object.ObjectName); dErrs[index] != ErrNone {
if dErrs[index] == ErrSignatureDoesNotMatch || dErrs[index] == ErrInvalidAccessKeyID {
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(dErrs[index]), r.URL, guessIsBrowserReq(r))
return
}
continue
}
dErrs[index] = deleteObject(ctx, bucket, object.ObjectName)
err := deleteObject(ctx, bucket, object.ObjectName)
if err != nil {
dErrs[index] = toAPIErrorCode(ctx, err)
}
}
// Collect deleted objects and errors if any.
var deletedObjects []ObjectIdentifier
var deleteErrors []DeleteError
for index, err := range dErrs {
for index, errCode := range dErrs {
object := deleteObjects.Objects[index]
// Success deleted objects are collected separately.
if err == nil {
deletedObjects = append(deletedObjects, object)
continue
}
if _, ok := err.(ObjectNotFound); ok {
// If the object is not found it should be
// accounted as deleted as per S3 spec.
if errCode == ErrNone || errCode == ErrNoSuchKey {
deletedObjects = append(deletedObjects, object)
continue
}
apiErr := toAPIError(ctx, err)
apiErr := getAPIError(errCode)
// Error during delete should be collected separately.
deleteErrors = append(deleteErrors, DeleteError{
Code: apiErr.Code,

@ -583,7 +583,22 @@ func (web *webAPIHandlers) RemoveObject(r *http.Request, args *RemoveObjectArgs,
claims, owner, authErr := webRequestAuthenticate(r)
if authErr != nil {
return toJSONError(authErr)
if authErr == errNoAuthToken {
// Check if all objects are allowed to be deleted anonymously
for _, object := range args.Objects {
if !globalPolicySys.IsAllowed(policy.Args{
Action: policy.DeleteObjectAction,
BucketName: args.BucketName,
ConditionValues: getConditionValues(r, "", ""),
IsOwner: false,
ObjectName: object,
}) {
return toJSONError(errAuthentication)
}
}
} else {
return toJSONError(authErr)
}
}
if args.BucketName == "" || len(args.Objects) == 0 {
@ -640,16 +655,20 @@ next:
return toJSONError(errMethodNotAllowed)
}
}
if !globalIAMSys.IsAllowed(iampolicy.Args{
AccountName: claims.Subject,
Action: iampolicy.DeleteObjectAction,
BucketName: args.BucketName,
ConditionValues: getConditionValues(r, "", claims.Subject),
IsOwner: owner,
ObjectName: objectName,
}) {
return toJSONError(errAccessDenied)
// Check for permissions only in the case of
// non-anonymous login. For anonymous login, policy has already
// been checked.
if authErr != errNoAuthToken {
if !globalIAMSys.IsAllowed(iampolicy.Args{
AccountName: claims.Subject,
Action: iampolicy.DeleteObjectAction,
BucketName: args.BucketName,
ConditionValues: getConditionValues(r, "", claims.Subject),
IsOwner: owner,
ObjectName: objectName,
}) {
return toJSONError(errAccessDenied)
}
}
if err = deleteObject(context.Background(), objectAPI, web.CacheAPI(), args.BucketName, objectName, r); err != nil {

Loading…
Cancel
Save