storj.io/minio@v0.0.0-20230509071714-0cbc90f649b1/pkg/bucket/policy/condition/func_test.go (about)

     1  /*
     2   * MinIO Cloud Storage, (C) 2018 MinIO, Inc.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package condition
    18  
    19  import (
    20  	"encoding/json"
    21  	"reflect"
    22  	"testing"
    23  )
    24  
    25  func TestFunctionsEvaluate(t *testing.T) {
    26  	func1, err := newNullFunc(S3XAmzCopySource, NewValueSet(NewBoolValue(true)))
    27  	if err != nil {
    28  		t.Fatalf("unexpected error. %v\n", err)
    29  	}
    30  
    31  	func2, err := newIPAddressFunc(AWSSourceIP, NewValueSet(NewStringValue("192.168.1.0/24")))
    32  	if err != nil {
    33  		t.Fatalf("unexpected error. %v\n", err)
    34  	}
    35  
    36  	func3, err := newStringEqualsFunc(S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/myobject")))
    37  	if err != nil {
    38  		t.Fatalf("unexpected error. %v\n", err)
    39  	}
    40  
    41  	func4, err := newStringLikeFunc(S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/myobject*")))
    42  	if err != nil {
    43  		t.Fatalf("unexpected error. %v\n", err)
    44  	}
    45  
    46  	case1Function := NewFunctions(func1, func2, func3, func4)
    47  
    48  	testCases := []struct {
    49  		functions      Functions
    50  		values         map[string][]string
    51  		expectedResult bool
    52  	}{
    53  		{case1Function, map[string][]string{
    54  			"x-amz-copy-source": {"mybucket/myobject"},
    55  			"SourceIp":          {"192.168.1.10"},
    56  		}, false},
    57  		{case1Function, map[string][]string{
    58  			"x-amz-copy-source": {"mybucket/myobject"},
    59  			"SourceIp":          {"192.168.1.10"},
    60  			"Refer":             {"http://example.org/"},
    61  		}, false},
    62  		{case1Function, map[string][]string{"x-amz-copy-source": {"mybucket/myobject"}}, false},
    63  		{case1Function, map[string][]string{"SourceIp": {"192.168.1.10"}}, false},
    64  		{case1Function, map[string][]string{
    65  			"x-amz-copy-source": {"mybucket/yourobject"},
    66  			"SourceIp":          {"192.168.1.10"},
    67  		}, false},
    68  		{case1Function, map[string][]string{
    69  			"x-amz-copy-source": {"mybucket/myobject"},
    70  			"SourceIp":          {"192.168.2.10"},
    71  		}, false},
    72  		{case1Function, map[string][]string{
    73  			"x-amz-copy-source": {"mybucket/myobject"},
    74  			"Refer":             {"http://example.org/"},
    75  		}, false},
    76  	}
    77  
    78  	for i, testCase := range testCases {
    79  		result := testCase.functions.Evaluate(testCase.values)
    80  
    81  		if result != testCase.expectedResult {
    82  			t.Errorf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
    83  		}
    84  	}
    85  }
    86  
    87  func TestFunctionsKeys(t *testing.T) {
    88  	func1, err := newNullFunc(S3XAmzCopySource, NewValueSet(NewBoolValue(true)))
    89  	if err != nil {
    90  		t.Fatalf("unexpected error. %v\n", err)
    91  	}
    92  
    93  	func2, err := newIPAddressFunc(AWSSourceIP, NewValueSet(NewStringValue("192.168.1.0/24")))
    94  	if err != nil {
    95  		t.Fatalf("unexpected error. %v\n", err)
    96  	}
    97  
    98  	func3, err := newStringEqualsFunc(S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/myobject")))
    99  	if err != nil {
   100  		t.Fatalf("unexpected error. %v\n", err)
   101  	}
   102  
   103  	func4, err := newStringLikeFunc(S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/myobject*")))
   104  	if err != nil {
   105  		t.Fatalf("unexpected error. %v\n", err)
   106  	}
   107  
   108  	testCases := []struct {
   109  		functions      Functions
   110  		expectedResult KeySet
   111  	}{
   112  		{NewFunctions(func1, func2, func3, func4), NewKeySet(S3XAmzCopySource, AWSSourceIP)},
   113  	}
   114  
   115  	for i, testCase := range testCases {
   116  		result := testCase.functions.Keys()
   117  
   118  		if !reflect.DeepEqual(result, testCase.expectedResult) {
   119  			t.Fatalf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, result)
   120  		}
   121  	}
   122  }
   123  
   124  func TestFunctionsMarshalJSON(t *testing.T) {
   125  	func1, err := newStringLikeFunc(S3XAmzMetadataDirective, NewValueSet(NewStringValue("REPL*")))
   126  	if err != nil {
   127  		t.Fatalf("unexpected error. %v\n", err)
   128  	}
   129  
   130  	func2, err := newStringEqualsFunc(S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/myobject")))
   131  	if err != nil {
   132  		t.Fatalf("unexpected error. %v\n", err)
   133  	}
   134  
   135  	func3, err := newStringNotEqualsFunc(S3XAmzServerSideEncryption, NewValueSet(NewStringValue("AES256")))
   136  	if err != nil {
   137  		t.Fatalf("unexpected error. %v\n", err)
   138  	}
   139  
   140  	func4, err := newNotIPAddressFunc(AWSSourceIP,
   141  		NewValueSet(NewStringValue("10.1.10.0/24")))
   142  	if err != nil {
   143  		t.Fatalf("unexpected error. %v\n", err)
   144  	}
   145  
   146  	func5, err := newStringNotLikeFunc(S3XAmzStorageClass, NewValueSet(NewStringValue("STANDARD")))
   147  	if err != nil {
   148  		t.Fatalf("unexpected error. %v\n", err)
   149  	}
   150  
   151  	func6, err := newNullFunc(S3XAmzServerSideEncryptionCustomerAlgorithm, NewValueSet(NewBoolValue(true)))
   152  	if err != nil {
   153  		t.Fatalf("unexpected error. %v\n", err)
   154  	}
   155  
   156  	func7, err := newIPAddressFunc(AWSSourceIP,
   157  		NewValueSet(NewStringValue("192.168.1.0/24")))
   158  	if err != nil {
   159  		t.Fatalf("unexpected error. %v\n", err)
   160  	}
   161  
   162  	case1Result := []byte(`{"IpAddress":{"aws:SourceIp":["192.168.1.0/24"]},"NotIpAddress":{"aws:SourceIp":["10.1.10.0/24"]},"Null":{"s3:x-amz-server-side-encryption-customer-algorithm":[true]},"StringEquals":{"s3:x-amz-copy-source":["mybucket/myobject"]},"StringLike":{"s3:x-amz-metadata-directive":["REPL*"]},"StringNotEquals":{"s3:x-amz-server-side-encryption":["AES256"]},"StringNotLike":{"s3:x-amz-storage-class":["STANDARD"]}}`)
   163  
   164  	case2Result := []byte(`{"Null":{"s3:x-amz-server-side-encryption-customer-algorithm":[true]}}`)
   165  
   166  	testCases := []struct {
   167  		functions      Functions
   168  		expectedResult []byte
   169  		expectErr      bool
   170  	}{
   171  		{NewFunctions(func1, func2, func3, func4, func5, func6, func7), case1Result, false},
   172  		{NewFunctions(func6), case2Result, false},
   173  		{NewFunctions(), []byte(`{}`), false},
   174  		{nil, []byte(`{}`), false},
   175  	}
   176  
   177  	for i, testCase := range testCases {
   178  		result, err := json.Marshal(testCase.functions)
   179  		expectErr := (err != nil)
   180  
   181  		if testCase.expectErr != expectErr {
   182  			t.Fatalf("case %v: error: expected: %v, got: %v", i+1, testCase.expectErr, expectErr)
   183  		}
   184  
   185  		if !testCase.expectErr {
   186  			if !reflect.DeepEqual(result, testCase.expectedResult) {
   187  				t.Fatalf("case %v: result: expected: %v, got: %v", i+1, string(testCase.expectedResult), string(result))
   188  			}
   189  		}
   190  	}
   191  }
   192  
   193  func TestFunctionsUnmarshalJSON(t *testing.T) {
   194  	case1Data := []byte(`{
   195      "StringLike": {
   196          "s3:x-amz-metadata-directive": "REPL*"
   197      },
   198      "StringEquals": {
   199          "s3:x-amz-copy-source": "mybucket/myobject"
   200      },
   201      "StringNotEquals": {
   202          "s3:x-amz-server-side-encryption": "AES256"
   203      },
   204      "NotIpAddress": {
   205          "aws:SourceIp": [
   206              "10.1.10.0/24",
   207              "10.10.1.0/24"
   208          ]
   209      },
   210      "StringNotLike": {
   211          "s3:x-amz-storage-class": "STANDARD"
   212      },
   213      "Null": {
   214          "s3:x-amz-server-side-encryption-customer-algorithm": true
   215      },
   216      "IpAddress": {
   217          "aws:SourceIp": [
   218              "192.168.1.0/24",
   219              "192.168.2.0/24"
   220          ]
   221      }
   222  }`)
   223  	func1, err := newStringLikeFunc(S3XAmzMetadataDirective, NewValueSet(NewStringValue("REPL*")))
   224  	if err != nil {
   225  		t.Fatalf("unexpected error. %v\n", err)
   226  	}
   227  
   228  	func2, err := newStringEqualsFunc(S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/myobject")))
   229  	if err != nil {
   230  		t.Fatalf("unexpected error. %v\n", err)
   231  	}
   232  
   233  	func3, err := newStringNotEqualsFunc(S3XAmzServerSideEncryption, NewValueSet(NewStringValue("AES256")))
   234  	if err != nil {
   235  		t.Fatalf("unexpected error. %v\n", err)
   236  	}
   237  
   238  	func4, err := newNotIPAddressFunc(AWSSourceIP,
   239  		NewValueSet(NewStringValue("10.1.10.0/24"), NewStringValue("10.10.1.0/24")))
   240  	if err != nil {
   241  		t.Fatalf("unexpected error. %v\n", err)
   242  	}
   243  
   244  	func5, err := newStringNotLikeFunc(S3XAmzStorageClass, NewValueSet(NewStringValue("STANDARD")))
   245  	if err != nil {
   246  		t.Fatalf("unexpected error. %v\n", err)
   247  	}
   248  
   249  	func6, err := newNullFunc(S3XAmzServerSideEncryptionCustomerAlgorithm, NewValueSet(NewBoolValue(true)))
   250  	if err != nil {
   251  		t.Fatalf("unexpected error. %v\n", err)
   252  	}
   253  
   254  	func7, err := newIPAddressFunc(AWSSourceIP,
   255  		NewValueSet(NewStringValue("192.168.1.0/24"), NewStringValue("192.168.2.0/24")))
   256  	if err != nil {
   257  		t.Fatalf("unexpected error. %v\n", err)
   258  	}
   259  
   260  	case2Data := []byte(`{
   261      "Null": {
   262          "s3:x-amz-server-side-encryption-customer-algorithm": true
   263      },
   264      "Null": {
   265          "s3:x-amz-server-side-encryption-customer-algorithm": "true"
   266      }
   267  }`)
   268  
   269  	case3Data := []byte(`{}`)
   270  
   271  	case4Data := []byte(`{
   272      "StringLike": {
   273          "s3:x-amz-metadata-directive": "REPL*"
   274      },
   275      "StringEquals": {
   276          "s3:x-amz-copy-source": "mybucket/myobject",
   277          "s3:prefix": [
   278             "",
   279             "home/"
   280          ],
   281          "s3:delimiter": [
   282             "/"
   283          ]
   284      },
   285      "StringNotEquals": {
   286          "s3:x-amz-server-side-encryption": "AES256"
   287      },
   288      "NotIpAddress": {
   289          "aws:SourceIp": [
   290              "10.1.10.0/24",
   291              "10.10.1.0/24"
   292          ]
   293      },
   294      "StringNotLike": {
   295          "s3:x-amz-storage-class": "STANDARD"
   296      },
   297      "Null": {
   298          "s3:x-amz-server-side-encryption-customer-algorithm": true
   299      },
   300      "IpAddress": {
   301          "aws:SourceIp": [
   302              "192.168.1.0/24",
   303              "192.168.2.0/24"
   304          ]
   305      }
   306  }`)
   307  
   308  	func2_1, err := newStringEqualsFunc(S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/myobject")))
   309  	if err != nil {
   310  		t.Fatalf("unexpected error. %v\n", err)
   311  	}
   312  
   313  	func2_2, err := newStringEqualsFunc(S3Prefix, NewValueSet(NewStringValue(""), NewStringValue("home/")))
   314  	if err != nil {
   315  		t.Fatalf("unexpected error. %v\n", err)
   316  	}
   317  
   318  	func2_3, err := newStringEqualsFunc(S3Delimiter, NewValueSet(NewStringValue("/")))
   319  	if err != nil {
   320  		t.Fatalf("unexpected error. %v\n", err)
   321  	}
   322  
   323  	testCases := []struct {
   324  		data           []byte
   325  		expectedResult Functions
   326  		expectErr      bool
   327  	}{
   328  		// Success case, basic conditions.
   329  		{case1Data, NewFunctions(func1, func2, func3, func4, func5, func6, func7), false},
   330  		// Duplicate conditions, success case only one value is preserved.
   331  		{case2Data, NewFunctions(func6), false},
   332  		// empty condition error.
   333  		{case3Data, nil, true},
   334  		// Success case multiple keys, same condition.
   335  		{case4Data, NewFunctions(func1, func2_1, func2_2, func2_3, func3, func4, func5, func6, func7), false},
   336  	}
   337  
   338  	for i, testCase := range testCases {
   339  		result := new(Functions)
   340  		err := json.Unmarshal(testCase.data, result)
   341  		expectErr := (err != nil)
   342  
   343  		if testCase.expectErr != expectErr {
   344  			t.Fatalf("case %v: error: expected: %v, got: %v", i+1, testCase.expectErr, expectErr)
   345  		}
   346  
   347  		if !testCase.expectErr {
   348  			if (*result).String() != testCase.expectedResult.String() {
   349  				t.Fatalf("case %v: result: expected: %v, got: %v", i+1, testCase.expectedResult, *result)
   350  			}
   351  		}
   352  	}
   353  }