From aec409ffcfd95b6e1643faefbf53b307d866e982 Mon Sep 17 00:00:00 2001 From: Mofei Zhang Date: Thu, 27 Feb 2020 20:35:04 +0800 Subject: [PATCH] Refactor: using middleware for policy valication. Signed-off-by: Mofei Zhang --- objectnode/api_handler.go | 4 + objectnode/api_handler_object.go | 148 +++++++++++++++++- objectnode/api_middleware.go | 27 ++-- objectnode/fs_volume.go | 20 ++- objectnode/policy_action.go | 112 ++++++++------ objectnode/result.go | 5 + objectnode/router.go | 257 +++++++++++++++++-------------- objectnode/server.go | 1 + 8 files changed, 391 insertions(+), 183 deletions(-) diff --git a/objectnode/api_handler.go b/objectnode/api_handler.go index 46f96c314..7e50235b2 100644 --- a/objectnode/api_handler.go +++ b/objectnode/api_handler.go @@ -38,6 +38,10 @@ type RequestParam struct { accessKey string } +func (p *RequestParam) GetVar(name string) string { + return p.vars[name] +} + func (o *ObjectNode) parseRequestParam(r *http.Request) (*RequestParam, error) { p := new(RequestParam) p.vars = mux.Vars(r) diff --git a/objectnode/api_handler_object.go b/objectnode/api_handler_object.go index 9609dce19..7a039021a 100644 --- a/objectnode/api_handler_object.go +++ b/objectnode/api_handler_object.go @@ -18,6 +18,7 @@ import ( "encoding/base64" "encoding/hex" "encoding/json" + "encoding/xml" "fmt" "io" "io/ioutil" @@ -819,7 +820,7 @@ func (o *ObjectNode) putObjectTaggingHandler(w http.ResponseWriter, r *http.Requ } var tagging = NewTagging() - if err = UnmarshalXMLEntity(requestBody, tagging); err != nil { + if err = xml.Unmarshal(requestBody, tagging); err != nil { log.LogWarnf("putObjectTaggingHandler: decode request body fail: requestID(%v) err(%v)", GetRequestID(r), err) _ = InvalidArgument.ServeResponse(w, r) return @@ -846,7 +847,7 @@ func (o *ObjectNode) deleteObjectTaggingHandler(w http.ResponseWriter, r *http.R var err error var param *RequestParam if param, err = o.parseRequestParam(r); err != nil { - log.LogErrorf("deleteObjectTaggingHandler: parse request param fail: requestID(%v) err(%v)", GetRequestID(r), err) + log.LogWarnf("deleteObjectTaggingHandler: parse request param fail: requestID(%v) err(%v)", GetRequestID(r), err) _ = InvalidArgument.ServeResponse(w, r) return } @@ -863,21 +864,154 @@ func (o *ObjectNode) deleteObjectTaggingHandler(w http.ResponseWriter, r *http.R } // Put object extend attribute (xattr) -func (o *ObjectNode) putObjectXAttr(w http.ResponseWriter, r *http.Request) { - // TODO: implement 'putObjectXAttr' +func (o *ObjectNode) putObjectXAttrHandler(w http.ResponseWriter, r *http.Request) { + var err error + var param *RequestParam + if param, err = o.parseRequestParam(r); err != nil { + log.LogWarnf("putObjectXAttrHandler: parse request param fail: requestID(%v) err(%v)", GetRequestID(r), err) + _ = InvalidArgument.ServeResponse(w, r) + return + } + if len(param.bucket) == 0 { + _ = NoSuchBucket.ServeResponse(w, r) + return + } + var vol *volume + if vol, err = o.getVol(param.bucket); err != nil { + _ = NoSuchBucket.ServeResponse(w, r) + return + } + if len(param.object) == 0 { + _ = NoSuchKey.ServeResponse(w, r) + return + } + var requestBody []byte + if requestBody, err = ioutil.ReadAll(r.Body); err != nil { + _ = ErrorCode{ + ErrorCode: "BadRequest", + ErrorMessage: err.Error(), + StatusCode: http.StatusBadRequest, + }.ServeResponse(w, r) + return + } + var putXAttrRequest = PutXAttrRequest{} + if err = xml.Unmarshal(requestBody, &putXAttrRequest); err != nil { + _ = ErrorCode{ + ErrorCode: "BadRequest", + ErrorMessage: err.Error(), + StatusCode: http.StatusBadRequest, + }.ServeResponse(w, r) + return + } + var key, value = putXAttrRequest.XAttr.Key, putXAttrRequest.XAttr.Value + if len(key) == 0 { + return + } + + if err = vol.SetXAttr(param.object, key, []byte(value)); err != nil { + if err == syscall.ENOENT { + _ = NoSuchKey.ServeResponse(w, r) + return + } + _ = InternalError.ServeResponse(w, r) + return + } + return } // Get object extend attribute (xattr) func (o *ObjectNode) getObjectXAttr(w http.ResponseWriter, r *http.Request) { - // TODO: implement 'getObjectXAttr' + var err error + var param *RequestParam + if param, err = o.parseRequestParam(r); err != nil { + log.LogWarnf("deleteObjectXAttrHandler: parse request param fail: requestID(%v) err(%v)", GetRequestID(r), err) + _ = InvalidArgument.ServeResponse(w, r) + return + } + if len(param.bucket) == 0 { + _ = InvalidArgument.ServeResponse(w, r) + return + } + var vol *volume + if vol, err = o.getVol(param.bucket); err != nil { + _ = NoSuchBucket.ServeResponse(w, r) + return + } + if len(param.object) == 0 { + _ = InvalidArgument.ServeResponse(w, r) + return + } + var xattrKey string + if xattrKey = param.GetVar("key"); len(xattrKey) == 0 { + _ = InvalidArgument.ServeResponse(w, r) + return + } + + var info *proto.XAttrInfo + if info, err = vol.GetXAttr(param.object, xattrKey); err != nil { + if err == syscall.ENOENT { + _ = NoSuchKey.ServeResponse(w, r) + return + } + _ = InternalError.ServeResponse(w, r) + return + } + var response = GetXAttrOutput{ + XAttr: &XAttr{ + Key: xattrKey, + Value: string(info.Get(xattrKey)), + }, + } + var marshaled []byte + if marshaled, err = MarshalXMLEntity(&response); err != nil { + _ = InternalError.ServeResponse(w, r) + return + } + _, _ = w.Write(marshaled) + return } // Delete object extend attribute (xattr) -func (o *ObjectNode) deleteObjectXAttr(w http.ResponseWriter, r *http.Request) { - // TODO: implement 'deleteObjectXAttr' +func (o *ObjectNode) deleteObjectXAttrHandler(w http.ResponseWriter, r *http.Request) { + var err error + var param *RequestParam + if param, err = o.parseRequestParam(r); err != nil { + log.LogWarnf("deleteObjectXAttrHandler: parse request param fail: requestID(%v) err(%v)", GetRequestID(r), err) + _ = InvalidArgument.ServeResponse(w, r) + return + } + if len(param.bucket) == 0 { + _ = InvalidArgument.ServeResponse(w, r) + return + } + var vol *volume + if vol, err = o.getVol(param.bucket); err != nil { + _ = NoSuchBucket.ServeResponse(w, r) + return + } + if len(param.object) == 0 { + _ = InvalidArgument.ServeResponse(w, r) + return + } + var xattrKey string + if xattrKey = param.GetVar("key"); len(xattrKey) == 0 { + _ = InvalidArgument.ServeResponse(w, r) + return + } + + if err = vol.DeleteXAttr(param.object, xattrKey); err != nil { + if err == syscall.ENOENT { + _ = NoSuchKey.ServeResponse(w, r) + return + } + _ = InternalError.ServeResponse(w, r) + return + } + return } // List object xattrs func (o *ObjectNode) listObjectXAttrs(w http.ResponseWriter, r *http.Request) { // TODO: implement 'listObjectXAttrs' + } diff --git a/objectnode/api_middleware.go b/objectnode/api_middleware.go index 1c4dec416..a5cfd15c5 100644 --- a/objectnode/api_middleware.go +++ b/objectnode/api_middleware.go @@ -70,10 +70,14 @@ func (o *ObjectNode) traceMiddleware(next http.Handler) http.Handler { } log.LogDebugf("traceMiddleware: trace request:\n"+ + " action(%v)\n"+ " requestID(%v) host(%v) method(%v) url(%v)\n"+ " header(%v)\n"+ " remote(%v) cost(%v)", - requestID, r.Host, r.Method, r.URL.String(), headerToString(r.Header), getRequestIP(r), time.Since(startTime)) + ActionFromRouteName(mux.CurrentRoute(r).GetName()).String(), + requestID, r.Host, r.Method, r.URL.String(), + headerToString(r.Header), + getRequestIP(r), time.Since(startTime)) } return handlerFunc @@ -81,15 +85,6 @@ func (o *ObjectNode) traceMiddleware(next http.Handler) http.Handler { func (o *ObjectNode) authMiddleware(next http.Handler) http.Handler { - var parseActionName = func(r *http.Request) string { - routeName := mux.CurrentRoute(r).GetName() - routeSNLoc := routeSNRegexp.FindStringIndex(routeName) - if len(routeSNLoc) != 2 { - return routeName - } - return routeName[:len(routeName)-33] - } - var isSignatureIgnoredAction = func(action Action) bool { if len(o.signatureIgnoredActions) == 0 { return false @@ -104,7 +99,7 @@ func (o *ObjectNode) authMiddleware(next http.Handler) http.Handler { return http.HandlerFunc( func(w http.ResponseWriter, r *http.Request) { - var currentAction = ActionFromString(parseActionName(r)) + var currentAction = ActionFromRouteName(mux.CurrentRoute(r).GetName()) if currentAction.IsKnown() && isSignatureIgnoredAction(currentAction) { next.ServeHTTP(w, r) return @@ -152,6 +147,16 @@ func (o *ObjectNode) authMiddleware(next http.Handler) http.Handler { }) } +func (o *ObjectNode) policyCheckMiddleware(next http.Handler) http.Handler { + return http.HandlerFunc( + func(w http.ResponseWriter, r *http.Request) { + action := ActionFromRouteName(mux.CurrentRoute(r).GetName()) + wrappedNext := o.policyCheck(next.ServeHTTP, action) + wrappedNext.ServeHTTP(w, r) + return + }) +} + func (o *ObjectNode) contentMiddleware(next http.Handler) http.Handler { var handlerFunc http.HandlerFunc = func(w http.ResponseWriter, r *http.Request) { if len(r.Header) > 0 && len(r.Header.Get(http.CanonicalHeaderKey(HeaderNameDecodeContentLength))) > 0 { diff --git a/objectnode/fs_volume.go b/objectnode/fs_volume.go index b8036bb18..0fe24f94c 100644 --- a/objectnode/fs_volume.go +++ b/objectnode/fs_volume.go @@ -160,7 +160,6 @@ func (v *volume) OSSMeta() *OSSMeta { } func (v *volume) getInodeFromPath(path string) (inode uint64, err error) { - // path == "/" if path == "/" { return volumeRootInode, nil } @@ -193,9 +192,22 @@ func (v *volume) getInodeFromPath(path string) (inode uint64, err error) { } func (v *volume) SetXAttr(path string, key string, data []byte) error { - inode, err1 := v.getInodeFromPath(path) - if err1 != nil { - return err1 + var err error + var inode uint64 + if inode, err = v.getInodeFromPath(path); err != nil && err != syscall.ENOENT { + return err + } + if err == syscall.ENOENT { + var dirs, filename = splitPath(path) + var parentID uint64 + if parentID, err = v.lookupDirectories(dirs, true); err != nil { + return err + } + var inodeInfo *proto.InodeInfo + if inodeInfo, err = v.mw.Create_ll(parentID, filename, 0600, 0, 0, nil); err != nil { + return err + } + inode = inodeInfo.Inode } return v.mw.XAttrSet_ll(inode, []byte(key), data) } diff --git a/objectnode/policy_action.go b/objectnode/policy_action.go index 0ec679927..73fb3bc0e 100644 --- a/objectnode/policy_action.go +++ b/objectnode/policy_action.go @@ -14,6 +14,13 @@ package objectnode +import ( + "strings" + + "github.com/chubaofs/chubaofs/util" + "github.com/google/uuid" +) + // https://docs.aws.amazon.com/AmazonS3/latest/dev/access-policy-language-overview.html // https://docs.aws.amazon.com/AmazonS3/latest/dev/example-bucket-policies.html @@ -28,54 +35,65 @@ func (a Action) IsKnown() bool { return len(a) != 0 && a != UnknownAction } +func (a Action) UniqueRouteName() (name string) { + var id uuid.UUID + var err error + if id, err = uuid.NewRandom(); err != nil { + name = a.String() + ":" + util.RandomString(32, util.UpperLetter|util.LowerLetter) + return + } + name = a.String() + ":" + strings.ReplaceAll(id.String(), "-", "") + return +} + const ( OSSActionPrefix = "oss:action:" GetObjectAction Action = OSSActionPrefix + "GetObject" - PutObjectAction = OSSActionPrefix + "PutObject" - CopyObjectAction = OSSActionPrefix + "CopyObject" - ListObjectsAction = OSSActionPrefix + "ListObjects" - DeleteObjectAction = OSSActionPrefix + "DeleteObject" - DeleteObjectsAction = OSSActionPrefix + "DeleteObjects" - HeadObjectAction = OSSActionPrefix + "HeadObject" - CreateBucketAction = OSSActionPrefix + "CreateBucket" - DeleteBucketAction = OSSActionPrefix + "DeleteBucket" - HeadBucketAction = OSSActionPrefix + "HeadBucket" - ListBucketAction = OSSActionPrefix + "ListBucket" - ListBucketVersionsAction = OSSActionPrefix + "ListBucketVersions" - ListBucketMultipartUploadsAction = OSSActionPrefix + "ListBucketMultipartUploads" - GetBucketPolicyAction = OSSActionPrefix + "GetBucketPolicy" - PutBucketPolicyAction = OSSActionPrefix + "PutBucketPolicy" - GetBucketAclAction = OSSActionPrefix + "GetBucketAcl" - PutBucketAclAction = OSSActionPrefix + "PutBucketAcl" - GetObjectAclAction = OSSActionPrefix + "GetObjectAcl" - GetObjectVersionAction = OSSActionPrefix + "GetObjectVersion" - PutObjectVersionAction = OSSActionPrefix + "PutObjectVersion" - GetObjectTorrentAction = OSSActionPrefix + "GetObjectTorrent" - PutObjectTorrentAction = OSSActionPrefix + "PutObjectTorrent" - PutObjectAclAction = OSSActionPrefix + "PutObjectAcl" - GetObjectVersionAclAction = OSSActionPrefix + "GetObjectVersionAcl" - PutObjectVersionAclAction = OSSActionPrefix + "PutObjectVersionAcl" - DeleteBucketPolicyAction = OSSActionPrefix + "DeleteBucketPolicy" - CreateMultipartUploadAction = OSSActionPrefix + "CreateMultipartUpload" - ListMultipartUploadsAction = OSSActionPrefix + "ListMultipartUploads" - UploadPartAction = OSSActionPrefix + "UploadPart" - ListPartsAction = OSSActionPrefix + "ListParts" - CompleteMultipartUploadAction = OSSActionPrefix + "CompleteMultipartUpload" - AbortMultipartUploadAction = OSSActionPrefix + "AbortMultipartUpload" - GetBucketLocationAction = OSSActionPrefix + "GetBucketLocation" - GetObjectXAttrAction = OSSActionPrefix + "GetObjectXAttr" - PutObjectXAttrAction = OSSActionPrefix + "PutObjectAttr" - ListObjectXAttrsAction = OSSActionPrefix + "ListObjectXAttrs" - DeleteObjectXAttrAction = OSSActionPrefix + "DeleteObjectXAttr" - GetObjectTaggingAction = OSSActionPrefix + "GetObjectTagging" - PutObjectTaggingAction = OSSActionPrefix + "PutObjectTagging" - DeleteObjectTaggingAction = OSSActionPrefix + "DeleteObjectTagging" - GetBucketTaggingAction = OSSActionPrefix + "GetBucketTagging" - PutBucketTaggingAction = OSSActionPrefix + "PutBucketTagging" - DeleteBucketTaggingAction = OSSActionPrefix + "DeleteBucketTagging" + PutObjectAction Action = OSSActionPrefix + "PutObject" + CopyObjectAction Action = OSSActionPrefix + "CopyObject" + ListObjectsAction Action = OSSActionPrefix + "ListObjects" + DeleteObjectAction Action = OSSActionPrefix + "DeleteObject" + DeleteObjectsAction Action = OSSActionPrefix + "DeleteObjects" + HeadObjectAction Action = OSSActionPrefix + "HeadObject" + CreateBucketAction Action = OSSActionPrefix + "CreateBucket" + DeleteBucketAction Action = OSSActionPrefix + "DeleteBucket" + HeadBucketAction Action = OSSActionPrefix + "HeadBucket" + ListBucketAction Action = OSSActionPrefix + "ListBucket" + ListBucketVersionsAction Action = OSSActionPrefix + "ListBucketVersions" + ListBucketMultipartUploadsAction Action = OSSActionPrefix + "ListBucketMultipartUploads" + GetBucketPolicyAction Action = OSSActionPrefix + "GetBucketPolicy" + PutBucketPolicyAction Action = OSSActionPrefix + "PutBucketPolicy" + GetBucketAclAction Action = OSSActionPrefix + "GetBucketAcl" + PutBucketAclAction Action = OSSActionPrefix + "PutBucketAcl" + GetObjectAclAction Action = OSSActionPrefix + "GetObjectAcl" + GetObjectVersionAction Action = OSSActionPrefix + "GetObjectVersion" + PutObjectVersionAction Action = OSSActionPrefix + "PutObjectVersion" + GetObjectTorrentAction Action = OSSActionPrefix + "GetObjectTorrent" + PutObjectTorrentAction Action = OSSActionPrefix + "PutObjectTorrent" + PutObjectAclAction Action = OSSActionPrefix + "PutObjectAcl" + GetObjectVersionAclAction Action = OSSActionPrefix + "GetObjectVersionAcl" + PutObjectVersionAclAction Action = OSSActionPrefix + "PutObjectVersionAcl" + DeleteBucketPolicyAction Action = OSSActionPrefix + "DeleteBucketPolicy" + CreateMultipartUploadAction Action = OSSActionPrefix + "CreateMultipartUpload" + ListMultipartUploadsAction Action = OSSActionPrefix + "ListMultipartUploads" + UploadPartAction Action = OSSActionPrefix + "UploadPart" + ListPartsAction Action = OSSActionPrefix + "ListParts" + CompleteMultipartUploadAction Action = OSSActionPrefix + "CompleteMultipartUpload" + AbortMultipartUploadAction Action = OSSActionPrefix + "AbortMultipartUpload" + GetBucketLocationAction Action = OSSActionPrefix + "GetBucketLocation" + GetObjectXAttrAction Action = OSSActionPrefix + "GetObjectXAttr" + PutObjectXAttrAction Action = OSSActionPrefix + "PutObjectAttr" + ListObjectXAttrsAction Action = OSSActionPrefix + "ListObjectXAttrs" + DeleteObjectXAttrAction Action = OSSActionPrefix + "DeleteObjectXAttr" + GetObjectTaggingAction Action = OSSActionPrefix + "GetObjectTagging" + PutObjectTaggingAction Action = OSSActionPrefix + "PutObjectTagging" + DeleteObjectTaggingAction Action = OSSActionPrefix + "DeleteObjectTagging" + GetBucketTaggingAction Action = OSSActionPrefix + "GetBucketTagging" + PutBucketTaggingAction Action = OSSActionPrefix + "PutBucketTagging" + DeleteBucketTaggingAction Action = OSSActionPrefix + "DeleteBucketTagging" - UnknownAction = OSSActionPrefix + "Unknown" + UnknownAction Action = OSSActionPrefix + "Unknown" ) var ( @@ -137,6 +155,14 @@ func ActionFromString(str string) Action { return UnknownAction } +func ActionFromRouteName(name string) Action { + routeSNLoc := routeSNRegexp.FindStringIndex(name) + if len(routeSNLoc) != 2 { + return ActionFromString(name) + } + return ActionFromString(name[:len(name)-33]) +} + func (s Statement) checkActions(p *RequestParam) bool { if s.Actions.Empty() { return true diff --git a/objectnode/result.go b/objectnode/result.go index 432416cc0..81e719cd7 100644 --- a/objectnode/result.go +++ b/objectnode/result.go @@ -298,6 +298,11 @@ type PutXAttrRequest struct { XAttr *XAttr `xml:"XAttr"` } +type GetXAttrOutput struct { + XMLName xml.Name `xml:"GetXAttrOutput"` + XAttr *XAttr `xml:"XAttr"` +} + type ListXAttrsResult struct { XMLName xml.Name `xml:"ListXAttrsResult"` XAttrs []*XAttr `xml:"XAttrs>XAttr"` diff --git a/objectnode/router.go b/objectnode/router.go index a7d4a40a5..f4e17d81f 100644 --- a/objectnode/router.go +++ b/objectnode/router.go @@ -16,10 +16,6 @@ package objectnode import ( "net/http" - "strings" - - "github.com/chubaofs/chubaofs/util" - "github.com/google/uuid" "github.com/gorilla/mux" ) @@ -35,264 +31,288 @@ func (o *ObjectNode) registerApiRouters(router *mux.Router) { } bucketRouters = append(bucketRouters, bRouter.PathPrefix("/{bucket}").Subrouter()) - var unionRouteName = func(action Action) (name string) { - var id uuid.UUID - var err error - if id, err = uuid.NewRandom(); err != nil { - name = action.String() + ":" + util.RandomString(32, util.UpperLetter|util.LowerLetter) - return - } - name = action.String() + ":" + strings.ReplaceAll(id.String(), "-", "") - return - } - var registerBucketHttpHeadRouters = func(r *mux.Router) { // Head object // API reference: https://docs.aws.amazon.com/AmazonS3/latest/API/API_HeadObject.html - r.Methods(http.MethodHead). + r.NewRoute().Name(HeadObjectAction.UniqueRouteName()). + Methods(http.MethodHead). Path("/{object:.+}"). - HandlerFunc(o.policyCheck(o.headObjectHandler, HeadObjectAction)). - Name(unionRouteName(HeadObjectAction)) + HandlerFunc(o.headObjectHandler) // Head bucket // API reference: https://docs.aws.amazon.com/AmazonS3/latest/API/API_HeadBucket.html - r.Methods(http.MethodHead). - HandlerFunc(o.policyCheck(o.headBucketHandler, HeadBucketAction)). - Name(unionRouteName(HeadBucketAction)) + r.NewRoute().Name(HeadBucketAction.UniqueRouteName()). + Methods(http.MethodHead). + HandlerFunc(o.headBucketHandler) } var registerBucketHttpGetRouters = func(r *mux.Router) { // Get object with pre-signed auth signature v2 // API reference: https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObject.html - r.Methods(http.MethodGet). + r.NewRoute().Name(GetObjectAction.UniqueRouteName()). + Methods(http.MethodGet). Path("/{object:.+}"). - HandlerFunc(o.policyCheck(o.getObjectHandler, GetObjectAction)). Queries("AWSAccessKeyId", "{accessKey:.+}", "Expires", "{expires:[0-9]+}", "Signature", "{signature:.+}"). - Name(unionRouteName(GetObjectAction)) + HandlerFunc(o.getObjectHandler) // Get object with pre-signed auth signature v4 // API reference: https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObject.html - r.Methods(http.MethodGet). + r.NewRoute().Name(GetObjectAction.UniqueRouteName()). + Methods(http.MethodGet). Path("/{object:.+}"). - HandlerFunc(o.policyCheck(o.getObjectHandler, GetObjectAction)). Queries("X-Amz-Credential", "{creadential:.+}", "X-Amz-Algorithm", "{algorithm:.+}", "X-Amz-Signature", "{signature:.+}", "X-Amz-Date", "{date:.+}", "X-Amz-SignedHeaders", "{signedHeaders:.+}", - "X-Amz-Expires", "{expires:[0-9]+}") + "X-Amz-Expires", "{expires:[0-9]+}"). + HandlerFunc(o.getObjectHandler) // Get object tagging // API reference: https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObjectTagging.html - r.Methods(http.MethodGet). + r.NewRoute().Name(GetObjectTaggingAction.UniqueRouteName()). + Methods(http.MethodGet). Path("/{object:.+}"). - HandlerFunc(o.policyCheck(o.getObjectTaggingHandler, GetObjectTaggingAction)). - Queries("tagging", "") + Queries("tagging", ""). + HandlerFunc(o.getObjectTaggingHandler) // Get object XAttr // Notes: ChubaoFS owned API for XAttr operation - r.Methods(http.MethodGet). + r.NewRoute().Name(GetObjectXAttrAction.UniqueRouteName()). + Methods(http.MethodGet). Path("/{object:.+}"). - HandlerFunc(o.policyCheck(o.getObjectXAttr, GetObjectXAttrAction)). - Queries("xattr", "", "key", "{key:.+}") + Queries("xattr", "", "key", "{key:.+}"). + HandlerFunc(o.getObjectXAttr) // List object XAttrs - r.Methods(http.MethodGet). + r.NewRoute().Name(ListObjectXAttrsAction.UniqueRouteName()). + Methods(http.MethodGet). Path("/{object:.+}"). - HandlerFunc(o.policyCheck(o.listObjectXAttrs, ListObjectXAttrsAction)). - Queries("xattr", "") + Queries("xattr", ""). + HandlerFunc(o.listObjectXAttrs) // Get object acl // API reference: https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObjectAcl.html - r.Methods(http.MethodGet). + r.NewRoute().Name(GetObjectAclAction.UniqueRouteName()). + Methods(http.MethodGet). Path("/{objject:.+}"). - HandlerFunc(o.policyCheck(o.getObjectACLHandler, GetObjectAclAction)). - Queries("acl", "") + Queries("acl", ""). + HandlerFunc(o.getObjectACLHandler) // Get object // API reference: https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObject.html - r.Methods(http.MethodGet). + r.NewRoute().Name(GetObjectAction.UniqueRouteName()). + Methods(http.MethodGet). Path("/{object:.+}"). - HandlerFunc(o.policyCheck(o.getObjectHandler, GetObjectAction)) + HandlerFunc(o.getObjectHandler) // List objects version 2 // API reference: https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjectsV2.html - r.Methods(http.MethodGet). - HandlerFunc(o.policyCheck(o.getBucketV2Handler, ListObjectsAction)). - Queries("list-type", "2") + r.NewRoute().Name(ListObjectsAction.UniqueRouteName()). + Methods(http.MethodGet). + Queries("list-type", "2"). + HandlerFunc(o.getBucketV2Handler) // List multipart uploads // API reference: https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListMultipartUploads.html - r.Methods(http.MethodGet). - HandlerFunc(o.policyCheck(o.listMultipartUploadsHandler, ListMultipartUploadsAction)). - Queries("uploads", "") + r.NewRoute().Name(ListMultipartUploadsAction.UniqueRouteName()). + Methods(http.MethodGet). + Queries("uploads", ""). + HandlerFunc(o.listMultipartUploadsHandler) // List parts // API reference: https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListParts.html - r.Methods(http.MethodGet). - HandlerFunc(o.policyCheck(o.listPartsHandler, ListPartsAction)). - Queries("uploadId", "{uploadId:.*}") + r.NewRoute().Name(ListPartsAction.UniqueRouteName()). + Methods(http.MethodGet). + Queries("uploadId", "{uploadId:.*}"). + HandlerFunc(o.listPartsHandler) // Get bucket location // API reference: https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketLocation.html - r.Methods(http.MethodGet). - HandlerFunc(o.policyCheck(o.getBucketLocation, GetBucketLocationAction)). - Queries("location", "") + r.NewRoute().Name(GetBucketLocationAction.UniqueRouteName()). + Methods(http.MethodGet). + Queries("location", ""). + HandlerFunc(o.getBucketLocation) // Get bucket policy // https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketPolicy.html - r.Methods(http.MethodGet). - HandlerFunc(o.policyCheck(o.getBucketPolicyHandler, GetBucketPolicyAction)). - Queries("policy", "") + r.NewRoute().Name(GetBucketPolicyAction.UniqueRouteName()). + Methods(http.MethodGet). + Queries("policy", ""). + HandlerFunc(o.getBucketPolicyHandler) // Get bucket acl // API reference: https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketAcl.html - r.Methods(http.MethodGet). - HandlerFunc(o.policyCheck(o.getBucketACLHandler, GetBucketAclAction)). - Queries("acl", "") + r.NewRoute().Name(GetBucketAclAction.UniqueRouteName()). + Methods(http.MethodGet). + Queries("acl", ""). + HandlerFunc(o.getBucketACLHandler) // Get bucket tagging // API reference: https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketTagging.html - r.Methods(http.MethodGet). - HandlerFunc(o.policyCheck(o.getBucketTaggingHandler, GetBucketTaggingAction)). - Queries("tagging", "") + r.NewRoute().Name(GetBucketTaggingAction.UniqueRouteName()). + Methods(http.MethodGet). + Queries("tagging", ""). + HandlerFunc(o.getBucketTaggingHandler) // List objects version 1 // API reference: https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjects.html - r.Methods(http.MethodGet). - HandlerFunc(o.policyCheck(o.getBucketV1Handler, ListObjectsAction)) + r.NewRoute().Name(ListObjectsAction.UniqueRouteName()). + Methods(http.MethodGet). + HandlerFunc(o.getBucketV1Handler) } var registerBucketHttpPostRouters = func(r *mux.Router) { // Create multipart upload // API reference: https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateMultipartUpload.html - r.Methods(http.MethodPost). + r.NewRoute().Name(CreateMultipartUploadAction.UniqueRouteName()). + Methods(http.MethodPost). Path("/{object:.+}"). - HandlerFunc(o.policyCheck(o.createMultipleUploadHandler, CreateMultipartUploadAction)). - Queries("uploads", "") + Queries("uploads", ""). + HandlerFunc(o.createMultipleUploadHandler) // Complete multipart // API reference: https://docs.aws.amazon.com/AmazonS3/latest/API/API_CompleteMultipartUpload.html - r.Methods(http.MethodPost). + r.NewRoute().Name(CompleteMultipartUploadAction.UniqueRouteName()). + Methods(http.MethodPost). Path("/{object:.+}"). - HandlerFunc(o.policyCheck(o.completeMultipartUploadHandler, CompleteMultipartUploadAction)). - Queries("uploadId", "{uploadId:.*}") + Queries("uploadId", "{uploadId:.*}"). + HandlerFunc(o.completeMultipartUploadHandler) // Delete objects (multiple objects) // API reference: https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteObjects.html - r.Methods(http.MethodPost). - HandlerFunc(o.policyCheck(o.deleteObjectsHandler, DeleteObjectsAction)). - Queries("delete", "") + r.NewRoute().Name(DeleteObjectsAction.UniqueRouteName()). + Methods(http.MethodPost). + Queries("delete", ""). + HandlerFunc(o.deleteObjectsHandler) } var registerBucketHttpPutRouters = func(r *mux.Router) { // Upload part // API reference: https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPart.html . - r.Methods(http.MethodPut). + r.NewRoute().Name(UploadPartAction.UniqueRouteName()). + Methods(http.MethodPut). Path("/{object:.+}"). - HandlerFunc(o.policyCheck(o.uploadPartHandler, UploadPartAction)). - Queries("partNumber", "{partNumber:[0-9]+}", "uploadId", "{uploadId:.*}") + Queries("partNumber", "{partNumber:[0-9]+}", "uploadId", "{uploadId:.*}"). + HandlerFunc(o.uploadPartHandler) // Copy object // API reference: https://docs.aws.amazon.com/AmazonS3/latest/API/API_CopyObject.html . - r.Methods(http.MethodPut). + r.NewRoute().Name(CopyObjectAction.UniqueRouteName()). + Methods(http.MethodPut). Path("/{object:.+}"). HeadersRegexp(HeaderNameCopySource, ".*?(\\/|%2F).*?"). - HandlerFunc(o.policyCheck(o.copyObjectHandler, CopyObjectAction)) + HandlerFunc(o.copyObjectHandler) // Put object tagging // API reference: https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObjectTagging.html - r.Methods(http.MethodPut). + r.NewRoute().Name(PutObjectTaggingAction.UniqueRouteName()). + Methods(http.MethodPut). Path("/{object:.+}"). - HandlerFunc(o.policyCheck(o.putObjectTaggingHandler, PutObjectTaggingAction)). - Queries("tagging", "") + Queries("tagging", ""). + HandlerFunc(o.putObjectTaggingHandler) // Put object xattrs // Notes: ChubaoFS owned API for XAttr operation - r.Methods(http.MethodPut). + r.NewRoute().Name(PutObjectXAttrAction.UniqueRouteName()). + Methods(http.MethodPut). Path("/{object:.+}"). - HandlerFunc(o.policyCheck(o.putObjectXAttr, PutObjectXAttrAction)). - Queries("xattr", "") + Queries("xattr", ""). + HandlerFunc(o.putObjectXAttrHandler) // Put object acl // API reference: https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketAcl.html - r.Methods(http.MethodPut). + r.NewRoute().Name(PutObjectAclAction.UniqueRouteName()). + Methods(http.MethodPut). Path("/{object:.+}"). - HandlerFunc(o.policyCheck(o.putObjectACLHandler, PutObjectAclAction)). - Queries("acl", "") + Queries("acl", ""). + HandlerFunc(o.putObjectACLHandler) // Put object // API reference: https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html - r.Methods(http.MethodPut). + r.NewRoute().Name(PutObjectAction.UniqueRouteName()). + Methods(http.MethodPut). Path("/{object:.+}"). - HandlerFunc(o.policyCheck(o.putObjectHandler, PutObjectAction)) + HandlerFunc(o.putObjectHandler) // Put bucket acl // API reference: https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketAcl.html - r.Methods(http.MethodPut). - HandlerFunc(o.policyCheck(o.putBucketACLHandler, PutBucketAclAction)). - Queries("acl", "") + r.NewRoute().Name(PutBucketAclAction.UniqueRouteName()). + Methods(http.MethodPut). + Queries("acl", ""). + HandlerFunc(o.putBucketACLHandler) // Put bucket policy // API reference: https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketPolicy.html - r.Methods(http.MethodPut). - HandlerFunc(o.policyCheck(o.putBucketPolicyHandler, PutBucketPolicyAction)). - Queries("policy", "") + r.NewRoute().Name(PutBucketPolicyAction.UniqueRouteName()). + Methods(http.MethodPut). + Queries("policy", ""). + HandlerFunc(o.putBucketPolicyHandler) // Put bucket tagging // API reference: https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketTagging.html - r.Methods(http.MethodPut). - HandlerFunc(o.policyCheck(o.putBucketTaggingHandler, PutBucketTaggingAction)). - Queries("tagging", "") + r.NewRoute().Name(PutBucketTaggingAction.UniqueRouteName()). + Methods(http.MethodPut). + Queries("tagging", ""). + HandlerFunc(o.putBucketTaggingHandler) // Create bucket // API reference: https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateBucket.html - r.Methods(http.MethodPut). + r.NewRoute().Name(CreateBucketAction.UniqueRouteName()). + Methods(http.MethodPut). HandlerFunc(o.createBucketHandler) } var registerBucketHttpDeleteRouters = func(r *mux.Router) { // Abort multipart upload // API reference: https://docs.aws.amazon.com/AmazonS3/latest/API/API_AbortMultipartUpload.html . - r.Methods(http.MethodDelete). + r.NewRoute().Name(AbortMultipartUploadAction.UniqueRouteName()). + Methods(http.MethodDelete). Path("/{object:.+}"). - HandlerFunc(o.policyCheck(o.abortMultipartUploadHandler, AbortMultipartUploadAction)). - Queries("uploadId", "{uploadId:.*}") + Queries("uploadId", "{uploadId:.*}"). + HandlerFunc(o.abortMultipartUploadHandler) // Delete object tagging // API reference: https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteObjectTagging.html - r.Methods(http.MethodDelete). + r.NewRoute().Name(DeleteObjectTaggingAction.UniqueRouteName()). + Methods(http.MethodDelete). Path("/{object:.+"). - HandlerFunc(o.policyCheck(o.deleteObjectTaggingHandler, DeleteObjectTaggingAction)). - Queries("tagging", "") + Queries("tagging", ""). + HandlerFunc(o.deleteObjectTaggingHandler) // Delete object xattrs // Notes: ChubaoFS owned API for XAttr operation - r.Methods(http.MethodDelete). + r.NewRoute().Name(DeleteObjectXAttrAction.UniqueRouteName()). + Methods(http.MethodDelete). Path("/{object:.+}"). - HandlerFunc(o.policyCheck(o.deleteObjectXAttr, DeleteObjectXAttrAction)). - Queries("xattr", "key", "{key:.+}}") + Queries("xattr", "key", "{key:.+}}"). + HandlerFunc(o.deleteObjectXAttrHandler) // Delete object // API reference: https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteObject.html . - r.Methods(http.MethodDelete). + r.NewRoute().Name(DeleteObjectAction.UniqueRouteName()). + Methods(http.MethodDelete). Path("/{object:.+}"). - HandlerFunc(o.policyCheck(o.deleteObjectHandler, DeleteObjectAction)) + HandlerFunc(o.deleteObjectHandler) // Delete bucket policy // API reference: https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteBucketPolicy.html - r.Methods(http.MethodDelete). - HandlerFunc(o.policyCheck(o.deleteBucketPolicyHandler, DeleteBucketPolicyAction)). - Queries("policy", "") + r.NewRoute().Name(DeleteBucketPolicyAction.UniqueRouteName()). + Methods(http.MethodDelete). + Queries("policy", ""). + HandlerFunc(o.deleteBucketPolicyHandler) // Delete bucket tagging // API reference: https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteBucketTagging.html - r.Methods(http.MethodDelete). - Handler(o.policyCheck(o.deleteBucketTaggingHandler, DeleteBucketTaggingAction)). - Queries("tagging", "") + r.NewRoute().Name(DeleteBucketTaggingAction.UniqueRouteName()). + Methods(http.MethodDelete). + Queries("tagging", ""). + HandlerFunc(o.deleteBucketTaggingHandler) // Delete bucket // API reference: https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteBucket.html - r.Methods(http.MethodDelete).HandlerFunc(o.policyCheck(o.deleteBucketHandler, DeleteBucketAction)) + r.NewRoute().Name(DeleteBucketAction.UniqueRouteName()). + Methods(http.MethodDelete). + HandlerFunc(o.deleteBucketHandler) } @@ -306,7 +326,8 @@ func (o *ObjectNode) registerApiRouters(router *mux.Router) { // List buckets // API reference: https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListBuckets.html - router.Methods(http.MethodGet). + router.NewRoute().Name(ListBucketAction.UniqueRouteName()). + Methods(http.MethodGet). HandlerFunc(o.listBucketsHandler) // Unsupported operation diff --git a/objectnode/server.go b/objectnode/server.go index 50938c3f0..625e05d69 100644 --- a/objectnode/server.go +++ b/objectnode/server.go @@ -165,6 +165,7 @@ func (o *ObjectNode) startMuxRestAPI() (err error) { router.Use( o.traceMiddleware, o.authMiddleware, + o.policyCheckMiddleware, o.contentMiddleware, )