storj.io/minio@v0.0.0-20230509071714-0cbc90f649b1/pkg/bucket/policy/condition/key.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  	"fmt"
    22  	"strings"
    23  )
    24  
    25  // Key - conditional key which is used to fetch values for any condition.
    26  // Refer https://docs.aws.amazon.com/IAM/latest/UserGuide/list_s3.html
    27  // for more information about available condition keys.
    28  type Key string
    29  
    30  const (
    31  	// S3XAmzCopySource - key representing x-amz-copy-source HTTP header applicable to PutObject API only.
    32  	S3XAmzCopySource Key = "s3:x-amz-copy-source"
    33  
    34  	// S3XAmzServerSideEncryption - key representing x-amz-server-side-encryption HTTP header applicable
    35  	// to PutObject API only.
    36  	S3XAmzServerSideEncryption Key = "s3:x-amz-server-side-encryption"
    37  
    38  	// S3XAmzServerSideEncryptionCustomerAlgorithm - key representing
    39  	// x-amz-server-side-encryption-customer-algorithm HTTP header applicable to PutObject API only.
    40  	S3XAmzServerSideEncryptionCustomerAlgorithm Key = "s3:x-amz-server-side-encryption-customer-algorithm"
    41  
    42  	// S3XAmzMetadataDirective - key representing x-amz-metadata-directive HTTP header applicable to
    43  	// PutObject API only.
    44  	S3XAmzMetadataDirective Key = "s3:x-amz-metadata-directive"
    45  
    46  	// S3XAmzContentSha256 - set a static content-sha256 for all calls for a given action.
    47  	S3XAmzContentSha256 = "s3:x-amz-content-sha256"
    48  
    49  	// S3XAmzStorageClass - key representing x-amz-storage-class HTTP header applicable to PutObject API
    50  	// only.
    51  	S3XAmzStorageClass Key = "s3:x-amz-storage-class"
    52  
    53  	// S3LocationConstraint - key representing LocationConstraint XML tag of CreateBucket API only.
    54  	S3LocationConstraint Key = "s3:LocationConstraint"
    55  
    56  	// S3Prefix - key representing prefix query parameter of ListBucket API only.
    57  	S3Prefix Key = "s3:prefix"
    58  
    59  	// S3Delimiter - key representing delimiter query parameter of ListBucket API only.
    60  	S3Delimiter Key = "s3:delimiter"
    61  
    62  	// S3VersionID - Enables you to limit the permission for the
    63  	// s3:PutObjectVersionTagging action to a specific object version.
    64  	S3VersionID Key = "s3:versionid"
    65  
    66  	// S3MaxKeys - key representing max-keys query parameter of ListBucket API only.
    67  	S3MaxKeys Key = "s3:max-keys"
    68  
    69  	// S3ObjectLockRemainingRetentionDays - key representing object-lock-remaining-retention-days
    70  	// Enables enforcement of an object relative to the remaining retention days, you can set
    71  	// minimum and maximum allowable retention periods for a bucket using a bucket policy.
    72  	// This key are specific for s3:PutObjectRetention API.
    73  	S3ObjectLockRemainingRetentionDays Key = "s3:object-lock-remaining-retention-days"
    74  
    75  	// S3ObjectLockMode - key representing object-lock-mode
    76  	// Enables enforcement of the specified object retention mode
    77  	S3ObjectLockMode Key = "s3:object-lock-mode"
    78  
    79  	// S3ObjectLockRetainUntilDate - key representing object-lock-retain-util-date
    80  	// Enables enforcement of a specific retain-until-date
    81  	S3ObjectLockRetainUntilDate Key = "s3:object-lock-retain-until-date"
    82  
    83  	// S3ObjectLockLegalHold - key representing object-local-legal-hold
    84  	// Enables enforcement of the specified object legal hold status
    85  	S3ObjectLockLegalHold Key = "s3:object-lock-legal-hold"
    86  
    87  	// AWSReferer - key representing Referer header of any API.
    88  	AWSReferer Key = "aws:Referer"
    89  
    90  	// AWSSourceIP - key representing client's IP address (not intermittent proxies) of any API.
    91  	AWSSourceIP Key = "aws:SourceIp"
    92  
    93  	// AWSUserAgent - key representing UserAgent header for any API.
    94  	AWSUserAgent Key = "aws:UserAgent"
    95  
    96  	// AWSSecureTransport - key representing if the clients request is authenticated or not.
    97  	AWSSecureTransport Key = "aws:SecureTransport"
    98  
    99  	// AWSCurrentTime - key representing the current time.
   100  	AWSCurrentTime Key = "aws:CurrentTime"
   101  
   102  	// AWSEpochTime - key representing the current epoch time.
   103  	AWSEpochTime Key = "aws:EpochTime"
   104  
   105  	// AWSPrincipalType - user principal type currently supported values are "User" and "Anonymous".
   106  	AWSPrincipalType Key = "aws:principaltype"
   107  
   108  	// AWSUserID - user unique ID, in MinIO this value is same as your user Access Key.
   109  	AWSUserID Key = "aws:userid"
   110  
   111  	// AWSUsername - user friendly name, in MinIO this value is same as your user Access Key.
   112  	AWSUsername Key = "aws:username"
   113  
   114  	// S3SignatureVersion - identifies the version of AWS Signature that you want to support for authenticated requests.
   115  	S3SignatureVersion = "s3:signatureversion"
   116  
   117  	// S3AuthType - optionally use this condition key to restrict incoming requests to use a specific authentication method.
   118  	S3AuthType = "s3:authType"
   119  )
   120  
   121  // AllSupportedKeys - is list of all all supported keys.
   122  var AllSupportedKeys = append([]Key{
   123  	S3SignatureVersion,
   124  	S3AuthType,
   125  	S3XAmzCopySource,
   126  	S3XAmzServerSideEncryption,
   127  	S3XAmzServerSideEncryptionCustomerAlgorithm,
   128  	S3XAmzMetadataDirective,
   129  	S3XAmzStorageClass,
   130  	S3XAmzContentSha256,
   131  	S3LocationConstraint,
   132  	S3Prefix,
   133  	S3Delimiter,
   134  	S3MaxKeys,
   135  	S3VersionID,
   136  	S3ObjectLockRemainingRetentionDays,
   137  	S3ObjectLockMode,
   138  	S3ObjectLockLegalHold,
   139  	S3ObjectLockRetainUntilDate,
   140  	AWSReferer,
   141  	AWSSourceIP,
   142  	AWSUserAgent,
   143  	AWSSecureTransport,
   144  	AWSCurrentTime,
   145  	AWSEpochTime,
   146  	AWSPrincipalType,
   147  	AWSUserID,
   148  	AWSUsername,
   149  	LDAPUser,
   150  	// Add new supported condition keys.
   151  }, JWTKeys...)
   152  
   153  // CommonKeys - is list of all common condition keys.
   154  var CommonKeys = append([]Key{
   155  	S3SignatureVersion,
   156  	S3AuthType,
   157  	S3XAmzContentSha256,
   158  	S3LocationConstraint,
   159  	AWSReferer,
   160  	AWSSourceIP,
   161  	AWSUserAgent,
   162  	AWSSecureTransport,
   163  	AWSCurrentTime,
   164  	AWSEpochTime,
   165  	AWSPrincipalType,
   166  	AWSUserID,
   167  	AWSUsername,
   168  	LDAPUser,
   169  }, JWTKeys...)
   170  
   171  func substFuncFromValues(values map[string][]string) func(string) string {
   172  	return func(v string) string {
   173  		for _, key := range CommonKeys {
   174  			// Empty values are not supported for policy variables.
   175  			if rvalues, ok := values[key.Name()]; ok && rvalues[0] != "" {
   176  				v = strings.Replace(v, key.VarName(), rvalues[0], -1)
   177  			}
   178  		}
   179  		return v
   180  	}
   181  }
   182  
   183  // IsValid - checks if key is valid or not.
   184  func (key Key) IsValid() bool {
   185  	for _, supKey := range AllSupportedKeys {
   186  		if supKey == key {
   187  			return true
   188  		}
   189  	}
   190  
   191  	return false
   192  }
   193  
   194  // MarshalJSON - encodes Key to JSON data.
   195  func (key Key) MarshalJSON() ([]byte, error) {
   196  	if !key.IsValid() {
   197  		return nil, fmt.Errorf("unknown key %v", key)
   198  	}
   199  
   200  	return json.Marshal(string(key))
   201  }
   202  
   203  // VarName - returns variable key name, such as "${aws:username}"
   204  func (key Key) VarName() string {
   205  	return fmt.Sprintf("${%s}", key)
   206  }
   207  
   208  // Name - returns key name which is stripped value of prefixes "aws:" and "s3:"
   209  func (key Key) Name() string {
   210  	keyString := string(key)
   211  
   212  	if strings.HasPrefix(keyString, "aws:") {
   213  		return strings.TrimPrefix(keyString, "aws:")
   214  	} else if strings.HasPrefix(keyString, "jwt:") {
   215  		return strings.TrimPrefix(keyString, "jwt:")
   216  	} else if strings.HasPrefix(keyString, "ldap:") {
   217  		return strings.TrimPrefix(keyString, "ldap:")
   218  	}
   219  	return strings.TrimPrefix(keyString, "s3:")
   220  }
   221  
   222  // UnmarshalJSON - decodes JSON data to Key.
   223  func (key *Key) UnmarshalJSON(data []byte) error {
   224  	var s string
   225  	if err := json.Unmarshal(data, &s); err != nil {
   226  		return err
   227  	}
   228  
   229  	parsedKey, err := parseKey(s)
   230  	if err != nil {
   231  		return err
   232  	}
   233  
   234  	*key = parsedKey
   235  	return nil
   236  }
   237  
   238  func parseKey(s string) (Key, error) {
   239  	key := Key(s)
   240  
   241  	if key.IsValid() {
   242  		return key, nil
   243  	}
   244  
   245  	return key, fmt.Errorf("invalid condition key '%v'", s)
   246  }
   247  
   248  // KeySet - set representation of slice of keys.
   249  type KeySet map[Key]struct{}
   250  
   251  // Add - add a key to key set.
   252  func (set KeySet) Add(key Key) {
   253  	set[key] = struct{}{}
   254  }
   255  
   256  // Merge merges two key sets, duplicates are overwritten
   257  func (set KeySet) Merge(mset KeySet) {
   258  	for k, v := range mset {
   259  		set[k] = v
   260  	}
   261  }
   262  
   263  // Difference - returns a key set contains difference of two keys.
   264  // Example:
   265  //     keySet1 := ["one", "two", "three"]
   266  //     keySet2 := ["two", "four", "three"]
   267  //     keySet1.Difference(keySet2) == ["one"]
   268  func (set KeySet) Difference(sset KeySet) KeySet {
   269  	nset := make(KeySet)
   270  
   271  	for k := range set {
   272  		if _, ok := sset[k]; !ok {
   273  			nset.Add(k)
   274  		}
   275  	}
   276  
   277  	return nset
   278  }
   279  
   280  // IsEmpty - returns whether key set is empty or not.
   281  func (set KeySet) IsEmpty() bool {
   282  	return len(set) == 0
   283  }
   284  
   285  func (set KeySet) String() string {
   286  	return fmt.Sprintf("%v", set.ToSlice())
   287  }
   288  
   289  // ToSlice - returns slice of keys.
   290  func (set KeySet) ToSlice() []Key {
   291  	keys := []Key{}
   292  
   293  	for key := range set {
   294  		keys = append(keys, key)
   295  	}
   296  
   297  	return keys
   298  }
   299  
   300  // NewKeySet - returns new KeySet contains given keys.
   301  func NewKeySet(keys ...Key) KeySet {
   302  	set := make(KeySet)
   303  	for _, key := range keys {
   304  		set.Add(key)
   305  	}
   306  
   307  	return set
   308  }
   309  
   310  // AllSupportedAdminKeys - is list of all admin supported keys.
   311  var AllSupportedAdminKeys = []Key{
   312  	AWSReferer,
   313  	AWSSourceIP,
   314  	AWSUserAgent,
   315  	AWSSecureTransport,
   316  	AWSCurrentTime,
   317  	AWSEpochTime,
   318  	// Add new supported condition keys.
   319  }