From 18c4e5d3576524584b15b45162f3da0dd2e91bea Mon Sep 17 00:00:00 2001 From: poornas Date: Thu, 1 Jun 2017 09:43:20 -0700 Subject: [PATCH] Enable browser support for gateway (#4425) --- cmd/admin-handlers_test.go | 10 +++--- cmd/benchmark-utils_test.go | 10 +++--- cmd/bucket-handlers.go | 6 +++- cmd/bucket-handlers_test.go | 33 +++++++++++++++++++ cmd/bucket-policy-handlers_test.go | 2 +- cmd/credential.go | 4 +-- cmd/credential_test.go | 2 +- cmd/event-notifier_test.go | 8 ++--- cmd/format-config-v1_test.go | 6 ++-- cmd/fs-v1-metadata_test.go | 4 +-- cmd/fs-v1-multipart_test.go | 10 +++--- cmd/fs-v1.go | 2 +- cmd/fs-v1_test.go | 14 ++++----- cmd/gateway-azure.go | 6 ---- cmd/gateway-main.go | 46 ++++++++++++++++++++++----- cmd/gateway-main_test.go | 27 +++++++++++++++- cmd/gateway-router.go | 2 -- cmd/gateway-s3.go | 10 +----- cmd/jwt_test.go | 2 +- cmd/object-api-getobject_test.go | 6 ++-- cmd/object-api-getobjectinfo_test.go | 2 +- cmd/object-api-interface.go | 2 +- cmd/object-api-listobjects_test.go | 4 +-- cmd/object-api-multipart_test.go | 24 +++++++------- cmd/object-api-putobject_test.go | 12 +++---- cmd/object_api_suite_test.go | 36 ++++++++++----------- cmd/post-policy_test.go | 4 +-- cmd/test-utils_test.go | 2 +- cmd/web-handlers.go | 47 +++++++++++++++++++++++----- cmd/web-handlers_test.go | 22 ++++++------- cmd/xl-v1-bucket.go | 2 +- cmd/xl-v1-healing-common_test.go | 2 +- cmd/xl-v1-healing_test.go | 12 +++---- cmd/xl-v1-list-objects-heal_test.go | 4 +-- cmd/xl-v1-metadata_test.go | 4 +-- cmd/xl-v1-multipart_test.go | 2 +- cmd/xl-v1-object_test.go | 12 +++---- docs/gateway/README.md | 3 ++ 38 files changed, 260 insertions(+), 146 deletions(-) diff --git a/cmd/admin-handlers_test.go b/cmd/admin-handlers_test.go index 68ccdd80e..deba24f5b 100644 --- a/cmd/admin-handlers_test.go +++ b/cmd/admin-handlers_test.go @@ -731,7 +731,7 @@ func TestListObjectsHealHandler(t *testing.T) { } defer adminTestBed.TearDown() - err = adminTestBed.objLayer.MakeBucket("mybucket") + err = adminTestBed.objLayer.MakeBucketWithLocation("mybucket","") if err != nil { t.Fatalf("Failed to make bucket - %v", err) } @@ -859,7 +859,7 @@ func TestHealBucketHandler(t *testing.T) { } defer adminTestBed.TearDown() - err = adminTestBed.objLayer.MakeBucket("mybucket") + err = adminTestBed.objLayer.MakeBucketWithLocation("mybucket","") if err != nil { t.Fatalf("Failed to make bucket - %v", err) } @@ -936,7 +936,7 @@ func TestHealObjectHandler(t *testing.T) { // Create an object myobject under bucket mybucket. bucketName := "mybucket" objName := "myobject" - err = adminTestBed.objLayer.MakeBucket(bucketName) + err = adminTestBed.objLayer.MakeBucketWithLocation(bucketName,"") if err != nil { t.Fatalf("Failed to make bucket %s - %v", bucketName, err) } @@ -1067,7 +1067,7 @@ func TestHealUploadHandler(t *testing.T) { // Create an object myobject under bucket mybucket. bucketName := "mybucket" objName := "myobject" - err = adminTestBed.objLayer.MakeBucket(bucketName) + err = adminTestBed.objLayer.MakeBucketWithLocation(bucketName,"") if err != nil { t.Fatalf("Failed to make bucket %s - %v", bucketName, err) } @@ -1455,7 +1455,7 @@ func TestListHealUploadsHandler(t *testing.T) { } defer adminTestBed.TearDown() - err = adminTestBed.objLayer.MakeBucket("mybucket") + err = adminTestBed.objLayer.MakeBucketWithLocation("mybucket","") if err != nil { t.Fatalf("Failed to make bucket - %v", err) } diff --git a/cmd/benchmark-utils_test.go b/cmd/benchmark-utils_test.go index f871c844a..13aa24942 100644 --- a/cmd/benchmark-utils_test.go +++ b/cmd/benchmark-utils_test.go @@ -39,7 +39,7 @@ func runPutObjectBenchmark(b *testing.B, obj ObjectLayer, objSize int) { // obtains random bucket name. bucket := getRandomBucketName() // create bucket. - err = obj.MakeBucket(bucket) + err = obj.MakeBucketWithLocation(bucket, "") if err != nil { b.Fatal(err) } @@ -78,7 +78,7 @@ func runPutObjectPartBenchmark(b *testing.B, obj ObjectLayer, partSize int) { object := getRandomObjectName() // create bucket. - err = obj.MakeBucket(bucket) + err = obj.MakeBucketWithLocation(bucket, "") if err != nil { b.Fatal(err) } @@ -199,7 +199,7 @@ func runGetObjectBenchmark(b *testing.B, obj ObjectLayer, objSize int) { // obtains random bucket name. bucket := getRandomBucketName() // create bucket. - err = obj.MakeBucket(bucket) + err = obj.MakeBucketWithLocation(bucket, "") if err != nil { b.Fatal(err) } @@ -307,7 +307,7 @@ func runPutObjectBenchmarkParallel(b *testing.B, obj ObjectLayer, objSize int) { // obtains random bucket name. bucket := getRandomBucketName() // create bucket. - err = obj.MakeBucket(bucket) + err = obj.MakeBucketWithLocation(bucket, "") if err != nil { b.Fatal(err) } @@ -355,7 +355,7 @@ func runGetObjectBenchmarkParallel(b *testing.B, obj ObjectLayer, objSize int) { // obtains random bucket name. bucket := getRandomBucketName() // create bucket. - err = obj.MakeBucket(bucket) + err = obj.MakeBucketWithLocation(bucket, "") if err != nil { b.Fatal(err) } diff --git a/cmd/bucket-handlers.go b/cmd/bucket-handlers.go index c997c1dba..2d35d4269 100644 --- a/cmd/bucket-handlers.go +++ b/cmd/bucket-handlers.go @@ -83,6 +83,10 @@ func enforceBucketPolicy(bucket, action, resource, referer string, queryParams u // Check if the action is allowed on the bucket/prefix. func isBucketActionAllowed(action, bucket, prefix string) bool { + if globalBucketPolicies == nil { + return false + } + policy := globalBucketPolicies.GetBucketPolicy(bucket) if policy == nil { return false @@ -389,7 +393,7 @@ func (api objectAPIHandlers) PutBucketHandler(w http.ResponseWriter, r *http.Req defer bucketLock.Unlock() // Proceed to creating a bucket. - err := objectAPI.MakeBucket(bucket) + err := objectAPI.MakeBucketWithLocation(bucket, "") if err != nil { errorIf(err, "Unable to create a bucket.") writeErrorResponse(w, toAPIErrorCode(err), r.URL) diff --git a/cmd/bucket-handlers_test.go b/cmd/bucket-handlers_test.go index 75a7fe44a..bd57e7eb9 100644 --- a/cmd/bucket-handlers_test.go +++ b/cmd/bucket-handlers_test.go @@ -771,3 +771,36 @@ func testAPIDeleteMultipleObjectsHandler(obj ObjectLayer, instanceType, bucketNa // `ExecObjectLayerAPINilTest` manages the operation. ExecObjectLayerAPINilTest(t, nilBucket, nilObject, instanceType, apiRouter, nilReq) } + +func TestIsBucketActionAllowed(t *testing.T) { + ExecObjectLayerAPITest(t, testIsBucketActionAllowedHandler, []string{"BucketLocation"}) +} + +func testIsBucketActionAllowedHandler(obj ObjectLayer, instanceType, bucketName string, apiRouter http.Handler, + credentials credential, t *testing.T) { + + testCases := []struct { + // input. + action string + bucket string + prefix string + isGlobalPoliciesNil bool + // flag indicating whether the test should pass. + shouldPass bool + }{ + {"s3:GetBucketLocation", "mybucket", "abc", true, false}, + {"s3:ListObject", "mybucket", "abc", false, false}, + } + for i, testCase := range testCases { + if testCase.isGlobalPoliciesNil { + globalBucketPolicies = nil + } else { + initBucketPolicies(obj) + } + isAllowed := isBucketActionAllowed(testCase.action, testCase.bucket, testCase.prefix) + if isAllowed != testCase.shouldPass { + t.Errorf("Case %d: Expected the response status to be `%t`, but instead found `%t`", i+1, testCase.shouldPass, isAllowed) + } + + } +} diff --git a/cmd/bucket-policy-handlers_test.go b/cmd/bucket-policy-handlers_test.go index a8ad8a3e1..5a625c2f4 100644 --- a/cmd/bucket-policy-handlers_test.go +++ b/cmd/bucket-policy-handlers_test.go @@ -251,7 +251,7 @@ func testPutBucketPolicyHandler(obj ObjectLayer, instanceType, bucketName string initBucketPolicies(obj) bucketName1 := fmt.Sprintf("%s-1", bucketName) - if err := obj.MakeBucket(bucketName1); err != nil { + if err := obj.MakeBucketWithLocation(bucketName1, ""); err != nil { t.Fatal(err) } diff --git a/cmd/credential.go b/cmd/credential.go index a30893b32..769707d84 100644 --- a/cmd/credential.go +++ b/cmd/credential.go @@ -28,14 +28,14 @@ const ( accessKeyMinLen = 5 accessKeyMaxLen = 20 secretKeyMinLen = 8 - secretKeyMaxLenAmazon = 40 + secretKeyMaxLenAmazon = 100 alphaNumericTable = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" alphaNumericTableLen = byte(len(alphaNumericTable)) ) var ( errInvalidAccessKeyLength = errors.New("Invalid access key, access key should be 5 to 20 characters in length") - errInvalidSecretKeyLength = errors.New("Invalid secret key, secret key should be 8 to 40 characters in length") + errInvalidSecretKeyLength = errors.New("Invalid secret key, secret key should be 8 to 100 characters in length") ) var secretKeyMaxLen = secretKeyMaxLenAmazon diff --git a/cmd/credential_test.go b/cmd/credential_test.go index 4d30519d3..b35d703de 100644 --- a/cmd/credential_test.go +++ b/cmd/credential_test.go @@ -42,7 +42,7 @@ func TestCreateCredential(t *testing.T) { // Secret key too small. {"myuser", "pass", false, errInvalidSecretKeyLength}, // Secret key too long. - {"myuser", "pass1234567890123456789012345678901234567", false, errInvalidSecretKeyLength}, + {"myuser", "pass1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890", false, errInvalidSecretKeyLength}, // Success when access key contains leading/trailing spaces. {" user ", cred.SecretKey, true, nil}, {"myuser", "mypassword", true, nil}, diff --git a/cmd/event-notifier_test.go b/cmd/event-notifier_test.go index f8e74b188..4b2087417 100644 --- a/cmd/event-notifier_test.go +++ b/cmd/event-notifier_test.go @@ -45,7 +45,7 @@ func TestInitEventNotifierFaultyDisks(t *testing.T) { } bucketName := "bucket" - if err := obj.MakeBucket(bucketName); err != nil { + if err := obj.MakeBucketWithLocation(bucketName, ""); err != nil { t.Fatal("Unexpected error:", err) } @@ -343,7 +343,7 @@ func TestInitEventNotifier(t *testing.T) { } // create bucket - if err := obj.MakeBucket(bucketName); err != nil { + if err := obj.MakeBucketWithLocation(bucketName, ""); err != nil { t.Fatal("Unexpected error:", err) } @@ -408,7 +408,7 @@ func TestListenBucketNotification(t *testing.T) { objectName := "object" // Create the bucket to listen on - if err := obj.MakeBucket(bucketName); err != nil { + if err := obj.MakeBucketWithLocation(bucketName, ""); err != nil { t.Fatal("Unexpected error:", err) } @@ -518,7 +518,7 @@ func TestAddRemoveBucketListenerConfig(t *testing.T) { // Make a bucket to store topicConfigs. randBucket := getRandomBucketName() - if err := obj.MakeBucket(randBucket); err != nil { + if err := obj.MakeBucketWithLocation(randBucket, ""); err != nil { t.Fatalf("Failed to make bucket %s", randBucket) } diff --git a/cmd/format-config-v1_test.go b/cmd/format-config-v1_test.go index c6761ec74..6e00adda6 100644 --- a/cmd/format-config-v1_test.go +++ b/cmd/format-config-v1_test.go @@ -223,7 +223,7 @@ func prepareFormatXLHealFreshDisks(obj ObjectLayer) ([]StorageAPI, error) { var err error xl := obj.(*xlObjects) - err = obj.MakeBucket("bucket") + err = obj.MakeBucketWithLocation("bucket", "") if err != nil { return []StorageAPI{}, err } @@ -346,7 +346,7 @@ func TestFormatXLHealCorruptedDisks(t *testing.T) { xl := obj.(*xlObjects) - err = obj.MakeBucket("bucket") + err = obj.MakeBucketWithLocation("bucket", "") if err != nil { t.Fatal(err) } @@ -419,7 +419,7 @@ func TestFormatXLReorderByInspection(t *testing.T) { xl := obj.(*xlObjects) - err = obj.MakeBucket("bucket") + err = obj.MakeBucketWithLocation("bucket", "") if err != nil { t.Fatal(err) } diff --git a/cmd/fs-v1-metadata_test.go b/cmd/fs-v1-metadata_test.go index 9d960f067..1e71acb63 100644 --- a/cmd/fs-v1-metadata_test.go +++ b/cmd/fs-v1-metadata_test.go @@ -48,7 +48,7 @@ func TestReadFSMetadata(t *testing.T) { bucketName := "bucket" objectName := "object" - if err := obj.MakeBucket(bucketName); err != nil { + if err := obj.MakeBucketWithLocation(bucketName, ""); err != nil { t.Fatal("Unexpected err: ", err) } sha256sum := "" @@ -85,7 +85,7 @@ func TestWriteFSMetadata(t *testing.T) { bucketName := "bucket" objectName := "object" - if err := obj.MakeBucket(bucketName); err != nil { + if err := obj.MakeBucketWithLocation(bucketName, ""); err != nil { t.Fatal("Unexpected err: ", err) } sha256sum := "" diff --git a/cmd/fs-v1-multipart_test.go b/cmd/fs-v1-multipart_test.go index 75ef537a5..c69807440 100644 --- a/cmd/fs-v1-multipart_test.go +++ b/cmd/fs-v1-multipart_test.go @@ -33,7 +33,7 @@ func TestFSWriteUploadJSON(t *testing.T) { bucketName := "bucket" objectName := "object" - obj.MakeBucket(bucketName) + obj.MakeBucketWithLocation(bucketName, "") _, err := obj.NewMultipartUpload(bucketName, objectName, nil) if err != nil { t.Fatal("Unexpected err: ", err) @@ -60,7 +60,7 @@ func TestNewMultipartUploadFaultyDisk(t *testing.T) { bucketName := "bucket" objectName := "object" - if err := obj.MakeBucket(bucketName); err != nil { + if err := obj.MakeBucketWithLocation(bucketName, ""); err != nil { t.Fatal("Cannot create bucket, err: ", err) } @@ -91,7 +91,7 @@ func TestPutObjectPartFaultyDisk(t *testing.T) { data := []byte("12345") dataLen := int64(len(data)) - if err = obj.MakeBucket(bucketName); err != nil { + if err = obj.MakeBucketWithLocation(bucketName, ""); err != nil { t.Fatal("Cannot create bucket, err: ", err) } @@ -122,7 +122,7 @@ func TestCompleteMultipartUploadFaultyDisk(t *testing.T) { objectName := "object" data := []byte("12345") - if err := obj.MakeBucket(bucketName); err != nil { + if err := obj.MakeBucketWithLocation(bucketName, ""); err != nil { t.Fatal("Cannot create bucket, err: ", err) } @@ -161,7 +161,7 @@ func TestListMultipartUploadsFaultyDisk(t *testing.T) { objectName := "object" data := []byte("12345") - if err := obj.MakeBucket(bucketName); err != nil { + if err := obj.MakeBucketWithLocation(bucketName, ""); err != nil { t.Fatal("Cannot create bucket, err: ", err) } diff --git a/cmd/fs-v1.go b/cmd/fs-v1.go index b33a700fb..590b7d1ad 100644 --- a/cmd/fs-v1.go +++ b/cmd/fs-v1.go @@ -302,7 +302,7 @@ func (fs fsObjects) statBucketDir(bucket string) (os.FileInfo, error) { // MakeBucket - create a new bucket, returns if it // already exists. -func (fs fsObjects) MakeBucket(bucket string) error { +func (fs fsObjects) MakeBucketWithLocation(bucket, location string) error { bucketDir, err := fs.getBucketDir(bucket) if err != nil { return toObjectErr(err, bucket) diff --git a/cmd/fs-v1_test.go b/cmd/fs-v1_test.go index 71962e99c..a79f0327b 100644 --- a/cmd/fs-v1_test.go +++ b/cmd/fs-v1_test.go @@ -66,7 +66,7 @@ func TestFSShutdown(t *testing.T) { obj := initFSObjects(disk, t) fs := obj.(*fsObjects) objectContent := "12345" - obj.MakeBucket(bucketName) + obj.MakeBucketWithLocation(bucketName, "") sha256sum := "" obj.PutObject(bucketName, objectName, int64(len(objectContent)), bytes.NewReader([]byte(objectContent)), nil, sha256sum) return fs, disk @@ -498,7 +498,7 @@ func TestFSGetBucketInfo(t *testing.T) { fs := obj.(*fsObjects) bucketName := "bucket" - obj.MakeBucket(bucketName) + obj.MakeBucketWithLocation(bucketName, "") // Test with valid parameters info, err := fs.GetBucketInfo(bucketName) @@ -533,7 +533,7 @@ func TestFSPutObject(t *testing.T) { bucketName := "bucket" objectName := "1/2/3/4/object" - if err := obj.MakeBucket(bucketName); err != nil { + if err := obj.MakeBucketWithLocation(bucketName, ""); err != nil { t.Fatal(err) } @@ -603,7 +603,7 @@ func TestFSDeleteObject(t *testing.T) { bucketName := "bucket" objectName := "object" - obj.MakeBucket(bucketName) + obj.MakeBucketWithLocation(bucketName, "") sha256sum := "" obj.PutObject(bucketName, objectName, int64(len("abcd")), bytes.NewReader([]byte("abcd")), nil, sha256sum) @@ -648,7 +648,7 @@ func TestFSDeleteBucket(t *testing.T) { fs := obj.(*fsObjects) bucketName := "bucket" - err := obj.MakeBucket(bucketName) + err := obj.MakeBucketWithLocation(bucketName, "") if err != nil { t.Fatal("Unexpected error: ", err) } @@ -666,7 +666,7 @@ func TestFSDeleteBucket(t *testing.T) { t.Fatal("Unexpected error: ", err) } - obj.MakeBucket(bucketName) + obj.MakeBucketWithLocation(bucketName, "") // Delete bucker should get error disk not found. removeAll(disk) @@ -687,7 +687,7 @@ func TestFSListBuckets(t *testing.T) { fs := obj.(*fsObjects) bucketName := "bucket" - if err := obj.MakeBucket(bucketName); err != nil { + if err := obj.MakeBucketWithLocation(bucketName, ""); err != nil { t.Fatal("Unexpected error: ", err) } diff --git a/cmd/gateway-azure.go b/cmd/gateway-azure.go index 39e7f4065..16f762f52 100644 --- a/cmd/gateway-azure.go +++ b/cmd/gateway-azure.go @@ -183,12 +183,6 @@ func (a *azureObjects) StorageInfo() StorageInfo { return StorageInfo{} } -// MakeBucket - Create a new container on azure backend. -func (a *azureObjects) MakeBucket(bucket string) error { - // will never be called, only satisfy ObjectLayer interface - return traceError(NotImplemented{}) -} - // MakeBucketWithLocation - Create a new container on azure backend. func (a *azureObjects) MakeBucketWithLocation(bucket, location string) error { err := a.client.CreateContainer(bucket, storage.ContainerAccessTypePrivate) diff --git a/cmd/gateway-main.go b/cmd/gateway-main.go index 9ca9d94e1..cd48525b6 100644 --- a/cmd/gateway-main.go +++ b/cmd/gateway-main.go @@ -19,12 +19,11 @@ package cmd import ( "errors" "fmt" + "github.com/gorilla/mux" + "github.com/minio/cli" "net/url" "os" "strings" - - "github.com/gorilla/mux" - "github.com/minio/cli" ) var gatewayTemplate = `NAME: @@ -45,6 +44,9 @@ ENVIRONMENT VARIABLES: MINIO_ACCESS_KEY: Username or access key of your storage backend. MINIO_SECRET_KEY: Password or secret key of your storage backend. + BROWSER: + MINIO_BROWSER: To disable web browser access, set this value to "off". + EXAMPLES: 1. Start minio gateway server for Azure Blob Storage backend. $ export MINIO_ACCESS_KEY=azureaccountname @@ -96,12 +98,27 @@ func mustGetGatewayCredsFromEnv() (accessKey, secretKey string) { return accessKey, secretKey } +// Set browser setting from environment variables +func mustSetBrowserSettingFromEnv(){ + if browser := os.Getenv("MINIO_BROWSER"); browser != "" { + browserFlag, err := ParseBrowserFlag(browser) + if err != nil { + fatalIf(errors.New("invalid value"), "Unknown value ā€˜%sā€™ in MINIO_BROWSER environment variable.", browser) + } + + // browser Envs are set globally, this does not represent + // if browser is turned off or on. + globalIsEnvBrowser = true + globalIsBrowserEnabled = bool(browserFlag) + } +} // Initialize gateway layer depending on the backend type. // Supported backend types are // // - Azure Blob Storage. // - Add your favorite backend here. func newGatewayLayer(backendType, endpoint, accessKey, secretKey string, secure bool) (GatewayLayer, error) { + switch gatewayBackend(backendType) { case azureBackend: return newAzureLayer(endpoint, accessKey, secretKey, secure) @@ -171,11 +188,11 @@ func gatewayMain(ctx *cli.Context) { // Fetch access and secret key from env. accessKey, secretKey := mustGetGatewayCredsFromEnv() + // Fetch browser env setting + mustSetBrowserSettingFromEnv() + // Initialize new gateway config. - // - // TODO: add support for custom region when we add - // support for S3 backend storage, currently this can - // default to "us-east-1" + newGatewayConfig(accessKey, secretKey, globalMinioDefaultRegion) // Get quiet flag from command line argument. @@ -214,6 +231,12 @@ func gatewayMain(ctx *cli.Context) { initNSLock(false) // Enable local namespace lock. router := mux.NewRouter().SkipClean(true) + + // Register web router when its enabled. + if globalIsBrowserEnabled { + aerr := registerWebRouter(router) + fatalIf(aerr, "Unable to configure web browser") + } registerGatewayAPIRouter(router, newObject) var handlerFns = []HandlerFunc{ @@ -224,6 +247,13 @@ func gatewayMain(ctx *cli.Context) { // Adds 'crossdomain.xml' policy handler to serve legacy flash clients. setCrossDomainPolicy, // Validates all incoming requests to have a valid date header. + // Redirect some pre-defined browser request paths to a static location prefix. + setBrowserRedirectHandler, + // Validates if incoming request is for restricted buckets. + setPrivateBucketHandler, + // Adds cache control for all browser requests. + setBrowserCacheControlHandler, + // Validates all incoming requests to have a valid date header. setTimeValidityHandler, // CORS setting for all browser API requests. setCorsHandler, @@ -234,6 +264,8 @@ func gatewayMain(ctx *cli.Context) { // routes them accordingly. Client receives a HTTP error for // invalid/unsupported signatures. setAuthHandler, + // Add new handlers here. + } apiServer := NewServerMux(serverAddr, registerHandlers(router, handlerFns...)) diff --git a/cmd/gateway-main_test.go b/cmd/gateway-main_test.go index dc1b986d5..1779725bf 100644 --- a/cmd/gateway-main_test.go +++ b/cmd/gateway-main_test.go @@ -16,7 +16,10 @@ package cmd -import "testing" +import ( + "os" + "testing" +) // Test parseGatewayEndpoint func TestParseGatewayEndpoint(t *testing.T) { @@ -48,3 +51,25 @@ func TestParseGatewayEndpoint(t *testing.T) { } } } + +func TestSetBrowserFromEnv(t *testing.T) { + browser := os.Getenv("MINIO_BROWSER") + + os.Setenv("MINIO_BROWSER", "on") + mustSetBrowserSettingFromEnv() + if globalIsBrowserEnabled != true { + t.Errorf("Expected the response status to be `%t`, but instead found `%t`", globalIsBrowserEnabled, false) + } + + os.Setenv("MINIO_BROWSER", "off") + mustSetBrowserSettingFromEnv() + if globalIsBrowserEnabled != false { + t.Errorf("Expected the response status to be `%t`, but instead found `%t`", globalIsBrowserEnabled, true) + } + os.Setenv("MINIO_BROWSER", "") + mustSetBrowserSettingFromEnv() + if globalIsBrowserEnabled != false { + t.Errorf("Expected the response status to be `%t`, but instead found `%t`", globalIsBrowserEnabled, true) + } + os.Setenv("MINIO_BROWSER", browser) +} diff --git a/cmd/gateway-router.go b/cmd/gateway-router.go index b1d16f310..b286ed6ed 100644 --- a/cmd/gateway-router.go +++ b/cmd/gateway-router.go @@ -27,8 +27,6 @@ import ( type GatewayLayer interface { ObjectLayer - MakeBucketWithLocation(bucket, location string) error - AnonGetObject(bucket, object string, startOffset int64, length int64, writer io.Writer) (err error) AnonGetObjectInfo(bucket, object string) (objInfo ObjectInfo, err error) diff --git a/cmd/gateway-s3.go b/cmd/gateway-s3.go index f2c2e49b5..027b1071a 100644 --- a/cmd/gateway-s3.go +++ b/cmd/gateway-s3.go @@ -17,12 +17,11 @@ package cmd import ( + "encoding/hex" "io" "net/http" "path" - "encoding/hex" - minio "github.com/minio/minio-go" "github.com/minio/minio-go/pkg/policy" ) @@ -133,12 +132,6 @@ func (l *s3Objects) StorageInfo() StorageInfo { return StorageInfo{} } -// MakeBucket creates a new container on S3 backend. -func (l *s3Objects) MakeBucket(bucket string) error { - // will never be called, only satisfy ObjectLayer interface - return traceError(NotImplemented{}) -} - // MakeBucket creates a new container on S3 backend. func (l *s3Objects) MakeBucketWithLocation(bucket, location string) error { err := l.Client.MakeBucket(bucket, location) @@ -565,6 +558,5 @@ func (l *s3Objects) DeleteBucketPolicies(bucket string) error { if err := l.Client.PutBucketPolicy(bucket, policy.BucketAccessPolicy{}); err != nil { return s3ToObjectError(traceError(err), bucket, "") } - return nil } diff --git a/cmd/jwt_test.go b/cmd/jwt_test.go index 7a101252e..3edc25c28 100644 --- a/cmd/jwt_test.go +++ b/cmd/jwt_test.go @@ -44,7 +44,7 @@ func testAuthenticate(authType string, t *testing.T) { // Secret key too small. {"myuser", "pass", errInvalidSecretKeyLength}, // Secret key too long. - {"myuser", "pass1234567890123456789012345678901234567", errInvalidSecretKeyLength}, + {"myuser", "pass1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890", errInvalidSecretKeyLength}, // Authentication error. {"myuser", "mypassword", errInvalidAccessKeyID}, // Authentication error. diff --git a/cmd/object-api-getobject_test.go b/cmd/object-api-getobject_test.go index 1e6b429a7..9f1dc89a0 100644 --- a/cmd/object-api-getobject_test.go +++ b/cmd/object-api-getobject_test.go @@ -39,7 +39,7 @@ func testGetObject(obj ObjectLayer, instanceType string, t TestErrHandler) { bucketName := getRandomBucketName() objectName := "test-object" // create bucket. - err := obj.MakeBucket(bucketName) + err := obj.MakeBucketWithLocation(bucketName, "") // Stop the test if creation of the bucket fails. if err != nil { t.Fatalf("%s : %s", instanceType, err.Error()) @@ -192,7 +192,7 @@ func testGetObjectPermissionDenied(obj ObjectLayer, instanceType string, disks [ // Setup for the tests. bucketName := getRandomBucketName() // create bucket. - err := obj.MakeBucket(bucketName) + err := obj.MakeBucketWithLocation(bucketName, "") // Stop the test if creation of the bucket fails. if err != nil { t.Fatalf("%s : %s", instanceType, err.Error()) @@ -303,7 +303,7 @@ func testGetObjectDiskNotFound(obj ObjectLayer, instanceType string, disks []str bucketName := getRandomBucketName() objectName := "test-object" // create bucket. - err := obj.MakeBucket(bucketName) + err := obj.MakeBucketWithLocation(bucketName, "") // Stop the test if creation of the bucket fails. if err != nil { t.Fatalf("%s : %s", instanceType, err.Error()) diff --git a/cmd/object-api-getobjectinfo_test.go b/cmd/object-api-getobjectinfo_test.go index bdba72689..6110e2737 100644 --- a/cmd/object-api-getobjectinfo_test.go +++ b/cmd/object-api-getobjectinfo_test.go @@ -29,7 +29,7 @@ func TestGetObjectInfo(t *testing.T) { // Testing GetObjectInfo(). func testGetObjectInfo(obj ObjectLayer, instanceType string, t TestErrHandler) { // This bucket is used for testing getObjectInfo operations. - err := obj.MakeBucket("test-getobjectinfo") + err := obj.MakeBucketWithLocation("test-getobjectinfo", "") if err != nil { t.Fatalf("%s : %s", instanceType, err.Error()) } diff --git a/cmd/object-api-interface.go b/cmd/object-api-interface.go index 2e4e26df7..36a54b8aa 100644 --- a/cmd/object-api-interface.go +++ b/cmd/object-api-interface.go @@ -25,7 +25,7 @@ type ObjectLayer interface { StorageInfo() StorageInfo // Bucket operations. - MakeBucket(bucket string) error + MakeBucketWithLocation(bucket string, location string) error GetBucketInfo(bucket string) (bucketInfo BucketInfo, err error) ListBuckets() (buckets []BucketInfo, err error) DeleteBucket(bucket string) error diff --git a/cmd/object-api-listobjects_test.go b/cmd/object-api-listobjects_test.go index 560a36101..90c2b8dda 100644 --- a/cmd/object-api-listobjects_test.go +++ b/cmd/object-api-listobjects_test.go @@ -41,7 +41,7 @@ func testListObjects(obj ObjectLayer, instanceType string, t TestErrHandler) { "empty-bucket", } for _, bucket := range testBuckets { - err := obj.MakeBucket(bucket) + err := obj.MakeBucketWithLocation(bucket, "") if err != nil { t.Fatalf("%s : %s", instanceType, err.Error()) } @@ -599,7 +599,7 @@ func BenchmarkListObjects(b *testing.B) { bucket := "ls-benchmark-bucket" // Create a bucket. - err = obj.MakeBucket(bucket) + err = obj.MakeBucketWithLocation(bucket, "") if err != nil { b.Fatal(err) } diff --git a/cmd/object-api-multipart_test.go b/cmd/object-api-multipart_test.go index 263bb36ae..36be3f8a2 100644 --- a/cmd/object-api-multipart_test.go +++ b/cmd/object-api-multipart_test.go @@ -52,7 +52,7 @@ func testObjectNewMultipartUpload(obj ObjectLayer, instanceType string, t TestEr } // Create bucket before intiating NewMultipartUpload. - err = obj.MakeBucket(bucket) + err = obj.MakeBucketWithLocation(bucket, "") if err != nil { // failed to create newbucket, abort. t.Fatalf("%s : %s", instanceType, err.Error()) @@ -91,7 +91,7 @@ func testObjectAbortMultipartUpload(obj ObjectLayer, instanceType string, t Test object := "minio-object" // Create bucket before intiating NewMultipartUpload. - err := obj.MakeBucket(bucket) + err := obj.MakeBucketWithLocation(bucket, "") if err != nil { // failed to create newbucket, abort. t.Fatalf("%s : %s", instanceType, err.Error()) @@ -137,7 +137,7 @@ func testObjectAPIIsUploadIDExists(obj ObjectLayer, instanceType string, t TestE object := "minio-object" // Create bucket before intiating NewMultipartUpload. - err := obj.MakeBucket(bucket) + err := obj.MakeBucketWithLocation(bucket, "") if err != nil { // Failed to create newbucket, abort. t.Fatalf("%s : %s", instanceType, err.Error()) @@ -173,7 +173,7 @@ func testPutObjectPartDiskNotFound(obj ObjectLayer, instanceType string, disks [ // objectNames[0]. // uploadIds [0]. // Create bucket before intiating NewMultipartUpload. - err := obj.MakeBucket(bucketNames[0]) + err := obj.MakeBucketWithLocation(bucketNames[0], "") if err != nil { // Failed to create newbucket, abort. t.Fatalf("%s : %s", instanceType, err.Error()) @@ -253,7 +253,7 @@ func testObjectAPIPutObjectPart(obj ObjectLayer, instanceType string, t TestErrH object := "minio-object" // Create bucket before intiating NewMultipartUpload. - err := obj.MakeBucket(bucket) + err := obj.MakeBucketWithLocation(bucket, "") if err != nil { // Failed to create newbucket, abort. t.Fatalf("%s : %s", instanceType, err.Error()) @@ -265,7 +265,7 @@ func testObjectAPIPutObjectPart(obj ObjectLayer, instanceType string, t TestErrH t.Fatalf("%s : %s", instanceType, err.Error()) } // Creating a dummy bucket for tests. - err = obj.MakeBucket("unused-bucket") + err = obj.MakeBucketWithLocation("unused-bucket", "") if err != nil { // Failed to create newbucket, abort. t.Fatalf("%s : %s", instanceType, err.Error()) @@ -386,7 +386,7 @@ func testListMultipartUploads(obj ObjectLayer, instanceType string, t TestErrHan // objectNames[0]. // uploadIds [0]. // Create bucket before initiating NewMultipartUpload. - err := obj.MakeBucket(bucketNames[0]) + err := obj.MakeBucketWithLocation(bucketNames[0], "") if err != nil { // Failed to create newbucket, abort. t.Fatalf("%s : %s", instanceType, err.Error()) @@ -404,7 +404,7 @@ func testListMultipartUploads(obj ObjectLayer, instanceType string, t TestErrHan // objectNames[0]. // uploadIds [1-3]. // Bucket to test for mutiple upload Id's for a given object. - err = obj.MakeBucket(bucketNames[1]) + err = obj.MakeBucketWithLocation(bucketNames[1], "") if err != nil { // Failed to create newbucket, abort. t.Fatalf("%s : %s", instanceType, err.Error()) @@ -425,7 +425,7 @@ func testListMultipartUploads(obj ObjectLayer, instanceType string, t TestErrHan // bucketnames[2]. // objectNames[0-2]. // uploadIds [4-9]. - err = obj.MakeBucket(bucketNames[2]) + err = obj.MakeBucketWithLocation(bucketNames[2], "") if err != nil { // Failed to create newbucket, abort. t.Fatalf("%s : %s", instanceType, err.Error()) @@ -1288,7 +1288,7 @@ func testListObjectPartsDiskNotFound(obj ObjectLayer, instanceType string, disks // objectNames[0]. // uploadIds [0]. // Create bucket before intiating NewMultipartUpload. - err := obj.MakeBucket(bucketNames[0]) + err := obj.MakeBucketWithLocation(bucketNames[0], "") if err != nil { // Failed to create newbucket, abort. t.Fatalf("%s : %s", instanceType, err.Error()) @@ -1531,7 +1531,7 @@ func testListObjectParts(obj ObjectLayer, instanceType string, t TestErrHandler) // objectNames[0]. // uploadIds [0]. // Create bucket before intiating NewMultipartUpload. - err := obj.MakeBucket(bucketNames[0]) + err := obj.MakeBucketWithLocation(bucketNames[0], "") if err != nil { // Failed to create newbucket, abort. t.Fatalf("%s : %s", instanceType, err.Error()) @@ -1769,7 +1769,7 @@ func testObjectCompleteMultipartUpload(obj ObjectLayer, instanceType string, t T // objectNames[0]. // uploadIds [0]. // Create bucket before intiating NewMultipartUpload. - err = obj.MakeBucket(bucketNames[0]) + err = obj.MakeBucketWithLocation(bucketNames[0], "") if err != nil { // Failed to create newbucket, abort. t.Fatalf("%s : %s", instanceType, err) diff --git a/cmd/object-api-putobject_test.go b/cmd/object-api-putobject_test.go index 4a8e702ce..cbd377f22 100644 --- a/cmd/object-api-putobject_test.go +++ b/cmd/object-api-putobject_test.go @@ -44,14 +44,14 @@ func testObjectAPIPutObject(obj ObjectLayer, instanceType string, t TestErrHandl object := "minio-object" // Create bucket. - err := obj.MakeBucket(bucket) + err := obj.MakeBucketWithLocation(bucket, "") if err != nil { // Failed to create newbucket, abort. t.Fatalf("%s : %s", instanceType, err.Error()) } // Creating a dummy bucket for tests. - err = obj.MakeBucket("unused-bucket") + err = obj.MakeBucketWithLocation("unused-bucket", "") if err != nil { // Failed to create newbucket, abort. t.Fatalf("%s : %s", instanceType, err.Error()) @@ -189,14 +189,14 @@ func testObjectAPIPutObjectDiskNotFound(obj ObjectLayer, instanceType string, di object := "minio-object" // Create bucket. - err := obj.MakeBucket(bucket) + err := obj.MakeBucketWithLocation(bucket, "") if err != nil { // Failed to create newbucket, abort. t.Fatalf("%s : %s", instanceType, err.Error()) } // Creating a dummy bucket for tests. - err = obj.MakeBucket("unused-bucket") + err = obj.MakeBucketWithLocation("unused-bucket", "") if err != nil { // Failed to create newbucket, abort. t.Fatalf("%s : %s", instanceType, err.Error()) @@ -303,7 +303,7 @@ func testObjectAPIPutObjectStaleFiles(obj ObjectLayer, instanceType string, disk object := "minio-object" // Create bucket. - err := obj.MakeBucket(bucket) + err := obj.MakeBucketWithLocation(bucket, "") if err != nil { // Failed to create newbucket, abort. t.Fatalf("%s : %s", instanceType, err.Error()) @@ -338,7 +338,7 @@ func testObjectAPIMultipartPutObjectStaleFiles(obj ObjectLayer, instanceType str object := "minio-object" // Create bucket. - err := obj.MakeBucket(bucket) + err := obj.MakeBucketWithLocation(bucket, "") if err != nil { // Failed to create newbucket, abort. t.Fatalf("%s : %s", instanceType, err.Error()) diff --git a/cmd/object_api_suite_test.go b/cmd/object_api_suite_test.go index 4fe4661ca..b7de80f98 100644 --- a/cmd/object_api_suite_test.go +++ b/cmd/object_api_suite_test.go @@ -79,7 +79,7 @@ func (s *ObjectLayerAPISuite) TestMakeBucket(c *C) { // Tests validate bucket creation. func testMakeBucket(obj ObjectLayer, instanceType string, c TestErrHandler) { - err := obj.MakeBucket("bucket-unknown") + err := obj.MakeBucketWithLocation("bucket-unknown", "") if err != nil { c.Fatalf("%s: %s", instanceType, err) } @@ -92,7 +92,7 @@ func (s *ObjectLayerAPISuite) TestMultipartObjectCreation(c *C) { // Tests validate creation of part files during Multipart operation. func testMultipartObjectCreation(obj ObjectLayer, instanceType string, c TestErrHandler) { - err := obj.MakeBucket("bucket") + err := obj.MakeBucketWithLocation("bucket", "") if err != nil { c.Fatalf("%s: %s", instanceType, err) } @@ -135,7 +135,7 @@ func (s *ObjectLayerAPISuite) TestMultipartObjectAbort(c *C) { // Tests validate abortion of Multipart operation. func testMultipartObjectAbort(obj ObjectLayer, instanceType string, c TestErrHandler) { - err := obj.MakeBucket("bucket") + err := obj.MakeBucketWithLocation("bucket", "") if err != nil { c.Fatalf("%s: %s", instanceType, err) } @@ -180,7 +180,7 @@ func (s *ObjectLayerAPISuite) TestMultipleObjectCreation(c *C) { // Tests validate object creation. func testMultipleObjectCreation(obj ObjectLayer, instanceType string, c TestErrHandler) { objects := make(map[string][]byte) - err := obj.MakeBucket("bucket") + err := obj.MakeBucketWithLocation("bucket", "") if err != nil { c.Fatalf("%s: %s", instanceType, err) } @@ -235,7 +235,7 @@ func (s *ObjectLayerAPISuite) TestPaging(c *C) { // Tests validate creation of objects and the order of listing using various filters for ListObjects operation. func testPaging(obj ObjectLayer, instanceType string, c TestErrHandler) { - obj.MakeBucket("bucket") + obj.MakeBucketWithLocation("bucket", "") result, err := obj.ListObjects("bucket", "", "", "", 0) if err != nil { c.Fatalf("%s: %s", instanceType, err) @@ -438,7 +438,7 @@ func (s *ObjectLayerAPISuite) TestObjectOverwriteWorks(c *C) { // Tests validate overwriting of an existing object. func testObjectOverwriteWorks(obj ObjectLayer, instanceType string, c TestErrHandler) { - err := obj.MakeBucket("bucket") + err := obj.MakeBucketWithLocation("bucket", "") if err != nil { c.Fatalf("%s: %s", instanceType, err) } @@ -488,11 +488,11 @@ func (s *ObjectLayerAPISuite) TestBucketRecreateFails(c *C) { // Tests validate that recreation of the bucket fails. func testBucketRecreateFails(obj ObjectLayer, instanceType string, c TestErrHandler) { - err := obj.MakeBucket("string") + err := obj.MakeBucketWithLocation("string", "") if err != nil { c.Fatalf("%s: %s", instanceType, err) } - err = obj.MakeBucket("string") + err = obj.MakeBucketWithLocation("string", "") if err == nil { c.Fatalf("%s: Expected error but found nil.", instanceType) } @@ -513,7 +513,7 @@ func testPutObject(obj ObjectLayer, instanceType string, c TestErrHandler) { length := int64(len(content)) readerEOF := newTestReaderEOF(content) readerNoEOF := newTestReaderNoEOF(content) - err := obj.MakeBucket("bucket") + err := obj.MakeBucketWithLocation("bucket", "") if err != nil { c.Fatalf("%s: %s", instanceType, err) } @@ -552,7 +552,7 @@ func (s *ObjectLayerAPISuite) TestPutObjectInSubdir(c *C) { // Tests validate PutObject with subdirectory prefix. func testPutObjectInSubdir(obj ObjectLayer, instanceType string, c TestErrHandler) { - err := obj.MakeBucket("bucket") + err := obj.MakeBucketWithLocation("bucket", "") if err != nil { c.Fatalf("%s: %s", instanceType, err) } @@ -593,7 +593,7 @@ func testListBuckets(obj ObjectLayer, instanceType string, c TestErrHandler) { } // add one and test exists. - err = obj.MakeBucket("bucket1") + err = obj.MakeBucketWithLocation("bucket1", "") if err != nil { c.Fatalf("%s: %s", instanceType, err) } @@ -607,7 +607,7 @@ func testListBuckets(obj ObjectLayer, instanceType string, c TestErrHandler) { } // add two and test exists. - err = obj.MakeBucket("bucket2") + err = obj.MakeBucketWithLocation("bucket2", "") if err != nil { c.Fatalf("%s: %s", instanceType, err) } @@ -621,7 +621,7 @@ func testListBuckets(obj ObjectLayer, instanceType string, c TestErrHandler) { } // add three and test exists + prefix. - err = obj.MakeBucket("bucket22") + err = obj.MakeBucketWithLocation("bucket22", "") if err != nil { c.Fatalf("%s: %s", instanceType, err) } @@ -645,11 +645,11 @@ func testListBucketsOrder(obj ObjectLayer, instanceType string, c TestErrHandler // if implementation contains a map, order of map keys will vary. // this ensures they return in the same order each time. // add one and test exists. - err := obj.MakeBucket("bucket1") + err := obj.MakeBucketWithLocation("bucket1", "") if err != nil { c.Fatalf("%s: %s", instanceType, err) } - err = obj.MakeBucket("bucket2") + err = obj.MakeBucketWithLocation("bucket2", "") if err != nil { c.Fatalf("%s: %s", instanceType, err) } @@ -698,7 +698,7 @@ func (s *ObjectLayerAPISuite) TestNonExistantObjectInBucket(c *C) { // Tests validate that GetObject fails on a non-existent bucket as expected. func testNonExistantObjectInBucket(obj ObjectLayer, instanceType string, c TestErrHandler) { - err := obj.MakeBucket("bucket") + err := obj.MakeBucketWithLocation("bucket", "") if err != nil { c.Fatalf("%s: %s", instanceType, err) } @@ -736,7 +736,7 @@ func (s *ObjectLayerAPISuite) TestGetDirectoryReturnsObjectNotFound(c *C) { // Tests validate that GetObject on an existing directory fails as expected. func testGetDirectoryReturnsObjectNotFound(obj ObjectLayer, instanceType string, c TestErrHandler) { bucketName := "bucket" - err := obj.MakeBucket(bucketName) + err := obj.MakeBucketWithLocation(bucketName, "") if err != nil { c.Fatalf("%s: %s", instanceType, err) } @@ -781,7 +781,7 @@ func (s *ObjectLayerAPISuite) TestContentType(c *C) { // Test content-type. func testContentType(obj ObjectLayer, instanceType string, c TestErrHandler) { - err := obj.MakeBucket("bucket") + err := obj.MakeBucketWithLocation("bucket", "") if err != nil { c.Fatalf("%s: %s", instanceType, err) } diff --git a/cmd/post-policy_test.go b/cmd/post-policy_test.go index 2f03ae2fa..c35d1503e 100644 --- a/cmd/post-policy_test.go +++ b/cmd/post-policy_test.go @@ -143,7 +143,7 @@ func testPostPolicyBucketHandler(obj ObjectLayer, instanceType string, t TestErr // objectNames[0]. // uploadIds [0]. // Create bucket before initiating NewMultipartUpload. - err = obj.MakeBucket(bucketName) + err = obj.MakeBucketWithLocation(bucketName, "") if err != nil { // Failed to create newbucket, abort. t.Fatalf("%s : %s", instanceType, err.Error()) @@ -459,7 +459,7 @@ func testPostPolicyBucketHandlerRedirect(obj ObjectLayer, instanceType string, t curTime := UTCNow() curTimePlus5Min := curTime.Add(time.Minute * 5) - err = obj.MakeBucket(bucketName) + err = obj.MakeBucketWithLocation(bucketName, "") if err != nil { // Failed to create newbucket, abort. t.Fatalf("%s : %s", instanceType, err.Error()) diff --git a/cmd/test-utils_test.go b/cmd/test-utils_test.go index 42654c138..b81148a20 100644 --- a/cmd/test-utils_test.go +++ b/cmd/test-utils_test.go @@ -1721,7 +1721,7 @@ func initAPIHandlerTest(obj ObjectLayer, endpoints []string) (string, http.Handl bucketName := getRandomBucketName() // Create bucket. - err := obj.MakeBucket(bucketName) + err := obj.MakeBucketWithLocation(bucketName, "") if err != nil { // failed to create newbucket, return err. return "", nil, err diff --git a/cmd/web-handlers.go b/cmd/web-handlers.go index 653e64872..bc4992e2e 100644 --- a/cmd/web-handlers.go +++ b/cmd/web-handlers.go @@ -132,7 +132,8 @@ func (web *webAPIHandlers) MakeBucket(r *http.Request, args *MakeBucketArgs, rep bucketLock := globalNSMutex.NewNSLock(args.BucketName, "") bucketLock.Lock() defer bucketLock.Unlock() - if err := objectAPI.MakeBucket(args.BucketName); err != nil { + + if err := objectAPI.MakeBucketWithLocation(args.BucketName, serverConfig.GetRegion()); err != nil { return toJSONError(err, args.BucketName) } @@ -679,6 +680,22 @@ func readBucketAccessPolicy(objAPI ObjectLayer, bucketName string) (policy.Bucke } +func getBucketAccessPolicy(objAPI ObjectLayer, bucketName string) (policy.BucketAccessPolicy, error) { + // FIXME: remove this code when S3 layer for gateway and server is unified. + var policyInfo policy.BucketAccessPolicy + var err error + + switch layer := objAPI.(type) { + case *s3Objects: + policyInfo, err = layer.GetBucketPolicies(bucketName) + case *azureObjects: + policyInfo, err = layer.GetBucketPolicies(bucketName) + default: + policyInfo, err = readBucketAccessPolicy(objAPI, bucketName) + } + return policyInfo, err +} + // GetBucketPolicy - get bucket policy. func (web *webAPIHandlers) GetBucketPolicy(r *http.Request, args *GetBucketPolicyArgs, reply *GetBucketPolicyRep) error { objectAPI := web.ObjectAPI() @@ -728,12 +745,14 @@ func (web *webAPIHandlers) ListAllBucketPolicies(r *http.Request, args *ListAllB if !isHTTPRequestValid(r) { return toJSONError(errAuthentication) } + var policyInfo, err = getBucketAccessPolicy(objectAPI, args.BucketName) - policyInfo, err := readBucketAccessPolicy(objectAPI, args.BucketName) if err != nil { - return toJSONError(err, args.BucketName) + _, ok := errorCause(err).(PolicyNotFound) + if !ok { + return toJSONError(err, args.BucketName) + } } - reply.UIVersion = browser.UIVersion for prefix, policy := range policy.GetPolicies(policyInfo.Statements, args.BucketName) { reply.Policies = append(reply.Policies, BucketAccessPolicy{ @@ -769,11 +788,26 @@ func (web *webAPIHandlers) SetBucketPolicy(r *http.Request, args *SetBucketPolic } } - policyInfo, err := readBucketAccessPolicy(objectAPI, args.BucketName) + var policyInfo, err = getBucketAccessPolicy(objectAPI, args.BucketName) + if err != nil { - return toJSONError(err, args.BucketName) + if _, ok := errorCause(err).(PolicyNotFound); !ok { + return toJSONError(err, args.BucketName) + } + policyInfo = policy.BucketAccessPolicy{Version: "2012-10-17"} } + policyInfo.Statements = policy.SetPolicy(policyInfo.Statements, bucketP, args.BucketName, args.Prefix) + switch g := objectAPI.(type) { + case GatewayLayer: + err = g.SetBucketPolicies(args.BucketName, policyInfo) + if err != nil { + return toJSONError(err) + } + reply.UIVersion = browser.UIVersion + return nil + } + if len(policyInfo.Statements) == 0 { err = persistAndNotifyBucketPolicyChange(args.BucketName, policyChange{true, nil}, objectAPI) if err != nil { @@ -798,7 +832,6 @@ func (web *webAPIHandlers) SetBucketPolicy(r *http.Request, args *SetBucketPolic } return toJSONError(err, args.BucketName) } - reply.UIVersion = browser.UIVersion return nil } diff --git a/cmd/web-handlers_test.go b/cmd/web-handlers_test.go index 64488268b..13681b7e7 100644 --- a/cmd/web-handlers_test.go +++ b/cmd/web-handlers_test.go @@ -315,7 +315,7 @@ func testListBucketsWebHandler(obj ObjectLayer, instanceType string, t TestErrHa bucketName := getRandomBucketName() // Create bucket. - err = obj.MakeBucket(bucketName) + err = obj.MakeBucketWithLocation(bucketName, "") if err != nil { // failed to create newbucket, abort. t.Fatalf("%s : %s", instanceType, err) @@ -366,7 +366,7 @@ func testListObjectsWebHandler(obj ObjectLayer, instanceType string, t TestErrHa objectSize := 1 * humanize.KiByte // Create bucket. - err = obj.MakeBucket(bucketName) + err = obj.MakeBucketWithLocation(bucketName, "") if err != nil { // failed to create newbucket, abort. t.Fatalf("%s : %s", instanceType, err) @@ -460,7 +460,7 @@ func testRemoveObjectWebHandler(obj ObjectLayer, instanceType string, t TestErrH objectSize := 1 * humanize.KiByte // Create bucket. - err = obj.MakeBucket(bucketName) + err = obj.MakeBucketWithLocation(bucketName, "") if err != nil { // failed to create newbucket, abort. t.Fatalf("%s : %s", instanceType, err) @@ -700,7 +700,7 @@ func testUploadWebHandler(obj ObjectLayer, instanceType string, t TestErrHandler return rec.Code } // Create bucket. - err = obj.MakeBucket(bucketName) + err = obj.MakeBucketWithLocation(bucketName, "") if err != nil { // failed to create newbucket, abort. t.Fatalf("%s : %s", instanceType, err) @@ -785,7 +785,7 @@ func testDownloadWebHandler(obj ObjectLayer, instanceType string, t TestErrHandl } // Create bucket. - err = obj.MakeBucket(bucketName) + err = obj.MakeBucketWithLocation(bucketName, "") if err != nil { // failed to create newbucket, abort. t.Fatalf("%s : %s", instanceType, err) @@ -852,7 +852,7 @@ func testWebHandlerDownloadZip(obj ObjectLayer, instanceType string, t TestErrHa fileThree := "cccccccccccccc" // Create bucket. - err = obj.MakeBucket(bucket) + err = obj.MakeBucketWithLocation(bucket, "") if err != nil { // failed to create newbucket, abort. t.Fatalf("%s : %s", instanceType, err) @@ -937,7 +937,7 @@ func testWebPresignedGetHandler(obj ObjectLayer, instanceType string, t TestErrH objectSize := 1 * humanize.KiByte // Create bucket. - err = obj.MakeBucket(bucketName) + err = obj.MakeBucketWithLocation(bucketName, "") if err != nil { // failed to create newbucket, abort. t.Fatalf("%s : %s", instanceType, err) @@ -1037,7 +1037,7 @@ func testWebGetBucketPolicyHandler(obj ObjectLayer, instanceType string, t TestE rec := httptest.NewRecorder() bucketName := getRandomBucketName() - if err := obj.MakeBucket(bucketName); err != nil { + if err := obj.MakeBucketWithLocation(bucketName, ""); err != nil { t.Fatal("Unexpected error: ", err) } @@ -1111,7 +1111,7 @@ func testWebListAllBucketPoliciesHandler(obj ObjectLayer, instanceType string, t rec := httptest.NewRecorder() bucketName := getRandomBucketName() - if err := obj.MakeBucket(bucketName); err != nil { + if err := obj.MakeBucketWithLocation(bucketName, ""); err != nil { t.Fatal("Unexpected error: ", err) } @@ -1209,7 +1209,7 @@ func testWebSetBucketPolicyHandler(obj ObjectLayer, instanceType string, t TestE // Create a bucket bucketName := getRandomBucketName() - if err = obj.MakeBucket(bucketName); err != nil { + if err = obj.MakeBucketWithLocation(bucketName, ""); err != nil { t.Fatal("Unexpected error: ", err) } @@ -1445,7 +1445,7 @@ func TestWebObjectLayerFaultyDisks(t *testing.T) { defer removeRoots(fsDirs) bucketName := "mybucket" - err = obj.MakeBucket(bucketName) + err = obj.MakeBucketWithLocation(bucketName, "") if err != nil { t.Fatal("Cannot make bucket:", err) } diff --git a/cmd/xl-v1-bucket.go b/cmd/xl-v1-bucket.go index af1eaca30..54dee3a6d 100644 --- a/cmd/xl-v1-bucket.go +++ b/cmd/xl-v1-bucket.go @@ -30,7 +30,7 @@ var bucketMetadataOpIgnoredErrs = append(bucketOpIgnoredErrs, errVolumeNotFound) /// Bucket operations // MakeBucket - make a bucket. -func (xl xlObjects) MakeBucket(bucket string) error { +func (xl xlObjects) MakeBucketWithLocation(bucket, location string) error { // Verify if bucket is valid. if !IsValidBucketName(bucket) { return traceError(BucketNameInvalid{Bucket: bucket}) diff --git a/cmd/xl-v1-healing-common_test.go b/cmd/xl-v1-healing-common_test.go index bceb35dfb..d9705395c 100644 --- a/cmd/xl-v1-healing-common_test.go +++ b/cmd/xl-v1-healing-common_test.go @@ -214,7 +214,7 @@ func TestListOnlineDisks(t *testing.T) { obj.DeleteObject(bucket, object) obj.DeleteBucket(bucket) - err = obj.MakeBucket("bucket") + err = obj.MakeBucketWithLocation("bucket", "") if err != nil { t.Fatalf("Failed to make a bucket %v", err) } diff --git a/cmd/xl-v1-healing_test.go b/cmd/xl-v1-healing_test.go index c230281bd..82853c17e 100644 --- a/cmd/xl-v1-healing_test.go +++ b/cmd/xl-v1-healing_test.go @@ -212,7 +212,7 @@ func TestHealFormatXL(t *testing.T) { t.Fatal(err) } xl = obj.(*xlObjects) - if err = obj.MakeBucket(getRandomBucketName()); err != nil { + if err = obj.MakeBucketWithLocation(getRandomBucketName(), ""); err != nil { t.Fatal(err) } for i := 0; i <= 2; i++ { @@ -248,7 +248,7 @@ func TestUndoMakeBucket(t *testing.T) { } bucketName := getRandomBucketName() - if err = obj.MakeBucket(bucketName); err != nil { + if err = obj.MakeBucketWithLocation(bucketName, ""); err != nil { t.Fatal(err) } xl := obj.(*xlObjects) @@ -288,7 +288,7 @@ func TestQuickHeal(t *testing.T) { } bucketName := getRandomBucketName() - if err = obj.MakeBucket(bucketName); err != nil { + if err = obj.MakeBucketWithLocation(bucketName, ""); err != nil { t.Fatal(err) } @@ -383,13 +383,13 @@ func TestListBucketsHeal(t *testing.T) { // Create a bucket that won't get corrupted saneBucket := "sanebucket" - if err = obj.MakeBucket(saneBucket); err != nil { + if err = obj.MakeBucketWithLocation(saneBucket, ""); err != nil { t.Fatal(err) } // Create a bucket that will be removed in some disks corruptedBucketName := getRandomBucketName() - if err = obj.MakeBucket(corruptedBucketName); err != nil { + if err = obj.MakeBucketWithLocation(corruptedBucketName, ""); err != nil { t.Fatal(err) } @@ -445,7 +445,7 @@ func TestHealObjectXL(t *testing.T) { object := "object" data := bytes.Repeat([]byte("a"), 5*1024*1024) - err = obj.MakeBucket(bucket) + err = obj.MakeBucketWithLocation(bucket, "") if err != nil { t.Fatalf("Failed to make a bucket - %v", err) } diff --git a/cmd/xl-v1-list-objects-heal_test.go b/cmd/xl-v1-list-objects-heal_test.go index af12060b2..4782aa353 100644 --- a/cmd/xl-v1-list-objects-heal_test.go +++ b/cmd/xl-v1-list-objects-heal_test.go @@ -48,7 +48,7 @@ func TestListObjectsHeal(t *testing.T) { objName := "obj" // Create test bucket - err = xl.MakeBucket(bucketName) + err = xl.MakeBucketWithLocation(bucketName, "") if err != nil { t.Fatal(err) } @@ -166,7 +166,7 @@ func TestListUploadsHeal(t *testing.T) { objName := path.Join(prefix, "obj") // Create test bucket. - err = xl.MakeBucket(bucketName) + err = xl.MakeBucketWithLocation(bucketName, "") if err != nil { t.Fatal(err) } diff --git a/cmd/xl-v1-metadata_test.go b/cmd/xl-v1-metadata_test.go index c20339e95..028d116ea 100644 --- a/cmd/xl-v1-metadata_test.go +++ b/cmd/xl-v1-metadata_test.go @@ -37,7 +37,7 @@ func testXLReadStat(obj ObjectLayer, instanceType string, disks []string, t *tes bucketName := getRandomBucketName() objectName := "test-object" // create bucket. - err := obj.MakeBucket(bucketName) + err := obj.MakeBucketWithLocation(bucketName, "") // Stop the test if creation of the bucket fails. if err != nil { t.Fatalf("%s : %s", instanceType, err.Error()) @@ -113,7 +113,7 @@ func testXLReadMetaParts(obj ObjectLayer, instanceType string, disks []string, t // objectNames[0]. // uploadIds [0]. // Create bucket before intiating NewMultipartUpload. - err := obj.MakeBucket(bucketNames[0]) + err := obj.MakeBucketWithLocation(bucketNames[0] ,"") if err != nil { // Failed to create newbucket, abort. t.Fatalf("%s : %s", instanceType, err.Error()) diff --git a/cmd/xl-v1-multipart_test.go b/cmd/xl-v1-multipart_test.go index 71d5dd03b..63f735a02 100644 --- a/cmd/xl-v1-multipart_test.go +++ b/cmd/xl-v1-multipart_test.go @@ -38,7 +38,7 @@ func TestUpdateUploadJSON(t *testing.T) { defer removeRoots(fsDirs) bucket, object := "bucket", "object" - err = obj.MakeBucket(bucket) + err = obj.MakeBucketWithLocation(bucket, "") if err != nil { t.Fatal(err) } diff --git a/cmd/xl-v1-object_test.go b/cmd/xl-v1-object_test.go index 86ffd8648..6e9eba874 100644 --- a/cmd/xl-v1-object_test.go +++ b/cmd/xl-v1-object_test.go @@ -42,7 +42,7 @@ func TestRepeatPutObjectPart(t *testing.T) { // cleaning up of temporary test directories defer removeRoots(disks) - err = objLayer.MakeBucket("bucket1") + err = objLayer.MakeBucketWithLocation("bucket1", "") if err != nil { t.Fatal(err) } @@ -86,7 +86,7 @@ func TestXLDeleteObjectBasic(t *testing.T) { } // Make bucket for Test 7 to pass - err = xl.MakeBucket("bucket") + err = xl.MakeBucketWithLocation("bucket", "") if err != nil { t.Fatal(err) } @@ -120,7 +120,7 @@ func TestXLDeleteObjectDiskNotFound(t *testing.T) { xl := obj.(*xlObjects) // Create "bucket" - err = obj.MakeBucket("bucket") + err = obj.MakeBucketWithLocation("bucket", "") if err != nil { t.Fatal(err) } @@ -170,7 +170,7 @@ func TestGetObjectNoQuorum(t *testing.T) { xl := obj.(*xlObjects) // Create "bucket" - err = obj.MakeBucket("bucket") + err = obj.MakeBucketWithLocation("bucket", "") if err != nil { t.Fatal(err) } @@ -222,7 +222,7 @@ func TestPutObjectNoQuorum(t *testing.T) { xl := obj.(*xlObjects) // Create "bucket" - err = obj.MakeBucket("bucket") + err = obj.MakeBucketWithLocation("bucket", "") if err != nil { t.Fatal(err) } @@ -279,7 +279,7 @@ func TestHealing(t *testing.T) { xl := obj.(*xlObjects) // Create "bucket" - err = obj.MakeBucket("bucket") + err = obj.MakeBucketWithLocation("bucket", "") if err != nil { t.Fatal(err) } diff --git a/docs/gateway/README.md b/docs/gateway/README.md index f3459bb3f..00922babf 100644 --- a/docs/gateway/README.md +++ b/docs/gateway/README.md @@ -16,7 +16,10 @@ export MINIO_ACCESS_KEY=azureaccountname export MINIO_SECRET_KEY=azureaccountkey minio gateway azure ``` +## Test using Minio Browser +Minio Gateway comes with an embedded web based object browser. Point your web browser to http://127.0.0.1:9000 ensure your server has started successfully. +![Screenshot](https://github.com/minio/minio/blob/master/docs/screenshots/minio-browser.jpg?raw=true) ## Test using Minio Client `mc` `mc` provides a modern alternative to UNIX commands such as ls, cat, cp, mirror, diff etc. It supports filesystems and Amazon S3 compatible cloud storage services.