@ -23,8 +23,10 @@ import (
"net/http"
"net/http"
"net/http/httptest"
"net/http/httptest"
"strconv"
"strconv"
"strings"
"testing"
"testing"
router "github.com/gorilla/mux"
"github.com/minio/minio-go/pkg/policy"
"github.com/minio/minio-go/pkg/policy"
)
)
@ -742,7 +744,12 @@ func testWebGetBucketPolicyHandler(obj ObjectLayer, instanceType string, t TestE
rec := httptest . NewRecorder ( )
rec := httptest . NewRecorder ( )
bucketName := getRandomBucketName ( )
bucketName := getRandomBucketName ( )
if err = obj . MakeBucket ( bucketName ) ; err != nil {
if err := obj . MakeBucket ( bucketName ) ; err != nil {
t . Fatal ( "Unexpected error: " , err )
}
policyDoc := "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Action\":[\"s3:GetBucketLocation\",\"s3:ListBucket\"],\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Resource\":[\"arn:aws:s3:::" + bucketName + "\"],\"Sid\":\"\"},{\"Action\":[\"s3:GetObject\"],\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Resource\":[\"arn:aws:s3:::" + bucketName + "/*\"],\"Sid\":\"\"}]}"
if err := writeBucketPolicy ( bucketName , obj , bytes . NewReader ( [ ] byte ( policyDoc ) ) , int64 ( len ( policyDoc ) ) ) ; err != nil {
t . Fatal ( "Unexpected error: " , err )
t . Fatal ( "Unexpected error: " , err )
}
}
@ -751,7 +758,7 @@ func testWebGetBucketPolicyHandler(obj ObjectLayer, instanceType string, t TestE
prefix string
prefix string
expectedResult policy . BucketPolicy
expectedResult policy . BucketPolicy
} {
} {
{ bucketName , "" , policy . BucketPolicyNone } ,
{ bucketName , "" , policy . BucketPolicyReadOnly } ,
}
}
for i , testCase := range testCases {
for i , testCase := range testCases {
@ -846,3 +853,286 @@ func testWebSetBucketPolicyHandler(obj ObjectLayer, instanceType string, t TestE
}
}
}
}
}
}
// TestWebCheckAuthorization - Test Authorization for all web handlers
func TestWebCheckAuthorization ( t * testing . T ) {
// Prepare XL backend
obj , fsDirs , e := prepareXL ( )
if e != nil {
t . Fatalf ( "Initialization of object layer failed for XL setup: %s" , e )
}
// Executing the object layer tests for XL.
defer removeRoots ( fsDirs )
// Register the API end points with XL/FS object layer.
apiRouter := initTestWebRPCEndPoint ( obj )
// initialize the server and obtain the credentials and root.
// credentials are necessary to sign the HTTP request.
rootPath , e := newTestConfig ( "us-east-1" )
if e != nil {
t . Fatalf ( "Init Test config failed" )
}
// remove the root folder after the test ends.
defer removeAll ( rootPath )
rec := httptest . NewRecorder ( )
// Check if web rpc calls return unauthorized request with an incorrect token
webRPCs := [ ] string { "ServerInfo" , "StorageInfo" , "MakeBucket" , "ListBuckets" , "ListObjects" , "RemoveObject" , "GenerateAuth" ,
"SetAuth" , "GetAuth" , "GetBucketPolicy" , "SetBucketPolicy" }
for _ , rpcCall := range webRPCs {
args := & GenericArgs { }
reply := & WebGenericRep { }
req , err := newTestWebRPCRequest ( "Web." + rpcCall , "Bearer fooauthorization" , args )
if err != nil {
t . Fatalf ( "Test %s: Failed to create HTTP request: <ERROR> %v" , rpcCall , err )
}
apiRouter . ServeHTTP ( rec , req )
if rec . Code != http . StatusOK {
t . Fatalf ( "Test %s: Expected the response status to be 200, but instead found `%d`" , rpcCall , rec . Code )
}
err = getTestWebRPCResponse ( rec , & reply )
if err == nil {
t . Fatalf ( "Test %s: Should fail" , rpcCall )
} else {
if ! strings . Contains ( err . Error ( ) , "Unauthorized request" ) {
t . Fatalf ( "Test %s: should fail with Unauthorized request. Found error: %v" , rpcCall , err )
}
}
}
// Test authorization of Web.Download
req , err := http . NewRequest ( "GET" , "/minio/download/bucket/object?token=wrongauth" , nil )
if err != nil {
t . Fatalf ( "Cannot create upload request, %v" , err )
}
apiRouter . ServeHTTP ( rec , req )
if rec . Code != http . StatusOK {
t . Fatalf ( "Expected the response status to be 200, but instead found `%d`" , rec . Code )
}
resp := string ( rec . Body . Bytes ( ) )
if ! strings . Contains ( resp , "Invalid token" ) {
t . Fatalf ( "Unexpected error message, expected: `Invalid token`, found: `%s`" , resp )
}
// Test authorization of Web.Upload
content := [ ] byte ( "temporary file's content" )
req , err = http . NewRequest ( "PUT" , "/minio/upload/bucket/object" , nil )
req . Header . Set ( "Authorization" , "Bearer foo-authorization" )
req . Header . Set ( "Content-Length" , strconv . Itoa ( len ( content ) ) )
req . Header . Set ( "x-amz-date" , "20160814T114029Z" )
req . Header . Set ( "Accept" , "*/*" )
req . Body = ioutil . NopCloser ( bytes . NewReader ( content ) )
if err != nil {
t . Fatalf ( "Cannot create upload request, %v" , err )
}
apiRouter . ServeHTTP ( rec , req )
if rec . Code != http . StatusOK {
t . Fatalf ( "Expected the response status to be 200, but instead found `%d`" , rec . Code )
}
resp = string ( rec . Body . Bytes ( ) )
if ! strings . Contains ( resp , "Invalid token" ) {
t . Fatalf ( "Unexpected error message, expected: `Invalid token`, found: `%s`" , resp )
}
}
// TestWebObjectLayerNotReady - Test RPCs responses when disks are not ready
func TestWebObjectLayerNotReady ( t * testing . T ) {
webHandlers := & webAPIHandlers {
ObjectAPI : func ( ) ObjectLayer { return nil } ,
}
// Initialize router.
apiRouter := router . NewRouter ( )
registerWebRouter ( apiRouter , webHandlers )
// initialize the server and obtain the credentials and root.
// credentials are necessary to sign the HTTP request.
rootPath , e := newTestConfig ( "us-east-1" )
if e != nil {
t . Fatalf ( "Init Test config failed" )
}
// remove the root folder after the test ends.
defer removeAll ( rootPath )
rec := httptest . NewRecorder ( )
credentials := serverConfig . GetCredential ( )
authorization , e := getWebRPCToken ( apiRouter , credentials . AccessKeyID , credentials . SecretAccessKey )
if e != nil {
t . Fatal ( "Cannot authenticate" )
}
// Check if web rpc calls return Server not initialized. ServerInfo, GenerateAuth,
// SetAuth and GetAuth are not concerned
webRPCs := [ ] string { "StorageInfo" , "MakeBucket" , "ListBuckets" , "ListObjects" , "RemoveObject" ,
"GetBucketPolicy" , "SetBucketPolicy" }
for _ , rpcCall := range webRPCs {
args := & GenericArgs { }
reply := & WebGenericRep { }
req , err := newTestWebRPCRequest ( "Web." + rpcCall , authorization , args )
if err != nil {
t . Fatalf ( "Test %s: Failed to create HTTP request: <ERROR> %v" , rpcCall , err )
}
apiRouter . ServeHTTP ( rec , req )
if rec . Code != http . StatusOK {
t . Fatalf ( "Test %s: Expected the response status to be 200, but instead found `%d`" , rpcCall , rec . Code )
}
err = getTestWebRPCResponse ( rec , & reply )
if err == nil {
t . Fatalf ( "Test %s: Should fail" , rpcCall )
} else {
if ! strings . Contains ( err . Error ( ) , "Server not initialized" ) {
t . Fatalf ( "Test %s: should fail with Unauthorized request. Found error: %v" , rpcCall , err )
}
}
}
// Test authorization of Web.Download
req , err := http . NewRequest ( "GET" , "/minio/download/bucket/object?token=" + authorization , nil )
if err != nil {
t . Fatalf ( "Cannot create upload request, %v" , err )
}
apiRouter . ServeHTTP ( rec , req )
if rec . Code != http . StatusOK {
t . Fatalf ( "Expected the response status to be 200, but instead found `%d`" , rec . Code )
}
resp := string ( rec . Body . Bytes ( ) )
if ! strings . Contains ( resp , "We encountered an internal error, please try again." ) {
t . Fatalf ( "Unexpected error message, expected: `Invalid token`, found: `%s`" , resp )
}
// Test authorization of Web.Upload
content := [ ] byte ( "temporary file's content" )
req , err = http . NewRequest ( "PUT" , "/minio/upload/bucket/object" , nil )
req . Header . Set ( "Authorization" , "Bearer " + authorization )
req . Header . Set ( "Content-Length" , strconv . Itoa ( len ( content ) ) )
req . Header . Set ( "x-amz-date" , "20160814T114029Z" )
req . Header . Set ( "Accept" , "*/*" )
req . Body = ioutil . NopCloser ( bytes . NewReader ( content ) )
if err != nil {
t . Fatalf ( "Cannot create upload request, %v" , err )
}
apiRouter . ServeHTTP ( rec , req )
if rec . Code != http . StatusOK {
t . Fatalf ( "Expected the response status to be 200, but instead found `%d`" , rec . Code )
}
resp = string ( rec . Body . Bytes ( ) )
if ! strings . Contains ( resp , "We encountered an internal error, please try again." ) {
t . Fatalf ( "Unexpected error message, expected: `Invalid token`, found: `%s`" , resp )
}
}
// TestWebObjectLayerFaultyDisks - Test Web RPC responses with faulty disks
func TestWebObjectLayerFaultyDisks ( t * testing . T ) {
// Prepare XL backend
obj , fsDirs , e := prepareXL ( )
if e != nil {
t . Fatalf ( "Initialization of object layer failed for XL setup: %s" , e )
}
// Executing the object layer tests for XL.
defer removeRoots ( fsDirs )
// Set faulty disks to XL backend
xl := obj . ( xlObjects )
for i , d := range xl . storageDisks {
xl . storageDisks [ i ] = newNaughtyDisk ( d . ( * posix ) , nil , errFaultyDisk )
}
webHandlers := & webAPIHandlers {
ObjectAPI : func ( ) ObjectLayer { return obj } ,
}
// Initialize router.
apiRouter := router . NewRouter ( )
registerWebRouter ( apiRouter , webHandlers )
// initialize the server and obtain the credentials and root.
// credentials are necessary to sign the HTTP request.
rootPath , e := newTestConfig ( "us-east-1" )
if e != nil {
t . Fatalf ( "Init Test config failed" )
}
// remove the root folder after the test ends.
defer removeAll ( rootPath )
rec := httptest . NewRecorder ( )
credentials := serverConfig . GetCredential ( )
authorization , e := getWebRPCToken ( apiRouter , credentials . AccessKeyID , credentials . SecretAccessKey )
if e != nil {
t . Fatal ( "Cannot authenticate" )
}
// Check if web rpc calls return errors with faulty disks. ServerInfo, GenerateAuth, SetAuth, GetAuth are not concerned
webRPCs := [ ] string { "MakeBucket" , "ListBuckets" , "ListObjects" , "RemoveObject" ,
"GetBucketPolicy" , "SetBucketPolicy" }
for _ , rpcCall := range webRPCs {
args := & GenericArgs { }
reply := & WebGenericRep { }
req , err := newTestWebRPCRequest ( "Web." + rpcCall , authorization , args )
if err != nil {
t . Fatalf ( "Test %s: Failed to create HTTP request: <ERROR> %v" , rpcCall , err )
}
apiRouter . ServeHTTP ( rec , req )
if rec . Code != http . StatusOK {
t . Fatalf ( "Test %s: Expected the response status to be 200, but instead found `%d`" , rpcCall , rec . Code )
}
err = getTestWebRPCResponse ( rec , & reply )
if err == nil {
t . Errorf ( "Test %s: Should fail" , rpcCall )
}
}
// Test Web.StorageInfo
storageInfoRequest := GenericArgs { }
storageInfoReply := & StorageInfoRep { }
req , err := newTestWebRPCRequest ( "Web.StorageInfo" , authorization , storageInfoRequest )
if err != nil {
t . Fatalf ( "Failed to create HTTP request: <ERROR> %v" , err )
}
apiRouter . ServeHTTP ( rec , req )
if rec . Code != http . StatusOK {
t . Fatalf ( "Expected the response status to be 200, but instead found `%d`" , rec . Code )
}
err = getTestWebRPCResponse ( rec , & storageInfoReply )
if err != nil {
t . Fatalf ( "Failed %v" , err )
}
if storageInfoReply . StorageInfo . Total != - 1 || storageInfoReply . StorageInfo . Free != - 1 {
t . Fatalf ( "Should get negative values of Total and Free since disks are faulty " )
}
// Test authorization of Web.Download
req , err = http . NewRequest ( "GET" , "/minio/download/bucket/object?token=" + authorization , nil )
if err != nil {
t . Fatalf ( "Cannot create upload request, %v" , err )
}
apiRouter . ServeHTTP ( rec , req )
if rec . Code != http . StatusOK {
t . Fatalf ( "Expected the response status to be 200, but instead found `%d`" , rec . Code )
}
resp := string ( rec . Body . Bytes ( ) )
if ! strings . Contains ( resp , "We encountered an internal error, please try again." ) {
t . Fatalf ( "Unexpected error message, expected: `Invalid token`, found: `%s`" , resp )
}
// Test authorization of Web.Upload
content := [ ] byte ( "temporary file's content" )
req , err = http . NewRequest ( "PUT" , "/minio/upload/bucket/object" , nil )
req . Header . Set ( "Authorization" , "Bearer " + authorization )
req . Header . Set ( "Content-Length" , strconv . Itoa ( len ( content ) ) )
req . Header . Set ( "x-amz-date" , "20160814T114029Z" )
req . Header . Set ( "Accept" , "*/*" )
req . Body = ioutil . NopCloser ( bytes . NewReader ( content ) )
if err != nil {
t . Fatalf ( "Cannot create upload request, %v" , err )
}
apiRouter . ServeHTTP ( rec , req )
if rec . Code != http . StatusOK {
t . Fatalf ( "Expected the response status to be 200, but instead found `%d`" , rec . Code )
}
resp = string ( rec . Body . Bytes ( ) )
if ! strings . Contains ( resp , "We encountered an internal error, please try again." ) {
t . Fatalf ( "Unexpected error message, expected: `Invalid token`, found: `%s`" , resp )
}
}