| 
									
										
										
										
											2020-05-20 04:53:54 +08:00
										 |  |  | /* | 
					
						
							|  |  |  |  * MinIO Cloud Storage, (C) 2020 MinIO, Inc. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Licensed under the Apache License, Version 2.0 (the "License"); | 
					
						
							|  |  |  |  * you may not use this file except in compliance with the License. | 
					
						
							|  |  |  |  * You may obtain a copy of the License at | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *     http://www.apache.org/licenses/LICENSE-2.0
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Unless required by applicable law or agreed to in writing, software | 
					
						
							|  |  |  |  * distributed under the License is distributed on an "AS IS" BASIS, | 
					
						
							|  |  |  |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
					
						
							|  |  |  |  * See the License for the specific language governing permissions and | 
					
						
							|  |  |  |  * limitations under the License. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | package cmd | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"bytes" | 
					
						
							|  |  |  | 	"context" | 
					
						
							| 
									
										
										
										
											2020-05-21 01:18:15 +08:00
										 |  |  | 	"errors" | 
					
						
							| 
									
										
										
										
											2020-05-20 04:53:54 +08:00
										 |  |  | 	"fmt" | 
					
						
							|  |  |  | 	"sync" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-15 00:38:05 +08:00
										 |  |  | 	"github.com/minio/minio-go/v7/pkg/tags" | 
					
						
							| 
									
										
										
										
											2020-12-22 08:21:33 +08:00
										 |  |  | 	"github.com/minio/minio/cmd/crypto" | 
					
						
							| 
									
										
										
										
											2020-08-21 01:38:53 +08:00
										 |  |  | 	"github.com/minio/minio/cmd/logger" | 
					
						
							| 
									
										
										
										
											2020-05-21 01:18:15 +08:00
										 |  |  | 	bucketsse "github.com/minio/minio/pkg/bucket/encryption" | 
					
						
							|  |  |  | 	"github.com/minio/minio/pkg/bucket/lifecycle" | 
					
						
							|  |  |  | 	objectlock "github.com/minio/minio/pkg/bucket/object/lock" | 
					
						
							| 
									
										
										
										
											2020-05-20 04:53:54 +08:00
										 |  |  | 	"github.com/minio/minio/pkg/bucket/policy" | 
					
						
							| 
									
										
										
										
											2020-07-22 08:49:56 +08:00
										 |  |  | 	"github.com/minio/minio/pkg/bucket/replication" | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 	"github.com/minio/minio/pkg/bucket/versioning" | 
					
						
							| 
									
										
										
										
											2020-05-21 01:18:15 +08:00
										 |  |  | 	"github.com/minio/minio/pkg/event" | 
					
						
							|  |  |  | 	"github.com/minio/minio/pkg/madmin" | 
					
						
							| 
									
										
										
										
											2020-06-02 13:32:53 +08:00
										 |  |  | 	"github.com/minio/minio/pkg/sync/errgroup" | 
					
						
							| 
									
										
										
										
											2020-05-20 04:53:54 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // BucketMetadataSys captures all bucket metadata for a given cluster.
 | 
					
						
							|  |  |  | type BucketMetadataSys struct { | 
					
						
							|  |  |  | 	sync.RWMutex | 
					
						
							|  |  |  | 	metadataMap map[string]BucketMetadata | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Remove bucket metadata from memory.
 | 
					
						
							|  |  |  | func (sys *BucketMetadataSys) Remove(bucket string) { | 
					
						
							| 
									
										
										
										
											2020-06-04 04:18:54 +08:00
										 |  |  | 	if globalIsGateway { | 
					
						
							| 
									
										
										
										
											2020-05-20 04:53:54 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	sys.Lock() | 
					
						
							|  |  |  | 	delete(sys.metadataMap, bucket) | 
					
						
							| 
									
										
										
										
											2020-10-17 08:59:31 +08:00
										 |  |  | 	globalBucketMonitor.DeleteBucket(bucket) | 
					
						
							| 
									
										
										
										
											2020-05-20 04:53:54 +08:00
										 |  |  | 	sys.Unlock() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Set - sets a new metadata in-memory.
 | 
					
						
							|  |  |  | // Only a shallow copy is saved and fields with references
 | 
					
						
							|  |  |  | // cannot be modified without causing a race condition,
 | 
					
						
							|  |  |  | // so they should be replaced atomically and not appended to, etc.
 | 
					
						
							|  |  |  | // Data is not persisted to disk.
 | 
					
						
							|  |  |  | func (sys *BucketMetadataSys) Set(bucket string, meta BucketMetadata) { | 
					
						
							|  |  |  | 	if globalIsGateway { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if bucket != minioMetaBucket { | 
					
						
							|  |  |  | 		sys.Lock() | 
					
						
							|  |  |  | 		sys.metadataMap[bucket] = meta | 
					
						
							|  |  |  | 		sys.Unlock() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Update update bucket metadata for the specified config file.
 | 
					
						
							|  |  |  | // The configData data should not be modified after being sent here.
 | 
					
						
							|  |  |  | func (sys *BucketMetadataSys) Update(bucket string, configFile string, configData []byte) error { | 
					
						
							| 
									
										
										
										
											2020-10-10 00:59:52 +08:00
										 |  |  | 	objAPI := newObjectLayerFn() | 
					
						
							| 
									
										
										
										
											2020-05-20 04:53:54 +08:00
										 |  |  | 	if objAPI == nil { | 
					
						
							|  |  |  | 		return errServerNotInitialized | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-04 04:18:54 +08:00
										 |  |  | 	if globalIsGateway { | 
					
						
							| 
									
										
										
										
											2020-05-22 02:03:59 +08:00
										 |  |  | 		// This code is needed only for gateway implementations.
 | 
					
						
							| 
									
										
										
										
											2020-06-16 13:09:39 +08:00
										 |  |  | 		switch configFile { | 
					
						
							|  |  |  | 		case bucketSSEConfig: | 
					
						
							| 
									
										
										
										
											2020-08-26 23:52:46 +08:00
										 |  |  | 			if globalGatewayName == NASBackendGateway { | 
					
						
							| 
									
										
										
										
											2020-06-16 13:09:39 +08:00
										 |  |  | 				meta, err := loadBucketMetadata(GlobalContext, objAPI, bucket) | 
					
						
							|  |  |  | 				if err != nil { | 
					
						
							|  |  |  | 					return err | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				meta.EncryptionConfigXML = configData | 
					
						
							|  |  |  | 				return meta.Save(GlobalContext, objAPI) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		case bucketLifecycleConfig: | 
					
						
							| 
									
										
										
										
											2020-08-26 23:52:46 +08:00
										 |  |  | 			if globalGatewayName == NASBackendGateway { | 
					
						
							| 
									
										
										
										
											2020-06-16 13:09:39 +08:00
										 |  |  | 				meta, err := loadBucketMetadata(GlobalContext, objAPI, bucket) | 
					
						
							|  |  |  | 				if err != nil { | 
					
						
							|  |  |  | 					return err | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				meta.LifecycleConfigXML = configData | 
					
						
							|  |  |  | 				return meta.Save(GlobalContext, objAPI) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		case bucketTaggingConfig: | 
					
						
							| 
									
										
										
										
											2020-08-26 23:52:46 +08:00
										 |  |  | 			if globalGatewayName == NASBackendGateway { | 
					
						
							| 
									
										
										
										
											2020-06-16 13:09:39 +08:00
										 |  |  | 				meta, err := loadBucketMetadata(GlobalContext, objAPI, bucket) | 
					
						
							|  |  |  | 				if err != nil { | 
					
						
							|  |  |  | 					return err | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				meta.TaggingConfigXML = configData | 
					
						
							|  |  |  | 				return meta.Save(GlobalContext, objAPI) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		case bucketNotificationConfig: | 
					
						
							| 
									
										
										
										
											2020-08-26 23:52:46 +08:00
										 |  |  | 			if globalGatewayName == NASBackendGateway { | 
					
						
							| 
									
										
										
										
											2020-06-16 13:09:39 +08:00
										 |  |  | 				meta, err := loadBucketMetadata(GlobalContext, objAPI, bucket) | 
					
						
							|  |  |  | 				if err != nil { | 
					
						
							|  |  |  | 					return err | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				meta.NotificationConfigXML = configData | 
					
						
							|  |  |  | 				return meta.Save(GlobalContext, objAPI) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		case bucketPolicyConfig: | 
					
						
							| 
									
										
										
										
											2020-06-04 04:18:54 +08:00
										 |  |  | 			if configData == nil { | 
					
						
							|  |  |  | 				return objAPI.DeleteBucketPolicy(GlobalContext, bucket) | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2020-05-20 04:53:54 +08:00
										 |  |  | 			config, err := policy.ParseConfig(bytes.NewReader(configData), bucket) | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				return err | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			return objAPI.SetBucketPolicy(GlobalContext, bucket, config) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return NotImplemented{} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if bucket == minioMetaBucket { | 
					
						
							|  |  |  | 		return errInvalidArgument | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-21 01:18:15 +08:00
										 |  |  | 	meta, err := loadBucketMetadata(GlobalContext, objAPI, bucket) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							| 
									
										
										
										
											2020-05-20 04:53:54 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	switch configFile { | 
					
						
							|  |  |  | 	case bucketPolicyConfig: | 
					
						
							|  |  |  | 		meta.PolicyConfigJSON = configData | 
					
						
							|  |  |  | 	case bucketNotificationConfig: | 
					
						
							| 
									
										
										
										
											2020-05-22 02:03:59 +08:00
										 |  |  | 		meta.NotificationConfigXML = configData | 
					
						
							| 
									
										
										
										
											2020-05-20 04:53:54 +08:00
										 |  |  | 	case bucketLifecycleConfig: | 
					
						
							|  |  |  | 		meta.LifecycleConfigXML = configData | 
					
						
							|  |  |  | 	case bucketSSEConfig: | 
					
						
							|  |  |  | 		meta.EncryptionConfigXML = configData | 
					
						
							| 
									
										
										
										
											2020-06-16 13:09:39 +08:00
										 |  |  | 	case bucketTaggingConfig: | 
					
						
							| 
									
										
										
										
											2020-05-20 04:53:54 +08:00
										 |  |  | 		meta.TaggingConfigXML = configData | 
					
						
							| 
									
										
										
										
											2020-08-21 04:18:06 +08:00
										 |  |  | 	case bucketQuotaConfigFile: | 
					
						
							|  |  |  | 		meta.QuotaConfigJSON = configData | 
					
						
							| 
									
										
										
										
											2020-05-20 04:53:54 +08:00
										 |  |  | 	case objectLockConfig: | 
					
						
							| 
									
										
										
										
											2020-08-21 04:18:06 +08:00
										 |  |  | 		if !globalIsErasure && !globalIsDistErasure { | 
					
						
							|  |  |  | 			return NotImplemented{} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-05-22 02:03:59 +08:00
										 |  |  | 		meta.ObjectLockConfigXML = configData | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 	case bucketVersioningConfig: | 
					
						
							| 
									
										
										
										
											2020-08-21 04:18:06 +08:00
										 |  |  | 		if !globalIsErasure && !globalIsDistErasure { | 
					
						
							|  |  |  | 			return NotImplemented{} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 		meta.VersioningConfigXML = configData | 
					
						
							| 
									
										
										
										
											2020-07-22 08:49:56 +08:00
										 |  |  | 	case bucketReplicationConfig: | 
					
						
							| 
									
										
										
										
											2020-08-21 04:18:06 +08:00
										 |  |  | 		if !globalIsErasure && !globalIsDistErasure { | 
					
						
							|  |  |  | 			return NotImplemented{} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-07-22 08:49:56 +08:00
										 |  |  | 		meta.ReplicationConfigXML = configData | 
					
						
							| 
									
										
										
										
											2020-07-29 02:50:47 +08:00
										 |  |  | 	case bucketTargetsFile: | 
					
						
							| 
									
										
										
										
											2020-12-22 08:21:33 +08:00
										 |  |  | 		meta.BucketTargetsConfigJSON, meta.BucketTargetsConfigMetaJSON, err = encryptBucketMetadata(meta.Name, configData, crypto.Context{bucket: meta.Name, bucketTargetsFile: bucketTargetsFile}) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return fmt.Errorf("Error encrypting bucket target metadata %w", err) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-05-20 04:53:54 +08:00
										 |  |  | 	default: | 
					
						
							|  |  |  | 		return fmt.Errorf("Unknown bucket %s metadata update requested %s", bucket, configFile) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if err := meta.Save(GlobalContext, objAPI); err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-21 01:18:15 +08:00
										 |  |  | 	sys.Set(bucket, meta) | 
					
						
							|  |  |  | 	globalNotificationSys.LoadBucketMetadata(GlobalContext, bucket) | 
					
						
							| 
									
										
										
										
											2020-05-20 04:53:54 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Get metadata for a bucket.
 | 
					
						
							|  |  |  | // If no metadata exists errConfigNotFound is returned and a new metadata is returned.
 | 
					
						
							|  |  |  | // Only a shallow copy is returned, so referenced data should not be modified,
 | 
					
						
							|  |  |  | // but can be replaced atomically.
 | 
					
						
							| 
									
										
										
										
											2020-08-21 01:38:53 +08:00
										 |  |  | //
 | 
					
						
							|  |  |  | // This function should only be used with
 | 
					
						
							|  |  |  | // - GetBucketInfo
 | 
					
						
							|  |  |  | // - ListBuckets
 | 
					
						
							|  |  |  | // For all other bucket specific metadata, use the relevant
 | 
					
						
							|  |  |  | // calls implemented specifically for each of those features.
 | 
					
						
							| 
									
										
										
										
											2020-05-20 04:53:54 +08:00
										 |  |  | func (sys *BucketMetadataSys) Get(bucket string) (BucketMetadata, error) { | 
					
						
							|  |  |  | 	if globalIsGateway || bucket == minioMetaBucket { | 
					
						
							|  |  |  | 		return newBucketMetadata(bucket), errConfigNotFound | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sys.RLock() | 
					
						
							|  |  |  | 	defer sys.RUnlock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	meta, ok := sys.metadataMap[bucket] | 
					
						
							|  |  |  | 	if !ok { | 
					
						
							|  |  |  | 		return newBucketMetadata(bucket), errConfigNotFound | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return meta, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | // GetVersioningConfig returns configured versioning config
 | 
					
						
							|  |  |  | // The returned object may not be modified.
 | 
					
						
							|  |  |  | func (sys *BucketMetadataSys) GetVersioningConfig(bucket string) (*versioning.Versioning, error) { | 
					
						
							|  |  |  | 	meta, err := sys.GetConfig(bucket) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return meta.versioningConfig, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-21 01:18:15 +08:00
										 |  |  | // GetTaggingConfig returns configured tagging config
 | 
					
						
							|  |  |  | // The returned object may not be modified.
 | 
					
						
							|  |  |  | func (sys *BucketMetadataSys) GetTaggingConfig(bucket string) (*tags.Tags, error) { | 
					
						
							|  |  |  | 	meta, err := sys.GetConfig(bucket) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		if errors.Is(err, errConfigNotFound) { | 
					
						
							|  |  |  | 			return nil, BucketTaggingNotFound{Bucket: bucket} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							| 
									
										
										
										
											2020-05-20 04:53:54 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-05-21 01:18:15 +08:00
										 |  |  | 	if meta.taggingConfig == nil { | 
					
						
							|  |  |  | 		return nil, BucketTaggingNotFound{Bucket: bucket} | 
					
						
							| 
									
										
										
										
											2020-05-20 04:53:54 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-05-21 01:18:15 +08:00
										 |  |  | 	return meta.taggingConfig, nil | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2020-05-20 04:53:54 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-21 01:18:15 +08:00
										 |  |  | // GetObjectLockConfig returns configured object lock config
 | 
					
						
							|  |  |  | // The returned object may not be modified.
 | 
					
						
							|  |  |  | func (sys *BucketMetadataSys) GetObjectLockConfig(bucket string) (*objectlock.Config, error) { | 
					
						
							|  |  |  | 	meta, err := sys.GetConfig(bucket) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		if errors.Is(err, errConfigNotFound) { | 
					
						
							|  |  |  | 			return nil, BucketObjectLockConfigNotFound{Bucket: bucket} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if meta.objectLockConfig == nil { | 
					
						
							|  |  |  | 		return nil, BucketObjectLockConfigNotFound{Bucket: bucket} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return meta.objectLockConfig, nil | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2020-05-20 04:53:54 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-21 01:18:15 +08:00
										 |  |  | // GetLifecycleConfig returns configured lifecycle config
 | 
					
						
							|  |  |  | // The returned object may not be modified.
 | 
					
						
							|  |  |  | func (sys *BucketMetadataSys) GetLifecycleConfig(bucket string) (*lifecycle.Lifecycle, error) { | 
					
						
							|  |  |  | 	meta, err := sys.GetConfig(bucket) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		if errors.Is(err, errConfigNotFound) { | 
					
						
							|  |  |  | 			return nil, BucketLifecycleNotFound{Bucket: bucket} | 
					
						
							| 
									
										
										
										
											2020-05-20 04:53:54 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-05-21 01:18:15 +08:00
										 |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if meta.lifecycleConfig == nil { | 
					
						
							|  |  |  | 		return nil, BucketLifecycleNotFound{Bucket: bucket} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return meta.lifecycleConfig, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // GetNotificationConfig returns configured notification config
 | 
					
						
							|  |  |  | // The returned object may not be modified.
 | 
					
						
							|  |  |  | func (sys *BucketMetadataSys) GetNotificationConfig(bucket string) (*event.Config, error) { | 
					
						
							| 
									
										
										
										
											2020-08-26 23:52:46 +08:00
										 |  |  | 	if globalIsGateway && globalGatewayName == NASBackendGateway { | 
					
						
							| 
									
										
										
										
											2020-06-04 04:18:54 +08:00
										 |  |  | 		// Only needed in case of NAS gateway.
 | 
					
						
							| 
									
										
										
										
											2020-10-10 00:59:52 +08:00
										 |  |  | 		objAPI := newObjectLayerFn() | 
					
						
							| 
									
										
										
										
											2020-06-04 04:18:54 +08:00
										 |  |  | 		if objAPI == nil { | 
					
						
							|  |  |  | 			return nil, errServerNotInitialized | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		meta, err := loadBucketMetadata(GlobalContext, objAPI, bucket) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return nil, err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return meta.notificationConfig, nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-21 01:18:15 +08:00
										 |  |  | 	meta, err := sys.GetConfig(bucket) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return meta.notificationConfig, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // GetSSEConfig returns configured SSE config
 | 
					
						
							|  |  |  | // The returned object may not be modified.
 | 
					
						
							|  |  |  | func (sys *BucketMetadataSys) GetSSEConfig(bucket string) (*bucketsse.BucketSSEConfig, error) { | 
					
						
							|  |  |  | 	meta, err := sys.GetConfig(bucket) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		if errors.Is(err, errConfigNotFound) { | 
					
						
							|  |  |  | 			return nil, BucketSSEConfigNotFound{Bucket: bucket} | 
					
						
							| 
									
										
										
										
											2020-05-20 04:53:54 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-05-21 01:18:15 +08:00
										 |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if meta.sseConfig == nil { | 
					
						
							|  |  |  | 		return nil, BucketSSEConfigNotFound{Bucket: bucket} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return meta.sseConfig, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // GetPolicyConfig returns configured bucket policy
 | 
					
						
							|  |  |  | // The returned object may not be modified.
 | 
					
						
							|  |  |  | func (sys *BucketMetadataSys) GetPolicyConfig(bucket string) (*policy.Policy, error) { | 
					
						
							| 
									
										
										
										
											2020-06-04 04:18:54 +08:00
										 |  |  | 	if globalIsGateway { | 
					
						
							| 
									
										
										
										
											2020-10-10 00:59:52 +08:00
										 |  |  | 		objAPI := newObjectLayerFn() | 
					
						
							| 
									
										
										
										
											2020-06-04 04:18:54 +08:00
										 |  |  | 		if objAPI == nil { | 
					
						
							|  |  |  | 			return nil, errServerNotInitialized | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return objAPI.GetBucketPolicy(GlobalContext, bucket) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-21 01:18:15 +08:00
										 |  |  | 	meta, err := sys.GetConfig(bucket) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		if errors.Is(err, errConfigNotFound) { | 
					
						
							|  |  |  | 			return nil, BucketPolicyNotFound{Bucket: bucket} | 
					
						
							| 
									
										
										
										
											2020-05-20 04:53:54 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-05-21 01:18:15 +08:00
										 |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if meta.policyConfig == nil { | 
					
						
							|  |  |  | 		return nil, BucketPolicyNotFound{Bucket: bucket} | 
					
						
							| 
									
										
										
										
											2020-05-20 04:53:54 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-05-21 01:18:15 +08:00
										 |  |  | 	return meta.policyConfig, nil | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2020-05-20 04:53:54 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-21 01:18:15 +08:00
										 |  |  | // GetQuotaConfig returns configured bucket quota
 | 
					
						
							|  |  |  | // The returned object may not be modified.
 | 
					
						
							|  |  |  | func (sys *BucketMetadataSys) GetQuotaConfig(bucket string) (*madmin.BucketQuota, error) { | 
					
						
							|  |  |  | 	meta, err := sys.GetConfig(bucket) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							| 
									
										
										
										
											2020-05-20 04:53:54 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-05-21 01:18:15 +08:00
										 |  |  | 	return meta.quotaConfig, nil | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2020-05-20 04:53:54 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-22 08:49:56 +08:00
										 |  |  | // GetReplicationConfig returns configured bucket replication config
 | 
					
						
							|  |  |  | // The returned object may not be modified.
 | 
					
						
							|  |  |  | func (sys *BucketMetadataSys) GetReplicationConfig(ctx context.Context, bucket string) (*replication.Config, error) { | 
					
						
							|  |  |  | 	meta, err := sys.GetConfig(bucket) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		if errors.Is(err, errConfigNotFound) { | 
					
						
							|  |  |  | 			return nil, BucketReplicationConfigNotFound{Bucket: bucket} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if meta.replicationConfig == nil { | 
					
						
							|  |  |  | 		return nil, BucketReplicationConfigNotFound{Bucket: bucket} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return meta.replicationConfig, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-31 10:55:22 +08:00
										 |  |  | // GetBucketTargetsConfig returns configured bucket targets for this bucket
 | 
					
						
							| 
									
										
										
										
											2020-07-22 08:49:56 +08:00
										 |  |  | // The returned object may not be modified.
 | 
					
						
							| 
									
										
										
										
											2020-07-31 10:55:22 +08:00
										 |  |  | func (sys *BucketMetadataSys) GetBucketTargetsConfig(bucket string) (*madmin.BucketTargets, error) { | 
					
						
							| 
									
										
										
										
											2020-07-22 08:49:56 +08:00
										 |  |  | 	meta, err := sys.GetConfig(bucket) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-07-29 02:50:47 +08:00
										 |  |  | 	if meta.bucketTargetConfig == nil { | 
					
						
							| 
									
										
										
										
											2020-07-31 10:55:22 +08:00
										 |  |  | 		return nil, BucketRemoteTargetNotFound{Bucket: bucket} | 
					
						
							| 
									
										
										
										
											2020-07-22 08:49:56 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-07-29 02:50:47 +08:00
										 |  |  | 	return meta.bucketTargetConfig, nil | 
					
						
							| 
									
										
										
										
											2020-07-22 08:49:56 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-10 11:36:00 +08:00
										 |  |  | // GetBucketTarget returns the target for the bucket and arn.
 | 
					
						
							|  |  |  | func (sys *BucketMetadataSys) GetBucketTarget(bucket string, arn string) (madmin.BucketTarget, error) { | 
					
						
							|  |  |  | 	targets, err := sys.GetBucketTargetsConfig(bucket) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return madmin.BucketTarget{}, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	for _, t := range targets.Targets { | 
					
						
							|  |  |  | 		if t.Arn == arn { | 
					
						
							|  |  |  | 			return t, nil | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return madmin.BucketTarget{}, errConfigNotFound | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-22 08:49:56 +08:00
										 |  |  | // GetConfig returns a specific configuration from the bucket metadata.
 | 
					
						
							| 
									
										
										
										
											2020-05-21 01:18:15 +08:00
										 |  |  | // The returned object may not be modified.
 | 
					
						
							|  |  |  | func (sys *BucketMetadataSys) GetConfig(bucket string) (BucketMetadata, error) { | 
					
						
							| 
									
										
										
										
											2020-10-10 00:59:52 +08:00
										 |  |  | 	objAPI := newObjectLayerFn() | 
					
						
							| 
									
										
										
										
											2020-05-21 01:18:15 +08:00
										 |  |  | 	if objAPI == nil { | 
					
						
							|  |  |  | 		return newBucketMetadata(bucket), errServerNotInitialized | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-04 04:18:54 +08:00
										 |  |  | 	if globalIsGateway { | 
					
						
							| 
									
										
										
										
											2020-05-21 01:18:15 +08:00
										 |  |  | 		return newBucketMetadata(bucket), NotImplemented{} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if bucket == minioMetaBucket { | 
					
						
							|  |  |  | 		return newBucketMetadata(bucket), errInvalidArgument | 
					
						
							| 
									
										
										
										
											2020-05-20 04:53:54 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-21 05:11:13 +08:00
										 |  |  | 	sys.RLock() | 
					
						
							| 
									
										
										
										
											2020-05-21 01:18:15 +08:00
										 |  |  | 	meta, ok := sys.metadataMap[bucket] | 
					
						
							| 
									
										
										
										
											2020-05-21 05:11:13 +08:00
										 |  |  | 	sys.RUnlock() | 
					
						
							| 
									
										
										
										
											2020-05-21 01:18:15 +08:00
										 |  |  | 	if ok { | 
					
						
							|  |  |  | 		return meta, nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	meta, err := loadBucketMetadata(GlobalContext, objAPI, bucket) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return meta, err | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-05-21 05:11:13 +08:00
										 |  |  | 	sys.Lock() | 
					
						
							| 
									
										
										
										
											2020-05-21 01:18:15 +08:00
										 |  |  | 	sys.metadataMap[bucket] = meta | 
					
						
							| 
									
										
										
										
											2020-05-21 05:11:13 +08:00
										 |  |  | 	sys.Unlock() | 
					
						
							| 
									
										
										
										
											2020-05-21 01:18:15 +08:00
										 |  |  | 	return meta, nil | 
					
						
							| 
									
										
										
										
											2020-05-20 04:53:54 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Init - initializes bucket metadata system for all buckets.
 | 
					
						
							|  |  |  | func (sys *BucketMetadataSys) Init(ctx context.Context, buckets []BucketInfo, objAPI ObjectLayer) error { | 
					
						
							|  |  |  | 	if objAPI == nil { | 
					
						
							|  |  |  | 		return errServerNotInitialized | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// In gateway mode, we don't need to load the policies
 | 
					
						
							|  |  |  | 	// from the backend.
 | 
					
						
							|  |  |  | 	if globalIsGateway { | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-21 01:38:53 +08:00
										 |  |  | 	// Load bucket metadata sys in background
 | 
					
						
							| 
									
										
										
										
											2020-10-23 04:36:24 +08:00
										 |  |  | 	go sys.load(ctx, buckets, objAPI) | 
					
						
							| 
									
										
										
										
											2020-08-21 01:38:53 +08:00
										 |  |  | 	return nil | 
					
						
							| 
									
										
										
										
											2020-05-20 04:53:54 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-02 13:32:53 +08:00
										 |  |  | // concurrently load bucket metadata to speed up loading bucket metadata.
 | 
					
						
							| 
									
										
										
										
											2020-10-23 04:36:24 +08:00
										 |  |  | func (sys *BucketMetadataSys) concurrentLoad(ctx context.Context, buckets []BucketInfo, objAPI ObjectLayer) { | 
					
						
							| 
									
										
										
										
											2020-06-02 13:32:53 +08:00
										 |  |  | 	g := errgroup.WithNErrs(len(buckets)) | 
					
						
							|  |  |  | 	for index := range buckets { | 
					
						
							|  |  |  | 		index := index | 
					
						
							|  |  |  | 		g.Go(func() error { | 
					
						
							| 
									
										
										
										
											2020-12-15 04:07:07 +08:00
										 |  |  | 			_, _ = objAPI.HealBucket(ctx, buckets[index].Name, madmin.HealOpts{ | 
					
						
							|  |  |  | 				// Ensure heal opts for bucket metadata be deep healed all the time.
 | 
					
						
							|  |  |  | 				ScanMode: madmin.HealDeepScan, | 
					
						
							|  |  |  | 			}) | 
					
						
							| 
									
										
										
										
											2020-06-02 13:32:53 +08:00
										 |  |  | 			meta, err := loadBucketMetadata(ctx, objAPI, buckets[index].Name) | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				return err | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			sys.Lock() | 
					
						
							|  |  |  | 			sys.metadataMap[buckets[index].Name] = meta | 
					
						
							|  |  |  | 			sys.Unlock() | 
					
						
							|  |  |  | 			return nil | 
					
						
							|  |  |  | 		}, index) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	for _, err := range g.Wait() { | 
					
						
							| 
									
										
										
										
											2020-05-20 04:53:54 +08:00
										 |  |  | 		if err != nil { | 
					
						
							| 
									
										
										
										
											2020-10-23 04:36:24 +08:00
										 |  |  | 			logger.LogIf(ctx, err) | 
					
						
							| 
									
										
										
										
											2020-05-20 04:53:54 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-02 13:32:53 +08:00
										 |  |  | // Loads bucket metadata for all buckets into BucketMetadataSys.
 | 
					
						
							| 
									
										
										
										
											2020-10-23 04:36:24 +08:00
										 |  |  | func (sys *BucketMetadataSys) load(ctx context.Context, buckets []BucketInfo, objAPI ObjectLayer) { | 
					
						
							| 
									
										
										
										
											2020-06-02 13:32:53 +08:00
										 |  |  | 	count := 100 // load 100 bucket metadata at a time.
 | 
					
						
							|  |  |  | 	for { | 
					
						
							|  |  |  | 		if len(buckets) < count { | 
					
						
							| 
									
										
										
										
											2020-10-23 04:36:24 +08:00
										 |  |  | 			sys.concurrentLoad(ctx, buckets, objAPI) | 
					
						
							|  |  |  | 			return | 
					
						
							| 
									
										
										
										
											2020-06-02 13:32:53 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-10-23 04:36:24 +08:00
										 |  |  | 		sys.concurrentLoad(ctx, buckets[:count], objAPI) | 
					
						
							| 
									
										
										
										
											2020-06-02 13:32:53 +08:00
										 |  |  | 		buckets = buckets[count:] | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-20 04:53:54 +08:00
										 |  |  | // NewBucketMetadataSys - creates new policy system.
 | 
					
						
							|  |  |  | func NewBucketMetadataSys() *BucketMetadataSys { | 
					
						
							|  |  |  | 	return &BucketMetadataSys{ | 
					
						
							|  |  |  | 		metadataMap: make(map[string]BucketMetadata), | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } |