fix: allow listBuckets with listBuckets permission (#9253)

master
Harshavardhana 5 years ago committed by GitHub
parent 73f9d8a636
commit ab66b23194
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 8
      cmd/auth-handler.go
  2. 57
      cmd/bucket-handlers.go
  3. 12
      cmd/test-utils_test.go

@ -272,7 +272,7 @@ func checkRequestAuthTypeToAccessKey(ctx context.Context, r *http.Request, actio
var cred auth.Credentials var cred auth.Credentials
switch getRequestAuthType(r) { switch getRequestAuthType(r) {
case authTypeUnknown, authTypeStreamingSigned: case authTypeUnknown, authTypeStreamingSigned:
return accessKey, owner, ErrAccessDenied return accessKey, owner, ErrSignatureVersionNotSupported
case authTypePresignedV2, authTypeSignedV2: case authTypePresignedV2, authTypeSignedV2:
if s3Err = isReqAuthenticatedV2(r); s3Err != ErrNone { if s3Err = isReqAuthenticatedV2(r); s3Err != ErrNone {
return accessKey, owner, s3Err return accessKey, owner, s3Err
@ -334,7 +334,7 @@ func checkRequestAuthTypeToAccessKey(ctx context.Context, r *http.Request, actio
// Request is allowed return the appropriate access key. // Request is allowed return the appropriate access key.
return cred.AccessKey, owner, ErrNone return cred.AccessKey, owner, ErrNone
} }
return accessKey, owner, ErrAccessDenied return cred.AccessKey, owner, ErrAccessDenied
} }
if globalIAMSys.IsAllowed(iampolicy.Args{ if globalIAMSys.IsAllowed(iampolicy.Args{
AccountName: cred.AccessKey, AccountName: cred.AccessKey,
@ -348,7 +348,7 @@ func checkRequestAuthTypeToAccessKey(ctx context.Context, r *http.Request, actio
// Request is allowed return the appropriate access key. // Request is allowed return the appropriate access key.
return cred.AccessKey, owner, ErrNone return cred.AccessKey, owner, ErrNone
} }
return accessKey, owner, ErrAccessDenied return cred.AccessKey, owner, ErrAccessDenied
} }
// Verify if request has valid AWS Signature Version '2'. // Verify if request has valid AWS Signature Version '2'.
@ -472,7 +472,7 @@ func isPutActionAllowed(atype authType, bucketName, objectName string, r *http.R
var owner bool var owner bool
switch atype { switch atype {
case authTypeUnknown: case authTypeUnknown:
return ErrAccessDenied return ErrSignatureVersionNotSupported
case authTypeSignedV2, authTypePresignedV2: case authTypeSignedV2, authTypePresignedV2:
cred, owner, s3Err = getReqAccessKeyV2(r) cred, owner, s3Err = getReqAccessKeyV2(r)
case authTypeStreamingSigned, authTypePresigned, authTypeSigned: case authTypeStreamingSigned, authTypePresigned, authTypeSigned:

@ -266,7 +266,7 @@ func (api objectAPIHandlers) ListBucketsHandler(w http.ResponseWriter, r *http.R
listBuckets := objectAPI.ListBuckets listBuckets := objectAPI.ListBuckets
accessKey, owner, s3Error := checkRequestAuthTypeToAccessKey(ctx, r, policy.ListAllMyBucketsAction, "", "") accessKey, owner, s3Error := checkRequestAuthTypeToAccessKey(ctx, r, policy.ListAllMyBucketsAction, "", "")
if s3Error != ErrNone { if s3Error != ErrNone && s3Error != ErrAccessDenied {
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(s3Error), r.URL, guessIsBrowserReq(r)) writeErrorResponse(ctx, w, errorCodes.ToAPIErr(s3Error), r.URL, guessIsBrowserReq(r))
return return
} }
@ -295,32 +295,43 @@ func (api objectAPIHandlers) ListBucketsHandler(w http.ResponseWriter, r *http.R
} }
} }
// Set prefix value for "s3:prefix" policy conditionals. if s3Error == ErrAccessDenied {
r.Header.Set("prefix", "") // Set prefix value for "s3:prefix" policy conditionals.
r.Header.Set("prefix", "")
// Set delimiter value for "s3:delimiter" policy conditionals.
r.Header.Set("delimiter", SlashSeparator) // Set delimiter value for "s3:delimiter" policy conditionals.
r.Header.Set("delimiter", SlashSeparator)
// err will be nil here as we already called this function
// earlier in this request. // err will be nil here as we already called this function
claims, _ := getClaimsFromToken(r) // earlier in this request.
var newBucketsInfo []BucketInfo claims, _ := getClaimsFromToken(r)
for _, bucketInfo := range bucketsInfo { n := 0
if globalIAMSys.IsAllowed(iampolicy.Args{ // Use the following trick to filter in place
AccountName: accessKey, // https://github.com/golang/go/wiki/SliceTricks#filter-in-place
Action: iampolicy.ListBucketAction, for _, bucketInfo := range bucketsInfo {
BucketName: bucketInfo.Name, if globalIAMSys.IsAllowed(iampolicy.Args{
ConditionValues: getConditionValues(r, "", accessKey, claims), AccountName: accessKey,
IsOwner: owner, Action: iampolicy.ListBucketAction,
ObjectName: "", BucketName: bucketInfo.Name,
Claims: claims, ConditionValues: getConditionValues(r, "", accessKey, claims),
}) { IsOwner: owner,
newBucketsInfo = append(newBucketsInfo, bucketInfo) ObjectName: "",
Claims: claims,
}) {
bucketsInfo[n] = bucketInfo
n++
}
}
bucketsInfo = bucketsInfo[:n]
// No buckets can be filtered return access denied error.
if len(bucketsInfo) == 0 {
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(s3Error), r.URL, guessIsBrowserReq(r))
return
} }
} }
// Generate response. // Generate response.
response := generateListBucketsResponse(newBucketsInfo) response := generateListBucketsResponse(bucketsInfo)
encodedSuccessResponse := encodeResponse(response) encodedSuccessResponse := encodeResponse(response)
// Write response. // Write response.

@ -1737,9 +1737,9 @@ func ExecObjectLayerAPIAnonTest(t *testing.T, obj ObjectLayer, testName, bucketN
apiRouter.ServeHTTP(rec, anonReq) apiRouter.ServeHTTP(rec, anonReq)
// expected error response when the unsigned HTTP request is not permitted. // expected error response when the unsigned HTTP request is not permitted.
accesDeniedHTTPStatus := getAPIError(ErrAccessDenied).HTTPStatusCode accessDenied := getAPIError(ErrAccessDenied).HTTPStatusCode
if rec.Code != accesDeniedHTTPStatus { if rec.Code != accessDenied {
t.Fatal(failTestStr(anonTestStr, fmt.Sprintf("Object API Nil Test expected to fail with %d, but failed with %d", accesDeniedHTTPStatus, rec.Code))) t.Fatal(failTestStr(anonTestStr, fmt.Sprintf("Object API Nil Test expected to fail with %d, but failed with %d", accessDenied, rec.Code)))
} }
// HEAD HTTTP request doesn't contain response body. // HEAD HTTTP request doesn't contain response body.
@ -1826,8 +1826,10 @@ func ExecObjectLayerAPIAnonTest(t *testing.T, obj ObjectLayer, testName, bucketN
} }
} }
if rec.Code != accesDeniedHTTPStatus { // expected error response when the unsigned HTTP request is not permitted.
t.Fatal(failTestStr(unknownSignTestStr, fmt.Sprintf("Object API Unknow auth test for \"%s\", expected to fail with %d, but failed with %d", testName, accesDeniedHTTPStatus, rec.Code))) unsupportedSignature := getAPIError(ErrSignatureVersionNotSupported).HTTPStatusCode
if rec.Code != unsupportedSignature {
t.Fatal(failTestStr(unknownSignTestStr, fmt.Sprintf("Object API Unknow auth test for \"%s\", expected to fail with %d, but failed with %d", testName, unsupportedSignature, rec.Code)))
} }
} }

Loading…
Cancel
Save