mirror of
https://github.com/minio/minio.git
synced 2024-12-24 22:25:54 -05:00
Merge pull request #1136 from harshavardhana/add-proxy
presigned: Fix a bug in presigned request verification.
This commit is contained in:
commit
1c33926239
25
Docker.md
25
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
|
||||
```
|
||||
|
@ -3,6 +3,5 @@ FROM scratch
|
||||
ADD minio.dockerimage /minio
|
||||
ADD export /export
|
||||
EXPOSE 9000
|
||||
EXPOSE 9001
|
||||
ENTRYPOINT ["/minio"]
|
||||
CMD ["server", "/export"]
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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"]
|
||||
|
||||
|
4
jwt.go
4
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()
|
||||
|
@ -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"]
|
||||
|
@ -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.
|
||||
|
42
routers.go
42
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...)
|
||||
}
|
||||
|
@ -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")
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
22
signature.go
22
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) {
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user