| 
									
										
										
										
											2021-04-19 03:41:13 +08:00
										 |  |  | // Copyright (c) 2015-2021 MinIO, Inc.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // This file is part of MinIO Object Storage stack
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // This program is free software: you can redistribute it and/or modify
 | 
					
						
							|  |  |  | // it under the terms of the GNU Affero General Public License as published by
 | 
					
						
							|  |  |  | // the Free Software Foundation, either version 3 of the License, or
 | 
					
						
							|  |  |  | // (at your option) any later version.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // This program is distributed in the hope that it will be useful
 | 
					
						
							|  |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
					
						
							|  |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
					
						
							|  |  |  | // GNU Affero General Public License for more details.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // You should have received a copy of the GNU Affero General Public License
 | 
					
						
							|  |  |  | // along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
					
						
							| 
									
										
										
										
											2018-04-25 06:53:30 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | package cmd | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"encoding/json" | 
					
						
							|  |  |  | 	"net/http" | 
					
						
							| 
									
										
										
										
											2020-04-01 15:04:25 +08:00
										 |  |  | 	"net/url" | 
					
						
							| 
									
										
										
										
											2020-04-07 04:44:16 +08:00
										 |  |  | 	"strconv" | 
					
						
							| 
									
										
										
										
											2020-04-01 15:04:25 +08:00
										 |  |  | 	"strings" | 
					
						
							|  |  |  | 	"time" | 
					
						
							| 
									
										
										
										
											2018-04-25 06:53:30 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-08 19:31:43 +08:00
										 |  |  | 	jsoniter "github.com/json-iterator/go" | 
					
						
							| 
									
										
										
										
											2020-07-15 00:38:05 +08:00
										 |  |  | 	miniogopolicy "github.com/minio/minio-go/v7/pkg/policy" | 
					
						
							| 
									
										
										
										
											2022-09-29 02:25:46 +08:00
										 |  |  | 	"github.com/minio/minio-go/v7/pkg/tags" | 
					
						
							| 
									
										
										
										
											2023-02-07 01:27:29 +08:00
										 |  |  | 	"github.com/minio/minio/internal/auth" | 
					
						
							| 
									
										
										
										
											2021-06-02 05:59:40 +08:00
										 |  |  | 	"github.com/minio/minio/internal/handlers" | 
					
						
							|  |  |  | 	xhttp "github.com/minio/minio/internal/http" | 
					
						
							|  |  |  | 	"github.com/minio/minio/internal/logger" | 
					
						
							| 
									
										
										
										
											2023-09-05 03:57:37 +08:00
										 |  |  | 	"github.com/minio/pkg/v2/policy" | 
					
						
							| 
									
										
										
										
											2018-04-25 06:53:30 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-07 03:52:56 +08:00
										 |  |  | // PolicySys - policy subsystem.
 | 
					
						
							| 
									
										
										
										
											2020-05-21 01:18:15 +08:00
										 |  |  | type PolicySys struct{} | 
					
						
							| 
									
										
										
										
											2018-04-25 06:53:30 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-20 04:53:54 +08:00
										 |  |  | // Get returns stored bucket policy
 | 
					
						
							| 
									
										
										
										
											2023-09-05 03:57:37 +08:00
										 |  |  | func (sys *PolicySys) Get(bucket string) (*policy.BucketPolicy, error) { | 
					
						
							| 
									
										
										
										
											2022-05-31 17:57:57 +08:00
										 |  |  | 	policy, _, err := globalBucketMetadataSys.GetPolicyConfig(bucket) | 
					
						
							|  |  |  | 	return policy, err | 
					
						
							| 
									
										
										
										
											2018-04-25 06:53:30 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // IsAllowed - checks given policy args is allowed to continue the Rest API.
 | 
					
						
							| 
									
										
										
										
											2023-09-05 03:57:37 +08:00
										 |  |  | func (sys *PolicySys) IsAllowed(args policy.BucketPolicyArgs) bool { | 
					
						
							| 
									
										
										
										
											2020-05-21 01:18:15 +08:00
										 |  |  | 	p, err := sys.Get(args.BucketName) | 
					
						
							|  |  |  | 	if err == nil { | 
					
						
							| 
									
										
										
										
											2020-05-20 04:53:54 +08:00
										 |  |  | 		return p.IsAllowed(args) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-21 01:18:15 +08:00
										 |  |  | 	// Log unhandled errors.
 | 
					
						
							|  |  |  | 	if _, ok := err.(BucketPolicyNotFound); !ok { | 
					
						
							|  |  |  | 		logger.LogIf(GlobalContext, err) | 
					
						
							| 
									
										
										
										
											2018-04-25 06:53:30 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// As policy is not available for given bucket name, returns IsOwner i.e.
 | 
					
						
							|  |  |  | 	// operation is allowed only for owner.
 | 
					
						
							|  |  |  | 	return args.IsOwner | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // NewPolicySys - creates new policy system.
 | 
					
						
							|  |  |  | func NewPolicySys() *PolicySys { | 
					
						
							| 
									
										
										
										
											2020-05-21 01:18:15 +08:00
										 |  |  | 	return &PolicySys{} | 
					
						
							| 
									
										
										
										
											2018-04-25 06:53:30 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-06 03:44:23 +08:00
										 |  |  | func getSTSConditionValues(r *http.Request, lc string, cred auth.Credentials) map[string][]string { | 
					
						
							|  |  |  | 	m := make(map[string][]string) | 
					
						
							|  |  |  | 	if d := r.Form.Get("DurationSeconds"); d != "" { | 
					
						
							|  |  |  | 		m["DurationSeconds"] = []string{d} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return m | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-07 01:27:29 +08:00
										 |  |  | func getConditionValues(r *http.Request, lc string, cred auth.Credentials) map[string][]string { | 
					
						
							| 
									
										
										
										
											2019-01-21 12:57:14 +08:00
										 |  |  | 	currTime := UTCNow() | 
					
						
							| 
									
										
										
										
											2020-04-01 15:04:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-07 01:27:29 +08:00
										 |  |  | 	var ( | 
					
						
							|  |  |  | 		username = cred.AccessKey | 
					
						
							|  |  |  | 		claims   = cred.Claims | 
					
						
							|  |  |  | 		groups   = cred.Groups | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-10 22:52:31 +08:00
										 |  |  | 	if cred.IsTemp() || cred.IsServiceAccount() { | 
					
						
							|  |  |  | 		// For derived credentials, check the parent user's permissions.
 | 
					
						
							|  |  |  | 		username = cred.ParentUser | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-01 15:04:25 +08:00
										 |  |  | 	principalType := "Anonymous" | 
					
						
							|  |  |  | 	if username != "" { | 
					
						
							|  |  |  | 		principalType = "User" | 
					
						
							| 
									
										
										
										
											2020-08-18 08:39:55 +08:00
										 |  |  | 		if len(claims) > 0 { | 
					
						
							|  |  |  | 			principalType = "AssumedRole" | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if username == globalActiveCred.AccessKey { | 
					
						
							|  |  |  | 			principalType = "Account" | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-04-01 15:04:25 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-08 13:43:01 +08:00
										 |  |  | 	vid := r.Form.Get(xhttp.VersionID) | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 	if vid == "" { | 
					
						
							|  |  |  | 		if u, err := url.Parse(r.Header.Get(xhttp.AmzCopySource)); err == nil { | 
					
						
							| 
									
										
										
										
											2021-08-08 13:43:01 +08:00
										 |  |  | 			vid = u.Query().Get(xhttp.VersionID) | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-03 00:34:15 +08:00
										 |  |  | 	authType := getRequestAuthType(r) | 
					
						
							|  |  |  | 	var signatureVersion string | 
					
						
							|  |  |  | 	switch authType { | 
					
						
							|  |  |  | 	case authTypeSignedV2, authTypePresignedV2: | 
					
						
							|  |  |  | 		signatureVersion = signV2Algorithm | 
					
						
							|  |  |  | 	case authTypeSigned, authTypePresigned, authTypeStreamingSigned, authTypePostPolicy: | 
					
						
							|  |  |  | 		signatureVersion = signV4Algorithm | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var authtype string | 
					
						
							|  |  |  | 	switch authType { | 
					
						
							|  |  |  | 	case authTypePresignedV2, authTypePresigned: | 
					
						
							|  |  |  | 		authtype = "REST-QUERY-STRING" | 
					
						
							|  |  |  | 	case authTypeSignedV2, authTypeSigned, authTypeStreamingSigned: | 
					
						
							|  |  |  | 		authtype = "REST-HEADER" | 
					
						
							|  |  |  | 	case authTypePostPolicy: | 
					
						
							|  |  |  | 		authtype = "POST" | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-27 09:39:30 +08:00
										 |  |  | 	args := map[string][]string{ | 
					
						
							| 
									
										
										
										
											2021-04-03 00:34:15 +08:00
										 |  |  | 		"CurrentTime":      {currTime.Format(time.RFC3339)}, | 
					
						
							|  |  |  | 		"EpochTime":        {strconv.FormatInt(currTime.Unix(), 10)}, | 
					
						
							|  |  |  | 		"SecureTransport":  {strconv.FormatBool(r.TLS != nil)}, | 
					
						
							| 
									
										
										
										
											2023-12-22 08:56:55 +08:00
										 |  |  | 		"SourceIp":         {handlers.GetSourceIPRaw(r)}, | 
					
						
							| 
									
										
										
										
											2021-04-03 00:34:15 +08:00
										 |  |  | 		"UserAgent":        {r.UserAgent()}, | 
					
						
							|  |  |  | 		"Referer":          {r.Referer()}, | 
					
						
							|  |  |  | 		"principaltype":    {principalType}, | 
					
						
							|  |  |  | 		"userid":           {username}, | 
					
						
							|  |  |  | 		"username":         {username}, | 
					
						
							|  |  |  | 		"versionid":        {vid}, | 
					
						
							|  |  |  | 		"signatureversion": {signatureVersion}, | 
					
						
							|  |  |  | 		"authType":         {authtype}, | 
					
						
							| 
									
										
										
										
											2018-12-27 09:39:30 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-04-25 06:53:30 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-07 04:44:16 +08:00
										 |  |  | 	if lc != "" { | 
					
						
							|  |  |  | 		args["LocationConstraint"] = []string{lc} | 
					
						
							| 
									
										
										
										
											2020-04-01 15:04:25 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-07 04:44:16 +08:00
										 |  |  | 	cloneHeader := r.Header.Clone() | 
					
						
							| 
									
										
										
										
											2023-11-28 03:30:19 +08:00
										 |  |  | 	if v := cloneHeader.Get("x-amz-signature-age"); v != "" { | 
					
						
							|  |  |  | 		args["signatureAge"] = []string{v} | 
					
						
							|  |  |  | 		cloneHeader.Del("x-amz-signature-age") | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-04-01 15:04:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-29 02:25:46 +08:00
										 |  |  | 	if userTags := cloneHeader.Get(xhttp.AmzObjectTagging); userTags != "" { | 
					
						
							|  |  |  | 		tag, _ := tags.ParseObjectTags(userTags) | 
					
						
							|  |  |  | 		if tag != nil { | 
					
						
							|  |  |  | 			tagMap := tag.ToMap() | 
					
						
							|  |  |  | 			keys := make([]string, 0, len(tagMap)) | 
					
						
							|  |  |  | 			for k, v := range tagMap { | 
					
						
							|  |  |  | 				args[pathJoin("ExistingObjectTag", k)] = []string{v} | 
					
						
							|  |  |  | 				args[pathJoin("RequestObjectTag", k)] = []string{v} | 
					
						
							|  |  |  | 				keys = append(keys, k) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			args["RequestObjectTagKeys"] = keys | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-01 15:04:25 +08:00
										 |  |  | 	for _, objLock := range []string{ | 
					
						
							|  |  |  | 		xhttp.AmzObjectLockMode, | 
					
						
							|  |  |  | 		xhttp.AmzObjectLockLegalHold, | 
					
						
							|  |  |  | 		xhttp.AmzObjectLockRetainUntilDate, | 
					
						
							|  |  |  | 	} { | 
					
						
							|  |  |  | 		if values, ok := cloneHeader[objLock]; ok { | 
					
						
							|  |  |  | 			args[strings.TrimPrefix(objLock, "X-Amz-")] = values | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		cloneHeader.Del(objLock) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for key, values := range cloneHeader { | 
					
						
							| 
									
										
										
										
											2022-09-29 02:25:46 +08:00
										 |  |  | 		if strings.EqualFold(key, xhttp.AmzObjectTagging) { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-04-25 06:53:30 +08:00
										 |  |  | 		if existingValues, found := args[key]; found { | 
					
						
							|  |  |  | 			args[key] = append(existingValues, values...) | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			args[key] = values | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-08 13:43:01 +08:00
										 |  |  | 	cloneURLValues := make(url.Values, len(r.Form)) | 
					
						
							|  |  |  | 	for k, v := range r.Form { | 
					
						
							| 
									
										
										
										
											2020-04-01 15:04:25 +08:00
										 |  |  | 		cloneURLValues[k] = v | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for _, objLock := range []string{ | 
					
						
							|  |  |  | 		xhttp.AmzObjectLockMode, | 
					
						
							|  |  |  | 		xhttp.AmzObjectLockLegalHold, | 
					
						
							|  |  |  | 		xhttp.AmzObjectLockRetainUntilDate, | 
					
						
							|  |  |  | 	} { | 
					
						
							|  |  |  | 		if values, ok := cloneURLValues[objLock]; ok { | 
					
						
							|  |  |  | 			args[strings.TrimPrefix(objLock, "X-Amz-")] = values | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		cloneURLValues.Del(objLock) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for key, values := range cloneURLValues { | 
					
						
							| 
									
										
										
										
											2018-04-25 06:53:30 +08:00
										 |  |  | 		if existingValues, found := args[key]; found { | 
					
						
							|  |  |  | 			args[key] = append(existingValues, values...) | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			args[key] = values | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-16 23:59:59 +08:00
										 |  |  | 	// JWT specific values
 | 
					
						
							| 
									
										
										
										
											2022-09-14 00:45:36 +08:00
										 |  |  | 	//
 | 
					
						
							|  |  |  | 	// Add all string claims
 | 
					
						
							| 
									
										
										
										
											2019-10-16 23:59:59 +08:00
										 |  |  | 	for k, v := range claims { | 
					
						
							|  |  |  | 		vStr, ok := v.(string) | 
					
						
							|  |  |  | 		if ok { | 
					
						
							| 
									
										
										
										
											2023-02-07 19:43:08 +08:00
										 |  |  | 			// Trim any LDAP specific prefix
 | 
					
						
							|  |  |  | 			args[strings.ToLower(strings.TrimPrefix(k, "ldap"))] = []string{vStr} | 
					
						
							| 
									
										
										
										
											2019-10-16 23:59:59 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-02-07 01:27:29 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-14 00:45:36 +08:00
										 |  |  | 	// Add groups claim which could be a list. This will ensure that the claim
 | 
					
						
							|  |  |  | 	// `jwt:groups` works.
 | 
					
						
							|  |  |  | 	if grpsVal, ok := claims["groups"]; ok { | 
					
						
							|  |  |  | 		if grpsIs, ok := grpsVal.([]interface{}); ok { | 
					
						
							|  |  |  | 			grps := []string{} | 
					
						
							|  |  |  | 			for _, gI := range grpsIs { | 
					
						
							|  |  |  | 				if g, ok := gI.(string); ok { | 
					
						
							|  |  |  | 					grps = append(grps, g) | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if len(grps) > 0 { | 
					
						
							|  |  |  | 				args["groups"] = grps | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-04-01 15:04:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-07 01:27:29 +08:00
										 |  |  | 	// if not claim groups are available use the one with auth.Credentials
 | 
					
						
							|  |  |  | 	if _, ok := args["groups"]; !ok { | 
					
						
							|  |  |  | 		if len(groups) > 0 { | 
					
						
							|  |  |  | 			args["groups"] = groups | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-25 06:53:30 +08:00
										 |  |  | 	return args | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | // PolicyToBucketAccessPolicy converts a MinIO policy into a minio-go policy data structure.
 | 
					
						
							| 
									
										
										
										
											2023-09-05 03:57:37 +08:00
										 |  |  | func PolicyToBucketAccessPolicy(bucketPolicy *policy.BucketPolicy) (*miniogopolicy.BucketAccessPolicy, error) { | 
					
						
							| 
									
										
										
										
											2018-04-25 06:53:30 +08:00
										 |  |  | 	// Return empty BucketAccessPolicy for empty bucket policy.
 | 
					
						
							|  |  |  | 	if bucketPolicy == nil { | 
					
						
							|  |  |  | 		return &miniogopolicy.BucketAccessPolicy{Version: policy.DefaultVersion}, nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	data, err := json.Marshal(bucketPolicy) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		// This should not happen because bucketPolicy is valid to convert to JSON data.
 | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var policyInfo miniogopolicy.BucketAccessPolicy | 
					
						
							| 
									
										
										
										
											2022-01-03 01:15:06 +08:00
										 |  |  | 	json := jsoniter.ConfigCompatibleWithStandardLibrary | 
					
						
							| 
									
										
										
										
											2018-04-25 06:53:30 +08:00
										 |  |  | 	if err = json.Unmarshal(data, &policyInfo); err != nil { | 
					
						
							|  |  |  | 		// This should not happen because data is valid to JSON data.
 | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return &policyInfo, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-05 03:57:37 +08:00
										 |  |  | // BucketAccessPolicyToPolicy - converts minio-go/policy.BucketAccessPolicy to policy.BucketPolicy.
 | 
					
						
							|  |  |  | func BucketAccessPolicyToPolicy(policyInfo *miniogopolicy.BucketAccessPolicy) (*policy.BucketPolicy, error) { | 
					
						
							| 
									
										
										
										
											2018-04-25 06:53:30 +08:00
										 |  |  | 	data, err := json.Marshal(policyInfo) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		// This should not happen because policyInfo is valid to convert to JSON data.
 | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-05 03:57:37 +08:00
										 |  |  | 	var bucketPolicy policy.BucketPolicy | 
					
						
							| 
									
										
										
										
											2022-01-03 01:15:06 +08:00
										 |  |  | 	json := jsoniter.ConfigCompatibleWithStandardLibrary | 
					
						
							| 
									
										
										
										
											2018-04-25 06:53:30 +08:00
										 |  |  | 	if err = json.Unmarshal(data, &bucketPolicy); err != nil { | 
					
						
							|  |  |  | 		// This should not happen because data is valid to JSON data.
 | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return &bucketPolicy, nil | 
					
						
							|  |  |  | } |