storj.io/minio@v0.0.0-20230509071714-0cbc90f649b1/cmd/bucket-policy.go (about) 1 /* 2 * MinIO Cloud Storage, (C) 2018,2020 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 cmd 18 19 import ( 20 "encoding/json" 21 "net/http" 22 "net/url" 23 "strconv" 24 "strings" 25 "time" 26 27 jsoniter "github.com/json-iterator/go" 28 miniogopolicy "github.com/minio/minio-go/v7/pkg/policy" 29 30 xhttp "storj.io/minio/cmd/http" 31 "storj.io/minio/cmd/logger" 32 "storj.io/minio/pkg/bucket/policy" 33 "storj.io/minio/pkg/handlers" 34 ) 35 36 // PolicySys - policy subsystem. 37 type PolicySys struct{} 38 39 // Get returns stored bucket policy 40 func (sys *PolicySys) Get(bucket string) (*policy.Policy, error) { 41 return globalBucketMetadataSys.GetPolicyConfig(bucket) 42 } 43 44 // IsAllowed - checks given policy args is allowed to continue the Rest API. 45 func (sys *PolicySys) IsAllowed(args policy.Args) bool { 46 p, err := sys.Get(args.BucketName) 47 if err == nil { 48 return p.IsAllowed(args) 49 } 50 51 // Log unhandled errors. 52 if _, ok := err.(BucketPolicyNotFound); !ok { 53 logger.LogIf(GlobalContext, err) 54 } 55 56 // As policy is not available for given bucket name, returns IsOwner i.e. 57 // operation is allowed only for owner. 58 return args.IsOwner 59 } 60 61 // NewPolicySys - creates new policy system. 62 func NewPolicySys() *PolicySys { 63 return &PolicySys{} 64 } 65 66 func getConditionValues(r *http.Request, lc string, username string, claims map[string]interface{}) map[string][]string { 67 currTime := UTCNow() 68 69 principalType := "Anonymous" 70 if username != "" { 71 principalType = "User" 72 if len(claims) > 0 { 73 principalType = "AssumedRole" 74 } 75 if username == globalActiveCred.AccessKey { 76 principalType = "Account" 77 } 78 } 79 80 vid := r.URL.Query().Get("versionId") 81 if vid == "" { 82 if u, err := url.Parse(r.Header.Get(xhttp.AmzCopySource)); err == nil { 83 vid = u.Query().Get("versionId") 84 } 85 } 86 87 authType := getRequestAuthType(r) 88 var signatureVersion string 89 switch authType { 90 case authTypeSignedV2, authTypePresignedV2: 91 signatureVersion = signV2Algorithm 92 case authTypeSigned, authTypePresigned, authTypeStreamingSigned, authTypePostPolicy: 93 signatureVersion = signV4Algorithm 94 } 95 96 var authtype string 97 switch authType { 98 case authTypePresignedV2, authTypePresigned: 99 authtype = "REST-QUERY-STRING" 100 case authTypeSignedV2, authTypeSigned, authTypeStreamingSigned: 101 authtype = "REST-HEADER" 102 case authTypePostPolicy: 103 authtype = "POST" 104 } 105 106 args := map[string][]string{ 107 "CurrentTime": {currTime.Format(time.RFC3339)}, 108 "EpochTime": {strconv.FormatInt(currTime.Unix(), 10)}, 109 "SecureTransport": {strconv.FormatBool(r.TLS != nil)}, 110 "SourceIp": {handlers.GetSourceIP(r)}, 111 "UserAgent": {r.UserAgent()}, 112 "Referer": {r.Referer()}, 113 "principaltype": {principalType}, 114 "userid": {username}, 115 "username": {username}, 116 "versionid": {vid}, 117 "signatureversion": {signatureVersion}, 118 "authType": {authtype}, 119 } 120 121 if lc != "" { 122 args["LocationConstraint"] = []string{lc} 123 } 124 125 cloneHeader := r.Header.Clone() 126 127 for _, objLock := range []string{ 128 xhttp.AmzObjectLockMode, 129 xhttp.AmzObjectLockLegalHold, 130 xhttp.AmzObjectLockRetainUntilDate, 131 } { 132 if values, ok := cloneHeader[objLock]; ok { 133 args[strings.TrimPrefix(objLock, "X-Amz-")] = values 134 } 135 cloneHeader.Del(objLock) 136 } 137 138 for key, values := range cloneHeader { 139 if existingValues, found := args[key]; found { 140 args[key] = append(existingValues, values...) 141 } else { 142 args[key] = values 143 } 144 } 145 146 var cloneURLValues = url.Values{} 147 for k, v := range r.URL.Query() { 148 cloneURLValues[k] = v 149 } 150 151 for _, objLock := range []string{ 152 xhttp.AmzObjectLockMode, 153 xhttp.AmzObjectLockLegalHold, 154 xhttp.AmzObjectLockRetainUntilDate, 155 } { 156 if values, ok := cloneURLValues[objLock]; ok { 157 args[strings.TrimPrefix(objLock, "X-Amz-")] = values 158 } 159 cloneURLValues.Del(objLock) 160 } 161 162 for key, values := range cloneURLValues { 163 if existingValues, found := args[key]; found { 164 args[key] = append(existingValues, values...) 165 } else { 166 args[key] = values 167 } 168 } 169 170 // JWT specific values 171 for k, v := range claims { 172 vStr, ok := v.(string) 173 if ok { 174 // Special case for AD/LDAP STS users 175 if k == ldapUser { 176 args["user"] = []string{vStr} 177 } else { 178 args[k] = []string{vStr} 179 } 180 } 181 } 182 183 return args 184 } 185 186 // PolicyToBucketAccessPolicy converts a MinIO policy into a minio-go policy data structure. 187 func PolicyToBucketAccessPolicy(bucketPolicy *policy.Policy) (*miniogopolicy.BucketAccessPolicy, error) { 188 // Return empty BucketAccessPolicy for empty bucket policy. 189 if bucketPolicy == nil { 190 return &miniogopolicy.BucketAccessPolicy{Version: policy.DefaultVersion}, nil 191 } 192 193 data, err := json.Marshal(bucketPolicy) 194 if err != nil { 195 // This should not happen because bucketPolicy is valid to convert to JSON data. 196 return nil, err 197 } 198 199 var policyInfo miniogopolicy.BucketAccessPolicy 200 var json = jsoniter.ConfigCompatibleWithStandardLibrary 201 if err = json.Unmarshal(data, &policyInfo); err != nil { 202 // This should not happen because data is valid to JSON data. 203 return nil, err 204 } 205 206 return &policyInfo, nil 207 } 208 209 // BucketAccessPolicyToPolicy - converts minio-go/policy.BucketAccessPolicy to policy.Policy. 210 func BucketAccessPolicyToPolicy(policyInfo *miniogopolicy.BucketAccessPolicy) (*policy.Policy, error) { 211 data, err := json.Marshal(policyInfo) 212 if err != nil { 213 // This should not happen because policyInfo is valid to convert to JSON data. 214 return nil, err 215 } 216 217 var bucketPolicy policy.Policy 218 var json = jsoniter.ConfigCompatibleWithStandardLibrary 219 if err = json.Unmarshal(data, &bucketPolicy); err != nil { 220 // This should not happen because data is valid to JSON data. 221 return nil, err 222 } 223 224 return &bucketPolicy, nil 225 }