storj.io/minio@v0.0.0-20230509071714-0cbc90f649b1/pkg/bucket/policy/condition/stringequalsfunc.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  	"fmt"
    21  	"net/http"
    22  	"sort"
    23  
    24  	"github.com/minio/minio-go/v7/pkg/s3utils"
    25  	"github.com/minio/minio-go/v7/pkg/set"
    26  )
    27  
    28  func toStringEqualsFuncString(n name, key Key, values set.StringSet) string {
    29  	valueStrings := values.ToSlice()
    30  	sort.Strings(valueStrings)
    31  
    32  	return fmt.Sprintf("%v:%v:%v", n, key, valueStrings)
    33  }
    34  
    35  // stringEqualsFunc - String equals function. It checks whether value by Key in given
    36  // values map is in condition values.
    37  // For example,
    38  //   - if values = ["mybucket/foo"], at evaluate() it returns whether string
    39  //     in value map for Key is in values.
    40  type stringEqualsFunc struct {
    41  	k      Key
    42  	values set.StringSet
    43  }
    44  
    45  // evaluate() - evaluates to check whether value by Key in given values is in
    46  // condition values.
    47  func (f stringEqualsFunc) evaluate(values map[string][]string) bool {
    48  	requestValue, ok := values[http.CanonicalHeaderKey(f.k.Name())]
    49  	if !ok {
    50  		requestValue = values[f.k.Name()]
    51  	}
    52  
    53  	fvalues := f.values.ApplyFunc(substFuncFromValues(values))
    54  	return !fvalues.Intersection(set.CreateStringSet(requestValue...)).IsEmpty()
    55  }
    56  
    57  // key() - returns condition key which is used by this condition function.
    58  func (f stringEqualsFunc) key() Key {
    59  	return f.k
    60  }
    61  
    62  // name() - returns "StringEquals" condition name.
    63  func (f stringEqualsFunc) name() name {
    64  	return stringEquals
    65  }
    66  
    67  func (f stringEqualsFunc) String() string {
    68  	return toStringEqualsFuncString(stringEquals, f.k, f.values)
    69  }
    70  
    71  // toMap - returns map representation of this function.
    72  func (f stringEqualsFunc) toMap() map[Key]ValueSet {
    73  	if !f.k.IsValid() {
    74  		return nil
    75  	}
    76  
    77  	values := NewValueSet()
    78  	for _, value := range f.values.ToSlice() {
    79  		values.Add(NewStringValue(value))
    80  	}
    81  
    82  	return map[Key]ValueSet{
    83  		f.k: values,
    84  	}
    85  }
    86  
    87  // stringNotEqualsFunc - String not equals function. It checks whether value by Key in
    88  // given values is NOT in condition values.
    89  // For example,
    90  //   - if values = ["mybucket/foo"], at evaluate() it returns whether string
    91  //     in value map for Key is NOT in values.
    92  type stringNotEqualsFunc struct {
    93  	stringEqualsFunc
    94  }
    95  
    96  // evaluate() - evaluates to check whether value by Key in given values is NOT in
    97  // condition values.
    98  func (f stringNotEqualsFunc) evaluate(values map[string][]string) bool {
    99  	return !f.stringEqualsFunc.evaluate(values)
   100  }
   101  
   102  // name() - returns "StringNotEquals" condition name.
   103  func (f stringNotEqualsFunc) name() name {
   104  	return stringNotEquals
   105  }
   106  
   107  func (f stringNotEqualsFunc) String() string {
   108  	return toStringEqualsFuncString(stringNotEquals, f.stringEqualsFunc.k, f.stringEqualsFunc.values)
   109  }
   110  
   111  func valuesToStringSlice(n name, values ValueSet) ([]string, error) {
   112  	valueStrings := []string{}
   113  
   114  	for value := range values {
   115  		s, err := value.GetString()
   116  		if err != nil {
   117  			return nil, fmt.Errorf("value must be a string for %v condition", n)
   118  		}
   119  
   120  		valueStrings = append(valueStrings, s)
   121  	}
   122  
   123  	return valueStrings, nil
   124  }
   125  
   126  func validateStringEqualsValues(n name, key Key, values set.StringSet) error {
   127  	for _, s := range values.ToSlice() {
   128  		switch key {
   129  		case S3XAmzCopySource:
   130  			bucket, object := path2BucketAndObject(s)
   131  			if object == "" {
   132  				return fmt.Errorf("invalid value '%v' for '%v' for %v condition", s, S3XAmzCopySource, n)
   133  			}
   134  			if err := s3utils.CheckValidBucketName(bucket); err != nil {
   135  				return err
   136  			}
   137  		case S3XAmzServerSideEncryption, S3XAmzServerSideEncryptionCustomerAlgorithm:
   138  			if s != "AES256" {
   139  				return fmt.Errorf("invalid value '%v' for '%v' for %v condition", s, S3XAmzServerSideEncryption, n)
   140  			}
   141  		case S3XAmzMetadataDirective:
   142  			if s != "COPY" && s != "REPLACE" {
   143  				return fmt.Errorf("invalid value '%v' for '%v' for %v condition", s, S3XAmzMetadataDirective, n)
   144  			}
   145  		case S3XAmzContentSha256:
   146  			if s == "" {
   147  				return fmt.Errorf("invalid empty value for '%v' for %v condition", S3XAmzContentSha256, n)
   148  			}
   149  		}
   150  	}
   151  
   152  	return nil
   153  }
   154  
   155  // newStringEqualsFunc - returns new StringEquals function.
   156  func newStringEqualsFunc(key Key, values ValueSet) (Function, error) {
   157  	valueStrings, err := valuesToStringSlice(stringEquals, values)
   158  	if err != nil {
   159  		return nil, err
   160  	}
   161  
   162  	return NewStringEqualsFunc(key, valueStrings...)
   163  }
   164  
   165  // NewStringEqualsFunc - returns new StringEquals function.
   166  func NewStringEqualsFunc(key Key, values ...string) (Function, error) {
   167  	sset := set.CreateStringSet(values...)
   168  	if err := validateStringEqualsValues(stringEquals, key, sset); err != nil {
   169  		return nil, err
   170  	}
   171  
   172  	return &stringEqualsFunc{key, sset}, nil
   173  }
   174  
   175  // newStringNotEqualsFunc - returns new StringNotEquals function.
   176  func newStringNotEqualsFunc(key Key, values ValueSet) (Function, error) {
   177  	valueStrings, err := valuesToStringSlice(stringNotEquals, values)
   178  	if err != nil {
   179  		return nil, err
   180  	}
   181  
   182  	return NewStringNotEqualsFunc(key, valueStrings...)
   183  }
   184  
   185  // NewStringNotEqualsFunc - returns new StringNotEquals function.
   186  func NewStringNotEqualsFunc(key Key, values ...string) (Function, error) {
   187  	sset := set.CreateStringSet(values...)
   188  	if err := validateStringEqualsValues(stringNotEquals, key, sset); err != nil {
   189  		return nil, err
   190  	}
   191  
   192  	return &stringNotEqualsFunc{stringEqualsFunc{key, sset}}, nil
   193  }