mirror of
https://github.com/minio/minio.git
synced 2025-04-08 05:35:33 -04:00
Improve coverage of web-handlers.go (#3157)
This patch additionally relaxes the requirement for accesskeys to be in a regexy set of values. Fixes #3063
This commit is contained in:
parent
f024deb1f8
commit
d9674f7524
@ -19,7 +19,6 @@ package cmd
|
|||||||
import (
|
import (
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"regexp"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// credential container for access and secret keys.
|
// credential container for access and secret keys.
|
||||||
@ -33,11 +32,15 @@ const (
|
|||||||
minioSecretID = 40
|
minioSecretID = 40
|
||||||
)
|
)
|
||||||
|
|
||||||
// isValidSecretKey - validate secret key.
|
// isValidAccessKey - validate access key for right length.
|
||||||
var isValidSecretKey = regexp.MustCompile(`^.{8,40}$`)
|
func isValidAccessKey(accessKey string) bool {
|
||||||
|
return len(accessKey) >= 5 && len(accessKey) <= 20
|
||||||
|
}
|
||||||
|
|
||||||
// isValidAccessKey - validate access key.
|
// isValidSecretKey - validate secret key for right length.
|
||||||
var isValidAccessKey = regexp.MustCompile(`^[a-zA-Z0-9\\-\\.\\_\\~]{5,20}$`)
|
func isValidSecretKey(secretKey string) bool {
|
||||||
|
return len(secretKey) >= 8 && len(secretKey) <= 40
|
||||||
|
}
|
||||||
|
|
||||||
// mustGenAccessKeys - must generate access credentials.
|
// mustGenAccessKeys - must generate access credentials.
|
||||||
func mustGenAccessKeys() (creds credential) {
|
func mustGenAccessKeys() (creds credential) {
|
||||||
|
@ -184,10 +184,10 @@ func Main() {
|
|||||||
SecretAccessKey: secretKey,
|
SecretAccessKey: secretKey,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if !isValidAccessKey.MatchString(serverConfig.GetCredential().AccessKeyID) {
|
if !isValidAccessKey(serverConfig.GetCredential().AccessKeyID) {
|
||||||
fatalIf(errInvalidArgument, "Invalid access key. Accept only a string starting with a alphabetic and containing from 5 to 20 characters.")
|
fatalIf(errInvalidArgument, "Invalid access key. Accept only a string starting with a alphabetic and containing from 5 to 20 characters.")
|
||||||
}
|
}
|
||||||
if !isValidSecretKey.MatchString(serverConfig.GetCredential().SecretAccessKey) {
|
if !isValidSecretKey(serverConfig.GetCredential().SecretAccessKey) {
|
||||||
fatalIf(errInvalidArgument, "Invalid secret key. Accept only a string containing from 8 to 40 characters.")
|
fatalIf(errInvalidArgument, "Invalid secret key. Accept only a string containing from 8 to 40 characters.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,28 +44,30 @@ const (
|
|||||||
// newJWT - returns new JWT object.
|
// newJWT - returns new JWT object.
|
||||||
func newJWT(expiry time.Duration) (*JWT, error) {
|
func newJWT(expiry time.Duration) (*JWT, error) {
|
||||||
if serverConfig == nil {
|
if serverConfig == nil {
|
||||||
return nil, errors.New("Server not initialized")
|
return nil, errServerNotInitialized
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save access, secret keys.
|
// Save access, secret keys.
|
||||||
cred := serverConfig.GetCredential()
|
cred := serverConfig.GetCredential()
|
||||||
if !isValidAccessKey.MatchString(cred.AccessKeyID) {
|
if !isValidAccessKey(cred.AccessKeyID) {
|
||||||
return nil, errors.New("Invalid access key")
|
return nil, errInvalidAccessKeyLength
|
||||||
}
|
}
|
||||||
if !isValidSecretKey.MatchString(cred.SecretAccessKey) {
|
if !isValidSecretKey(cred.SecretAccessKey) {
|
||||||
return nil, errors.New("Invalid secret key")
|
return nil, errInvalidSecretKeyLength
|
||||||
}
|
}
|
||||||
|
|
||||||
return &JWT{cred, expiry}, nil
|
return &JWT{cred, expiry}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var errInvalidAccessKeyLength = errors.New("Invalid access key, access key should be 5 to 20 characters in length.")
|
||||||
|
var errInvalidSecretKeyLength = errors.New("Invalid secret key, secret key should be 8 to 40 characters in length.")
|
||||||
|
|
||||||
// GenerateToken - generates a new Json Web Token based on the incoming access key.
|
// GenerateToken - generates a new Json Web Token based on the incoming access key.
|
||||||
func (jwt *JWT) GenerateToken(accessKey string) (string, error) {
|
func (jwt *JWT) GenerateToken(accessKey string) (string, error) {
|
||||||
// Trim spaces.
|
// Trim spaces.
|
||||||
accessKey = strings.TrimSpace(accessKey)
|
accessKey = strings.TrimSpace(accessKey)
|
||||||
|
|
||||||
if !isValidAccessKey.MatchString(accessKey) {
|
if !isValidAccessKey(accessKey) {
|
||||||
return "", errors.New("Invalid access key")
|
return "", errInvalidAccessKeyLength
|
||||||
}
|
}
|
||||||
|
|
||||||
tUTCNow := time.Now().UTC()
|
tUTCNow := time.Now().UTC()
|
||||||
@ -79,7 +81,6 @@ func (jwt *JWT) GenerateToken(accessKey string) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var errInvalidAccessKeyID = errors.New("The access key ID you provided does not exist in our records.")
|
var errInvalidAccessKeyID = errors.New("The access key ID you provided does not exist in our records.")
|
||||||
|
|
||||||
var errAuthentication = errors.New("Authentication failed, check your access credentials.")
|
var errAuthentication = errors.New("Authentication failed, check your access credentials.")
|
||||||
|
|
||||||
// Authenticate - authenticates incoming access key and secret key.
|
// Authenticate - authenticates incoming access key and secret key.
|
||||||
@ -87,11 +88,11 @@ func (jwt *JWT) Authenticate(accessKey, secretKey string) error {
|
|||||||
// Trim spaces.
|
// Trim spaces.
|
||||||
accessKey = strings.TrimSpace(accessKey)
|
accessKey = strings.TrimSpace(accessKey)
|
||||||
|
|
||||||
if !isValidAccessKey.MatchString(accessKey) {
|
if !isValidAccessKey(accessKey) {
|
||||||
return errors.New("Invalid access key")
|
return errInvalidAccessKeyLength
|
||||||
}
|
}
|
||||||
if !isValidSecretKey.MatchString(secretKey) {
|
if !isValidSecretKey(secretKey) {
|
||||||
return errors.New("Invalid secret key")
|
return errInvalidSecretKeyLength
|
||||||
}
|
}
|
||||||
|
|
||||||
if accessKey != jwt.AccessKeyID {
|
if accessKey != jwt.AccessKeyID {
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
@ -72,25 +71,23 @@ func TestNewJWT(t *testing.T) {
|
|||||||
expectedErr error
|
expectedErr error
|
||||||
}{
|
}{
|
||||||
// Test non-existent config directory.
|
// Test non-existent config directory.
|
||||||
{path.Join(path1, "non-existent-dir"), false, nil, fmt.Errorf("Server not initialized")},
|
{path.Join(path1, "non-existent-dir"), false, nil, errServerNotInitialized},
|
||||||
// Test empty config directory.
|
// Test empty config directory.
|
||||||
{path2, false, nil, fmt.Errorf("Server not initialized")},
|
{path2, false, nil, errServerNotInitialized},
|
||||||
// Test empty config file.
|
// Test empty config file.
|
||||||
{path3, false, nil, fmt.Errorf("Server not initialized")},
|
{path3, false, nil, errServerNotInitialized},
|
||||||
// Test initialized config file.
|
// Test initialized config file.
|
||||||
{path4, true, nil, nil},
|
{path4, true, nil, nil},
|
||||||
// Test to read already created config file.
|
// Test to read already created config file.
|
||||||
{path4, false, nil, nil},
|
{path4, false, nil, nil},
|
||||||
// Access key is too small.
|
// Access key is too small.
|
||||||
{path4, false, &credential{"user", "pass"}, fmt.Errorf("Invalid access key")},
|
{path4, false, &credential{"user", "pass"}, errInvalidAccessKeyLength},
|
||||||
// Access key is too long.
|
// Access key is too long.
|
||||||
{path4, false, &credential{"user12345678901234567", "pass"}, fmt.Errorf("Invalid access key")},
|
{path4, false, &credential{"user12345678901234567", "pass"}, errInvalidAccessKeyLength},
|
||||||
// Access key contains unsupported characters.
|
|
||||||
{path4, false, &credential{"!@#$%^&*()", "pass"}, fmt.Errorf("Invalid access key")},
|
|
||||||
// Secret key is too small.
|
// Secret key is too small.
|
||||||
{path4, false, &credential{"myuser", "pass"}, fmt.Errorf("Invalid secret key")},
|
{path4, false, &credential{"myuser", "pass"}, errInvalidSecretKeyLength},
|
||||||
// Secret key is too long.
|
// Secret key is too long.
|
||||||
{path4, false, &credential{"myuser", "pass1234567890123456789012345678901234567"}, fmt.Errorf("Invalid secret key")},
|
{path4, false, &credential{"myuser", "pass1234567890123456789012345678901234567"}, errInvalidSecretKeyLength},
|
||||||
// Valid access/secret keys.
|
// Valid access/secret keys.
|
||||||
{path4, false, &credential{"myuser", "mypassword"}, nil},
|
{path4, false, &credential{"myuser", "mypassword"}, nil},
|
||||||
}
|
}
|
||||||
@ -114,7 +111,6 @@ func TestNewJWT(t *testing.T) {
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatalf("%+v: expected: %s, got: <nil>", testCase, testCase.expectedErr)
|
t.Fatalf("%+v: expected: %s, got: <nil>", testCase, testCase.expectedErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
if testCase.expectedErr.Error() != err.Error() {
|
if testCase.expectedErr.Error() != err.Error() {
|
||||||
t.Fatalf("%+v: expected: %s, got: %s", testCase, testCase.expectedErr, err)
|
t.Fatalf("%+v: expected: %s, got: %s", testCase, testCase.expectedErr, err)
|
||||||
}
|
}
|
||||||
@ -143,11 +139,11 @@ func TestGenerateToken(t *testing.T) {
|
|||||||
expectedErr error
|
expectedErr error
|
||||||
}{
|
}{
|
||||||
// Access key is too small.
|
// Access key is too small.
|
||||||
{"user", fmt.Errorf("Invalid access key")},
|
{"user", errInvalidAccessKeyLength},
|
||||||
// Access key is too long.
|
// Access key is too long.
|
||||||
{"user12345678901234567", fmt.Errorf("Invalid access key")},
|
{"user12345678901234567", errInvalidAccessKeyLength},
|
||||||
// Access key contains unsupported characters.
|
// Access key contains unsupported characters.
|
||||||
{"!@#$%^&*()", fmt.Errorf("Invalid access key")},
|
{"!@#$", errInvalidAccessKeyLength},
|
||||||
// Valid access key.
|
// Valid access key.
|
||||||
{"myuser", nil},
|
{"myuser", nil},
|
||||||
// Valid access key with leading/trailing spaces.
|
// Valid access key with leading/trailing spaces.
|
||||||
@ -191,15 +187,15 @@ func TestAuthenticate(t *testing.T) {
|
|||||||
expectedErr error
|
expectedErr error
|
||||||
}{
|
}{
|
||||||
// Access key too small.
|
// Access key too small.
|
||||||
{"user", "pass", fmt.Errorf("Invalid access key")},
|
{"user", "pass", errInvalidAccessKeyLength},
|
||||||
// Access key too long.
|
// Access key too long.
|
||||||
{"user12345678901234567", "pass", fmt.Errorf("Invalid access key")},
|
{"user12345678901234567", "pass", errInvalidAccessKeyLength},
|
||||||
// Access key contains unsuppported characters.
|
// Access key contains unsuppported characters.
|
||||||
{"!@#$%^&*()", "pass", fmt.Errorf("Invalid access key")},
|
{"!@#$", "pass", errInvalidAccessKeyLength},
|
||||||
// Secret key too small.
|
// Secret key too small.
|
||||||
{"myuser", "pass", fmt.Errorf("Invalid secret key")},
|
{"myuser", "pass", errInvalidSecretKeyLength},
|
||||||
// Secret key too long.
|
// Secret key too long.
|
||||||
{"myuser", "pass1234567890123456789012345678901234567", fmt.Errorf("Invalid secret key")},
|
{"myuser", "pass1234567890123456789012345678901234567", errInvalidSecretKeyLength},
|
||||||
// Authentication error.
|
// Authentication error.
|
||||||
{"myuser", "mypassword", errInvalidAccessKeyID},
|
{"myuser", "mypassword", errInvalidAccessKeyID},
|
||||||
// Authentication error.
|
// Authentication error.
|
||||||
|
@ -47,7 +47,7 @@ func parseCredentialHeader(credElement string) (credentialHeader, APIErrorCode)
|
|||||||
if len(credElements) != 5 {
|
if len(credElements) != 5 {
|
||||||
return credentialHeader{}, ErrCredMalformed
|
return credentialHeader{}, ErrCredMalformed
|
||||||
}
|
}
|
||||||
if !isValidAccessKey.MatchString(credElements[0]) {
|
if !isValidAccessKey(credElements[0]) {
|
||||||
return credentialHeader{}, ErrInvalidAccessKeyID
|
return credentialHeader{}, ErrInvalidAccessKeyID
|
||||||
}
|
}
|
||||||
// Save access key id.
|
// Save access key id.
|
||||||
|
@ -116,10 +116,10 @@ func TestParseCredentialHeader(t *testing.T) {
|
|||||||
expectedErrCode: ErrCredMalformed,
|
expectedErrCode: ErrCredMalformed,
|
||||||
},
|
},
|
||||||
// Test Case - 4.
|
// Test Case - 4.
|
||||||
// Test case with malformed AccessKey.
|
// Test case with AccessKey of length 4.
|
||||||
{
|
{
|
||||||
inputCredentialStr: generateCredentialStr(
|
inputCredentialStr: generateCredentialStr(
|
||||||
"^#@..!23",
|
"^#@.",
|
||||||
time.Now().UTC().Format(yyyymmdd),
|
time.Now().UTC().Format(yyyymmdd),
|
||||||
"ABCD",
|
"ABCD",
|
||||||
"ABCD",
|
"ABCD",
|
||||||
|
@ -19,7 +19,6 @@ package cmd
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
@ -86,7 +85,7 @@ type ServerInfoRep struct {
|
|||||||
// ServerInfo - get server info.
|
// ServerInfo - get server info.
|
||||||
func (web *webAPIHandlers) ServerInfo(r *http.Request, args *WebGenericArgs, reply *ServerInfoRep) error {
|
func (web *webAPIHandlers) ServerInfo(r *http.Request, args *WebGenericArgs, reply *ServerInfoRep) error {
|
||||||
if !isJWTReqAuthenticated(r) {
|
if !isJWTReqAuthenticated(r) {
|
||||||
return &json2.Error{Message: "Unauthorized request"}
|
return &json2.Error{Message: errAuthentication.Error()}
|
||||||
}
|
}
|
||||||
host, err := os.Hostname()
|
host, err := os.Hostname()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -122,12 +121,12 @@ type StorageInfoRep struct {
|
|||||||
|
|
||||||
// StorageInfo - web call to gather storage usage statistics.
|
// StorageInfo - web call to gather storage usage statistics.
|
||||||
func (web *webAPIHandlers) StorageInfo(r *http.Request, args *GenericArgs, reply *StorageInfoRep) error {
|
func (web *webAPIHandlers) StorageInfo(r *http.Request, args *GenericArgs, reply *StorageInfoRep) error {
|
||||||
if !isJWTReqAuthenticated(r) {
|
|
||||||
return &json2.Error{Message: "Unauthorized request"}
|
|
||||||
}
|
|
||||||
objectAPI := web.ObjectAPI()
|
objectAPI := web.ObjectAPI()
|
||||||
if objectAPI == nil {
|
if objectAPI == nil {
|
||||||
return &json2.Error{Message: "Server not initialized"}
|
return &json2.Error{Message: errServerNotInitialized.Error()}
|
||||||
|
}
|
||||||
|
if !isJWTReqAuthenticated(r) {
|
||||||
|
return &json2.Error{Message: errAuthentication.Error()}
|
||||||
}
|
}
|
||||||
reply.StorageInfo = objectAPI.StorageInfo()
|
reply.StorageInfo = objectAPI.StorageInfo()
|
||||||
reply.UIVersion = miniobrowser.UIVersion
|
reply.UIVersion = miniobrowser.UIVersion
|
||||||
@ -141,12 +140,12 @@ type MakeBucketArgs struct {
|
|||||||
|
|
||||||
// MakeBucket - make a bucket.
|
// MakeBucket - make a bucket.
|
||||||
func (web *webAPIHandlers) MakeBucket(r *http.Request, args *MakeBucketArgs, reply *WebGenericRep) error {
|
func (web *webAPIHandlers) MakeBucket(r *http.Request, args *MakeBucketArgs, reply *WebGenericRep) error {
|
||||||
if !isJWTReqAuthenticated(r) {
|
|
||||||
return &json2.Error{Message: "Unauthorized request"}
|
|
||||||
}
|
|
||||||
objectAPI := web.ObjectAPI()
|
objectAPI := web.ObjectAPI()
|
||||||
if objectAPI == nil {
|
if objectAPI == nil {
|
||||||
return &json2.Error{Message: "Server not initialized"}
|
return &json2.Error{Message: errServerNotInitialized.Error()}
|
||||||
|
}
|
||||||
|
if !isJWTReqAuthenticated(r) {
|
||||||
|
return &json2.Error{Message: errAuthentication.Error()}
|
||||||
}
|
}
|
||||||
if err := objectAPI.MakeBucket(args.BucketName); err != nil {
|
if err := objectAPI.MakeBucket(args.BucketName); err != nil {
|
||||||
return &json2.Error{Message: err.Error()}
|
return &json2.Error{Message: err.Error()}
|
||||||
@ -171,12 +170,12 @@ type WebBucketInfo struct {
|
|||||||
|
|
||||||
// ListBuckets - list buckets api.
|
// ListBuckets - list buckets api.
|
||||||
func (web *webAPIHandlers) ListBuckets(r *http.Request, args *WebGenericArgs, reply *ListBucketsRep) error {
|
func (web *webAPIHandlers) ListBuckets(r *http.Request, args *WebGenericArgs, reply *ListBucketsRep) error {
|
||||||
if !isJWTReqAuthenticated(r) {
|
|
||||||
return &json2.Error{Message: "Unauthorized request"}
|
|
||||||
}
|
|
||||||
objectAPI := web.ObjectAPI()
|
objectAPI := web.ObjectAPI()
|
||||||
if objectAPI == nil {
|
if objectAPI == nil {
|
||||||
return &json2.Error{Message: "Server not initialized"}
|
return &json2.Error{Message: errServerNotInitialized.Error()}
|
||||||
|
}
|
||||||
|
if !isJWTReqAuthenticated(r) {
|
||||||
|
return &json2.Error{Message: errAuthentication.Error()}
|
||||||
}
|
}
|
||||||
buckets, err := objectAPI.ListBuckets()
|
buckets, err := objectAPI.ListBuckets()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -221,15 +220,15 @@ type WebObjectInfo struct {
|
|||||||
|
|
||||||
// ListObjects - list objects api.
|
// ListObjects - list objects api.
|
||||||
func (web *webAPIHandlers) ListObjects(r *http.Request, args *ListObjectsArgs, reply *ListObjectsRep) error {
|
func (web *webAPIHandlers) ListObjects(r *http.Request, args *ListObjectsArgs, reply *ListObjectsRep) error {
|
||||||
|
objectAPI := web.ObjectAPI()
|
||||||
|
if objectAPI == nil {
|
||||||
|
return &json2.Error{Message: errServerNotInitialized.Error()}
|
||||||
|
}
|
||||||
marker := ""
|
marker := ""
|
||||||
if !isJWTReqAuthenticated(r) {
|
if !isJWTReqAuthenticated(r) {
|
||||||
return &json2.Error{Message: "Unauthorized request"}
|
return &json2.Error{Message: errAuthentication.Error()}
|
||||||
}
|
}
|
||||||
for {
|
for {
|
||||||
objectAPI := web.ObjectAPI()
|
|
||||||
if objectAPI == nil {
|
|
||||||
return &json2.Error{Message: "Server not initialized"}
|
|
||||||
}
|
|
||||||
lo, err := objectAPI.ListObjects(args.BucketName, args.Prefix, marker, "/", 1000)
|
lo, err := objectAPI.ListObjects(args.BucketName, args.Prefix, marker, "/", 1000)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &json2.Error{Message: err.Error()}
|
return &json2.Error{Message: err.Error()}
|
||||||
@ -264,13 +263,12 @@ type RemoveObjectArgs struct {
|
|||||||
|
|
||||||
// RemoveObject - removes an object.
|
// RemoveObject - removes an object.
|
||||||
func (web *webAPIHandlers) RemoveObject(r *http.Request, args *RemoveObjectArgs, reply *WebGenericRep) error {
|
func (web *webAPIHandlers) RemoveObject(r *http.Request, args *RemoveObjectArgs, reply *WebGenericRep) error {
|
||||||
if !isJWTReqAuthenticated(r) {
|
|
||||||
return &json2.Error{Message: "Unauthorized request"}
|
|
||||||
}
|
|
||||||
reply.UIVersion = miniobrowser.UIVersion
|
|
||||||
objectAPI := web.ObjectAPI()
|
objectAPI := web.ObjectAPI()
|
||||||
if objectAPI == nil {
|
if objectAPI == nil {
|
||||||
return &json2.Error{Message: "Server not initialized"}
|
return &json2.Error{Message: errServerNotInitialized.Error()}
|
||||||
|
}
|
||||||
|
if !isJWTReqAuthenticated(r) {
|
||||||
|
return &json2.Error{Message: errAuthentication.Error()}
|
||||||
}
|
}
|
||||||
if err := objectAPI.DeleteObject(args.BucketName, args.ObjectName); err != nil {
|
if err := objectAPI.DeleteObject(args.BucketName, args.ObjectName); err != nil {
|
||||||
return &json2.Error{Message: err.Error()}
|
return &json2.Error{Message: err.Error()}
|
||||||
@ -320,7 +318,7 @@ type GenerateAuthReply struct {
|
|||||||
|
|
||||||
func (web webAPIHandlers) GenerateAuth(r *http.Request, args *WebGenericArgs, reply *GenerateAuthReply) error {
|
func (web webAPIHandlers) GenerateAuth(r *http.Request, args *WebGenericArgs, reply *GenerateAuthReply) error {
|
||||||
if !isJWTReqAuthenticated(r) {
|
if !isJWTReqAuthenticated(r) {
|
||||||
return &json2.Error{Message: "Unauthorized request"}
|
return &json2.Error{Message: errAuthentication.Error()}
|
||||||
}
|
}
|
||||||
cred := mustGenAccessKeys()
|
cred := mustGenAccessKeys()
|
||||||
reply.AccessKey = cred.AccessKeyID
|
reply.AccessKey = cred.AccessKeyID
|
||||||
@ -345,13 +343,13 @@ type SetAuthReply struct {
|
|||||||
// SetAuth - Set accessKey and secretKey credentials.
|
// SetAuth - Set accessKey and secretKey credentials.
|
||||||
func (web *webAPIHandlers) SetAuth(r *http.Request, args *SetAuthArgs, reply *SetAuthReply) error {
|
func (web *webAPIHandlers) SetAuth(r *http.Request, args *SetAuthArgs, reply *SetAuthReply) error {
|
||||||
if !isJWTReqAuthenticated(r) {
|
if !isJWTReqAuthenticated(r) {
|
||||||
return &json2.Error{Message: "Unauthorized request"}
|
return &json2.Error{Message: errAuthentication.Error()}
|
||||||
}
|
}
|
||||||
if !isValidAccessKey.MatchString(args.AccessKey) {
|
if !isValidAccessKey(args.AccessKey) {
|
||||||
return &json2.Error{Message: "Invalid Access Key"}
|
return &json2.Error{Message: errInvalidAccessKeyLength.Error()}
|
||||||
}
|
}
|
||||||
if !isValidSecretKey.MatchString(args.SecretKey) {
|
if !isValidSecretKey(args.SecretKey) {
|
||||||
return &json2.Error{Message: "Invalid Secret Key"}
|
return &json2.Error{Message: errInvalidSecretKeyLength.Error()}
|
||||||
}
|
}
|
||||||
|
|
||||||
cred := credential{args.AccessKey, args.SecretKey}
|
cred := credential{args.AccessKey, args.SecretKey}
|
||||||
@ -430,7 +428,7 @@ type GetAuthReply struct {
|
|||||||
// GetAuth - return accessKey and secretKey credentials.
|
// GetAuth - return accessKey and secretKey credentials.
|
||||||
func (web *webAPIHandlers) GetAuth(r *http.Request, args *WebGenericArgs, reply *GetAuthReply) error {
|
func (web *webAPIHandlers) GetAuth(r *http.Request, args *WebGenericArgs, reply *GetAuthReply) error {
|
||||||
if !isJWTReqAuthenticated(r) {
|
if !isJWTReqAuthenticated(r) {
|
||||||
return &json2.Error{Message: "Unauthorized request"}
|
return &json2.Error{Message: errAuthentication.Error()}
|
||||||
}
|
}
|
||||||
creds := serverConfig.GetCredential()
|
creds := serverConfig.GetCredential()
|
||||||
reply.AccessKey = creds.AccessKeyID
|
reply.AccessKey = creds.AccessKeyID
|
||||||
@ -441,8 +439,14 @@ func (web *webAPIHandlers) GetAuth(r *http.Request, args *WebGenericArgs, reply
|
|||||||
|
|
||||||
// Upload - file upload handler.
|
// Upload - file upload handler.
|
||||||
func (web *webAPIHandlers) Upload(w http.ResponseWriter, r *http.Request) {
|
func (web *webAPIHandlers) Upload(w http.ResponseWriter, r *http.Request) {
|
||||||
|
objectAPI := web.ObjectAPI()
|
||||||
|
if objectAPI == nil {
|
||||||
|
writeWebErrorResponse(w, errServerNotInitialized)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if !isJWTReqAuthenticated(r) {
|
if !isJWTReqAuthenticated(r) {
|
||||||
writeWebErrorResponse(w, errInvalidToken)
|
writeWebErrorResponse(w, errAuthentication)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
@ -452,11 +456,6 @@ func (web *webAPIHandlers) Upload(w http.ResponseWriter, r *http.Request) {
|
|||||||
// Extract incoming metadata if any.
|
// Extract incoming metadata if any.
|
||||||
metadata := extractMetadataFromHeader(r.Header)
|
metadata := extractMetadataFromHeader(r.Header)
|
||||||
|
|
||||||
objectAPI := web.ObjectAPI()
|
|
||||||
if objectAPI == nil {
|
|
||||||
writeWebErrorResponse(w, errors.New("Server not initialized"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
sha256sum := ""
|
sha256sum := ""
|
||||||
if _, err := objectAPI.PutObject(bucket, object, -1, r.Body, metadata, sha256sum); err != nil {
|
if _, err := objectAPI.PutObject(bucket, object, -1, r.Body, metadata, sha256sum); err != nil {
|
||||||
writeWebErrorResponse(w, err)
|
writeWebErrorResponse(w, err)
|
||||||
@ -483,6 +482,12 @@ func (web *webAPIHandlers) Upload(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
// Download - file download handler.
|
// Download - file download handler.
|
||||||
func (web *webAPIHandlers) Download(w http.ResponseWriter, r *http.Request) {
|
func (web *webAPIHandlers) Download(w http.ResponseWriter, r *http.Request) {
|
||||||
|
objectAPI := web.ObjectAPI()
|
||||||
|
if objectAPI == nil {
|
||||||
|
writeWebErrorResponse(w, errServerNotInitialized)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
bucket := vars["bucket"]
|
bucket := vars["bucket"]
|
||||||
object := vars["object"]
|
object := vars["object"]
|
||||||
@ -501,17 +506,12 @@ func (web *webAPIHandlers) Download(w http.ResponseWriter, r *http.Request) {
|
|||||||
return []byte(jwt.SecretAccessKey), nil
|
return []byte(jwt.SecretAccessKey), nil
|
||||||
})
|
})
|
||||||
if e != nil || !token.Valid {
|
if e != nil || !token.Valid {
|
||||||
writeWebErrorResponse(w, errInvalidToken)
|
writeWebErrorResponse(w, errAuthentication)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Add content disposition.
|
// Add content disposition.
|
||||||
w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", path.Base(object)))
|
w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", path.Base(object)))
|
||||||
|
|
||||||
objectAPI := web.ObjectAPI()
|
|
||||||
if objectAPI == nil {
|
|
||||||
writeWebErrorResponse(w, errors.New("Server not initialized"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
objInfo, err := objectAPI.GetObjectInfo(bucket, object)
|
objInfo, err := objectAPI.GetObjectInfo(bucket, object)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
writeWebErrorResponse(w, err)
|
writeWebErrorResponse(w, err)
|
||||||
@ -527,12 +527,17 @@ func (web *webAPIHandlers) Download(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
// writeWebErrorResponse - set HTTP status code and write error description to the body.
|
// writeWebErrorResponse - set HTTP status code and write error description to the body.
|
||||||
func writeWebErrorResponse(w http.ResponseWriter, err error) {
|
func writeWebErrorResponse(w http.ResponseWriter, err error) {
|
||||||
// Handle invalid token as a special case.
|
if err == errAuthentication {
|
||||||
if err == errInvalidToken {
|
|
||||||
w.WriteHeader(http.StatusForbidden)
|
w.WriteHeader(http.StatusForbidden)
|
||||||
w.Write([]byte(err.Error()))
|
w.Write([]byte(err.Error()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if err == errServerNotInitialized {
|
||||||
|
w.WriteHeader(http.StatusServiceUnavailable)
|
||||||
|
w.Write([]byte(err.Error()))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Convert error type to api error code.
|
// Convert error type to api error code.
|
||||||
var apiErrCode APIErrorCode
|
var apiErrCode APIErrorCode
|
||||||
switch err.(type) {
|
switch err.(type) {
|
||||||
@ -602,14 +607,15 @@ func readBucketAccessPolicy(objAPI ObjectLayer, bucketName string) (policy.Bucke
|
|||||||
|
|
||||||
// GetBucketPolicy - get bucket policy.
|
// GetBucketPolicy - get bucket policy.
|
||||||
func (web *webAPIHandlers) GetBucketPolicy(r *http.Request, args *GetBucketPolicyArgs, reply *GetBucketPolicyRep) error {
|
func (web *webAPIHandlers) GetBucketPolicy(r *http.Request, args *GetBucketPolicyArgs, reply *GetBucketPolicyRep) error {
|
||||||
if !isJWTReqAuthenticated(r) {
|
|
||||||
return &json2.Error{Message: "Unauthorized request"}
|
|
||||||
}
|
|
||||||
|
|
||||||
objectAPI := web.ObjectAPI()
|
objectAPI := web.ObjectAPI()
|
||||||
if objectAPI == nil {
|
if objectAPI == nil {
|
||||||
return &json2.Error{Message: "Server not initialized"}
|
return &json2.Error{Message: errServerNotInitialized.Error()}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !isJWTReqAuthenticated(r) {
|
||||||
|
return &json2.Error{Message: errAuthentication.Error()}
|
||||||
|
}
|
||||||
|
|
||||||
policyInfo, err := readBucketAccessPolicy(objectAPI, args.BucketName)
|
policyInfo, err := readBucketAccessPolicy(objectAPI, args.BucketName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &json2.Error{Message: err.Error()}
|
return &json2.Error{Message: err.Error()}
|
||||||
@ -640,14 +646,15 @@ type ListAllBucketPoliciesRep struct {
|
|||||||
|
|
||||||
// GetllBucketPolicy - get all bucket policy.
|
// GetllBucketPolicy - get all bucket policy.
|
||||||
func (web *webAPIHandlers) ListAllBucketPolicies(r *http.Request, args *ListAllBucketPoliciesArgs, reply *ListAllBucketPoliciesRep) error {
|
func (web *webAPIHandlers) ListAllBucketPolicies(r *http.Request, args *ListAllBucketPoliciesArgs, reply *ListAllBucketPoliciesRep) error {
|
||||||
if !isJWTReqAuthenticated(r) {
|
|
||||||
return &json2.Error{Message: "Unauthorized request"}
|
|
||||||
}
|
|
||||||
|
|
||||||
objectAPI := web.ObjectAPI()
|
objectAPI := web.ObjectAPI()
|
||||||
if objectAPI == nil {
|
if objectAPI == nil {
|
||||||
return &json2.Error{Message: "Server not initialized"}
|
return &json2.Error{Message: errServerNotInitialized.Error()}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !isJWTReqAuthenticated(r) {
|
||||||
|
return &json2.Error{Message: errAuthentication.Error()}
|
||||||
|
}
|
||||||
|
|
||||||
policyInfo, err := readBucketAccessPolicy(objectAPI, args.BucketName)
|
policyInfo, err := readBucketAccessPolicy(objectAPI, args.BucketName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &json2.Error{Message: err.Error()}
|
return &json2.Error{Message: err.Error()}
|
||||||
@ -672,17 +679,18 @@ type SetBucketPolicyArgs struct {
|
|||||||
|
|
||||||
// SetBucketPolicy - set bucket policy.
|
// SetBucketPolicy - set bucket policy.
|
||||||
func (web *webAPIHandlers) SetBucketPolicy(r *http.Request, args *SetBucketPolicyArgs, reply *WebGenericRep) error {
|
func (web *webAPIHandlers) SetBucketPolicy(r *http.Request, args *SetBucketPolicyArgs, reply *WebGenericRep) error {
|
||||||
if !isJWTReqAuthenticated(r) {
|
|
||||||
return &json2.Error{Message: "Unauthorized request"}
|
|
||||||
}
|
|
||||||
objectAPI := web.ObjectAPI()
|
objectAPI := web.ObjectAPI()
|
||||||
if objectAPI == nil {
|
if objectAPI == nil {
|
||||||
return &json2.Error{Message: "Server not initialized"}
|
return &json2.Error{Message: errServerNotInitialized.Error()}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !isJWTReqAuthenticated(r) {
|
||||||
|
return &json2.Error{Message: errAuthentication.Error()}
|
||||||
}
|
}
|
||||||
|
|
||||||
bucketP := policy.BucketPolicy(args.Policy)
|
bucketP := policy.BucketPolicy(args.Policy)
|
||||||
if !bucketP.IsValidBucketPolicy() {
|
if !bucketP.IsValidBucketPolicy() {
|
||||||
return &json2.Error{Message: "Invalid policy " + args.Policy}
|
return &json2.Error{Message: "Invalid policy type " + args.Policy}
|
||||||
}
|
}
|
||||||
|
|
||||||
policyInfo, err := readBucketAccessPolicy(objectAPI, args.BucketName)
|
policyInfo, err := readBucketAccessPolicy(objectAPI, args.BucketName)
|
||||||
@ -745,11 +753,14 @@ type PresignedGetRep struct {
|
|||||||
|
|
||||||
// PresignedGET - returns presigned-Get url.
|
// PresignedGET - returns presigned-Get url.
|
||||||
func (web *webAPIHandlers) PresignedGet(r *http.Request, args *PresignedGetArgs, reply *PresignedGetRep) error {
|
func (web *webAPIHandlers) PresignedGet(r *http.Request, args *PresignedGetArgs, reply *PresignedGetRep) error {
|
||||||
|
if web.ObjectAPI() == nil {
|
||||||
|
return &json2.Error{Message: errServerNotInitialized.Error()}
|
||||||
|
}
|
||||||
if !isJWTReqAuthenticated(r) {
|
if !isJWTReqAuthenticated(r) {
|
||||||
return &json2.Error{Message: "Unauthorized request"}
|
return &json2.Error{Message: errAuthentication.Error()}
|
||||||
}
|
}
|
||||||
if args.BucketName == "" || args.ObjectName == "" {
|
if args.BucketName == "" || args.ObjectName == "" {
|
||||||
return &json2.Error{Message: "Required arguments: Host, Bucket, Object"}
|
return &json2.Error{Message: "Bucket, Object are mandatory arguments."}
|
||||||
}
|
}
|
||||||
reply.UIVersion = miniobrowser.UIVersion
|
reply.UIVersion = miniobrowser.UIVersion
|
||||||
reply.URL = presignedGet(args.HostName, args.BucketName, args.ObjectName)
|
reply.URL = presignedGet(args.HostName, args.BucketName, args.ObjectName)
|
||||||
|
@ -31,6 +31,69 @@ import (
|
|||||||
"github.com/minio/minio-go/pkg/set"
|
"github.com/minio/minio-go/pkg/set"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Tests private function writeWebErrorResponse.
|
||||||
|
func TestWriteWebErrorResponse(t *testing.T) {
|
||||||
|
var buffer bytes.Buffer
|
||||||
|
testCases := []struct {
|
||||||
|
webErr error
|
||||||
|
apiErrCode APIErrorCode
|
||||||
|
}{
|
||||||
|
// List of various errors and their corresponding API errors.
|
||||||
|
{
|
||||||
|
webErr: StorageFull{},
|
||||||
|
apiErrCode: ErrStorageFull,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
webErr: BucketNotFound{},
|
||||||
|
apiErrCode: ErrNoSuchBucket,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
webErr: BucketNameInvalid{},
|
||||||
|
apiErrCode: ErrInvalidBucketName,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
webErr: BadDigest{},
|
||||||
|
apiErrCode: ErrBadDigest,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
webErr: IncompleteBody{},
|
||||||
|
apiErrCode: ErrIncompleteBody,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
webErr: ObjectExistsAsDirectory{},
|
||||||
|
apiErrCode: ErrObjectExistsAsDirectory,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
webErr: ObjectNotFound{},
|
||||||
|
apiErrCode: ErrNoSuchKey,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
webErr: ObjectNameInvalid{},
|
||||||
|
apiErrCode: ErrNoSuchKey,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
webErr: InsufficientWriteQuorum{},
|
||||||
|
apiErrCode: ErrWriteQuorum,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
webErr: InsufficientReadQuorum{},
|
||||||
|
apiErrCode: ErrReadQuorum,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate all the test cases.
|
||||||
|
for i, testCase := range testCases {
|
||||||
|
writeWebErrorResponse(newFlushWriter(&buffer), testCase.webErr)
|
||||||
|
desc := getAPIError(testCase.apiErrCode).Description
|
||||||
|
recvDesc := buffer.Bytes()
|
||||||
|
// Check if the written desc is same as the one expected.
|
||||||
|
if !bytes.Equal(recvDesc, []byte(desc)) {
|
||||||
|
t.Errorf("Test %d: Unexpected response, expecting %s, got %s", i+1, desc, string(buffer.Bytes()))
|
||||||
|
}
|
||||||
|
buffer.Reset()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Authenticate and get JWT token - will be called before every webrpc handler invocation
|
// Authenticate and get JWT token - will be called before every webrpc handler invocation
|
||||||
func getWebRPCToken(apiRouter http.Handler, accessKey, secretKey string) (token string, err error) {
|
func getWebRPCToken(apiRouter http.Handler, accessKey, secretKey string) (token string, err error) {
|
||||||
rec := httptest.NewRecorder()
|
rec := httptest.NewRecorder()
|
||||||
@ -823,8 +886,8 @@ func testWebPresignedGetHandler(obj ObjectLayer, instanceType string, t TestErrH
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatalf("Failed, %v", err)
|
t.Fatalf("Failed, %v", err)
|
||||||
}
|
}
|
||||||
if err.Error() != "Required arguments: Host, Bucket, Object" {
|
if err.Error() != "Bucket, Object are mandatory arguments." {
|
||||||
t.Fatalf("Unexpected, expected `Required arguments: Host, Bucket, Object`, got %s", err)
|
t.Fatalf("Unexpected, expected `Bucket, Object are mandatory arguments`, got %s", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1118,8 +1181,13 @@ func TestWebCheckAuthorization(t *testing.T) {
|
|||||||
rec := httptest.NewRecorder()
|
rec := httptest.NewRecorder()
|
||||||
|
|
||||||
// Check if web rpc calls return unauthorized request with an incorrect token
|
// Check if web rpc calls return unauthorized request with an incorrect token
|
||||||
webRPCs := []string{"ServerInfo", "StorageInfo", "MakeBucket", "ListBuckets", "ListObjects", "RemoveObject", "GenerateAuth",
|
webRPCs := []string{
|
||||||
"SetAuth", "GetAuth", "GetBucketPolicy", "SetBucketPolicy"}
|
"ServerInfo", "StorageInfo", "MakeBucket",
|
||||||
|
"ListBuckets", "ListObjects", "RemoveObject",
|
||||||
|
"GenerateAuth", "SetAuth", "GetAuth",
|
||||||
|
"GetBucketPolicy", "SetBucketPolicy", "ListAllBucketPolicies",
|
||||||
|
"PresignedGet",
|
||||||
|
}
|
||||||
for _, rpcCall := range webRPCs {
|
for _, rpcCall := range webRPCs {
|
||||||
args := &GenericArgs{}
|
args := &GenericArgs{}
|
||||||
reply := &WebGenericRep{}
|
reply := &WebGenericRep{}
|
||||||
@ -1135,26 +1203,28 @@ func TestWebCheckAuthorization(t *testing.T) {
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatalf("Test %s: Should fail", rpcCall)
|
t.Fatalf("Test %s: Should fail", rpcCall)
|
||||||
} else {
|
} else {
|
||||||
if !strings.Contains(err.Error(), "Unauthorized request") {
|
if !strings.Contains(err.Error(), errAuthentication.Error()) {
|
||||||
t.Fatalf("Test %s: should fail with Unauthorized request. Found error: %v", rpcCall, err)
|
t.Fatalf("Test %s: should fail with Unauthorized request. Found error: %v", rpcCall, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rec = httptest.NewRecorder()
|
||||||
// Test authorization of Web.Download
|
// Test authorization of Web.Download
|
||||||
req, err := http.NewRequest("GET", "/minio/download/bucket/object?token=wrongauth", nil)
|
req, err := http.NewRequest("GET", "/minio/download/bucket/object?token=wrongauth", nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Cannot create upload request, %v", err)
|
t.Fatalf("Cannot create upload request, %v", err)
|
||||||
}
|
}
|
||||||
apiRouter.ServeHTTP(rec, req)
|
apiRouter.ServeHTTP(rec, req)
|
||||||
if rec.Code != http.StatusOK {
|
if rec.Code != http.StatusForbidden {
|
||||||
t.Fatalf("Expected the response status to be 200, but instead found `%d`", rec.Code)
|
t.Fatalf("Expected the response status to be 403, but instead found `%d`", rec.Code)
|
||||||
}
|
}
|
||||||
resp := string(rec.Body.Bytes())
|
resp := string(rec.Body.Bytes())
|
||||||
if !strings.Contains(resp, "Invalid token") {
|
if !strings.EqualFold(resp, errAuthentication.Error()) {
|
||||||
t.Fatalf("Unexpected error message, expected: `Invalid token`, found: `%s`", resp)
|
t.Fatalf("Unexpected error message, expected: %s, found: `%s`", errAuthentication, resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rec = httptest.NewRecorder()
|
||||||
// Test authorization of Web.Upload
|
// Test authorization of Web.Upload
|
||||||
content := []byte("temporary file's content")
|
content := []byte("temporary file's content")
|
||||||
req, err = http.NewRequest("PUT", "/minio/upload/bucket/object", nil)
|
req, err = http.NewRequest("PUT", "/minio/upload/bucket/object", nil)
|
||||||
@ -1167,12 +1237,12 @@ func TestWebCheckAuthorization(t *testing.T) {
|
|||||||
t.Fatalf("Cannot create upload request, %v", err)
|
t.Fatalf("Cannot create upload request, %v", err)
|
||||||
}
|
}
|
||||||
apiRouter.ServeHTTP(rec, req)
|
apiRouter.ServeHTTP(rec, req)
|
||||||
if rec.Code != http.StatusOK {
|
if rec.Code != http.StatusForbidden {
|
||||||
t.Fatalf("Expected the response status to be 200, but instead found `%d`", rec.Code)
|
t.Fatalf("Expected the response status to be 403, but instead found `%d`", rec.Code)
|
||||||
}
|
}
|
||||||
resp = string(rec.Body.Bytes())
|
resp = string(rec.Body.Bytes())
|
||||||
if !strings.Contains(resp, "Invalid token") {
|
if !strings.EqualFold(resp, errAuthentication.Error()) {
|
||||||
t.Fatalf("Unexpected error message, expected: `Invalid token`, found: `%s`", resp)
|
t.Fatalf("Unexpected error message, expected: `%s`, found: `%s`", errAuthentication, resp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1201,7 +1271,7 @@ func TestWebObjectLayerNotReady(t *testing.T) {
|
|||||||
// Check if web rpc calls return Server not initialized. ServerInfo, GenerateAuth,
|
// Check if web rpc calls return Server not initialized. ServerInfo, GenerateAuth,
|
||||||
// SetAuth and GetAuth are not concerned
|
// SetAuth and GetAuth are not concerned
|
||||||
webRPCs := []string{"StorageInfo", "MakeBucket", "ListBuckets", "ListObjects", "RemoveObject",
|
webRPCs := []string{"StorageInfo", "MakeBucket", "ListBuckets", "ListObjects", "RemoveObject",
|
||||||
"GetBucketPolicy", "SetBucketPolicy"}
|
"GetBucketPolicy", "SetBucketPolicy", "ListAllBucketPolicies"}
|
||||||
for _, rpcCall := range webRPCs {
|
for _, rpcCall := range webRPCs {
|
||||||
args := &GenericArgs{}
|
args := &GenericArgs{}
|
||||||
reply := &WebGenericRep{}
|
reply := &WebGenericRep{}
|
||||||
@ -1217,26 +1287,28 @@ func TestWebObjectLayerNotReady(t *testing.T) {
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatalf("Test %s: Should fail", rpcCall)
|
t.Fatalf("Test %s: Should fail", rpcCall)
|
||||||
} else {
|
} else {
|
||||||
if !strings.Contains(err.Error(), "Server not initialized") {
|
if !strings.EqualFold(err.Error(), errServerNotInitialized.Error()) {
|
||||||
t.Fatalf("Test %s: should fail with Unauthorized request. Found error: %v", rpcCall, err)
|
t.Fatalf("Test %s: should fail with %s Found error: %v", rpcCall, errServerNotInitialized, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rec = httptest.NewRecorder()
|
||||||
// Test authorization of Web.Download
|
// Test authorization of Web.Download
|
||||||
req, err := http.NewRequest("GET", "/minio/download/bucket/object?token="+authorization, nil)
|
req, err := http.NewRequest("GET", "/minio/download/bucket/object?token="+authorization, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Cannot create upload request, %v", err)
|
t.Fatalf("Cannot create upload request, %v", err)
|
||||||
}
|
}
|
||||||
apiRouter.ServeHTTP(rec, req)
|
apiRouter.ServeHTTP(rec, req)
|
||||||
if rec.Code != http.StatusOK {
|
if rec.Code != http.StatusServiceUnavailable {
|
||||||
t.Fatalf("Expected the response status to be 200, but instead found `%d`", rec.Code)
|
t.Fatalf("Expected the response status to be 503, but instead found `%d`", rec.Code)
|
||||||
}
|
}
|
||||||
resp := string(rec.Body.Bytes())
|
resp := string(rec.Body.Bytes())
|
||||||
if !strings.Contains(resp, "We encountered an internal error, please try again.") {
|
if !strings.EqualFold(resp, errServerNotInitialized.Error()) {
|
||||||
t.Fatalf("Unexpected error message, expected: `Invalid token`, found: `%s`", resp)
|
t.Fatalf("Unexpected error message, expected: `%s`, found: `%s`", errServerNotInitialized, resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rec = httptest.NewRecorder()
|
||||||
// Test authorization of Web.Upload
|
// Test authorization of Web.Upload
|
||||||
content := []byte("temporary file's content")
|
content := []byte("temporary file's content")
|
||||||
req, err = http.NewRequest("PUT", "/minio/upload/bucket/object", nil)
|
req, err = http.NewRequest("PUT", "/minio/upload/bucket/object", nil)
|
||||||
@ -1249,12 +1321,12 @@ func TestWebObjectLayerNotReady(t *testing.T) {
|
|||||||
t.Fatalf("Cannot create upload request, %v", err)
|
t.Fatalf("Cannot create upload request, %v", err)
|
||||||
}
|
}
|
||||||
apiRouter.ServeHTTP(rec, req)
|
apiRouter.ServeHTTP(rec, req)
|
||||||
if rec.Code != http.StatusOK {
|
if rec.Code != http.StatusServiceUnavailable {
|
||||||
t.Fatalf("Expected the response status to be 200, but instead found `%d`", rec.Code)
|
t.Fatalf("Expected the response status to be 503, but instead found `%d`", rec.Code)
|
||||||
}
|
}
|
||||||
resp = string(rec.Body.Bytes())
|
resp = string(rec.Body.Bytes())
|
||||||
if !strings.Contains(resp, "We encountered an internal error, please try again.") {
|
if !strings.EqualFold(resp, errServerNotInitialized.Error()) {
|
||||||
t.Fatalf("Unexpected error message, expected: `Invalid token`, found: `%s`", resp)
|
t.Fatalf("Unexpected error message, expected: `%s`, found: `%s`", errServerNotInitialized, resp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user