| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | /* | 
					
						
							|  |  |  |  |  * Minio Cloud Storage, (C) 2015, 2016 Minio, Inc. | 
					
						
							|  |  |  |  |  * | 
					
						
							|  |  |  |  |  * Licensed under the Apache License, Version 2.0 (the "License"); | 
					
						
							|  |  |  |  |  * you may not use this file except in compliance with the License. | 
					
						
							|  |  |  |  |  * You may obtain a copy of the License at | 
					
						
							|  |  |  |  |  * | 
					
						
							|  |  |  |  |  *     http://www.apache.org/licenses/LICENSE-2.0
 | 
					
						
							|  |  |  |  |  * | 
					
						
							|  |  |  |  |  * Unless required by applicable law or agreed to in writing, software | 
					
						
							|  |  |  |  |  * distributed under the License is distributed on an "AS IS" BASIS, | 
					
						
							|  |  |  |  |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
					
						
							|  |  |  |  |  * See the License for the specific language governing permissions and | 
					
						
							|  |  |  |  |  * limitations under the License. | 
					
						
							|  |  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2016-08-19 07:23:42 +08:00
										 |  |  |  | package cmd | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2016-08-11 11:10:48 +08:00
										 |  |  |  | 	"bytes" | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 	"encoding/json" | 
					
						
							|  |  |  |  | 	"errors" | 
					
						
							|  |  |  |  | 	"fmt" | 
					
						
							|  |  |  |  | 	"testing" | 
					
						
							| 
									
										
										
										
											2016-08-20 18:16:38 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-30 11:45:11 +08:00
										 |  |  |  | 	"github.com/minio/minio-go/pkg/policy" | 
					
						
							| 
									
										
										
										
											2016-08-20 18:16:38 +08:00
										 |  |  |  | 	"github.com/minio/minio-go/pkg/set" | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | ) | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-20 18:16:38 +08:00
										 |  |  |  | // Common bucket actions for both read and write policies.
 | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | var ( | 
					
						
							|  |  |  |  | 	readWriteBucketActions = []string{ | 
					
						
							|  |  |  |  | 		"s3:GetBucketLocation", | 
					
						
							|  |  |  |  | 		"s3:ListBucket", | 
					
						
							|  |  |  |  | 		"s3:ListBucketMultipartUploads", | 
					
						
							|  |  |  |  | 		// Add more bucket level read-write actions here.
 | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	readWriteObjectActions = []string{ | 
					
						
							|  |  |  |  | 		"s3:AbortMultipartUpload", | 
					
						
							|  |  |  |  | 		"s3:DeleteObject", | 
					
						
							|  |  |  |  | 		"s3:GetObject", | 
					
						
							|  |  |  |  | 		"s3:ListMultipartUploadParts", | 
					
						
							|  |  |  |  | 		"s3:PutObject", | 
					
						
							|  |  |  |  | 		// Add more object level read-write actions here.
 | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | ) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // Write only actions.
 | 
					
						
							|  |  |  |  | var ( | 
					
						
							|  |  |  |  | 	writeOnlyBucketActions = []string{ | 
					
						
							|  |  |  |  | 		"s3:GetBucketLocation", | 
					
						
							|  |  |  |  | 		"s3:ListBucketMultipartUploads", | 
					
						
							|  |  |  |  | 		// Add more bucket level write actions here.
 | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	writeOnlyObjectActions = []string{ | 
					
						
							|  |  |  |  | 		"s3:AbortMultipartUpload", | 
					
						
							|  |  |  |  | 		"s3:DeleteObject", | 
					
						
							|  |  |  |  | 		"s3:ListMultipartUploadParts", | 
					
						
							|  |  |  |  | 		"s3:PutObject", | 
					
						
							|  |  |  |  | 		// Add more object level write actions here.
 | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | ) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // Read only actions.
 | 
					
						
							|  |  |  |  | var ( | 
					
						
							|  |  |  |  | 	readOnlyBucketActions = []string{ | 
					
						
							|  |  |  |  | 		"s3:GetBucketLocation", | 
					
						
							|  |  |  |  | 		"s3:ListBucket", | 
					
						
							|  |  |  |  | 		// Add more bucket level read actions here.
 | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	readOnlyObjectActions = []string{ | 
					
						
							|  |  |  |  | 		"s3:GetObject", | 
					
						
							|  |  |  |  | 		// Add more object level read actions here.
 | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | ) | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-11 11:10:48 +08:00
										 |  |  |  | // Obtain bucket statement for read-write bucketPolicy.
 | 
					
						
							| 
									
										
										
										
											2016-07-01 14:49:59 +08:00
										 |  |  |  | func getReadWriteObjectStatement(bucketName, objectPrefix string) policyStatement { | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 	objectResourceStatement := policyStatement{} | 
					
						
							| 
									
										
										
										
											2016-07-01 14:49:59 +08:00
										 |  |  |  | 	objectResourceStatement.Effect = "Allow" | 
					
						
							| 
									
										
										
										
											2016-09-20 04:52:28 +08:00
										 |  |  |  | 	objectResourceStatement.Principal = map[string]interface{}{ | 
					
						
							|  |  |  |  | 		"AWS": "*", | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-01-11 08:43:48 +08:00
										 |  |  |  | 	objectResourceStatement.Resources = set.CreateStringSet([]string{fmt.Sprintf("%s%s", bucketARNPrefix, bucketName+"/"+objectPrefix+"*")}...) | 
					
						
							| 
									
										
										
										
											2016-08-20 18:16:38 +08:00
										 |  |  |  | 	objectResourceStatement.Actions = set.CreateStringSet(readWriteObjectActions...) | 
					
						
							| 
									
										
										
										
											2016-07-01 14:49:59 +08:00
										 |  |  |  | 	return objectResourceStatement | 
					
						
							|  |  |  |  | } | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-11 11:10:48 +08:00
										 |  |  |  | // Obtain object statement for read-write bucketPolicy.
 | 
					
						
							| 
									
										
										
										
											2016-07-01 14:49:59 +08:00
										 |  |  |  | func getReadWriteBucketStatement(bucketName, objectPrefix string) policyStatement { | 
					
						
							|  |  |  |  | 	bucketResourceStatement := policyStatement{} | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 	bucketResourceStatement.Effect = "Allow" | 
					
						
							| 
									
										
										
										
											2016-09-20 04:52:28 +08:00
										 |  |  |  | 	bucketResourceStatement.Principal = map[string]interface{}{ | 
					
						
							|  |  |  |  | 		"AWS": "*", | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-01-11 08:43:48 +08:00
										 |  |  |  | 	bucketResourceStatement.Resources = set.CreateStringSet([]string{fmt.Sprintf("%s%s", bucketARNPrefix, bucketName)}...) | 
					
						
							| 
									
										
										
										
											2016-08-20 18:16:38 +08:00
										 |  |  |  | 	bucketResourceStatement.Actions = set.CreateStringSet(readWriteBucketActions...) | 
					
						
							| 
									
										
										
										
											2016-07-01 14:49:59 +08:00
										 |  |  |  | 	return bucketResourceStatement | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-11 11:10:48 +08:00
										 |  |  |  | // Obtain statements for read-write bucketPolicy.
 | 
					
						
							| 
									
										
										
										
											2016-07-01 14:49:59 +08:00
										 |  |  |  | func getReadWriteStatement(bucketName, objectPrefix string) []policyStatement { | 
					
						
							|  |  |  |  | 	statements := []policyStatement{} | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 	// Save the read write policy.
 | 
					
						
							| 
									
										
										
										
											2016-07-01 14:49:59 +08:00
										 |  |  |  | 	statements = append(statements, getReadWriteBucketStatement(bucketName, objectPrefix), getReadWriteObjectStatement(bucketName, objectPrefix)) | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 	return statements | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-11 11:10:48 +08:00
										 |  |  |  | // Obtain bucket statement for read only bucketPolicy.
 | 
					
						
							| 
									
										
										
										
											2016-07-01 14:49:59 +08:00
										 |  |  |  | func getReadOnlyBucketStatement(bucketName, objectPrefix string) policyStatement { | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 	bucketResourceStatement := policyStatement{} | 
					
						
							|  |  |  |  | 	bucketResourceStatement.Effect = "Allow" | 
					
						
							| 
									
										
										
										
											2016-09-20 04:52:28 +08:00
										 |  |  |  | 	bucketResourceStatement.Principal = map[string]interface{}{ | 
					
						
							|  |  |  |  | 		"AWS": "*", | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-01-11 08:43:48 +08:00
										 |  |  |  | 	bucketResourceStatement.Resources = set.CreateStringSet([]string{fmt.Sprintf("%s%s", bucketARNPrefix, bucketName)}...) | 
					
						
							| 
									
										
										
										
											2016-08-20 18:16:38 +08:00
										 |  |  |  | 	bucketResourceStatement.Actions = set.CreateStringSet(readOnlyBucketActions...) | 
					
						
							| 
									
										
										
										
											2016-07-01 14:49:59 +08:00
										 |  |  |  | 	return bucketResourceStatement | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-11 11:10:48 +08:00
										 |  |  |  | // Obtain object statement for read only bucketPolicy.
 | 
					
						
							| 
									
										
										
										
											2016-07-01 14:49:59 +08:00
										 |  |  |  | func getReadOnlyObjectStatement(bucketName, objectPrefix string) policyStatement { | 
					
						
							|  |  |  |  | 	objectResourceStatement := policyStatement{} | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 	objectResourceStatement.Effect = "Allow" | 
					
						
							| 
									
										
										
										
											2016-09-20 04:52:28 +08:00
										 |  |  |  | 	objectResourceStatement.Principal = map[string]interface{}{ | 
					
						
							|  |  |  |  | 		"AWS": "*", | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-01-11 08:43:48 +08:00
										 |  |  |  | 	objectResourceStatement.Resources = set.CreateStringSet([]string{fmt.Sprintf("%s%s", bucketARNPrefix, bucketName+"/"+objectPrefix+"*")}...) | 
					
						
							| 
									
										
										
										
											2016-08-20 18:16:38 +08:00
										 |  |  |  | 	objectResourceStatement.Actions = set.CreateStringSet(readOnlyObjectActions...) | 
					
						
							| 
									
										
										
										
											2016-07-01 14:49:59 +08:00
										 |  |  |  | 	return objectResourceStatement | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-11 11:10:48 +08:00
										 |  |  |  | // Obtain statements for read only bucketPolicy.
 | 
					
						
							| 
									
										
										
										
											2016-07-01 14:49:59 +08:00
										 |  |  |  | func getReadOnlyStatement(bucketName, objectPrefix string) []policyStatement { | 
					
						
							|  |  |  |  | 	statements := []policyStatement{} | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 	// Save the read only policy.
 | 
					
						
							| 
									
										
										
										
											2016-07-01 14:49:59 +08:00
										 |  |  |  | 	statements = append(statements, getReadOnlyBucketStatement(bucketName, objectPrefix), getReadOnlyObjectStatement(bucketName, objectPrefix)) | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 	return statements | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-11 11:10:48 +08:00
										 |  |  |  | // Obtain bucket statements for write only bucketPolicy.
 | 
					
						
							| 
									
										
										
										
											2016-07-01 14:49:59 +08:00
										 |  |  |  | func getWriteOnlyBucketStatement(bucketName, objectPrefix string) policyStatement { | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 	bucketResourceStatement := policyStatement{} | 
					
						
							|  |  |  |  | 	bucketResourceStatement.Effect = "Allow" | 
					
						
							| 
									
										
										
										
											2016-09-20 04:52:28 +08:00
										 |  |  |  | 	bucketResourceStatement.Principal = map[string]interface{}{ | 
					
						
							|  |  |  |  | 		"AWS": "*", | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-01-11 08:43:48 +08:00
										 |  |  |  | 	bucketResourceStatement.Resources = set.CreateStringSet([]string{fmt.Sprintf("%s%s", bucketARNPrefix, bucketName)}...) | 
					
						
							| 
									
										
										
										
											2016-08-20 18:16:38 +08:00
										 |  |  |  | 	bucketResourceStatement.Actions = set.CreateStringSet(writeOnlyBucketActions...) | 
					
						
							| 
									
										
										
										
											2016-07-01 14:49:59 +08:00
										 |  |  |  | 	return bucketResourceStatement | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-11 11:10:48 +08:00
										 |  |  |  | // Obtain object statements for write only bucketPolicy.
 | 
					
						
							| 
									
										
										
										
											2016-07-01 14:49:59 +08:00
										 |  |  |  | func getWriteOnlyObjectStatement(bucketName, objectPrefix string) policyStatement { | 
					
						
							|  |  |  |  | 	objectResourceStatement := policyStatement{} | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 	objectResourceStatement.Effect = "Allow" | 
					
						
							| 
									
										
										
										
											2016-09-20 04:52:28 +08:00
										 |  |  |  | 	objectResourceStatement.Principal = map[string]interface{}{ | 
					
						
							|  |  |  |  | 		"AWS": "*", | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-01-11 08:43:48 +08:00
										 |  |  |  | 	objectResourceStatement.Resources = set.CreateStringSet([]string{fmt.Sprintf("%s%s", bucketARNPrefix, bucketName+"/"+objectPrefix+"*")}...) | 
					
						
							| 
									
										
										
										
											2016-08-20 18:16:38 +08:00
										 |  |  |  | 	objectResourceStatement.Actions = set.CreateStringSet(writeOnlyObjectActions...) | 
					
						
							| 
									
										
										
										
											2016-07-01 14:49:59 +08:00
										 |  |  |  | 	return objectResourceStatement | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-11 11:10:48 +08:00
										 |  |  |  | // Obtain statements for write only bucketPolicy.
 | 
					
						
							| 
									
										
										
										
											2016-07-01 14:49:59 +08:00
										 |  |  |  | func getWriteOnlyStatement(bucketName, objectPrefix string) []policyStatement { | 
					
						
							|  |  |  |  | 	statements := []policyStatement{} | 
					
						
							|  |  |  |  | 	// Write only policy.
 | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 	// Save the write only policy.
 | 
					
						
							| 
									
										
										
										
											2016-07-01 14:49:59 +08:00
										 |  |  |  | 	statements = append(statements, getWriteOnlyBucketStatement(bucketName, objectPrefix), getWriteOnlyBucketStatement(bucketName, objectPrefix)) | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 	return statements | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // Tests validate Action validator.
 | 
					
						
							|  |  |  |  | func TestIsValidActions(t *testing.T) { | 
					
						
							|  |  |  |  | 	testCases := []struct { | 
					
						
							|  |  |  |  | 		// input.
 | 
					
						
							| 
									
										
										
										
											2016-08-20 18:16:38 +08:00
										 |  |  |  | 		actions set.StringSet | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 		// expected output.
 | 
					
						
							|  |  |  |  | 		err error | 
					
						
							|  |  |  |  | 		// flag indicating whether the test should pass.
 | 
					
						
							|  |  |  |  | 		shouldPass bool | 
					
						
							|  |  |  |  | 	}{ | 
					
						
							|  |  |  |  | 		// Inputs with unsupported Action.
 | 
					
						
							|  |  |  |  | 		// Test case - 1.
 | 
					
						
							|  |  |  |  | 		// "s3:ListObject" is an invalid Action.
 | 
					
						
							| 
									
										
										
										
											2016-08-20 18:16:38 +08:00
										 |  |  |  | 		{set.CreateStringSet([]string{"s3:GetObject", "s3:ListObject", "s3:RemoveObject"}...), | 
					
						
							| 
									
										
										
										
											2016-11-16 10:14:23 +08:00
										 |  |  |  | 			errors.New("Unsupported actions found: ‘set.StringSet{\"s3:RemoveObject\":struct {}{}, \"s3:ListObject\":struct {}{}}’, please validate your policy document"), false}, | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 		// Test case - 2.
 | 
					
						
							|  |  |  |  | 		// Empty Actions.
 | 
					
						
							| 
									
										
										
										
											2016-11-16 10:14:23 +08:00
										 |  |  |  | 		{set.CreateStringSet([]string{}...), errors.New("Action list cannot be empty"), false}, | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 		// Test case - 3.
 | 
					
						
							|  |  |  |  | 		// "s3:DeleteEverything"" is an invalid Action.
 | 
					
						
							| 
									
										
										
										
											2016-08-20 18:16:38 +08:00
										 |  |  |  | 		{set.CreateStringSet([]string{"s3:GetObject", "s3:ListBucket", "s3:PutObject", "s3:DeleteEverything"}...), | 
					
						
							| 
									
										
										
										
											2016-11-16 10:14:23 +08:00
										 |  |  |  | 			errors.New("Unsupported actions found: ‘set.StringSet{\"s3:DeleteEverything\":struct {}{}}’, please validate your policy document"), false}, | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 		// Inputs with valid Action.
 | 
					
						
							|  |  |  |  | 		// Test Case - 4.
 | 
					
						
							| 
									
										
										
										
											2016-08-20 18:16:38 +08:00
										 |  |  |  | 		{set.CreateStringSet([]string{ | 
					
						
							|  |  |  |  | 			"s3:*", "*", "s3:GetObject", "s3:ListBucket", | 
					
						
							|  |  |  |  | 			"s3:PutObject", "s3:GetBucketLocation", "s3:DeleteObject", | 
					
						
							|  |  |  |  | 			"s3:AbortMultipartUpload", "s3:ListBucketMultipartUploads", | 
					
						
							|  |  |  |  | 			"s3:ListMultipartUploadParts"}...), nil, true}, | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 	for i, testCase := range testCases { | 
					
						
							|  |  |  |  | 		err := isValidActions(testCase.actions) | 
					
						
							|  |  |  |  | 		if err != nil && testCase.shouldPass { | 
					
						
							|  |  |  |  | 			t.Errorf("Test %d: Expected to pass, but failed with: <ERROR> %s", i+1, err.Error()) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		if err == nil && !testCase.shouldPass { | 
					
						
							|  |  |  |  | 			t.Errorf("Test %d: Expected to fail with <ERROR> \"%s\", but passed instead", i+1, testCase.err.Error()) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // Tests validate Effect validator.
 | 
					
						
							|  |  |  |  | func TestIsValidEffect(t *testing.T) { | 
					
						
							|  |  |  |  | 	testCases := []struct { | 
					
						
							|  |  |  |  | 		// input.
 | 
					
						
							|  |  |  |  | 		effect string | 
					
						
							|  |  |  |  | 		// expected output.
 | 
					
						
							|  |  |  |  | 		err error | 
					
						
							|  |  |  |  | 		// flag indicating whether the test should pass.
 | 
					
						
							|  |  |  |  | 		shouldPass bool | 
					
						
							|  |  |  |  | 	}{ | 
					
						
							|  |  |  |  | 		// Inputs with unsupported Effect.
 | 
					
						
							|  |  |  |  | 		// Test case - 1.
 | 
					
						
							| 
									
										
										
										
											2016-11-16 10:14:23 +08:00
										 |  |  |  | 		{"", errors.New("Policy effect cannot be empty"), false}, | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 		// Test case - 2.
 | 
					
						
							| 
									
										
										
										
											2016-11-16 10:14:23 +08:00
										 |  |  |  | 		{"DontAllow", errors.New("Unsupported Effect found: ‘DontAllow’, please validate your policy document"), false}, | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 		// Test case - 3.
 | 
					
						
							| 
									
										
										
										
											2016-11-16 10:14:23 +08:00
										 |  |  |  | 		{"NeverAllow", errors.New("Unsupported Effect found: ‘NeverAllow’, please validate your policy document"), false}, | 
					
						
							| 
									
										
										
										
											2016-08-20 18:16:38 +08:00
										 |  |  |  | 		// Test case - 4.
 | 
					
						
							| 
									
										
										
										
											2016-11-16 10:14:23 +08:00
										 |  |  |  | 		{"AllowAlways", errors.New("Unsupported Effect found: ‘AllowAlways’, please validate your policy document"), false}, | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 		// Inputs with valid Effect.
 | 
					
						
							|  |  |  |  | 		// Test Case - 5.
 | 
					
						
							| 
									
										
										
										
											2016-08-20 18:16:38 +08:00
										 |  |  |  | 		{"Allow", nil, true}, | 
					
						
							|  |  |  |  | 		// Test Case - 6.
 | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 		{"Deny", nil, true}, | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	for i, testCase := range testCases { | 
					
						
							|  |  |  |  | 		err := isValidEffect(testCase.effect) | 
					
						
							|  |  |  |  | 		if err != nil && testCase.shouldPass { | 
					
						
							|  |  |  |  | 			t.Errorf("Test %d: Expected to pass, but failed with: <ERROR> %s", i+1, err.Error()) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		if err == nil && !testCase.shouldPass { | 
					
						
							|  |  |  |  | 			t.Errorf("Test %d: Expected to fail with <ERROR> \"%s\", but passed instead", i+1, testCase.err.Error()) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		// Failed as expected, but does it fail for the expected reason.
 | 
					
						
							|  |  |  |  | 		if err != nil && !testCase.shouldPass { | 
					
						
							|  |  |  |  | 			if err.Error() != testCase.err.Error() { | 
					
						
							|  |  |  |  | 				t.Errorf("Test %d: Expected to fail with error \"%s\", but instead failed with error \"%s\"", i+1, testCase.err.Error(), err.Error()) | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // Tests validate Resources validator.
 | 
					
						
							|  |  |  |  | func TestIsValidResources(t *testing.T) { | 
					
						
							|  |  |  |  | 	testCases := []struct { | 
					
						
							|  |  |  |  | 		// input.
 | 
					
						
							|  |  |  |  | 		resources []string | 
					
						
							|  |  |  |  | 		// expected output.
 | 
					
						
							|  |  |  |  | 		err error | 
					
						
							|  |  |  |  | 		// flag indicating whether the test should pass.
 | 
					
						
							|  |  |  |  | 		shouldPass bool | 
					
						
							|  |  |  |  | 	}{ | 
					
						
							|  |  |  |  | 		// Inputs with unsupported Action.
 | 
					
						
							|  |  |  |  | 		// Test case - 1.
 | 
					
						
							|  |  |  |  | 		// Empty Resources.
 | 
					
						
							| 
									
										
										
										
											2016-11-16 10:14:23 +08:00
										 |  |  |  | 		{[]string{}, errors.New("Resource list cannot be empty"), false}, | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 		// Test case - 2.
 | 
					
						
							| 
									
										
										
										
											2017-01-11 08:43:48 +08:00
										 |  |  |  | 		// A valid resource should have prefix bucketARNPrefix.
 | 
					
						
							| 
									
										
										
										
											2016-11-16 10:14:23 +08:00
										 |  |  |  | 		{[]string{"my-resource"}, errors.New("Unsupported resource style found: ‘my-resource’, please validate your policy document"), false}, | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 		// Test case - 3.
 | 
					
						
							| 
									
										
										
										
											2017-01-11 08:43:48 +08:00
										 |  |  |  | 		// A Valid resource should have bucket name followed by bucketARNPrefix.
 | 
					
						
							|  |  |  |  | 		{[]string{bucketARNPrefix}, errors.New("Invalid resource style found: ‘arn:aws:s3:::’, please validate your policy document"), false}, | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 		// Test Case - 4.
 | 
					
						
							| 
									
										
										
										
											2017-01-11 08:43:48 +08:00
										 |  |  |  | 		// Valid resource shouldn't have slash('/') followed by bucketARNPrefix.
 | 
					
						
							|  |  |  |  | 		{[]string{bucketARNPrefix + "/"}, errors.New("Invalid resource style found: ‘arn:aws:s3:::/’, please validate your policy document"), false}, | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 		// Test cases with valid Resources.
 | 
					
						
							| 
									
										
										
										
											2017-01-11 08:43:48 +08:00
										 |  |  |  | 		{[]string{bucketARNPrefix + "my-bucket"}, nil, true}, | 
					
						
							|  |  |  |  | 		{[]string{bucketARNPrefix + "my-bucket/Asia/*"}, nil, true}, | 
					
						
							|  |  |  |  | 		{[]string{bucketARNPrefix + "my-bucket/Asia/India/*"}, nil, true}, | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 	for i, testCase := range testCases { | 
					
						
							| 
									
										
										
										
											2016-08-20 18:16:38 +08:00
										 |  |  |  | 		err := isValidResources(set.CreateStringSet(testCase.resources...)) | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 		if err != nil && testCase.shouldPass { | 
					
						
							|  |  |  |  | 			t.Errorf("Test %d: Expected to pass, but failed with: <ERROR> %s", i+1, err.Error()) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		if err == nil && !testCase.shouldPass { | 
					
						
							|  |  |  |  | 			t.Errorf("Test %d: Expected to fail with <ERROR> \"%s\", but passed instead", i+1, testCase.err.Error()) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		// Failed as expected, but does it fail for the expected reason.
 | 
					
						
							|  |  |  |  | 		if err != nil && !testCase.shouldPass { | 
					
						
							|  |  |  |  | 			if err.Error() != testCase.err.Error() { | 
					
						
							|  |  |  |  | 				t.Errorf("Test %d: Expected to fail with error \"%s\", but instead failed with error \"%s\"", i+1, testCase.err.Error(), err.Error()) | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // Tests validate principals validator.
 | 
					
						
							|  |  |  |  | func TestIsValidPrincipals(t *testing.T) { | 
					
						
							|  |  |  |  | 	testCases := []struct { | 
					
						
							|  |  |  |  | 		// input.
 | 
					
						
							|  |  |  |  | 		principals []string | 
					
						
							|  |  |  |  | 		// expected output.
 | 
					
						
							|  |  |  |  | 		err error | 
					
						
							|  |  |  |  | 		// flag indicating whether the test should pass.
 | 
					
						
							|  |  |  |  | 		shouldPass bool | 
					
						
							|  |  |  |  | 	}{ | 
					
						
							|  |  |  |  | 		// Inputs with unsupported Principals.
 | 
					
						
							|  |  |  |  | 		// Test case - 1.
 | 
					
						
							|  |  |  |  | 		// Empty Principals list.
 | 
					
						
							| 
									
										
										
										
											2016-11-16 10:14:23 +08:00
										 |  |  |  | 		{[]string{}, errors.New("Principal cannot be empty"), false}, | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 		// Test case - 2.
 | 
					
						
							|  |  |  |  | 		// "*" is the only valid principal.
 | 
					
						
							| 
									
										
										
										
											2016-11-16 10:14:23 +08:00
										 |  |  |  | 		{[]string{"my-principal"}, errors.New("Unsupported principals found: ‘set.StringSet{\"my-principal\":struct {}{}}’, please validate your policy document"), false}, | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 		// Test case - 3.
 | 
					
						
							| 
									
										
										
										
											2016-11-16 10:14:23 +08:00
										 |  |  |  | 		{[]string{"*", "111122233"}, errors.New("Unsupported principals found: ‘set.StringSet{\"111122233\":struct {}{}}’, please validate your policy document"), false}, | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 		// Test case - 4.
 | 
					
						
							|  |  |  |  | 		// Test case with valid principal value.
 | 
					
						
							|  |  |  |  | 		{[]string{"*"}, nil, true}, | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	for i, testCase := range testCases { | 
					
						
							| 
									
										
										
										
											2016-09-20 04:52:28 +08:00
										 |  |  |  | 		err := isValidPrincipals(map[string]interface{}{ | 
					
						
							|  |  |  |  | 			"AWS": testCase.principals, | 
					
						
							|  |  |  |  | 		}) | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 		if err != nil && testCase.shouldPass { | 
					
						
							|  |  |  |  | 			t.Errorf("Test %d: Expected to pass, but failed with: <ERROR> %s", i+1, err.Error()) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		if err == nil && !testCase.shouldPass { | 
					
						
							|  |  |  |  | 			t.Errorf("Test %d: Expected to fail with <ERROR> \"%s\", but passed instead", i+1, testCase.err.Error()) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		// Failed as expected, but does it fail for the expected reason.
 | 
					
						
							|  |  |  |  | 		if err != nil && !testCase.shouldPass { | 
					
						
							|  |  |  |  | 			if err.Error() != testCase.err.Error() { | 
					
						
							|  |  |  |  | 				t.Errorf("Test %d: Expected to fail with error \"%s\", but instead failed with error \"%s\"", i+1, testCase.err.Error(), err.Error()) | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-30 11:45:11 +08:00
										 |  |  |  | // getEmptyConditionKeyMap - returns a function that generates a
 | 
					
						
							|  |  |  |  | // condition key map for a given key.
 | 
					
						
							|  |  |  |  | func getEmptyConditionKeyMap(conditionKey string) func() map[string]map[string]set.StringSet { | 
					
						
							|  |  |  |  | 	emptyConditonGenerator := func() map[string]map[string]set.StringSet { | 
					
						
							|  |  |  |  | 		emptyMap := make(map[string]set.StringSet) | 
					
						
							|  |  |  |  | 		conditions := make(map[string]map[string]set.StringSet) | 
					
						
							|  |  |  |  | 		conditions[conditionKey] = emptyMap | 
					
						
							|  |  |  |  | 		return conditions | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return emptyConditonGenerator | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | // Tests validate policyStatement condition validator.
 | 
					
						
							|  |  |  |  | func TestIsValidConditions(t *testing.T) { | 
					
						
							|  |  |  |  | 	// returns empty conditions map.
 | 
					
						
							| 
									
										
										
										
											2016-08-20 18:16:38 +08:00
										 |  |  |  | 	setEmptyConditions := func() map[string]map[string]set.StringSet { | 
					
						
							|  |  |  |  | 		return make(map[string]map[string]set.StringSet) | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// returns map with the "StringEquals" set to empty map.
 | 
					
						
							| 
									
										
										
										
											2017-01-30 11:45:11 +08:00
										 |  |  |  | 	setEmptyStringEquals := getEmptyConditionKeyMap("StringEquals") | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// returns map with the "StringNotEquals" set to empty map.
 | 
					
						
							| 
									
										
										
										
											2017-01-30 11:45:11 +08:00
										 |  |  |  | 	setEmptyStringNotEquals := getEmptyConditionKeyMap("StringNotEquals") | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// returns map with the "StringLike" set to empty map.
 | 
					
						
							|  |  |  |  | 	setEmptyStringLike := getEmptyConditionKeyMap("StringLike") | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// returns map with the "StringNotLike" set to empty map.
 | 
					
						
							|  |  |  |  | 	setEmptyStringNotLike := getEmptyConditionKeyMap("StringNotLike") | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// Generate conditions.
 | 
					
						
							| 
									
										
										
										
											2016-08-20 18:16:38 +08:00
										 |  |  |  | 	generateConditions := func(key1, key2, value string) map[string]map[string]set.StringSet { | 
					
						
							|  |  |  |  | 		innerMap := make(map[string]set.StringSet) | 
					
						
							|  |  |  |  | 		innerMap[key2] = set.CreateStringSet(value) | 
					
						
							|  |  |  |  | 		conditions := make(map[string]map[string]set.StringSet) | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 		conditions[key1] = innerMap | 
					
						
							|  |  |  |  | 		return conditions | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// generate ambigious conditions.
 | 
					
						
							| 
									
										
										
										
											2016-08-20 18:16:38 +08:00
										 |  |  |  | 	generateAmbigiousConditions := func() map[string]map[string]set.StringSet { | 
					
						
							| 
									
										
										
										
											2017-01-30 11:45:11 +08:00
										 |  |  |  | 		prefixMap := make(map[string]set.StringSet) | 
					
						
							|  |  |  |  | 		prefixMap["s3:prefix"] = set.CreateStringSet("Asia/") | 
					
						
							| 
									
										
										
										
											2016-08-20 18:16:38 +08:00
										 |  |  |  | 		conditions := make(map[string]map[string]set.StringSet) | 
					
						
							| 
									
										
										
										
											2017-01-30 11:45:11 +08:00
										 |  |  |  | 		conditions["StringEquals"] = prefixMap | 
					
						
							|  |  |  |  | 		conditions["StringNotEquals"] = prefixMap | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 		return conditions | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// generate valid and non valid type in the condition map.
 | 
					
						
							| 
									
										
										
										
											2016-08-20 18:16:38 +08:00
										 |  |  |  | 	generateValidInvalidConditions := func() map[string]map[string]set.StringSet { | 
					
						
							|  |  |  |  | 		innerMap := make(map[string]set.StringSet) | 
					
						
							|  |  |  |  | 		innerMap["s3:prefix"] = set.CreateStringSet("Asia/") | 
					
						
							|  |  |  |  | 		conditions := make(map[string]map[string]set.StringSet) | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 		conditions["StringEquals"] = innerMap | 
					
						
							|  |  |  |  | 		conditions["InvalidType"] = innerMap | 
					
						
							|  |  |  |  | 		return conditions | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// generate valid and invalid keys for valid types in the same condition map.
 | 
					
						
							| 
									
										
										
										
											2016-08-20 18:16:38 +08:00
										 |  |  |  | 	generateValidInvalidConditionKeys := func() map[string]map[string]set.StringSet { | 
					
						
							|  |  |  |  | 		innerMapValid := make(map[string]set.StringSet) | 
					
						
							|  |  |  |  | 		innerMapValid["s3:prefix"] = set.CreateStringSet("Asia/") | 
					
						
							|  |  |  |  | 		innerMapInValid := make(map[string]set.StringSet) | 
					
						
							|  |  |  |  | 		innerMapInValid["s3:invalid"] = set.CreateStringSet("Asia/") | 
					
						
							|  |  |  |  | 		conditions := make(map[string]map[string]set.StringSet) | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 		conditions["StringEquals"] = innerMapValid | 
					
						
							|  |  |  |  | 		conditions["StringEquals"] = innerMapInValid | 
					
						
							|  |  |  |  | 		return conditions | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// List of Conditions used for test cases.
 | 
					
						
							| 
									
										
										
										
											2016-08-20 18:16:38 +08:00
										 |  |  |  | 	testConditions := []map[string]map[string]set.StringSet{ | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 		generateConditions("StringValues", "s3:max-keys", "100"), | 
					
						
							|  |  |  |  | 		generateConditions("StringEquals", "s3:Object", "100"), | 
					
						
							|  |  |  |  | 		generateAmbigiousConditions(), | 
					
						
							|  |  |  |  | 		generateValidInvalidConditions(), | 
					
						
							|  |  |  |  | 		generateValidInvalidConditionKeys(), | 
					
						
							|  |  |  |  | 		setEmptyConditions(), | 
					
						
							|  |  |  |  | 		setEmptyStringEquals(), | 
					
						
							|  |  |  |  | 		setEmptyStringNotEquals(), | 
					
						
							| 
									
										
										
										
											2017-01-30 11:45:11 +08:00
										 |  |  |  | 		setEmptyStringLike(), | 
					
						
							|  |  |  |  | 		setEmptyStringNotLike(), | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 		generateConditions("StringEquals", "s3:prefix", "Asia/"), | 
					
						
							|  |  |  |  | 		generateConditions("StringEquals", "s3:max-keys", "100"), | 
					
						
							|  |  |  |  | 		generateConditions("StringNotEquals", "s3:prefix", "Asia/"), | 
					
						
							|  |  |  |  | 		generateConditions("StringNotEquals", "s3:max-keys", "100"), | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-31 01:20:16 +08:00
										 |  |  |  | 	getObjectActionSet := set.CreateStringSet("s3:GetObject") | 
					
						
							|  |  |  |  | 	roBucketActionSet := set.CreateStringSet(readOnlyBucketActions...) | 
					
						
							|  |  |  |  | 	maxKeysConditionErr := fmt.Errorf("Unsupported condition key %s for the given actions %s, "+ | 
					
						
							|  |  |  |  | 		"please validate your policy document", "s3:max-keys", getObjectActionSet) | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 	testCases := []struct { | 
					
						
							| 
									
										
										
										
											2017-01-31 01:20:16 +08:00
										 |  |  |  | 		inputActions   set.StringSet | 
					
						
							| 
									
										
										
										
											2016-08-20 18:16:38 +08:00
										 |  |  |  | 		inputCondition map[string]map[string]set.StringSet | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 		// expected result.
 | 
					
						
							|  |  |  |  | 		expectedErr error | 
					
						
							|  |  |  |  | 		// flag indicating whether test should pass.
 | 
					
						
							|  |  |  |  | 		shouldPass bool | 
					
						
							|  |  |  |  | 	}{ | 
					
						
							|  |  |  |  | 		// Malformed conditions.
 | 
					
						
							|  |  |  |  | 		// Test case - 1.
 | 
					
						
							|  |  |  |  | 		// "StringValues" is an invalid type.
 | 
					
						
							| 
									
										
										
										
											2017-01-31 01:20:16 +08:00
										 |  |  |  | 		{roBucketActionSet, testConditions[0], fmt.Errorf("Unsupported condition type 'StringValues', " + | 
					
						
							| 
									
										
										
										
											2016-11-16 10:14:23 +08:00
										 |  |  |  | 			"please validate your policy document"), false}, | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 		// Test case - 2.
 | 
					
						
							|  |  |  |  | 		// "s3:Object" is an invalid key.
 | 
					
						
							| 
									
										
										
										
											2017-01-31 01:20:16 +08:00
										 |  |  |  | 		{roBucketActionSet, testConditions[1], fmt.Errorf("Unsupported condition key " + | 
					
						
							| 
									
										
										
										
											2016-11-16 10:14:23 +08:00
										 |  |  |  | 			"'StringEquals', please validate your policy document"), false}, | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 		// Test case - 3.
 | 
					
						
							|  |  |  |  | 		// Test case with Ambigious conditions set.
 | 
					
						
							| 
									
										
										
										
											2017-01-31 01:20:16 +08:00
										 |  |  |  | 		{roBucketActionSet, testConditions[2], fmt.Errorf("Ambigious condition values for key 's3:prefix', " + | 
					
						
							| 
									
										
										
										
											2016-11-16 10:14:23 +08:00
										 |  |  |  | 			"please validate your policy document"), false}, | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 		// Test case - 4.
 | 
					
						
							|  |  |  |  | 		// Test case with valid and invalid condition types.
 | 
					
						
							| 
									
										
										
										
											2017-01-31 01:20:16 +08:00
										 |  |  |  | 		{roBucketActionSet, testConditions[3], fmt.Errorf("Unsupported condition type 'InvalidType', " + | 
					
						
							| 
									
										
										
										
											2016-11-16 10:14:23 +08:00
										 |  |  |  | 			"please validate your policy document"), false}, | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 		// Test case - 5.
 | 
					
						
							|  |  |  |  | 		// Test case with valid and invalid condition keys.
 | 
					
						
							| 
									
										
										
										
											2017-01-31 01:20:16 +08:00
										 |  |  |  | 		{roBucketActionSet, testConditions[4], fmt.Errorf("Unsupported condition key 'StringEquals', " + | 
					
						
							| 
									
										
										
										
											2016-11-16 10:14:23 +08:00
										 |  |  |  | 			"please validate your policy document"), false}, | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 		// Test cases with valid conditions.
 | 
					
						
							|  |  |  |  | 		// Test case - 6.
 | 
					
						
							| 
									
										
										
										
											2017-01-31 01:20:16 +08:00
										 |  |  |  | 		{roBucketActionSet, testConditions[5], nil, true}, | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 		// Test case - 7.
 | 
					
						
							| 
									
										
										
										
											2017-01-31 01:20:16 +08:00
										 |  |  |  | 		{roBucketActionSet, testConditions[6], nil, true}, | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 		// Test case - 8.
 | 
					
						
							| 
									
										
										
										
											2017-01-31 01:20:16 +08:00
										 |  |  |  | 		{roBucketActionSet, testConditions[7], nil, true}, | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 		// Test case - 9.
 | 
					
						
							| 
									
										
										
										
											2017-01-31 01:20:16 +08:00
										 |  |  |  | 		{roBucketActionSet, testConditions[8], nil, true}, | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 		// Test case - 10.
 | 
					
						
							| 
									
										
										
										
											2017-01-31 01:20:16 +08:00
										 |  |  |  | 		{roBucketActionSet, testConditions[9], nil, true}, | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 		// Test case - 11.
 | 
					
						
							| 
									
										
										
										
											2017-01-31 01:20:16 +08:00
										 |  |  |  | 		{roBucketActionSet, testConditions[10], nil, true}, | 
					
						
							| 
									
										
										
										
											2017-01-30 11:45:11 +08:00
										 |  |  |  | 		// Test case - 12.
 | 
					
						
							| 
									
										
										
										
											2017-01-31 01:20:16 +08:00
										 |  |  |  | 		{roBucketActionSet, testConditions[11], nil, true}, | 
					
						
							| 
									
										
										
										
											2017-01-30 11:45:11 +08:00
										 |  |  |  | 		// Test case - 13.
 | 
					
						
							| 
									
										
										
										
											2017-01-31 01:20:16 +08:00
										 |  |  |  | 		{getObjectActionSet, testConditions[11], maxKeysConditionErr, false}, | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 	for i, testCase := range testCases { | 
					
						
							| 
									
										
										
										
											2017-01-31 01:20:16 +08:00
										 |  |  |  | 		actualErr := isValidConditions(testCase.inputActions, testCase.inputCondition) | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 		if actualErr != nil && testCase.shouldPass { | 
					
						
							|  |  |  |  | 			t.Errorf("Test %d: Expected to pass, but failed with: <ERROR> %s", i+1, actualErr.Error()) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		if actualErr == nil && !testCase.shouldPass { | 
					
						
							|  |  |  |  | 			t.Errorf("Test %d: Expected to fail with <ERROR> \"%s\", but passed instead", i+1, testCase.expectedErr.Error()) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		// Failed as expected, but does it fail for the expected reason.
 | 
					
						
							|  |  |  |  | 		if actualErr != nil && !testCase.shouldPass { | 
					
						
							|  |  |  |  | 			if actualErr.Error() != testCase.expectedErr.Error() { | 
					
						
							|  |  |  |  | 				t.Errorf("Test %d: Expected to fail with error \"%s\", but instead failed with error \"%s\"", i+1, testCase.expectedErr.Error(), actualErr.Error()) | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // Tests validate Policy Action and Resource fields.
 | 
					
						
							| 
									
										
										
										
											2016-08-11 11:10:48 +08:00
										 |  |  |  | func TestCheckbucketPolicyResources(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 	// constructing policy statement without invalidPrefixActions (check bucket-policy-parser.go).
 | 
					
						
							|  |  |  |  | 	setValidPrefixActions := func(statements []policyStatement) []policyStatement { | 
					
						
							| 
									
										
										
										
											2016-08-20 18:16:38 +08:00
										 |  |  |  | 		statements[0].Actions = set.CreateStringSet([]string{"s3:DeleteObject", "s3:PutObject"}...) | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 		return statements | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-08-15 17:44:48 +08:00
										 |  |  |  | 	// contracting policy statement with recursive resources.
 | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 	// should result in ErrMalformedPolicy
 | 
					
						
							|  |  |  |  | 	setRecurseResource := func(statements []policyStatement) []policyStatement { | 
					
						
							| 
									
										
										
										
											2016-08-20 18:16:38 +08:00
										 |  |  |  | 		statements[0].Resources = set.CreateStringSet([]string{"arn:aws:s3:::minio-bucket/Asia/*", "arn:aws:s3:::minio-bucket/Asia/India/*"}...) | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 		return statements | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-06 10:58:48 +08:00
										 |  |  |  | 	// constructing policy statement with lexically close characters.
 | 
					
						
							|  |  |  |  | 	// should not result in ErrMalformedPolicy
 | 
					
						
							|  |  |  |  | 	setResourceLexical := func(statements []policyStatement) []policyStatement { | 
					
						
							| 
									
										
										
										
											2016-08-20 18:16:38 +08:00
										 |  |  |  | 		statements[0].Resources = set.CreateStringSet([]string{"arn:aws:s3:::minio-bucket/op*", "arn:aws:s3:::minio-bucket/oo*"}...) | 
					
						
							| 
									
										
										
										
											2016-05-06 10:58:48 +08:00
										 |  |  |  | 		return statements | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-11 11:10:48 +08:00
										 |  |  |  | 	// List of bucketPolicy used for tests.
 | 
					
						
							|  |  |  |  | 	bucketAccessPolicies := []bucketPolicy{ | 
					
						
							|  |  |  |  | 		// bucketPolicy - 1.
 | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 		// Contains valid read only policy statement.
 | 
					
						
							| 
									
										
										
										
											2016-07-01 14:49:59 +08:00
										 |  |  |  | 		{Version: "1.0", Statements: getReadOnlyStatement("minio-bucket", "")}, | 
					
						
							| 
									
										
										
										
											2016-08-11 11:10:48 +08:00
										 |  |  |  | 		// bucketPolicy - 2.
 | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 		// Contains valid read-write only policy statement.
 | 
					
						
							| 
									
										
										
										
											2016-07-01 14:49:59 +08:00
										 |  |  |  | 		{Version: "1.0", Statements: getReadWriteStatement("minio-bucket", "Asia/")}, | 
					
						
							| 
									
										
										
										
											2016-08-11 11:10:48 +08:00
										 |  |  |  | 		// bucketPolicy - 3.
 | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 		// Contains valid write only policy statement.
 | 
					
						
							| 
									
										
										
										
											2016-07-01 14:49:59 +08:00
										 |  |  |  | 		{Version: "1.0", Statements: getWriteOnlyStatement("minio-bucket", "Asia/India/")}, | 
					
						
							| 
									
										
										
										
											2016-08-11 11:10:48 +08:00
										 |  |  |  | 		// bucketPolicy - 4.
 | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 		// Contains invalidPrefixActions.
 | 
					
						
							|  |  |  |  | 		// Since resourcePrefix is not to the bucket-name, it return ErrMalformedPolicy.
 | 
					
						
							| 
									
										
										
										
											2016-07-01 14:49:59 +08:00
										 |  |  |  | 		{Version: "1.0", Statements: getReadOnlyStatement("minio-bucket-fail", "Asia/India/")}, | 
					
						
							| 
									
										
										
										
											2016-08-11 11:10:48 +08:00
										 |  |  |  | 		// bucketPolicy - 5.
 | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 		// 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.
 | 
					
						
							| 
									
										
										
										
											2016-07-01 14:49:59 +08:00
										 |  |  |  | 		{Version: "1.0", Statements: setValidPrefixActions(getWriteOnlyStatement("minio-bucket-fail", "Asia/India/"))}, | 
					
						
							| 
									
										
										
										
											2016-08-11 11:10:48 +08:00
										 |  |  |  | 		// bucketPolicy - 6.
 | 
					
						
							| 
									
										
										
										
											2016-08-15 17:44:48 +08:00
										 |  |  |  | 		// contracting policy statement with recursive resources.
 | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 		// should result in ErrMalformedPolicy
 | 
					
						
							| 
									
										
										
										
											2016-07-01 14:49:59 +08:00
										 |  |  |  | 		{Version: "1.0", Statements: setRecurseResource(setValidPrefixActions(getWriteOnlyStatement("minio-bucket", "")))}, | 
					
						
							| 
									
										
										
										
											2016-05-06 10:58:48 +08:00
										 |  |  |  | 		// BucketPolciy - 7.
 | 
					
						
							| 
									
										
										
										
											2016-05-07 03:32:44 +08:00
										 |  |  |  | 		// constructing policy statement with non recursive but
 | 
					
						
							| 
									
										
										
										
											2016-05-06 10:58:48 +08:00
										 |  |  |  | 		// lexically close resources.
 | 
					
						
							|  |  |  |  | 		// should result in ErrNone.
 | 
					
						
							| 
									
										
										
										
											2016-07-01 14:49:59 +08:00
										 |  |  |  | 		{Version: "1.0", Statements: setResourceLexical(setValidPrefixActions(getWriteOnlyStatement("minio-bucket", "oo")))}, | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	testCases := []struct { | 
					
						
							| 
									
										
										
										
											2016-08-11 11:10:48 +08:00
										 |  |  |  | 		inputPolicy bucketPolicy | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 		// expected results.
 | 
					
						
							|  |  |  |  | 		apiErrCode APIErrorCode | 
					
						
							|  |  |  |  | 		// Flag indicating whether the test should pass.
 | 
					
						
							|  |  |  |  | 		shouldPass bool | 
					
						
							|  |  |  |  | 	}{ | 
					
						
							|  |  |  |  | 		// Test case - 1.
 | 
					
						
							|  |  |  |  | 		{bucketAccessPolicies[0], ErrNone, true}, | 
					
						
							|  |  |  |  | 		// Test case - 2.
 | 
					
						
							|  |  |  |  | 		{bucketAccessPolicies[1], ErrNone, true}, | 
					
						
							|  |  |  |  | 		// Test case - 3.
 | 
					
						
							|  |  |  |  | 		{bucketAccessPolicies[2], ErrNone, true}, | 
					
						
							|  |  |  |  | 		// Test case - 4.
 | 
					
						
							|  |  |  |  | 		// contains invalidPrefixActions (check bucket-policy-parser.go).
 | 
					
						
							|  |  |  |  | 		// Resource prefix will not be equal to the bucket name in this case.
 | 
					
						
							|  |  |  |  | 		{bucketAccessPolicies[3], ErrMalformedPolicy, false}, | 
					
						
							|  |  |  |  | 		// Test case - 5.
 | 
					
						
							|  |  |  |  | 		// actions contain invalidPrefixActions (check bucket-policy-parser.go).
 | 
					
						
							|  |  |  |  | 		// Resource prefix bucket part is not equal to the bucket name in this case.
 | 
					
						
							|  |  |  |  | 		{bucketAccessPolicies[4], ErrMalformedPolicy, false}, | 
					
						
							|  |  |  |  | 		// Test case - 6.
 | 
					
						
							| 
									
										
										
										
											2016-08-15 17:44:48 +08:00
										 |  |  |  | 		// contracting policy statement with recursive resources.
 | 
					
						
							| 
									
										
										
										
											2016-06-09 16:53:56 +08:00
										 |  |  |  | 		// should result in ErrPolicyNesting.
 | 
					
						
							|  |  |  |  | 		{bucketAccessPolicies[5], ErrPolicyNesting, false}, | 
					
						
							| 
									
										
										
										
											2016-05-06 10:58:48 +08:00
										 |  |  |  | 		// Test case - 7.
 | 
					
						
							|  |  |  |  | 		// constructing policy statement with lexically close
 | 
					
						
							|  |  |  |  | 		// characters.
 | 
					
						
							|  |  |  |  | 		// should result in ErrNone.
 | 
					
						
							|  |  |  |  | 		{bucketAccessPolicies[6], ErrNone, true}, | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 	for i, testCase := range testCases { | 
					
						
							| 
									
										
										
										
											2016-08-11 11:10:48 +08:00
										 |  |  |  | 		apiErrCode := checkBucketPolicyResources("minio-bucket", &testCase.inputPolicy) | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 		if apiErrCode != ErrNone && testCase.shouldPass { | 
					
						
							|  |  |  |  | 			t.Errorf("Test %d: Expected to pass, but failed with Errocode %v", i+1, apiErrCode) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		if apiErrCode == ErrNone && !testCase.shouldPass { | 
					
						
							|  |  |  |  | 			t.Errorf("Test %d: Expected to fail with ErrCode %v, but passed instead", i+1, testCase.apiErrCode) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		// Failed as expected, but does it fail for the expected reason.
 | 
					
						
							|  |  |  |  | 		if apiErrCode != ErrNone && !testCase.shouldPass { | 
					
						
							|  |  |  |  | 			if testCase.apiErrCode != apiErrCode { | 
					
						
							|  |  |  |  | 				t.Errorf("Test %d: Expected to fail with error code %v, but instead failed with error code %v", i+1, testCase.apiErrCode, apiErrCode) | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // Tests validate parsing of BucketAccessPolicy.
 | 
					
						
							|  |  |  |  | func TestParseBucketPolicy(t *testing.T) { | 
					
						
							|  |  |  |  | 	// set Unsupported Actions.
 | 
					
						
							|  |  |  |  | 	setUnsupportedActions := func(statements []policyStatement) []policyStatement { | 
					
						
							|  |  |  |  | 		// "s3:DeleteEverything"" is an Unsupported Action.
 | 
					
						
							| 
									
										
										
										
											2016-08-20 18:16:38 +08:00
										 |  |  |  | 		statements[0].Actions = set.CreateStringSet([]string{"s3:GetObject", "s3:ListBucket", "s3:PutObject", "s3:DeleteEverything"}...) | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 		return statements | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	// set unsupported Effect.
 | 
					
						
							|  |  |  |  | 	setUnsupportedEffect := func(statements []policyStatement) []policyStatement { | 
					
						
							|  |  |  |  | 		// Effect "Don't allow" is Unsupported.
 | 
					
						
							|  |  |  |  | 		statements[0].Effect = "DontAllow" | 
					
						
							|  |  |  |  | 		return statements | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	// set unsupported principals.
 | 
					
						
							|  |  |  |  | 	setUnsupportedPrincipals := func(statements []policyStatement) []policyStatement { | 
					
						
							|  |  |  |  | 		// "User1111"" is an Unsupported Principal.
 | 
					
						
							| 
									
										
										
										
											2016-09-20 04:52:28 +08:00
										 |  |  |  | 		statements[0].Principal = map[string]interface{}{ | 
					
						
							|  |  |  |  | 			"AWS": []string{"*", "User1111"}, | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 		return statements | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	// set unsupported Resources.
 | 
					
						
							|  |  |  |  | 	setUnsupportedResources := func(statements []policyStatement) []policyStatement { | 
					
						
							|  |  |  |  | 		// "s3:DeleteEverything"" is an Unsupported Action.
 | 
					
						
							| 
									
										
										
										
											2016-08-20 18:16:38 +08:00
										 |  |  |  | 		statements[0].Resources = set.CreateStringSet([]string{"my-resource"}...) | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 		return statements | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-08-11 11:10:48 +08:00
										 |  |  |  | 	// List of bucketPolicy used for test cases.
 | 
					
						
							|  |  |  |  | 	bucketAccesPolicies := []bucketPolicy{ | 
					
						
							|  |  |  |  | 		// bucketPolicy - 0.
 | 
					
						
							|  |  |  |  | 		// bucketPolicy statement empty.
 | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 		{Version: "1.0"}, | 
					
						
							| 
									
										
										
										
											2016-08-11 11:10:48 +08:00
										 |  |  |  | 		// bucketPolicy - 1.
 | 
					
						
							|  |  |  |  | 		// bucketPolicy version empty.
 | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 		{Version: "", Statements: []policyStatement{}}, | 
					
						
							| 
									
										
										
										
											2016-08-11 11:10:48 +08:00
										 |  |  |  | 		// bucketPolicy - 2.
 | 
					
						
							|  |  |  |  | 		// Readonly bucketPolicy.
 | 
					
						
							| 
									
										
										
										
											2016-07-01 14:49:59 +08:00
										 |  |  |  | 		{Version: "1.0", Statements: getReadOnlyStatement("minio-bucket", "")}, | 
					
						
							| 
									
										
										
										
											2016-08-11 11:10:48 +08:00
										 |  |  |  | 		// bucketPolicy - 3.
 | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 		// Read-Write bucket policy.
 | 
					
						
							| 
									
										
										
										
											2016-07-01 14:49:59 +08:00
										 |  |  |  | 		{Version: "1.0", Statements: getReadWriteStatement("minio-bucket", "Asia/")}, | 
					
						
							| 
									
										
										
										
											2016-08-11 11:10:48 +08:00
										 |  |  |  | 		// bucketPolicy - 4.
 | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 		// Write only bucket policy.
 | 
					
						
							| 
									
										
										
										
											2016-07-01 14:49:59 +08:00
										 |  |  |  | 		{Version: "1.0", Statements: getWriteOnlyStatement("minio-bucket", "Asia/India/")}, | 
					
						
							| 
									
										
										
										
											2016-08-11 11:10:48 +08:00
										 |  |  |  | 		// bucketPolicy - 5.
 | 
					
						
							|  |  |  |  | 		// bucketPolicy statement contains unsupported action.
 | 
					
						
							| 
									
										
										
										
											2016-07-01 14:49:59 +08:00
										 |  |  |  | 		{Version: "1.0", Statements: setUnsupportedActions(getReadOnlyStatement("minio-bucket", ""))}, | 
					
						
							| 
									
										
										
										
											2016-08-11 11:10:48 +08:00
										 |  |  |  | 		// bucketPolicy - 6.
 | 
					
						
							|  |  |  |  | 		// bucketPolicy statement contains unsupported Effect.
 | 
					
						
							| 
									
										
										
										
											2016-07-01 14:49:59 +08:00
										 |  |  |  | 		{Version: "1.0", Statements: setUnsupportedEffect(getReadWriteStatement("minio-bucket", "Asia/"))}, | 
					
						
							| 
									
										
										
										
											2016-08-11 11:10:48 +08:00
										 |  |  |  | 		// bucketPolicy - 7.
 | 
					
						
							|  |  |  |  | 		// bucketPolicy statement contains unsupported Principal.
 | 
					
						
							| 
									
										
										
										
											2016-07-01 14:49:59 +08:00
										 |  |  |  | 		{Version: "1.0", Statements: setUnsupportedPrincipals(getWriteOnlyStatement("minio-bucket", "Asia/India/"))}, | 
					
						
							| 
									
										
										
										
											2016-08-11 11:10:48 +08:00
										 |  |  |  | 		// bucketPolicy - 8.
 | 
					
						
							|  |  |  |  | 		// bucketPolicy statement contains unsupported Resource.
 | 
					
						
							| 
									
										
										
										
											2016-07-01 14:49:59 +08:00
										 |  |  |  | 		{Version: "1.0", Statements: setUnsupportedResources(getWriteOnlyStatement("minio-bucket", "Asia/India/"))}, | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	testCases := []struct { | 
					
						
							| 
									
										
										
										
											2016-08-11 11:10:48 +08:00
										 |  |  |  | 		inputPolicy bucketPolicy | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 		// expected results.
 | 
					
						
							| 
									
										
										
										
											2016-08-11 11:10:48 +08:00
										 |  |  |  | 		expectedPolicy bucketPolicy | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 		err            error | 
					
						
							|  |  |  |  | 		// Flag indicating whether the test should pass.
 | 
					
						
							|  |  |  |  | 		shouldPass bool | 
					
						
							|  |  |  |  | 	}{ | 
					
						
							|  |  |  |  | 		// Test case - 1.
 | 
					
						
							| 
									
										
										
										
											2016-08-11 11:10:48 +08:00
										 |  |  |  | 		// bucketPolicy statement empty.
 | 
					
						
							| 
									
										
										
										
											2016-11-16 10:14:23 +08:00
										 |  |  |  | 		{bucketAccesPolicies[0], bucketPolicy{}, errors.New("Policy statement cannot be empty"), false}, | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 		// Test case - 2.
 | 
					
						
							| 
									
										
										
										
											2016-08-11 11:10:48 +08:00
										 |  |  |  | 		// bucketPolicy version empty.
 | 
					
						
							| 
									
										
										
										
											2016-11-16 10:14:23 +08:00
										 |  |  |  | 		{bucketAccesPolicies[1], bucketPolicy{}, errors.New("Policy version cannot be empty"), false}, | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 		// Test case - 3.
 | 
					
						
							| 
									
										
										
										
											2016-08-11 11:10:48 +08:00
										 |  |  |  | 		// Readonly bucketPolicy.
 | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 		{bucketAccesPolicies[2], bucketAccesPolicies[2], nil, true}, | 
					
						
							|  |  |  |  | 		// Test case - 4.
 | 
					
						
							|  |  |  |  | 		// Read-Write bucket policy.
 | 
					
						
							|  |  |  |  | 		{bucketAccesPolicies[3], bucketAccesPolicies[3], nil, true}, | 
					
						
							|  |  |  |  | 		// Test case - 5.
 | 
					
						
							|  |  |  |  | 		// Write only bucket policy.
 | 
					
						
							|  |  |  |  | 		{bucketAccesPolicies[4], bucketAccesPolicies[4], nil, true}, | 
					
						
							|  |  |  |  | 		// Test case - 6.
 | 
					
						
							| 
									
										
										
										
											2016-08-11 11:10:48 +08:00
										 |  |  |  | 		// bucketPolicy statement contains unsupported action.
 | 
					
						
							| 
									
										
										
										
											2016-11-16 10:14:23 +08:00
										 |  |  |  | 		{bucketAccesPolicies[5], bucketAccesPolicies[5], fmt.Errorf("Unsupported actions found: ‘set.StringSet{\"s3:DeleteEverything\":struct {}{}}’, please validate your policy document"), false}, | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 		// Test case - 7.
 | 
					
						
							| 
									
										
										
										
											2016-08-11 11:10:48 +08:00
										 |  |  |  | 		// bucketPolicy statement contains unsupported Effect.
 | 
					
						
							| 
									
										
										
										
											2016-11-16 10:14:23 +08:00
										 |  |  |  | 		{bucketAccesPolicies[6], bucketAccesPolicies[6], fmt.Errorf("Unsupported Effect found: ‘DontAllow’, please validate your policy document"), false}, | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 		// Test case - 8.
 | 
					
						
							| 
									
										
										
										
											2016-08-11 11:10:48 +08:00
										 |  |  |  | 		// bucketPolicy statement contains unsupported Principal.
 | 
					
						
							| 
									
										
										
										
											2016-11-16 10:14:23 +08:00
										 |  |  |  | 		{bucketAccesPolicies[7], bucketAccesPolicies[7], fmt.Errorf("Unsupported principals found: ‘set.StringSet{\"User1111\":struct {}{}}’, please validate your policy document"), false}, | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 		// Test case - 9.
 | 
					
						
							| 
									
										
										
										
											2016-08-11 11:10:48 +08:00
										 |  |  |  | 		// bucketPolicy statement contains unsupported Resource.
 | 
					
						
							| 
									
										
										
										
											2016-11-16 10:14:23 +08:00
										 |  |  |  | 		{bucketAccesPolicies[8], bucketAccesPolicies[8], fmt.Errorf("Unsupported resource style found: ‘my-resource’, please validate your policy document"), false}, | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 	for i, testCase := range testCases { | 
					
						
							| 
									
										
										
										
											2016-08-11 11:10:48 +08:00
										 |  |  |  | 		var buffer bytes.Buffer | 
					
						
							|  |  |  |  | 		encoder := json.NewEncoder(&buffer) | 
					
						
							|  |  |  |  | 		err := encoder.Encode(testCase.inputPolicy) | 
					
						
							|  |  |  |  | 		if err != nil { | 
					
						
							|  |  |  |  | 			t.Fatalf("Test %d: Couldn't Marshal bucket policy %s", i+1, err) | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-11 11:10:48 +08:00
										 |  |  |  | 		var actualAccessPolicy = &bucketPolicy{} | 
					
						
							|  |  |  |  | 		err = parseBucketPolicy(&buffer, actualAccessPolicy) | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 		if err != nil && testCase.shouldPass { | 
					
						
							|  |  |  |  | 			t.Errorf("Test %d: Expected to pass, but failed with: <ERROR> %s", i+1, err.Error()) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		if err == nil && !testCase.shouldPass { | 
					
						
							|  |  |  |  | 			t.Errorf("Test %d: Expected to fail with <ERROR> \"%s\", but passed instead", i+1, testCase.err.Error()) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		// Failed as expected, but does it fail for the expected reason.
 | 
					
						
							|  |  |  |  | 		if err != nil && !testCase.shouldPass { | 
					
						
							|  |  |  |  | 			if err.Error() != testCase.err.Error() { | 
					
						
							|  |  |  |  | 				t.Errorf("Test %d: Expected to fail with error \"%s\", but instead failed with error \"%s\"", i+1, testCase.err.Error(), err.Error()) | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		// Test passes as expected, but the output values are verified for correctness here.
 | 
					
						
							|  |  |  |  | 		if err == nil && testCase.shouldPass { | 
					
						
							| 
									
										
										
										
											2016-08-11 11:10:48 +08:00
										 |  |  |  | 			if testCase.expectedPolicy.String() != actualAccessPolicy.String() { | 
					
						
							| 
									
										
										
										
											2016-04-16 09:23:19 +08:00
										 |  |  |  | 				t.Errorf("Test %d: The expected statements from resource statement generator doesn't match the actual statements", i+1) | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | } | 
					
						
							| 
									
										
										
										
											2017-01-30 11:45:11 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | func TestAWSRefererCondition(t *testing.T) { | 
					
						
							|  |  |  |  | 	resource := set.CreateStringSet([]string{ | 
					
						
							|  |  |  |  | 		fmt.Sprintf("%s%s", bucketARNPrefix, "minio-bucket"+"/"+"Asia"+"*"), | 
					
						
							|  |  |  |  | 	}...) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	conditionsKeyMap := make(policy.ConditionKeyMap) | 
					
						
							|  |  |  |  | 	conditionsKeyMap.Add("aws:Referer", | 
					
						
							|  |  |  |  | 		set.CreateStringSet("www.example.com", | 
					
						
							|  |  |  |  | 			"http://www.example.com")) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	requestConditionKeyMap := make(map[string]set.StringSet) | 
					
						
							|  |  |  |  | 	requestConditionKeyMap["referer"] = set.CreateStringSet("www.example.com") | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	testCases := []struct { | 
					
						
							|  |  |  |  | 		effect       string | 
					
						
							|  |  |  |  | 		conditionKey string | 
					
						
							|  |  |  |  | 		match        bool | 
					
						
							|  |  |  |  | 	}{ | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			effect:       "Allow", | 
					
						
							|  |  |  |  | 			conditionKey: "StringLike", | 
					
						
							|  |  |  |  | 			match:        true, | 
					
						
							|  |  |  |  | 		}, | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			effect:       "Allow", | 
					
						
							|  |  |  |  | 			conditionKey: "StringNotLike", | 
					
						
							|  |  |  |  | 			match:        false, | 
					
						
							|  |  |  |  | 		}, | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			effect:       "Deny", | 
					
						
							|  |  |  |  | 			conditionKey: "StringLike", | 
					
						
							|  |  |  |  | 			match:        true, | 
					
						
							|  |  |  |  | 		}, | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			effect:       "Deny", | 
					
						
							|  |  |  |  | 			conditionKey: "StringNotLike", | 
					
						
							|  |  |  |  | 			match:        false, | 
					
						
							|  |  |  |  | 		}, | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	for i, test := range testCases { | 
					
						
							|  |  |  |  | 		conditions := make(map[string]map[string]set.StringSet) | 
					
						
							|  |  |  |  | 		conditions[test.conditionKey] = conditionsKeyMap | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		allowStatement := policyStatement{ | 
					
						
							|  |  |  |  | 			Sid:    "Testing AWS referer condition", | 
					
						
							|  |  |  |  | 			Effect: test.effect, | 
					
						
							|  |  |  |  | 			Principal: map[string]interface{}{ | 
					
						
							|  |  |  |  | 				"AWS": "*", | 
					
						
							|  |  |  |  | 			}, | 
					
						
							|  |  |  |  | 			Resources:  resource, | 
					
						
							|  |  |  |  | 			Conditions: conditions, | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if result := bucketPolicyConditionMatch(requestConditionKeyMap, allowStatement); result != test.match { | 
					
						
							|  |  |  |  | 			t.Errorf("Test %d -  Expected conditons to evaluate to %v but got %v", | 
					
						
							|  |  |  |  | 				i+1, test.match, result) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | } |