From 91a092792aa9d39f0c9abf74f9c1198ccbd4ee24 Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Thu, 18 Feb 2016 02:13:52 -0800 Subject: [PATCH] presigned: Fix a bug in presigned request verification. Additionally add Docker proxy configuration. --- Docker.md | 25 ++++++++++++++++-- Dockerfile | 1 - auth-handler.go | 18 +++---------- bucket-handlers.go | 20 +++++++------- jwt.go | 4 +-- object-handlers.go | 22 +++++++-------- pkg/signature/signature-v4.go | 5 +++- routers.go | 42 ++++++++++++++++++----------- server-main.go | 13 +++++---- server_fs_test.go | 4 +-- signature.go | 22 +++++++++++++++ web-handlers.go | 50 +++++++++++++++++------------------ 12 files changed, 136 insertions(+), 90 deletions(-) diff --git a/Docker.md b/Docker.md index bc1ba4465..11ec2fc6d 100644 --- a/Docker.md +++ b/Docker.md @@ -9,7 +9,7 @@ sudo apt-get install Docker.io ### Generating `minio configs` for the first time. ```bash -docker run -p 9000:9001 minio/minio:latest +docker run -p 9000 minio/minio:latest ``` ### Persist `minio configs`. @@ -28,5 +28,26 @@ docker create -v /export --name minio-export minio/my-minio /bin/true You can then use the `--volumes-from` flag to mount the `/export` volume in another container. ```bash -docker run -p 9000:9001 --volumes-from minio-export --name minio1 minio/my-minio +docker run -p 9000 --volumes-from minio-export --name minio1 minio/my-minio +``` + +### Setup a sample proxy in front using Caddy. + +Please download [Caddy Server](https://caddyserver.com/download) + +Create a caddy configuration file as below, change the ip addresses for your environment. +```bash +cat Caddyfile +10.0.0.3:2015 { + proxy / localhost:9000 { + proxy_header Host {host} + } + tls off +} +``` + +```bash +$ ./caddy +Activating privacy features... done. +10.0.0.3:2015 ``` diff --git a/Dockerfile b/Dockerfile index 359db118e..400796d9f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,6 +3,5 @@ FROM scratch ADD minio.dockerimage /minio ADD export /export EXPOSE 9000 -EXPOSE 9001 ENTRYPOINT ["/minio"] CMD ["server", "/export"] diff --git a/auth-handler.go b/auth-handler.go index 4086fa14f..f47131822 100644 --- a/auth-handler.go +++ b/auth-handler.go @@ -16,12 +16,7 @@ package main -import ( - "fmt" - "net/http" - - jwtgo "github.com/dgrijalva/jwt-go" -) +import "net/http" const ( signV4Algorithm = "AWS4-HMAC-SHA256" @@ -69,15 +64,8 @@ func (a authHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { // Verify JWT authorization header is present. if isRequestJWT(r) { - // Validate Authorization header to be valid. - jwt := InitJWT() - token, e := jwtgo.ParseFromRequest(r, func(token *jwtgo.Token) (interface{}, error) { - if _, ok := token.Method.(*jwtgo.SigningMethodHMAC); !ok { - return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"]) - } - return jwt.secretAccessKey, nil - }) - if e != nil || !token.Valid { + // Validate Authorization header if its valid. + if !isJWTReqAuthenticated(r) { w.WriteHeader(http.StatusUnauthorized) return } diff --git a/bucket-handlers.go b/bucket-handlers.go index 9f50369b1..2103d1799 100644 --- a/bucket-handlers.go +++ b/bucket-handlers.go @@ -34,7 +34,7 @@ import ( // GetBucketLocationHandler - GET Bucket location. // ------------------------- // This operation returns bucket location. -func (api CloudStorageAPI) GetBucketLocationHandler(w http.ResponseWriter, r *http.Request) { +func (api storageAPI) GetBucketLocationHandler(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) bucket := vars["bucket"] @@ -81,7 +81,7 @@ func (api CloudStorageAPI) GetBucketLocationHandler(w http.ResponseWriter, r *ht // completed or aborted. This operation returns at most 1,000 multipart // uploads in the response. // -func (api CloudStorageAPI) ListMultipartUploadsHandler(w http.ResponseWriter, r *http.Request) { +func (api storageAPI) ListMultipartUploadsHandler(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) bucket := vars["bucket"] @@ -130,7 +130,7 @@ func (api CloudStorageAPI) ListMultipartUploadsHandler(w http.ResponseWriter, r // of the objects in a bucket. You can use the request parameters as selection // criteria to return a subset of the objects in a bucket. // -func (api CloudStorageAPI) ListObjectsHandler(w http.ResponseWriter, r *http.Request) { +func (api storageAPI) ListObjectsHandler(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) bucket := vars["bucket"] @@ -186,7 +186,7 @@ func (api CloudStorageAPI) ListObjectsHandler(w http.ResponseWriter, r *http.Req // ----------- // This implementation of the GET operation returns a list of all buckets // owned by the authenticated sender of the request. -func (api CloudStorageAPI) ListBucketsHandler(w http.ResponseWriter, r *http.Request) { +func (api storageAPI) ListBucketsHandler(w http.ResponseWriter, r *http.Request) { if isRequestRequiresACLCheck(r) { writeErrorResponse(w, r, AccessDenied, r.URL.Path) return @@ -215,7 +215,7 @@ func (api CloudStorageAPI) ListBucketsHandler(w http.ResponseWriter, r *http.Req // PutBucketHandler - PUT Bucket // ---------- // This implementation of the PUT operation creates a new bucket for authenticated request -func (api CloudStorageAPI) PutBucketHandler(w http.ResponseWriter, r *http.Request) { +func (api storageAPI) PutBucketHandler(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) bucket := vars["bucket"] @@ -323,7 +323,7 @@ func extractHTTPFormValues(reader *multipart.Reader) (io.Reader, map[string]stri // ---------- // This implementation of the POST operation handles object creation with a specified // signature policy in multipart/form-data -func (api CloudStorageAPI) PostPolicyBucketHandler(w http.ResponseWriter, r *http.Request) { +func (api storageAPI) PostPolicyBucketHandler(w http.ResponseWriter, r *http.Request) { // if body of request is non-nil then check for validity of Content-Length if r.Body != nil { /// if Content-Length is unknown/missing, deny the request @@ -403,7 +403,7 @@ func (api CloudStorageAPI) PostPolicyBucketHandler(w http.ResponseWriter, r *htt // PutBucketACLHandler - PUT Bucket ACL // ---------- // This implementation of the PUT operation modifies the bucketACL for authenticated request -func (api CloudStorageAPI) PutBucketACLHandler(w http.ResponseWriter, r *http.Request) { +func (api storageAPI) PutBucketACLHandler(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) bucket := vars["bucket"] @@ -445,7 +445,7 @@ func (api CloudStorageAPI) PutBucketACLHandler(w http.ResponseWriter, r *http.Re // of a bucket. One must have permission to access the bucket to // know its ``acl``. This operation willl return response of 404 // if bucket not found and 403 for invalid credentials. -func (api CloudStorageAPI) GetBucketACLHandler(w http.ResponseWriter, r *http.Request) { +func (api storageAPI) GetBucketACLHandler(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) bucket := vars["bucket"] @@ -487,7 +487,7 @@ func (api CloudStorageAPI) GetBucketACLHandler(w http.ResponseWriter, r *http.Re // The operation returns a 200 OK if the bucket exists and you // have permission to access it. Otherwise, the operation might // return responses such as 404 Not Found and 403 Forbidden. -func (api CloudStorageAPI) HeadBucketHandler(w http.ResponseWriter, r *http.Request) { +func (api storageAPI) HeadBucketHandler(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) bucket := vars["bucket"] @@ -520,7 +520,7 @@ func (api CloudStorageAPI) HeadBucketHandler(w http.ResponseWriter, r *http.Requ } // DeleteBucketHandler - Delete bucket -func (api CloudStorageAPI) DeleteBucketHandler(w http.ResponseWriter, r *http.Request) { +func (api storageAPI) DeleteBucketHandler(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) bucket := vars["bucket"] diff --git a/jwt.go b/jwt.go index db6944994..8b495d990 100644 --- a/jwt.go +++ b/jwt.go @@ -37,8 +37,8 @@ const ( tokenExpires time.Duration = 10 ) -// InitJWT - initialize. -func InitJWT() *JWT { +// initJWT - initialize. +func initJWT() *JWT { jwt := &JWT{} // Load credentials. config, err := loadConfigV2() diff --git a/object-handlers.go b/object-handlers.go index 51b75e03c..d78420e13 100644 --- a/object-handlers.go +++ b/object-handlers.go @@ -51,7 +51,7 @@ func setResponseHeaders(w http.ResponseWriter, reqParams url.Values) { // ---------- // This implementation of the GET operation retrieves object. To use GET, // you must have READ access to the object. -func (api CloudStorageAPI) GetObjectHandler(w http.ResponseWriter, r *http.Request) { +func (api storageAPI) GetObjectHandler(w http.ResponseWriter, r *http.Request) { var object, bucket string vars := mux.Vars(r) bucket = vars["bucket"] @@ -109,7 +109,7 @@ func (api CloudStorageAPI) GetObjectHandler(w http.ResponseWriter, r *http.Reque // HeadObjectHandler - HEAD Object // ----------- // The HEAD operation retrieves metadata from an object without returning the object itself. -func (api CloudStorageAPI) HeadObjectHandler(w http.ResponseWriter, r *http.Request) { +func (api storageAPI) HeadObjectHandler(w http.ResponseWriter, r *http.Request) { var object, bucket string vars := mux.Vars(r) bucket = vars["bucket"] @@ -150,7 +150,7 @@ func (api CloudStorageAPI) HeadObjectHandler(w http.ResponseWriter, r *http.Requ // PutObjectHandler - PUT Object // ---------- // This implementation of the PUT operation adds an object to a bucket. -func (api CloudStorageAPI) PutObjectHandler(w http.ResponseWriter, r *http.Request) { +func (api storageAPI) PutObjectHandler(w http.ResponseWriter, r *http.Request) { var object, bucket string vars := mux.Vars(r) bucket = vars["bucket"] @@ -231,10 +231,10 @@ func (api CloudStorageAPI) PutObjectHandler(w http.ResponseWriter, r *http.Reque writeSuccessResponse(w, nil) } -/// Multipart CloudStorageAPI +/// Multipart storageAPI // NewMultipartUploadHandler - New multipart upload -func (api CloudStorageAPI) NewMultipartUploadHandler(w http.ResponseWriter, r *http.Request) { +func (api storageAPI) NewMultipartUploadHandler(w http.ResponseWriter, r *http.Request) { var object, bucket string vars := mux.Vars(r) bucket = vars["bucket"] @@ -281,7 +281,7 @@ func (api CloudStorageAPI) NewMultipartUploadHandler(w http.ResponseWriter, r *h } // PutObjectPartHandler - Upload part -func (api CloudStorageAPI) PutObjectPartHandler(w http.ResponseWriter, r *http.Request) { +func (api storageAPI) PutObjectPartHandler(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) bucket := vars["bucket"] object := vars["object"] @@ -373,7 +373,7 @@ func (api CloudStorageAPI) PutObjectPartHandler(w http.ResponseWriter, r *http.R } // AbortMultipartUploadHandler - Abort multipart upload -func (api CloudStorageAPI) AbortMultipartUploadHandler(w http.ResponseWriter, r *http.Request) { +func (api storageAPI) AbortMultipartUploadHandler(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) bucket := vars["bucket"] object := vars["object"] @@ -414,7 +414,7 @@ func (api CloudStorageAPI) AbortMultipartUploadHandler(w http.ResponseWriter, r } // ListObjectPartsHandler - List object parts -func (api CloudStorageAPI) ListObjectPartsHandler(w http.ResponseWriter, r *http.Request) { +func (api storageAPI) ListObjectPartsHandler(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) bucket := vars["bucket"] object := vars["object"] @@ -472,7 +472,7 @@ func (api CloudStorageAPI) ListObjectPartsHandler(w http.ResponseWriter, r *http } // CompleteMultipartUploadHandler - Complete multipart upload -func (api CloudStorageAPI) CompleteMultipartUploadHandler(w http.ResponseWriter, r *http.Request) { +func (api storageAPI) CompleteMultipartUploadHandler(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) bucket := vars["bucket"] object := vars["object"] @@ -542,10 +542,10 @@ func (api CloudStorageAPI) CompleteMultipartUploadHandler(w http.ResponseWriter, writeSuccessResponse(w, encodedSuccessResponse) } -/// Delete CloudStorageAPI +/// Delete storageAPI // DeleteObjectHandler - Delete object -func (api CloudStorageAPI) DeleteObjectHandler(w http.ResponseWriter, r *http.Request) { +func (api storageAPI) DeleteObjectHandler(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) bucket := vars["bucket"] object := vars["object"] diff --git a/pkg/signature/signature-v4.go b/pkg/signature/signature-v4.go index 619286971..624722cf4 100644 --- a/pkg/signature/signature-v4.go +++ b/pkg/signature/signature-v4.go @@ -273,7 +273,7 @@ func (s *Signature) DoesPresignedSignatureMatch() (bool, *probe.Error) { query := make(url.Values) query.Set("X-Amz-Algorithm", signV4Algorithm) - if time.Now().UTC().Sub(preSignV4Values.Date) > time.Duration(preSignV4Values.Expires)/time.Second { + if time.Now().UTC().Sub(preSignV4Values.Date) > time.Duration(preSignV4Values.Expires) { return false, ErrExpiredPresignRequest("Presigned request already expired, please initiate a new request.") } @@ -281,6 +281,7 @@ func (s *Signature) DoesPresignedSignatureMatch() (bool, *probe.Error) { t := preSignV4Values.Date expireSeconds := int(time.Duration(preSignV4Values.Expires) / time.Second) + // Construct the query. query.Set("X-Amz-Date", t.Format(iso8601Format)) query.Set("X-Amz-Expires", strconv.Itoa(expireSeconds)) query.Set("X-Amz-SignedHeaders", s.getSignedHeaders(s.extractedSignedHeaders)) @@ -293,6 +294,8 @@ func (s *Signature) DoesPresignedSignatureMatch() (bool, *probe.Error) { } query[k] = v } + + // Get the encoded query. encodedQuery := query.Encode() // Verify if date query is same. diff --git a/routers.go b/routers.go index 3e87d7548..1f995240a 100644 --- a/routers.go +++ b/routers.go @@ -30,8 +30,8 @@ import ( signV4 "github.com/minio/minio/pkg/signature" ) -// CloudStorageAPI container for S3 compatible API. -type CloudStorageAPI struct { +// storageAPI container for S3 compatible API. +type storageAPI struct { // Once true log all incoming requests. AccessLog bool // Filesystem instance. @@ -42,8 +42,8 @@ type CloudStorageAPI struct { Region string } -// WebAPI container for Web API. -type WebAPI struct { +// webAPI container for Web API. +type webAPI struct { // FSPath filesystem path. FSPath string // Once true log all incoming request. @@ -59,8 +59,8 @@ type WebAPI struct { secretAccessKey string } -// registerCloudStorageAPI - register all the handlers to their respective paths -func registerCloudStorageAPI(mux *router.Router, a CloudStorageAPI, w *WebAPI) { +// registerAPIHandlers - register all the handlers to their respective paths +func registerAPIHandlers(mux *router.Router, a storageAPI, w *webAPI) { // Minio rpc router minio := mux.NewRoute().PathPrefix(privateBucket).Subrouter() @@ -110,8 +110,8 @@ func registerCloudStorageAPI(mux *router.Router, a CloudStorageAPI, w *WebAPI) { api.Methods("GET").HandlerFunc(a.ListBucketsHandler) } -// getNewWebAPI instantiate a new WebAPI. -func getNewWebAPI(conf cloudServerConfig) *WebAPI { +// initWeb instantiate a new Web. +func initWeb(conf cloudServerConfig) *webAPI { // Split host port. host, port, e := net.SplitHostPort(conf.Address) fatalIf(probe.NewError(e), "Unable to parse web addess.", nil) @@ -126,7 +126,7 @@ func getNewWebAPI(conf cloudServerConfig) *WebAPI { client, e := minio.NewV4(net.JoinHostPort(host, port), conf.AccessKeyID, conf.SecretAccessKey, inSecure) fatalIf(probe.NewError(e), "Unable to initialize minio client", nil) - w := &WebAPI{ + w := &webAPI{ FSPath: conf.Path, AccessLog: conf.AccessLog, Client: client, @@ -138,15 +138,15 @@ func getNewWebAPI(conf cloudServerConfig) *WebAPI { return w } -// getNewCloudStorageAPI instantiate a new CloudStorageAPI. -func getNewCloudStorageAPI(conf cloudServerConfig) CloudStorageAPI { +// initAPI instantiate a new StorageAPI. +func initAPI(conf cloudServerConfig) storageAPI { fs, err := fs.New(conf.Path, conf.MinFreeDisk) fatalIf(err.Trace(), "Initializing filesystem failed.", nil) sign, err := signV4.New(conf.AccessKeyID, conf.SecretAccessKey, conf.Region) fatalIf(err.Trace(conf.AccessKeyID, conf.SecretAccessKey, conf.Region), "Initializing signature version '4' failed.", nil) - return CloudStorageAPI{ + return storageAPI{ AccessLog: conf.AccessLog, Filesystem: fs, Signature: sign, @@ -154,7 +154,14 @@ func getNewCloudStorageAPI(conf cloudServerConfig) CloudStorageAPI { } } -func getCloudStorageAPIHandler(api CloudStorageAPI, web *WebAPI) http.Handler { +// server handler returns final handler before initializing server. +func serverHandler(conf cloudServerConfig) http.Handler { + // Initialize API. + api := initAPI(conf) + + // Initialize Web. + web := initWeb(conf) + var handlerFns = []HandlerFunc{ // Redirect some pre-defined browser request paths to a static // location prefix. @@ -175,8 +182,13 @@ func getCloudStorageAPIHandler(api CloudStorageAPI, web *WebAPI) http.Handler { // invalid/unsupported signatures. setAuthHandler, } - handlerFns = append(handlerFns, setCorsHandler) + + // Initialize router. mux := router.NewRouter() - registerCloudStorageAPI(mux, api, web) + + // Register all API handlers. + registerAPIHandlers(mux, api, web) + + // Register rest of the handlers. return registerHandlers(mux, handlerFns...) } diff --git a/server-main.go b/server-main.go index fa94738e5..b922f1b0e 100644 --- a/server-main.go +++ b/server-main.go @@ -90,12 +90,12 @@ type cloudServerConfig struct { KeyFile string // Domain key } -// configureAPIServer configure a new server instance -func configureAPIServer(conf cloudServerConfig) (*http.Server, *probe.Error) { +// configureServer configure a new server instance +func configureServer(conf cloudServerConfig) (*http.Server, *probe.Error) { // Minio server config apiServer := &http.Server{ Addr: conf.Address, - Handler: getCloudStorageAPIHandler(getNewCloudStorageAPI(conf), getNewWebAPI(conf)), + Handler: serverHandler(conf), MaxHeaderBytes: 1 << 20, } @@ -285,13 +285,16 @@ func serverMain(c *cli.Context) { KeyFile: keyFile, } - // configure API server. - apiServer, err := configureAPIServer(serverConfig) + // configure server. + apiServer, err := configureServer(serverConfig) errorIf(err.Trace(), "Failed to configure API server.", nil) Println("\nMinio Object Storage:") printServerMsg(apiServer) + Println("\nMinio Browser:") + printServerMsg(apiServer) + Println("\nTo configure Minio Client:") if runtime.GOOS == "windows" { Println(" Download \"mc\" from https://dl.minio.io/client/mc/release/" + runtime.GOOS + "-" + runtime.GOARCH + "/mc.exe") diff --git a/server_fs_test.go b/server_fs_test.go index cbdac349e..f07de50c8 100644 --- a/server_fs_test.go +++ b/server_fs_test.go @@ -101,9 +101,7 @@ func (s *MyAPIFSCacheSuite) SetUpSuite(c *C) { SecretAccessKey: s.secretAccessKey, Region: "us-east-1", } - cloudStorageAPI := getNewCloudStorageAPI(cloudServer) - webAPI := getNewWebAPI(cloudServer) - httpHandler := getCloudStorageAPIHandler(cloudStorageAPI, webAPI) + httpHandler := serverHandler(cloudServer) testAPIFSCacheServer = httptest.NewServer(httpHandler) } diff --git a/signature.go b/signature.go index 58981ab06..e96a219e0 100644 --- a/signature.go +++ b/signature.go @@ -1,3 +1,19 @@ +/* + * Minio Cloud Storage, (C) 2015, 2016 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 main import ( @@ -9,6 +25,7 @@ import ( signV4 "github.com/minio/minio/pkg/signature" ) +// Verify if request has JWT. func isRequestJWT(r *http.Request) bool { if _, ok := r.Header["Authorization"]; ok { if strings.HasPrefix(r.Header.Get("Authorization"), jwtAlgorithm) { @@ -18,6 +35,7 @@ func isRequestJWT(r *http.Request) bool { return false } +// Verify if request has AWS Signature Version '4'. func isRequestSignatureV4(r *http.Request) bool { if _, ok := r.Header["Authorization"]; ok { if strings.HasPrefix(r.Header.Get("Authorization"), signV4Algorithm) { @@ -27,6 +45,7 @@ func isRequestSignatureV4(r *http.Request) bool { return false } +// Verify if request has AWS Presignature Version '4'. func isRequestPresignedSignatureV4(r *http.Request) bool { if _, ok := r.URL.Query()["X-Amz-Credential"]; ok { return ok @@ -34,6 +53,7 @@ func isRequestPresignedSignatureV4(r *http.Request) bool { return false } +// Verify if request has AWS Post policy Signature Version '4'. func isRequestPostPolicySignatureV4(r *http.Request) bool { if _, ok := r.Header["Content-Type"]; ok { if strings.Contains(r.Header.Get("Content-Type"), "multipart/form-data") { @@ -43,6 +63,7 @@ func isRequestPostPolicySignatureV4(r *http.Request) bool { return false } +// Verify if request requires ACL check. func isRequestRequiresACLCheck(r *http.Request) bool { if isRequestSignatureV4(r) || isRequestPresignedSignatureV4(r) || isRequestPostPolicySignatureV4(r) { return false @@ -50,6 +71,7 @@ func isRequestRequiresACLCheck(r *http.Request) bool { return true } +// Verify if request has valid AWS Signature Version '4'. func isSignV4ReqAuthenticated(sign *signV4.Signature, r *http.Request) bool { auth := sign.SetHTTPRequestToVerify(r) if isRequestSignatureV4(r) { diff --git a/web-handlers.go b/web-handlers.go index eb8bff393..ffeb339d2 100644 --- a/web-handlers.go +++ b/web-handlers.go @@ -36,11 +36,11 @@ import ( "github.com/minio/minio/pkg/probe" ) -// isJWTReqAuthencatied validates if any incoming request to be a valid JWT -// authenticated request. -func isJWTReqAuthencatied(req *http.Request) bool { - jwt := InitJWT() - tokenRequest, e := jwtgo.ParseFromRequest(req, func(token *jwtgo.Token) (interface{}, error) { +// isJWTReqAuthenticated validates if any incoming request to be a +// valid JWT authenticated request. +func isJWTReqAuthenticated(req *http.Request) bool { + jwt := initJWT() + token, e := jwtgo.ParseFromRequest(req, func(token *jwtgo.Token) (interface{}, error) { if _, ok := token.Method.(*jwtgo.SigningMethodHMAC); !ok { return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"]) } @@ -49,18 +49,18 @@ func isJWTReqAuthencatied(req *http.Request) bool { if e != nil { return false } - return tokenRequest.Valid + return token.Valid } // GetUIVersion - get UI version -func (web WebAPI) GetUIVersion(r *http.Request, args *GenericArgs, reply *GenericRep) error { +func (web webAPI) GetUIVersion(r *http.Request, args *GenericArgs, reply *GenericRep) error { reply.UIVersion = uiVersion return nil } // ServerInfo - get server info. -func (web *WebAPI) ServerInfo(r *http.Request, args *ServerInfoArgs, reply *ServerInfoRep) error { - if !isJWTReqAuthencatied(r) { +func (web *webAPI) ServerInfo(r *http.Request, args *ServerInfoArgs, reply *ServerInfoRep) error { + if !isJWTReqAuthenticated(r) { return &json2.Error{Message: "Unauthorized request"} } host, err := os.Hostname() @@ -88,8 +88,8 @@ func (web *WebAPI) ServerInfo(r *http.Request, args *ServerInfoArgs, reply *Serv } // DiskInfo - get disk statistics. -func (web *WebAPI) DiskInfo(r *http.Request, args *DiskInfoArgs, reply *DiskInfoRep) error { - if !isJWTReqAuthencatied(r) { +func (web *webAPI) DiskInfo(r *http.Request, args *DiskInfoArgs, reply *DiskInfoRep) error { + if !isJWTReqAuthenticated(r) { return &json2.Error{Message: "Unauthorized request"} } info, e := disk.GetInfo(web.FSPath) @@ -102,8 +102,8 @@ func (web *WebAPI) DiskInfo(r *http.Request, args *DiskInfoArgs, reply *DiskInfo } // MakeBucket - make a bucket. -func (web *WebAPI) MakeBucket(r *http.Request, args *MakeBucketArgs, reply *GenericRep) error { - if !isJWTReqAuthencatied(r) { +func (web *webAPI) MakeBucket(r *http.Request, args *MakeBucketArgs, reply *GenericRep) error { + if !isJWTReqAuthenticated(r) { return &json2.Error{Message: "Unauthorized request"} } reply.UIVersion = uiVersion @@ -115,8 +115,8 @@ func (web *WebAPI) MakeBucket(r *http.Request, args *MakeBucketArgs, reply *Gene } // ListBuckets - list buckets api. -func (web *WebAPI) ListBuckets(r *http.Request, args *ListBucketsArgs, reply *ListBucketsRep) error { - if !isJWTReqAuthencatied(r) { +func (web *webAPI) ListBuckets(r *http.Request, args *ListBucketsArgs, reply *ListBucketsRep) error { + if !isJWTReqAuthenticated(r) { return &json2.Error{Message: "Unauthorized request"} } buckets, e := web.Client.ListBuckets() @@ -134,8 +134,8 @@ func (web *WebAPI) ListBuckets(r *http.Request, args *ListBucketsArgs, reply *Li } // ListObjects - list objects api. -func (web *WebAPI) ListObjects(r *http.Request, args *ListObjectsArgs, reply *ListObjectsRep) error { - if !isJWTReqAuthencatied(r) { +func (web *webAPI) ListObjects(r *http.Request, args *ListObjectsArgs, reply *ListObjectsRep) error { + if !isJWTReqAuthenticated(r) { return &json2.Error{Message: "Unauthorized request"} } doneCh := make(chan struct{}) @@ -182,8 +182,8 @@ func getTargetHost(apiAddress, targetHost string) (string, *probe.Error) { } // PutObjectURL - generates url for upload access. -func (web *WebAPI) PutObjectURL(r *http.Request, args *PutObjectURLArgs, reply *PutObjectURLRep) error { - if !isJWTReqAuthencatied(r) { +func (web *webAPI) PutObjectURL(r *http.Request, args *PutObjectURLArgs, reply *PutObjectURLRep) error { + if !isJWTReqAuthenticated(r) { return &json2.Error{Message: "Unauthorized request"} } targetHost, err := getTargetHost(web.apiAddress, args.TargetHost) @@ -204,8 +204,8 @@ func (web *WebAPI) PutObjectURL(r *http.Request, args *PutObjectURLArgs, reply * } // GetObjectURL - generates url for download access. -func (web *WebAPI) GetObjectURL(r *http.Request, args *GetObjectURLArgs, reply *GetObjectURLRep) error { - if !isJWTReqAuthencatied(r) { +func (web *webAPI) GetObjectURL(r *http.Request, args *GetObjectURLArgs, reply *GetObjectURLRep) error { + if !isJWTReqAuthenticated(r) { return &json2.Error{Message: "Unauthorized request"} } @@ -236,8 +236,8 @@ func (web *WebAPI) GetObjectURL(r *http.Request, args *GetObjectURLArgs, reply * } // RemoveObject - removes an object. -func (web *WebAPI) RemoveObject(r *http.Request, args *RemoveObjectArgs, reply *GenericRep) error { - if !isJWTReqAuthencatied(r) { +func (web *webAPI) RemoveObject(r *http.Request, args *RemoveObjectArgs, reply *GenericRep) error { + if !isJWTReqAuthenticated(r) { return &json2.Error{Message: "Unauthorized request"} } reply.UIVersion = uiVersion @@ -249,8 +249,8 @@ func (web *WebAPI) RemoveObject(r *http.Request, args *RemoveObjectArgs, reply * } // Login - user login handler. -func (web *WebAPI) Login(r *http.Request, args *LoginArgs, reply *LoginRep) error { - jwt := InitJWT() +func (web *webAPI) Login(r *http.Request, args *LoginArgs, reply *LoginRep) error { + jwt := initJWT() if jwt.Authenticate(args.Username, args.Password) { token, err := jwt.GenerateToken(args.Username) if err != nil {