storj.io/minio@v0.0.0-20230509071714-0cbc90f649b1/pkg/bucket/policy/resource.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 policy 18 19 import ( 20 "encoding/json" 21 "strings" 22 23 "storj.io/minio/pkg/bucket/policy/condition" 24 "storj.io/minio/pkg/wildcard" 25 ) 26 27 // ResourceARNPrefix - resource ARN prefix as per AWS S3 specification. 28 const ResourceARNPrefix = "arn:aws:s3:::" 29 30 // Resource - resource in policy statement. 31 type Resource struct { 32 BucketName string 33 Pattern string 34 } 35 36 func (r Resource) isBucketPattern() bool { 37 return !strings.Contains(r.Pattern, "/") 38 } 39 40 func (r Resource) isObjectPattern() bool { 41 return strings.Contains(r.Pattern, "/") || strings.Contains(r.BucketName, "*") 42 } 43 44 // IsValid - checks whether Resource is valid or not. 45 func (r Resource) IsValid() bool { 46 return r.BucketName != "" && r.Pattern != "" 47 } 48 49 // Match - matches object name with resource pattern. 50 func (r Resource) Match(resource string, conditionValues map[string][]string) bool { 51 pattern := r.Pattern 52 for _, key := range condition.CommonKeys { 53 // Empty values are not supported for policy variables. 54 if rvalues, ok := conditionValues[key.Name()]; ok && rvalues[0] != "" { 55 pattern = strings.Replace(pattern, key.VarName(), rvalues[0], -1) 56 } 57 } 58 59 return wildcard.Match(pattern, resource) 60 } 61 62 // MarshalJSON - encodes Resource to JSON data. 63 func (r Resource) MarshalJSON() ([]byte, error) { 64 if !r.IsValid() { 65 return nil, Errorf("invalid resource %v", r) 66 } 67 68 return json.Marshal(r.String()) 69 } 70 71 func (r Resource) String() string { 72 return ResourceARNPrefix + r.Pattern 73 } 74 75 // UnmarshalJSON - decodes JSON data to Resource. 76 func (r *Resource) UnmarshalJSON(data []byte) error { 77 var s string 78 if err := json.Unmarshal(data, &s); err != nil { 79 return err 80 } 81 82 parsedResource, err := parseResource(s) 83 if err != nil { 84 return err 85 } 86 87 *r = parsedResource 88 89 return nil 90 } 91 92 // Validate - validates Resource is for given bucket or not. 93 func (r Resource) Validate(bucketName string) error { 94 if !r.IsValid() { 95 return Errorf("invalid resource") 96 } 97 98 if !wildcard.Match(r.BucketName, bucketName) { 99 return Errorf("bucket name does not match") 100 } 101 102 return nil 103 } 104 105 // parseResource - parses string to Resource. 106 func parseResource(s string) (Resource, error) { 107 if !strings.HasPrefix(s, ResourceARNPrefix) { 108 return Resource{}, Errorf("invalid resource '%v'", s) 109 } 110 111 pattern := strings.TrimPrefix(s, ResourceARNPrefix) 112 tokens := strings.SplitN(pattern, "/", 2) 113 bucketName := tokens[0] 114 if bucketName == "" { 115 return Resource{}, Errorf("invalid resource format '%v'", s) 116 } 117 118 return Resource{ 119 BucketName: bucketName, 120 Pattern: pattern, 121 }, nil 122 } 123 124 // NewResource - creates new resource. 125 func NewResource(bucketName, keyName string) Resource { 126 pattern := bucketName 127 if keyName != "" { 128 if !strings.HasPrefix(keyName, "/") { 129 pattern += "/" 130 } 131 132 pattern += keyName 133 } 134 135 return Resource{ 136 BucketName: bucketName, 137 Pattern: pattern, 138 } 139 }