From 5b74f918d4f588927151254af6d6fc8ac7c79eee Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Wed, 9 May 2018 21:02:26 -0700 Subject: [PATCH] Implement a dummy GetBucketACL for legacy reasons (#5906) GetBucketACL call returns empty for all GET in ACL requests, the primary purpose of this PR is to provide legacy API support for legacy applications. Fixes #5706 --- cmd/acl-handlers.go | 141 ++++++++++++++++++++++++++++++++++++++++ cmd/api-router.go | 4 ++ cmd/generic-handlers.go | 9 +++ 3 files changed, 154 insertions(+) create mode 100644 cmd/acl-handlers.go diff --git a/cmd/acl-handlers.go b/cmd/acl-handlers.go new file mode 100644 index 000000000..8a67754a0 --- /dev/null +++ b/cmd/acl-handlers.go @@ -0,0 +1,141 @@ +/* + * Minio Cloud Storage, (C) 2018 Minio, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cmd + +import ( + "encoding/xml" + "net/http" + + "github.com/gorilla/mux" + "github.com/minio/minio/pkg/policy" +) + +// Data types used for returning dummy access control +// policy XML, these variables shouldn't be used elsewhere +// they are only defined to be used in this file alone. +type grantee struct { + XMLNS string `xml:"xmlns:xsi,attr"` + XMLXSI string `xml:"xsi:type,attr"` + Type string `xml:"Type"` + ID string `xml:"ID,omitempty"` + DisplayName string `xml:"DisplayName,omitempty"` + URI string `xml:"URI,omitempty"` +} + +type grant struct { + Grantee grantee `xml:"Grantee"` + Permission string `xml:"Permission"` +} + +type accessControlPolicy struct { + XMLName xml.Name `xml:"AccessControlPolicy"` + Owner Owner `xml:"Owner"` + AccessControlList struct { + Grants []grant `xml:"Grant"` + } `xml:"AccessControlList"` +} + +// GetBucketACLHandler - GET Bucket ACL +// ----------------- +// This operation uses the ACL +// subresource to return the ACL of a specified bucket. +func (api objectAPIHandlers) GetBucketACLHandler(w http.ResponseWriter, r *http.Request) { + ctx := newContext(r, "GetBucketACL") + + vars := mux.Vars(r) + bucket := vars["bucket"] + + objAPI := api.ObjectAPI() + if objAPI == nil { + writeErrorResponse(w, ErrServerNotInitialized, r.URL) + return + } + + // Allow getBucketACL if policy action is set, since this is a dummy call + // we are simply re-purposing the bucketPolicyAction. + if s3Error := checkRequestAuthType(ctx, r, policy.GetBucketPolicyAction, bucket, ""); s3Error != ErrNone { + writeErrorResponse(w, s3Error, r.URL) + return + } + + // Before proceeding validate if bucket exists. + _, err := objAPI.GetBucketInfo(ctx, bucket) + if err != nil { + writeErrorResponse(w, toAPIErrorCode(err), r.URL) + return + } + + acl := &accessControlPolicy{} + acl.AccessControlList.Grants = append(acl.AccessControlList.Grants, grant{ + Grantee: grantee{ + Type: "CanonicalUser", + }, + Permission: "FULL_CONTROL", + }) + if err := xml.NewEncoder(w).Encode(acl); err != nil { + writeErrorResponse(w, toAPIErrorCode(err), r.URL) + return + } + + w.(http.Flusher).Flush() +} + +// GetObjectACLHandler - GET Object ACL +// ----------------- +// This operation uses the ACL +// subresource to return the ACL of a specified object. +func (api objectAPIHandlers) GetObjectACLHandler(w http.ResponseWriter, r *http.Request) { + ctx := newContext(r, "GetObjectACL") + + vars := mux.Vars(r) + bucket := vars["bucket"] + object := vars["object"] + + objAPI := api.ObjectAPI() + if objAPI == nil { + writeErrorResponse(w, ErrServerNotInitialized, r.URL) + return + } + + // Allow getObjectACL if policy action is set, since this is a dummy call + // we are simply re-purposing the bucketPolicyAction. + if s3Error := checkRequestAuthType(ctx, r, policy.GetBucketPolicyAction, bucket, ""); s3Error != ErrNone { + writeErrorResponse(w, s3Error, r.URL) + return + } + + // Before proceeding validate if object exists. + _, err := objAPI.GetObjectInfo(ctx, bucket, object) + if err != nil { + writeErrorResponse(w, toAPIErrorCode(err), r.URL) + return + } + + acl := &accessControlPolicy{} + acl.AccessControlList.Grants = append(acl.AccessControlList.Grants, grant{ + Grantee: grantee{ + Type: "CanonicalUser", + }, + Permission: "FULL_CONTROL", + }) + if err := xml.NewEncoder(w).Encode(acl); err != nil { + writeErrorResponse(w, toAPIErrorCode(err), r.URL) + return + } + + w.(http.Flusher).Flush() +} diff --git a/cmd/api-router.go b/cmd/api-router.go index f5c51a7f4..f7f80ef41 100644 --- a/cmd/api-router.go +++ b/cmd/api-router.go @@ -83,6 +83,10 @@ func registerAPIRouter(router *mux.Router) { bucket.Methods("GET").HandlerFunc(httpTraceAll(api.GetBucketLocationHandler)).Queries("location", "") // GetBucketPolicy bucket.Methods("GET").HandlerFunc(httpTraceAll(api.GetBucketPolicyHandler)).Queries("policy", "") + + // GetBucketACL -- this is a dummy call. + bucket.Methods("GET").HandlerFunc(httpTraceAll(api.GetBucketACLHandler)).Queries("acl", "") + // GetBucketNotification bucket.Methods("GET").HandlerFunc(httpTraceAll(api.GetBucketNotificationHandler)).Queries("notification", "") // ListenBucketNotification diff --git a/cmd/generic-handlers.go b/cmd/generic-handlers.go index 5c334b80c..37715bf5c 100644 --- a/cmd/generic-handlers.go +++ b/cmd/generic-handlers.go @@ -420,6 +420,11 @@ func setIgnoreResourcesHandler(h http.Handler) http.Handler { // Checks requests for not implemented Bucket resources func ignoreNotImplementedBucketResources(req *http.Request) bool { for name := range req.URL.Query() { + // Enable GetBucketACL dummy call specifically. + if name == "acl" && req.Method == http.MethodGet { + return false + } + if notimplementedBucketResourceNames[name] { return true } @@ -430,6 +435,10 @@ func ignoreNotImplementedBucketResources(req *http.Request) bool { // Checks requests for not implemented Object resources func ignoreNotImplementedObjectResources(req *http.Request) bool { for name := range req.URL.Query() { + // Enable GetObjectACL dummy call specifically. + if name == "acl" && req.Method == http.MethodGet { + return false + } if notimplementedObjectResourceNames[name] { return true }