mirror of https://github.com/minio/minio.git
Provide 200 response with per object error listing on access denied for delete multiple object request (#4817)
This commit is contained in:
parent
a2f2044528
commit
3d21119ec8
|
@ -240,9 +240,14 @@ func (api objectAPIHandlers) DeleteMultipleObjectsHandler(w http.ResponseWriter,
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if s3Error := checkRequestAuthType(r, bucket, "s3:DeleteObject", serverConfig.GetRegion()); s3Error != ErrNone {
|
var authError APIErrorCode
|
||||||
writeErrorResponse(w, s3Error, r.URL)
|
if authError = checkRequestAuthType(r, bucket, "s3:DeleteObject", serverConfig.GetRegion()); authError != ErrNone {
|
||||||
return
|
// In the event access is denied, a 200 response should still be returned
|
||||||
|
// http://docs.aws.amazon.com/AmazonS3/latest/API/multiobjectdeleteapi.html
|
||||||
|
if authError != ErrAccessDenied {
|
||||||
|
writeErrorResponse(w, authError, r.URL)
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Content-Length is required and should be non-zero
|
// Content-Length is required and should be non-zero
|
||||||
|
@ -284,10 +289,19 @@ func (api objectAPIHandlers) DeleteMultipleObjectsHandler(w http.ResponseWriter,
|
||||||
for index, object := range deleteObjects.Objects {
|
for index, object := range deleteObjects.Objects {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func(i int, obj ObjectIdentifier) {
|
go func(i int, obj ObjectIdentifier) {
|
||||||
|
defer wg.Done()
|
||||||
|
// If the request is denied access, each item
|
||||||
|
// should be marked as 'AccessDenied'
|
||||||
|
if authError == ErrAccessDenied {
|
||||||
|
dErrs[i] = PrefixAccessDenied{
|
||||||
|
Bucket: bucket,
|
||||||
|
Object: obj.ObjectName,
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
objectLock := globalNSMutex.NewNSLock(bucket, obj.ObjectName)
|
objectLock := globalNSMutex.NewNSLock(bucket, obj.ObjectName)
|
||||||
objectLock.Lock()
|
objectLock.Lock()
|
||||||
defer objectLock.Unlock()
|
defer objectLock.Unlock()
|
||||||
defer wg.Done()
|
|
||||||
|
|
||||||
dErr := objectAPI.DeleteObject(bucket, obj.ObjectName)
|
dErr := objectAPI.DeleteObject(bucket, obj.ObjectName)
|
||||||
if dErr != nil {
|
if dErr != nil {
|
||||||
|
|
|
@ -650,6 +650,17 @@ func testAPIDeleteMultipleObjectsHandler(obj ObjectLayer, instanceType, bucketNa
|
||||||
|
|
||||||
return objectIdentifierList
|
return objectIdentifierList
|
||||||
}
|
}
|
||||||
|
getDeleteErrorList := func(objects []ObjectIdentifier) (deleteErrorList []DeleteError) {
|
||||||
|
for _, obj := range objects {
|
||||||
|
deleteErrorList = append(deleteErrorList, DeleteError{
|
||||||
|
Code: errorCodeResponse[ErrAccessDenied].Code,
|
||||||
|
Message: errorCodeResponse[ErrAccessDenied].Description,
|
||||||
|
Key: obj.ObjectName,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return deleteErrorList
|
||||||
|
}
|
||||||
|
|
||||||
requestList := []DeleteObjectsRequest{
|
requestList := []DeleteObjectsRequest{
|
||||||
{Quiet: false, Objects: getObjectIdentifierList(objectNames[:5])},
|
{Quiet: false, Objects: getObjectIdentifierList(objectNames[:5])},
|
||||||
|
@ -670,6 +681,10 @@ func testAPIDeleteMultipleObjectsHandler(obj ObjectLayer, instanceType, bucketNa
|
||||||
errorResponse := generateMultiDeleteResponse(requestList[1].Quiet, requestList[1].Objects, nil)
|
errorResponse := generateMultiDeleteResponse(requestList[1].Quiet, requestList[1].Objects, nil)
|
||||||
encodedErrorResponse := encodeResponse(errorResponse)
|
encodedErrorResponse := encodeResponse(errorResponse)
|
||||||
|
|
||||||
|
anonRequest := encodeResponse(requestList[0])
|
||||||
|
anonResponse := generateMultiDeleteResponse(requestList[0].Quiet, nil, getDeleteErrorList(requestList[0].Objects))
|
||||||
|
encodedAnonResponse := encodeResponse(anonResponse)
|
||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
bucket string
|
bucket string
|
||||||
objects []byte
|
objects []byte
|
||||||
|
@ -718,15 +733,32 @@ func testAPIDeleteMultipleObjectsHandler(obj ObjectLayer, instanceType, bucketNa
|
||||||
expectedContent: encodedErrorResponse,
|
expectedContent: encodedErrorResponse,
|
||||||
expectedRespStatus: http.StatusOK,
|
expectedRespStatus: http.StatusOK,
|
||||||
},
|
},
|
||||||
|
// Test case - 5.
|
||||||
|
// Anonymous user access denied response
|
||||||
|
// Currently anonymous users cannot delete multiple objects in Minio server
|
||||||
|
{
|
||||||
|
bucket: bucketName,
|
||||||
|
objects: anonRequest,
|
||||||
|
accessKey: "",
|
||||||
|
secretKey: "",
|
||||||
|
expectedContent: encodedAnonResponse,
|
||||||
|
expectedRespStatus: http.StatusOK,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, testCase := range testCases {
|
for i, testCase := range testCases {
|
||||||
var req *http.Request
|
var req *http.Request
|
||||||
var actualContent []byte
|
var actualContent []byte
|
||||||
|
|
||||||
// Indicating that all parts are uploaded and initiating completeMultipartUpload.
|
// Generate a signed or anonymous request based on the testCase
|
||||||
req, err = newTestSignedRequestV4("POST", getDeleteMultipleObjectsURL("", bucketName),
|
if testCase.accessKey != "" {
|
||||||
int64(len(testCase.objects)), bytes.NewReader(testCase.objects), testCase.accessKey, testCase.secretKey)
|
req, err = newTestSignedRequestV4("POST", getDeleteMultipleObjectsURL("", bucketName),
|
||||||
|
int64(len(testCase.objects)), bytes.NewReader(testCase.objects), testCase.accessKey, testCase.secretKey)
|
||||||
|
} else {
|
||||||
|
req, err = newTestRequest("POST", getDeleteMultipleObjectsURL("", bucketName),
|
||||||
|
int64(len(testCase.objects)), bytes.NewReader(testCase.objects))
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to create HTTP request for DeleteMultipleObjects: <ERROR> %v", err)
|
t.Fatalf("Failed to create HTTP request for DeleteMultipleObjects: <ERROR> %v", err)
|
||||||
}
|
}
|
||||||
|
@ -753,8 +785,6 @@ func testAPIDeleteMultipleObjectsHandler(obj ObjectLayer, instanceType, bucketNa
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Currently anonymous user cannot delete multiple objects in Minio server, hence no test case is required.
|
|
||||||
|
|
||||||
// HTTP request to test the case of `objectLayer` being set to `nil`.
|
// HTTP request to test the case of `objectLayer` being set to `nil`.
|
||||||
// There is no need to use an existing bucket or valid input for creating the request,
|
// There is no need to use an existing bucket or valid input for creating the request,
|
||||||
// since the `objectLayer==nil` check is performed before any other checks inside the handlers.
|
// since the `objectLayer==nil` check is performed before any other checks inside the handlers.
|
||||||
|
|
Loading…
Reference in New Issue