diff --git a/bucket-policy-handlers.go b/bucket-policy-handlers.go index 9700f2896..31cfb79fd 100644 --- a/bucket-policy-handlers.go +++ b/bucket-policy-handlers.go @@ -21,7 +21,6 @@ import ( "io" "io/ioutil" "net/http" - "regexp" "strings" mux "github.com/gorilla/mux" @@ -65,41 +64,48 @@ func bucketPolicyMatchStatement(action string, resource string, conditions map[s // Verify if given action matches with policy statement. func bucketPolicyActionMatch(action string, statement policyStatement) bool { for _, policyAction := range statement.Actions { - // Policy action can be a regex, validate the action with matching string. - matched, err := regexp.MatchString(policyAction, action) - fatalIf(err, "Invalid action \"%s\" in bucket policy.", action) - if matched { + if matched := actionMatch(policyAction, action); matched { return true } } return false } -// Match function matches wild cards in 'pattern' for resource. -func resourceMatch(pattern, resource string) bool { +// Match function matches wild cards in 'pattern' for 'text'. +func wildCardMatch(pattern, text string) bool { if pattern == "" { - return resource == pattern + return text == pattern } if pattern == "*" { return true } parts := strings.Split(pattern, "*") if len(parts) == 1 { - return resource == pattern + return text == pattern } tGlob := strings.HasSuffix(pattern, "*") end := len(parts) - 1 - if !strings.HasPrefix(resource, parts[0]) { + if !strings.HasPrefix(text, parts[0]) { return false } for i := 1; i < end; i++ { - if !strings.Contains(resource, parts[i]) { + if !strings.Contains(text, parts[i]) { return false } - idx := strings.Index(resource, parts[i]) + len(parts[i]) - resource = resource[idx:] + idx := strings.Index(text, parts[i]) + len(parts[i]) + text = text[idx:] } - return tGlob || strings.HasSuffix(resource, parts[end]) + return tGlob || strings.HasSuffix(text, parts[end]) +} + +// Match function matches wild cards in 'pattern' for resource. +func resourceMatch(pattern, resource string) bool { + return wildCardMatch(pattern, resource) +} + +// Match function matches wild cards in 'pattern' for action. +func actionMatch(pattern, action string) bool { + return wildCardMatch(pattern, action) } // Verify if given resource matches with policy statement. @@ -109,11 +115,11 @@ func bucketPolicyResourceMatch(resource string, statement policyStatement) bool // the requested object can be given access based on the already set bucket policy if // the match is successful. // More info: http://docs.aws.amazon.com/AmazonS3/latest/dev/s3-arn-format.html . - if matched := resourceMatch(resourcep, resource); !matched { - return false + if matched := resourceMatch(resourcep, resource); matched { + return true } } - return true + return false } // Verify if given condition matches with policy statement. diff --git a/bucket-policy-handlers_test.go b/bucket-policy-handlers_test.go index 3847100f3..57a956ea7 100644 --- a/bucket-policy-handlers_test.go +++ b/bucket-policy-handlers_test.go @@ -24,7 +24,7 @@ import ( // Tests validate Bucket policy resource matcher. func TestBucketPolicyResourceMatch(t *testing.T) { - // generates\ statement with given resource.. + // generates statement with given resource.. generateStatement := func(resource string) policyStatement { statement := policyStatement{} statement.Resources = []string{resource} @@ -76,3 +76,160 @@ func TestBucketPolicyResourceMatch(t *testing.T) { } } } + +// TestBucketPolicyActionMatch - Test validates whether given action on the +// bucket/object matches the allowed actions in policyStatement. +// This test preserves the allowed actions for all 3 sets of policies, that is read-write,read-only, write-only. +// The intention of the test is to catch any changes made to allowed action for on eof the above 3 major policy groups mentioned. +func TestBucketPolicyActionMatch(t *testing.T) { + bucketName := "test-bucket" + objectPrefix := "test-object" + + testCases := []struct { + action string + statement policyStatement + expectedResult bool + }{ + // s3:GetBucketLocation is the action necessary to be present in the bucket policy to allow + // fetching of bucket location on an Anonymous/unsigned request. + + //r ead-write bucket policy is expected to allow GetBucketLocation operation on an anonymous request (Test case - 1). + {"s3:GetBucketLocation", getReadWriteBucketStatement(bucketName, objectPrefix), true}, + // write-only bucket policy is expected to allow GetBucketLocation operation on an anonymous request (Test case - 2). + {"s3:GetBucketLocation", getWriteOnlyBucketStatement(bucketName, objectPrefix), true}, + // read-only bucket policy is expected to allow GetBucketLocation operation on an anonymous request (Test case - 3). + {"s3:GetBucketLocation", getReadOnlyBucketStatement(bucketName, objectPrefix), true}, + + // Any of the Object level access permissions shouldn't allow for GetBucketLocation operation on an Anonymous/unsigned request (Test cases 4-6). + {"s3:GetBucketLocation", getReadWriteObjectStatement(bucketName, objectPrefix), false}, + {"s3:GetBucketLocation", getWriteOnlyObjectStatement(bucketName, objectPrefix), false}, + {"s3:GetBucketLocation", getReadOnlyObjectStatement(bucketName, objectPrefix), false}, + + // s3:ListBucketMultipartUploads is the action necessary to be present in the bucket policy to allow + // Listing of multipart uploads in a given bucket for an Anonymous/unsigned request. + + //read-write bucket policy is expected to allow ListBucketMultipartUploads operation on an anonymous request (Test case 7). + {"s3:ListBucketMultipartUploads", getReadWriteBucketStatement(bucketName, objectPrefix), true}, + // write-only bucket policy is expected to allow ListBucketMultipartUploads operation on an anonymous request (Test case 8). + {"s3:ListBucketMultipartUploads", getWriteOnlyBucketStatement(bucketName, objectPrefix), true}, + // read-only bucket policy is expected to not allow ListBucketMultipartUploads operation on an anonymous request (Test case 9). + // the allowed actions in read-only bucket statement are "s3:GetBucketLocation","s3:ListBucket", + // this shouldnot allow for ListBucketMultipartUploads operations. + {"s3:ListBucketMultipartUploads", getReadOnlyBucketStatement(bucketName, objectPrefix), false}, + + // Any of the object level policy will not allow for s3:ListBucketMultipartUploads (Test cases 10-12). + {"s3:ListBucketMultipartUploads", getReadWriteObjectStatement(bucketName, objectPrefix), false}, + {"s3:ListBucketMultipartUploads", getWriteOnlyObjectStatement(bucketName, objectPrefix), false}, + {"s3:ListBucketMultipartUploads", getReadOnlyObjectStatement(bucketName, objectPrefix), false}, + + // s3:ListBucket is the action necessary to be present in the bucket policy to allow + // listing of all objects inside a given bucket on an Anonymous/unsigned request. + + // Cases for testing ListBucket access for different Bucket level access permissions. + // read-only bucket policy is expected to allow ListBucket operation on an anonymous request (Test case 13). + {"s3:ListBucket", getReadOnlyBucketStatement(bucketName, objectPrefix), true}, + // read-write bucket policy is expected to allow ListBucket operation on an anonymous request (Test case 14). + {"s3:ListBucket", getReadWriteBucketStatement(bucketName, objectPrefix), true}, + // write-only bucket policy is expected to not allow ListBucket operation on an anonymous request (Test case 15). + // the allowed actions in write-only bucket statement are "s3:GetBucketLocation", "s3:ListBucketMultipartUploads", + // this shouldnot allow for ListBucket operations. + {"s3:ListBucket", getWriteOnlyBucketStatement(bucketName, objectPrefix), false}, + + // Cases for testing ListBucket access for different Object level access permissions (Test cases 16-18). + // Any of the Object level access permissions shouldn't allow for ListBucket operation on an Anonymous/unsigned request. + {"s3:ListBucket", getReadOnlyObjectStatement(bucketName, objectPrefix), false}, + {"s3:ListBucket", getReadWriteObjectStatement(bucketName, objectPrefix), false}, + {"s3:ListBucket", getWriteOnlyObjectStatement(bucketName, objectPrefix), false}, + + // s3:DeleteObject is the action necessary to be present in the bucket policy to allow + // deleting/removal of objects inside a given bucket for an Anonymous/unsigned request. + + // Cases for testing DeleteObject access for different Bucket level access permissions (Test cases 19-21). + // Any of the Bucket level access permissions shouldn't allow for DeleteObject operation on an Anonymous/unsigned request. + {"s3:DeleteObject", getReadOnlyBucketStatement(bucketName, objectPrefix), false}, + {"s3:DeleteObject", getReadWriteBucketStatement(bucketName, objectPrefix), false}, + {"s3:DeleteObject", getWriteOnlyBucketStatement(bucketName, objectPrefix), false}, + + // Cases for testing DeleteObject access for different Object level access permissions (Test cases 22). + // read-only bucket policy is expected to not allow Delete Object operation on an anonymous request. + {"s3:DeleteObject", getReadOnlyObjectStatement(bucketName, objectPrefix), false}, + // read-write bucket policy is expected to allow Delete Bucket operation on an anonymous request (Test cases 23). + {"s3:DeleteObject", getReadWriteObjectStatement(bucketName, objectPrefix), true}, + // write-only bucket policy is expected to allow Delete Object operation on an anonymous request (Test cases 24). + {"s3:DeleteObject", getWriteOnlyObjectStatement(bucketName, objectPrefix), true}, + + // s3:AbortMultipartUpload is the action necessary to be present in the bucket policy to allow + // cancelling or abortion of an already initiated multipart upload operation for an Anonymous/unsigned request. + + // Cases for testing AbortMultipartUpload access for different Bucket level access permissions (Test cases 25-27). + // Any of the Bucket level access permissions shouldn't allow for AbortMultipartUpload operation on an Anonymous/unsigned request. + {"s3:AbortMultipartUpload", getReadOnlyBucketStatement(bucketName, objectPrefix), false}, + {"s3:AbortMultipartUpload", getReadWriteBucketStatement(bucketName, objectPrefix), false}, + {"s3:AbortMultipartUpload", getWriteOnlyBucketStatement(bucketName, objectPrefix), false}, + + // Cases for testing AbortMultipartUpload access for different Object level access permissions. + // read-only object policy is expected to not allow AbortMultipartUpload operation on an anonymous request (Test case 28). + {"s3:AbortMultipartUpload", getReadOnlyObjectStatement(bucketName, objectPrefix), false}, + // read-write object policy is expected to allow AbortMultipartUpload operation on an anonymous request (Test case 29). + {"s3:AbortMultipartUpload", getReadWriteObjectStatement(bucketName, objectPrefix), true}, + // write-only object policy is expected to allow AbortMultipartUpload operation on an anonymous request (Test case 30). + {"s3:AbortMultipartUpload", getWriteOnlyObjectStatement(bucketName, objectPrefix), true}, + + // s3:PutObject is the action necessary to be present in the bucket policy to allow + // uploading of an object for an Anonymous/unsigned request. + + // Cases for testing PutObject access for different Bucket level access permissions (Test cases 31-33). + // Any of the Bucket level access permissions shouldn't allow for PutObject operation on an Anonymous/unsigned request. + {"s3:PutObject", getReadOnlyBucketStatement(bucketName, objectPrefix), false}, + {"s3:PutObject", getReadWriteBucketStatement(bucketName, objectPrefix), false}, + {"s3:PutObject", getWriteOnlyBucketStatement(bucketName, objectPrefix), false}, + + // Cases for testing PutObject access for different Object level access permissions. + // read-only object policy is expected to not allow PutObject operation on an anonymous request (Test case 34). + {"s3:PutObject", getReadOnlyObjectStatement(bucketName, objectPrefix), false}, + // read-write object policy is expected to allow PutObject operation on an anonymous request (Test case 35). + {"s3:PutObject", getReadWriteObjectStatement(bucketName, objectPrefix), true}, + // write-only object policy is expected to allow PutObject operation on an anonymous request (Test case 36). + {"s3:PutObject", getWriteOnlyObjectStatement(bucketName, objectPrefix), true}, + + // s3:GetObject is the action necessary to be present in the bucket policy to allow + // downloading of an object for an Anonymous/unsigned request. + + // Cases for testing GetObject access for different Bucket level access permissions (Test cases 37-39). + // Any of the Bucket level access permissions shouldn't allow for GetObject operation on an Anonymous/unsigned request. + {"s3:GetObject", getReadOnlyBucketStatement(bucketName, objectPrefix), false}, + {"s3:GetObject", getReadWriteBucketStatement(bucketName, objectPrefix), false}, + {"s3:GetObject", getWriteOnlyBucketStatement(bucketName, objectPrefix), false}, + + // Cases for testing GetObject access for different Object level access permissions. + // read-only bucket policy is expected to allow downloading of an Object on an anonymous request (Test case 40). + {"s3:GetObject", getReadOnlyObjectStatement(bucketName, objectPrefix), true}, + // read-write bucket policy is expected to allow downloading of an Object on an anonymous request (Test case 41). + {"s3:GetObject", getReadWriteObjectStatement(bucketName, objectPrefix), true}, + // write-only bucket policy is expected to not allow downloading of an Object on an anonymous request (Test case 42). + {"s3:GetObject", getWriteOnlyObjectStatement(bucketName, objectPrefix), false}, + + // s3:ListMultipartUploadParts is the action necessary to be present in the bucket policy to allow + // Listing of uploaded parts for an Anonymous/unsigned request. + + // Any of the Bucket level access permissions shouldn't allow for ListMultipartUploadParts operation on an Anonymous/unsigned request. + // read-only bucket policy is expected to not allow ListMultipartUploadParts operation on an anonymous request (Test cases 43-45). + {"s3:ListMultipartUploadParts", getReadOnlyBucketStatement(bucketName, objectPrefix), false}, + {"s3:ListMultipartUploadParts", getReadWriteBucketStatement(bucketName, objectPrefix), false}, + {"s3:ListMultipartUploadParts", getWriteOnlyBucketStatement(bucketName, objectPrefix), false}, + + // read-only object policy is expected to not allow ListMultipartUploadParts operation on an anonymous request (Test case 46). + {"s3:ListMultipartUploadParts", getReadOnlyObjectStatement(bucketName, objectPrefix), false}, + // read-write object policy is expected to allow ListMultipartUploadParts operation on an anonymous request (Test case 47). + {"s3:ListMultipartUploadParts", getReadWriteObjectStatement(bucketName, objectPrefix), true}, + // write-only object policy is expected to allow ListMultipartUploadParts operation on an anonymous request (Test case 48). + {"s3:ListMultipartUploadParts", getWriteOnlyObjectStatement(bucketName, objectPrefix), true}, + } + for i, testCase := range testCases { + actualResult := bucketPolicyActionMatch(testCase.action, testCase.statement) + if testCase.expectedResult != actualResult { + t.Errorf("Test %d: Expected the result to be `%v`, but instead found it to be `%v`", i+1, testCase.expectedResult, actualResult) + } + } + +} diff --git a/bucket-policy-parser.go b/bucket-policy-parser.go index ed17449c0..d5bff1174 100644 --- a/bucket-policy-parser.go +++ b/bucket-policy-parser.go @@ -34,6 +34,8 @@ const ( // supportedActionMap - lists all the actions supported by minio. var supportedActionMap = map[string]struct{}{ + "*": {}, + "s3:*": {}, "s3:GetObject": {}, "s3:ListBucket": {}, "s3:PutObject": {}, diff --git a/bucket-policy-parser_test.go b/bucket-policy-parser_test.go index fa3f79b60..8a5d64f7e 100644 --- a/bucket-policy-parser_test.go +++ b/bucket-policy-parser_test.go @@ -69,60 +69,89 @@ var ( } ) -// Obtain statements for read-write BucketPolicy. -func setReadWriteStatement(bucketName, objectPrefix string) []policyStatement { - bucketResourceStatement := policyStatement{} +// Obtain bucket statement for read-write BucketPolicy. +func getReadWriteObjectStatement(bucketName, objectPrefix string) policyStatement { objectResourceStatement := policyStatement{} - statements := []policyStatement{} - - bucketResourceStatement.Effect = "Allow" - bucketResourceStatement.Principal.AWS = []string{"*"} - bucketResourceStatement.Resources = []string{fmt.Sprintf("%s%s", AWSResourcePrefix, bucketName)} - bucketResourceStatement.Actions = readWriteBucketActions objectResourceStatement.Effect = "Allow" objectResourceStatement.Principal.AWS = []string{"*"} objectResourceStatement.Resources = []string{fmt.Sprintf("%s%s", AWSResourcePrefix, bucketName+"/"+objectPrefix+"*")} objectResourceStatement.Actions = readWriteObjectActions + return objectResourceStatement +} + +// Obtain object statement for read-write BucketPolicy. +func getReadWriteBucketStatement(bucketName, objectPrefix string) policyStatement { + bucketResourceStatement := policyStatement{} + bucketResourceStatement.Effect = "Allow" + bucketResourceStatement.Principal.AWS = []string{"*"} + bucketResourceStatement.Resources = []string{fmt.Sprintf("%s%s", AWSResourcePrefix, bucketName)} + bucketResourceStatement.Actions = readWriteBucketActions + return bucketResourceStatement +} + +// Obtain statements for read-write BucketPolicy. +func getReadWriteStatement(bucketName, objectPrefix string) []policyStatement { + statements := []policyStatement{} // Save the read write policy. - statements = append(statements, bucketResourceStatement, objectResourceStatement) + statements = append(statements, getReadWriteBucketStatement(bucketName, objectPrefix), getReadWriteObjectStatement(bucketName, objectPrefix)) return statements } -// Obtain statements for read only BucketPolicy. -func setReadOnlyStatement(bucketName, objectPrefix string) []policyStatement { +// Obtain bucket statement for read only BucketPolicy. +func getReadOnlyBucketStatement(bucketName, objectPrefix string) policyStatement { bucketResourceStatement := policyStatement{} - objectResourceStatement := policyStatement{} - statements := []policyStatement{} - bucketResourceStatement.Effect = "Allow" bucketResourceStatement.Principal.AWS = []string{"*"} bucketResourceStatement.Resources = []string{fmt.Sprintf("%s%s", AWSResourcePrefix, bucketName)} bucketResourceStatement.Actions = readOnlyBucketActions + return bucketResourceStatement +} + +// Obtain object statement for read only BucketPolicy. +func getReadOnlyObjectStatement(bucketName, objectPrefix string) policyStatement { + objectResourceStatement := policyStatement{} objectResourceStatement.Effect = "Allow" objectResourceStatement.Principal.AWS = []string{"*"} objectResourceStatement.Resources = []string{fmt.Sprintf("%s%s", AWSResourcePrefix, bucketName+"/"+objectPrefix+"*")} objectResourceStatement.Actions = readOnlyObjectActions + return objectResourceStatement +} + +// Obtain statements for read only BucketPolicy. +func getReadOnlyStatement(bucketName, objectPrefix string) []policyStatement { + statements := []policyStatement{} // Save the read only policy. - statements = append(statements, bucketResourceStatement, objectResourceStatement) + statements = append(statements, getReadOnlyBucketStatement(bucketName, objectPrefix), getReadOnlyObjectStatement(bucketName, objectPrefix)) return statements } -// Obtain statements for write only BucketPolicy. -func setWriteOnlyStatement(bucketName, objectPrefix string) []policyStatement { +// Obtain bucket statements for write only BucketPolicy. +func getWriteOnlyBucketStatement(bucketName, objectPrefix string) policyStatement { + bucketResourceStatement := policyStatement{} - objectResourceStatement := policyStatement{} - statements := []policyStatement{} - // Write only policy. bucketResourceStatement.Effect = "Allow" bucketResourceStatement.Principal.AWS = []string{"*"} bucketResourceStatement.Resources = []string{fmt.Sprintf("%s%s", AWSResourcePrefix, bucketName)} bucketResourceStatement.Actions = writeOnlyBucketActions + return bucketResourceStatement +} + +// Obtain object statements for write only BucketPolicy. +func getWriteOnlyObjectStatement(bucketName, objectPrefix string) policyStatement { + objectResourceStatement := policyStatement{} objectResourceStatement.Effect = "Allow" objectResourceStatement.Principal.AWS = []string{"*"} objectResourceStatement.Resources = []string{fmt.Sprintf("%s%s", AWSResourcePrefix, bucketName+"/"+objectPrefix+"*")} objectResourceStatement.Actions = writeOnlyObjectActions + return objectResourceStatement +} + +// Obtain statements for write only BucketPolicy. +func getWriteOnlyStatement(bucketName, objectPrefix string) []policyStatement { + statements := []policyStatement{} + // Write only policy. // Save the write only policy. - statements = append(statements, bucketResourceStatement, objectResourceStatement) + statements = append(statements, getWriteOnlyBucketStatement(bucketName, objectPrefix), getWriteOnlyBucketStatement(bucketName, objectPrefix)) return statements } @@ -145,11 +174,13 @@ func TestIsValidActions(t *testing.T) { {[]string{}, errors.New("Action list cannot be empty."), false}, // Test case - 3. // "s3:DeleteEverything"" is an invalid Action. - {[]string{"s3:GetObject", "s3:ListBucket", "s3:PutObject", "s3:DeleteEverything"}, errors.New("Unsupported action found: ‘s3:DeleteEverything’, please validate your policy document."), false}, + {[]string{"s3:GetObject", "s3:ListBucket", "s3:PutObject", "s3:DeleteEverything"}, + errors.New("Unsupported action found: ‘s3:DeleteEverything’, please validate your policy document."), false}, // Inputs with valid Action. // Test Case - 4. - {[]string{"s3:GetObject", "s3:ListBucket", "s3:PutObject", "s3:GetBucketLocation", "s3:DeleteObject", "s3:AbortMultipartUpload", "s3:ListBucketMultipartUploads", "s3:ListMultipartUploadParts"}, nil, true}, + {[]string{"s3:*", "*", "s3:GetObject", "s3:ListBucket", + "s3:PutObject", "s3:GetBucketLocation", "s3:DeleteObject", "s3:AbortMultipartUpload", "s3:ListBucketMultipartUploads", "s3:ListMultipartUploadParts"}, nil, true}, } for i, testCase := range testCases { err := isValidActions(testCase.actions) @@ -464,31 +495,31 @@ func TestCheckBucketPolicyResources(t *testing.T) { bucketAccessPolicies := []BucketPolicy{ // BucketPolicy - 1. // Contains valid read only policy statement. - {Version: "1.0", Statements: setReadOnlyStatement("minio-bucket", "")}, + {Version: "1.0", Statements: getReadOnlyStatement("minio-bucket", "")}, // BucketPolicy - 2. // Contains valid read-write only policy statement. - {Version: "1.0", Statements: setReadWriteStatement("minio-bucket", "Asia/")}, + {Version: "1.0", Statements: getReadWriteStatement("minio-bucket", "Asia/")}, // BucketPolicy - 3. // Contains valid write only policy statement. - {Version: "1.0", Statements: setWriteOnlyStatement("minio-bucket", "Asia/India/")}, + {Version: "1.0", Statements: getWriteOnlyStatement("minio-bucket", "Asia/India/")}, // BucketPolicy - 4. // Contains invalidPrefixActions. // Since resourcePrefix is not to the bucket-name, it return ErrMalformedPolicy. - {Version: "1.0", Statements: setReadOnlyStatement("minio-bucket-fail", "Asia/India/")}, + {Version: "1.0", Statements: getReadOnlyStatement("minio-bucket-fail", "Asia/India/")}, // BucketPolicy - 5. // constructing policy statement without invalidPrefixActions (check bucket-policy-parser.go). // but bucket part of the resource is not equal to the bucket name. // this results in return of ErrMalformedPolicy. - {Version: "1.0", Statements: setValidPrefixActions(setWriteOnlyStatement("minio-bucket-fail", "Asia/India/"))}, + {Version: "1.0", Statements: setValidPrefixActions(getWriteOnlyStatement("minio-bucket-fail", "Asia/India/"))}, // BucketPolicy - 6. // contructing policy statement with recursive resources. // should result in ErrMalformedPolicy - {Version: "1.0", Statements: setRecurseResource(setValidPrefixActions(setWriteOnlyStatement("minio-bucket", "")))}, + {Version: "1.0", Statements: setRecurseResource(setValidPrefixActions(getWriteOnlyStatement("minio-bucket", "")))}, // BucketPolciy - 7. // constructing policy statement with non recursive but // lexically close resources. // should result in ErrNone. - {Version: "1.0", Statements: setResourceLexical(setValidPrefixActions(setWriteOnlyStatement("minio-bucket", "oo")))}, + {Version: "1.0", Statements: setResourceLexical(setValidPrefixActions(getWriteOnlyStatement("minio-bucket", "oo")))}, } testCases := []struct { @@ -575,25 +606,25 @@ func TestParseBucketPolicy(t *testing.T) { {Version: "", Statements: []policyStatement{}}, // BucketPolicy - 2. // Readonly BucketPolicy. - {Version: "1.0", Statements: setReadOnlyStatement("minio-bucket", "")}, + {Version: "1.0", Statements: getReadOnlyStatement("minio-bucket", "")}, // BucketPolicy - 3. // Read-Write bucket policy. - {Version: "1.0", Statements: setReadWriteStatement("minio-bucket", "Asia/")}, + {Version: "1.0", Statements: getReadWriteStatement("minio-bucket", "Asia/")}, // BucketPolicy - 4. // Write only bucket policy. - {Version: "1.0", Statements: setWriteOnlyStatement("minio-bucket", "Asia/India/")}, + {Version: "1.0", Statements: getWriteOnlyStatement("minio-bucket", "Asia/India/")}, // BucketPolicy - 5. // BucketPolicy statement contains unsupported action. - {Version: "1.0", Statements: setUnsupportedActions(setReadOnlyStatement("minio-bucket", ""))}, + {Version: "1.0", Statements: setUnsupportedActions(getReadOnlyStatement("minio-bucket", ""))}, // BucketPolicy - 6. // BucketPolicy statement contains unsupported Effect. - {Version: "1.0", Statements: setUnsupportedEffect(setReadWriteStatement("minio-bucket", "Asia/"))}, + {Version: "1.0", Statements: setUnsupportedEffect(getReadWriteStatement("minio-bucket", "Asia/"))}, // BucketPolicy - 7. // BucketPolicy statement contains unsupported Principal. - {Version: "1.0", Statements: setUnsupportedPrincipals(setWriteOnlyStatement("minio-bucket", "Asia/India/"))}, + {Version: "1.0", Statements: setUnsupportedPrincipals(getWriteOnlyStatement("minio-bucket", "Asia/India/"))}, // BucketPolicy - 8. // BucketPolicy statement contains unsupported Resource. - {Version: "1.0", Statements: setUnsupportedResources(setWriteOnlyStatement("minio-bucket", "Asia/India/"))}, + {Version: "1.0", Statements: setUnsupportedResources(getWriteOnlyStatement("minio-bucket", "Asia/India/"))}, } testCases := []struct {