| 
									
										
										
										
											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 policy | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"encoding/json" | 
					
						
							|  |  |  | 	"strings" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-28 06:12:34 +08:00
										 |  |  | 	"github.com/minio/minio/pkg/bucket/policy/condition" | 
					
						
							| 
									
										
										
										
											2021-05-29 06:17:01 +08:00
										 |  |  | 	"github.com/minio/pkg/wildcard" | 
					
						
							| 
									
										
										
										
											2018-04-25 06:53:30 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // ResourceARNPrefix - resource ARN prefix as per AWS S3 specification.
 | 
					
						
							|  |  |  | const ResourceARNPrefix = "arn:aws:s3:::" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Resource - resource in policy statement.
 | 
					
						
							|  |  |  | type Resource struct { | 
					
						
							| 
									
										
										
										
											2018-05-17 07:17:00 +08:00
										 |  |  | 	BucketName string | 
					
						
							|  |  |  | 	Pattern    string | 
					
						
							| 
									
										
										
										
											2018-04-25 06:53:30 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (r Resource) isBucketPattern() bool { | 
					
						
							| 
									
										
										
										
											2018-05-17 07:17:00 +08:00
										 |  |  | 	return !strings.Contains(r.Pattern, "/") | 
					
						
							| 
									
										
										
										
											2018-04-25 06:53:30 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (r Resource) isObjectPattern() bool { | 
					
						
							| 
									
										
										
										
											2018-05-17 07:17:00 +08:00
										 |  |  | 	return strings.Contains(r.Pattern, "/") || strings.Contains(r.BucketName, "*") | 
					
						
							| 
									
										
										
										
											2018-04-25 06:53:30 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // IsValid - checks whether Resource is valid or not.
 | 
					
						
							|  |  |  | func (r Resource) IsValid() bool { | 
					
						
							| 
									
										
										
										
											2018-05-17 07:17:00 +08:00
										 |  |  | 	return r.BucketName != "" && r.Pattern != "" | 
					
						
							| 
									
										
										
										
											2018-04-25 06:53:30 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Match - matches object name with resource pattern.
 | 
					
						
							| 
									
										
										
										
											2019-01-21 12:57:14 +08:00
										 |  |  | func (r Resource) Match(resource string, conditionValues map[string][]string) bool { | 
					
						
							|  |  |  | 	pattern := r.Pattern | 
					
						
							|  |  |  | 	for _, key := range condition.CommonKeys { | 
					
						
							|  |  |  | 		// Empty values are not supported for policy variables.
 | 
					
						
							|  |  |  | 		if rvalues, ok := conditionValues[key.Name()]; ok && rvalues[0] != "" { | 
					
						
							|  |  |  | 			pattern = strings.Replace(pattern, key.VarName(), rvalues[0], -1) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return wildcard.Match(pattern, resource) | 
					
						
							| 
									
										
										
										
											2018-04-25 06:53:30 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // MarshalJSON - encodes Resource to JSON data.
 | 
					
						
							|  |  |  | func (r Resource) MarshalJSON() ([]byte, error) { | 
					
						
							|  |  |  | 	if !r.IsValid() { | 
					
						
							| 
									
										
										
										
											2020-01-04 03:28:52 +08:00
										 |  |  | 		return nil, Errorf("invalid resource %v", r) | 
					
						
							| 
									
										
										
										
											2018-04-25 06:53:30 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return json.Marshal(r.String()) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (r Resource) String() string { | 
					
						
							| 
									
										
										
										
											2018-05-17 07:17:00 +08:00
										 |  |  | 	return ResourceARNPrefix + r.Pattern | 
					
						
							| 
									
										
										
										
											2018-04-25 06:53:30 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // UnmarshalJSON - decodes JSON data to Resource.
 | 
					
						
							|  |  |  | func (r *Resource) UnmarshalJSON(data []byte) error { | 
					
						
							|  |  |  | 	var s string | 
					
						
							|  |  |  | 	if err := json.Unmarshal(data, &s); err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	parsedResource, err := parseResource(s) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	*r = parsedResource | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Validate - validates Resource is for given bucket or not.
 | 
					
						
							|  |  |  | func (r Resource) Validate(bucketName string) error { | 
					
						
							|  |  |  | 	if !r.IsValid() { | 
					
						
							| 
									
										
										
										
											2020-01-04 03:28:52 +08:00
										 |  |  | 		return Errorf("invalid resource") | 
					
						
							| 
									
										
										
										
											2018-04-25 06:53:30 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-17 07:17:00 +08:00
										 |  |  | 	if !wildcard.Match(r.BucketName, bucketName) { | 
					
						
							| 
									
										
										
										
											2020-01-04 03:28:52 +08:00
										 |  |  | 		return Errorf("bucket name does not match") | 
					
						
							| 
									
										
										
										
											2018-04-25 06:53:30 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // parseResource - parses string to Resource.
 | 
					
						
							|  |  |  | func parseResource(s string) (Resource, error) { | 
					
						
							|  |  |  | 	if !strings.HasPrefix(s, ResourceARNPrefix) { | 
					
						
							| 
									
										
										
										
											2020-01-04 03:28:52 +08:00
										 |  |  | 		return Resource{}, Errorf("invalid resource '%v'", s) | 
					
						
							| 
									
										
										
										
											2018-04-25 06:53:30 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	pattern := strings.TrimPrefix(s, ResourceARNPrefix) | 
					
						
							|  |  |  | 	tokens := strings.SplitN(pattern, "/", 2) | 
					
						
							|  |  |  | 	bucketName := tokens[0] | 
					
						
							|  |  |  | 	if bucketName == "" { | 
					
						
							| 
									
										
										
										
											2020-01-04 03:28:52 +08:00
										 |  |  | 		return Resource{}, Errorf("invalid resource format '%v'", s) | 
					
						
							| 
									
										
										
										
											2018-04-25 06:53:30 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return Resource{ | 
					
						
							| 
									
										
										
										
											2018-05-17 07:17:00 +08:00
										 |  |  | 		BucketName: bucketName, | 
					
						
							|  |  |  | 		Pattern:    pattern, | 
					
						
							| 
									
										
										
										
											2018-04-25 06:53:30 +08:00
										 |  |  | 	}, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // NewResource - creates new resource.
 | 
					
						
							|  |  |  | func NewResource(bucketName, keyName string) Resource { | 
					
						
							|  |  |  | 	pattern := bucketName | 
					
						
							|  |  |  | 	if keyName != "" { | 
					
						
							|  |  |  | 		if !strings.HasPrefix(keyName, "/") { | 
					
						
							|  |  |  | 			pattern += "/" | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		pattern += keyName | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return Resource{ | 
					
						
							| 
									
										
										
										
											2018-05-17 07:17:00 +08:00
										 |  |  | 		BucketName: bucketName, | 
					
						
							|  |  |  | 		Pattern:    pattern, | 
					
						
							| 
									
										
										
										
											2018-04-25 06:53:30 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | } |