| 
									
										
										
										
											2019-11-02 06:53:16 +08:00
										 |  |  | /* | 
					
						
							|  |  |  |  * MinIO Cloud Storage, (C) 2019 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" | 
					
						
							| 
									
										
										
										
											2019-11-12 10:42:10 +08:00
										 |  |  | 	"errors" | 
					
						
							| 
									
										
										
										
											2019-12-25 05:49:48 +08:00
										 |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2020-04-27 12:42:41 +08:00
										 |  |  | 	"time" | 
					
						
							| 
									
										
										
										
											2019-11-12 10:42:10 +08:00
										 |  |  | 	"unicode/utf8" | 
					
						
							| 
									
										
										
										
											2019-11-02 06:53:16 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	etcd "github.com/coreos/etcd/clientv3" | 
					
						
							|  |  |  | 	"github.com/minio/minio/cmd/config" | 
					
						
							|  |  |  | 	"github.com/minio/minio/cmd/logger" | 
					
						
							|  |  |  | 	"github.com/minio/minio/pkg/auth" | 
					
						
							|  |  |  | 	"github.com/minio/minio/pkg/madmin" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func handleEncryptedConfigBackend(objAPI ObjectLayer, server bool) error { | 
					
						
							|  |  |  | 	if !server { | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-05 11:04:06 +08:00
										 |  |  | 	encrypted, err := checkBackendEncrypted(objAPI) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return fmt.Errorf("Unable to encrypt config %w", err) | 
					
						
							| 
									
										
										
										
											2019-11-02 06:53:16 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if encrypted { | 
					
						
							|  |  |  | 		// backend is encrypted, but credentials are not specified
 | 
					
						
							|  |  |  | 		// we shall fail right here. if not proceed forward.
 | 
					
						
							|  |  |  | 		if !globalConfigEncrypted || !globalActiveCred.IsValid() { | 
					
						
							|  |  |  | 			return config.ErrMissingCredentialsBackendEncrypted(nil) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		// backend is not yet encrypted, check if encryption of
 | 
					
						
							|  |  |  | 		// backend is requested if not return nil and proceed
 | 
					
						
							|  |  |  | 		// forward.
 | 
					
						
							|  |  |  | 		if !globalConfigEncrypted { | 
					
						
							|  |  |  | 			return nil | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if !globalActiveCred.IsValid() { | 
					
						
							| 
									
										
										
										
											2020-01-10 18:35:06 +08:00
										 |  |  | 			return config.ErrMissingCredentialsBackendEncrypted(nil) | 
					
						
							| 
									
										
										
										
											2019-11-02 06:53:16 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-05 11:04:06 +08:00
										 |  |  | 	// Migrate IAM configuration
 | 
					
						
							|  |  |  | 	if err = migrateConfigPrefixToEncrypted(objAPI, globalOldCred, encrypted); err != nil { | 
					
						
							|  |  |  | 		return fmt.Errorf("Unable to migrate all config at .minio.sys/config/: %w", err) | 
					
						
							| 
									
										
										
										
											2019-11-02 06:53:16 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-05-05 11:04:06 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							| 
									
										
										
										
											2019-11-02 06:53:16 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const ( | 
					
						
							|  |  |  | 	backendEncryptedFile = "backend-encrypted" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var ( | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 	backendEncryptedMigrationIncomplete = []byte("incomplete") | 
					
						
							|  |  |  | 	backendEncryptedMigrationComplete   = []byte("encrypted") | 
					
						
							| 
									
										
										
										
											2019-11-02 06:53:16 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func checkBackendEtcdEncrypted(ctx context.Context, client *etcd.Client) (bool, error) { | 
					
						
							|  |  |  | 	data, err := readKeyEtcd(ctx, client, backendEncryptedFile) | 
					
						
							|  |  |  | 	if err != nil && err != errConfigNotFound { | 
					
						
							|  |  |  | 		return false, err | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 	return err == nil && bytes.Equal(data, backendEncryptedMigrationComplete), nil | 
					
						
							| 
									
										
										
										
											2019-11-02 06:53:16 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func checkBackendEncrypted(objAPI ObjectLayer) (bool, error) { | 
					
						
							| 
									
										
										
										
											2020-04-10 00:30:02 +08:00
										 |  |  | 	data, err := readConfig(GlobalContext, objAPI, backendEncryptedFile) | 
					
						
							| 
									
										
										
										
											2019-11-02 06:53:16 +08:00
										 |  |  | 	if err != nil && err != errConfigNotFound { | 
					
						
							|  |  |  | 		return false, err | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 	return err == nil && bytes.Equal(data, backendEncryptedMigrationComplete), nil | 
					
						
							| 
									
										
										
										
											2019-11-02 06:53:16 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-12 04:01:21 +08:00
										 |  |  | // decryptData - decrypts input data with more that one credentials,
 | 
					
						
							|  |  |  | func decryptData(edata []byte, creds ...auth.Credentials) ([]byte, error) { | 
					
						
							|  |  |  | 	var err error | 
					
						
							|  |  |  | 	var data []byte | 
					
						
							|  |  |  | 	for _, cred := range creds { | 
					
						
							|  |  |  | 		data, err = madmin.DecryptData(cred.String(), bytes.NewReader(edata)) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			if err == madmin.ErrMaliciousData { | 
					
						
							|  |  |  | 				continue | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			return nil, err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		break | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return data, err | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 05:26:39 +08:00
										 |  |  | func migrateIAMConfigsEtcdToEncrypted(ctx context.Context, client *etcd.Client) error { | 
					
						
							| 
									
										
										
										
											2019-11-02 06:53:16 +08:00
										 |  |  | 	encrypted, err := checkBackendEtcdEncrypted(ctx, client) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if encrypted { | 
					
						
							|  |  |  | 		// backend is encrypted, but credentials are not specified
 | 
					
						
							|  |  |  | 		// we shall fail right here. if not proceed forward.
 | 
					
						
							|  |  |  | 		if !globalConfigEncrypted || !globalActiveCred.IsValid() { | 
					
						
							|  |  |  | 			return config.ErrMissingCredentialsBackendEncrypted(nil) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		// backend is not yet encrypted, check if encryption of
 | 
					
						
							|  |  |  | 		// backend is requested if not return nil and proceed
 | 
					
						
							|  |  |  | 		// forward.
 | 
					
						
							|  |  |  | 		if !globalConfigEncrypted { | 
					
						
							|  |  |  | 			return nil | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if !globalActiveCred.IsValid() { | 
					
						
							|  |  |  | 			return errInvalidArgument | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if encrypted { | 
					
						
							|  |  |  | 		// No key rotation requested, and backend is
 | 
					
						
							|  |  |  | 		// already encrypted. We proceed without migration.
 | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | 		if !globalOldCred.IsValid() { | 
					
						
							| 
									
										
										
										
											2019-11-02 06:53:16 +08:00
										 |  |  | 			return nil | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// No real reason to rotate if old and new creds are same.
 | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | 		if globalOldCred.Equal(globalActiveCred) { | 
					
						
							| 
									
										
										
										
											2019-11-02 06:53:16 +08:00
										 |  |  | 			return nil | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 		logger.Info("Attempting rotation of encrypted IAM users and policies on etcd with newly supplied credentials") | 
					
						
							| 
									
										
										
										
											2019-11-02 06:53:16 +08:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 		logger.Info("Attempting encryption of all IAM users and policies on etcd") | 
					
						
							| 
									
										
										
										
											2019-11-02 06:53:16 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-27 12:42:41 +08:00
										 |  |  | 	listCtx, cancel := context.WithTimeout(ctx, 1*time.Minute) | 
					
						
							|  |  |  | 	defer cancel() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	r, err := client.Get(listCtx, minioConfigPrefix, etcd.WithPrefix(), etcd.WithKeysOnly()) | 
					
						
							| 
									
										
										
										
											2019-11-02 06:53:16 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if err = saveKeyEtcd(ctx, client, backendEncryptedFile, backendEncryptedMigrationIncomplete); err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-02 06:53:16 +08:00
										 |  |  | 	for _, kv := range r.Kvs { | 
					
						
							|  |  |  | 		var ( | 
					
						
							|  |  |  | 			cdata    []byte | 
					
						
							|  |  |  | 			cencdata []byte | 
					
						
							|  |  |  | 		) | 
					
						
							|  |  |  | 		cdata, err = readKeyEtcd(ctx, client, string(kv.Key)) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			switch err { | 
					
						
							|  |  |  | 			case errConfigNotFound: | 
					
						
							|  |  |  | 				// Perhaps not present or someone deleted it.
 | 
					
						
							|  |  |  | 				continue | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		var data []byte | 
					
						
							| 
									
										
										
										
											2019-11-02 06:53:16 +08:00
										 |  |  | 		// Is rotating of creds requested?
 | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | 		if globalOldCred.IsValid() { | 
					
						
							|  |  |  | 			data, err = decryptData(cdata, globalOldCred, globalActiveCred) | 
					
						
							| 
									
										
										
										
											2019-11-02 06:53:16 +08:00
										 |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				if err == madmin.ErrMaliciousData { | 
					
						
							| 
									
										
										
										
											2019-11-12 04:01:21 +08:00
										 |  |  | 					return config.ErrInvalidRotatingCredentialsBackendEncrypted(nil) | 
					
						
							| 
									
										
										
										
											2019-11-02 06:53:16 +08:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2019-11-12 04:01:21 +08:00
										 |  |  | 				return err | 
					
						
							| 
									
										
										
										
											2019-11-02 06:53:16 +08:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2019-11-12 04:01:21 +08:00
										 |  |  | 		} else { | 
					
						
							|  |  |  | 			data = cdata | 
					
						
							| 
									
										
										
										
											2019-11-02 06:53:16 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-12 10:42:10 +08:00
										 |  |  | 		if !utf8.Valid(data) { | 
					
						
							| 
									
										
										
										
											2020-01-10 18:35:06 +08:00
										 |  |  | 			_, err = decryptData(data, globalActiveCred) | 
					
						
							|  |  |  | 			if err == nil { | 
					
						
							|  |  |  | 				// Config is already encrypted with right keys
 | 
					
						
							|  |  |  | 				continue | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			return errors.New("config data not in plain-text form or encrypted") | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		cencdata, err = madmin.EncryptData(globalActiveCred.String(), data) | 
					
						
							| 
									
										
										
										
											2019-11-02 06:53:16 +08:00
										 |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if err = saveKeyEtcd(ctx, client, string(kv.Key), cencdata); err != nil { | 
					
						
							|  |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-01-10 18:35:06 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | 	if encrypted && globalActiveCred.IsValid() && globalOldCred.IsValid() { | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 		logger.Info("Rotation complete, please make sure to unset MINIO_ACCESS_KEY_OLD and MINIO_SECRET_KEY_OLD envs") | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-01-10 18:35:06 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 	return saveKeyEtcd(ctx, client, backendEncryptedFile, backendEncryptedMigrationComplete) | 
					
						
							| 
									
										
										
										
											2019-11-02 06:53:16 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func migrateConfigPrefixToEncrypted(objAPI ObjectLayer, activeCredOld auth.Credentials, encrypted bool) error { | 
					
						
							|  |  |  | 	if encrypted { | 
					
						
							|  |  |  | 		// No key rotation requested, and backend is
 | 
					
						
							|  |  |  | 		// already encrypted. We proceed without migration.
 | 
					
						
							|  |  |  | 		if !activeCredOld.IsValid() { | 
					
						
							|  |  |  | 			return nil | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// No real reason to rotate if old and new creds are same.
 | 
					
						
							|  |  |  | 		if activeCredOld.Equal(globalActiveCred) { | 
					
						
							|  |  |  | 			return nil | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 		logger.Info("Attempting rotation of encrypted config, IAM users and policies on MinIO with newly supplied credentials") | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		logger.Info("Attempting encryption of all config, IAM users and policies on MinIO backend") | 
					
						
							| 
									
										
										
										
											2019-11-02 06:53:16 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-10 00:30:02 +08:00
										 |  |  | 	err := saveConfig(GlobalContext, objAPI, backendEncryptedFile, backendEncryptedMigrationIncomplete) | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							| 
									
										
										
										
											2019-11-02 06:53:16 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var marker string | 
					
						
							|  |  |  | 	for { | 
					
						
							| 
									
										
										
										
											2020-04-10 00:30:02 +08:00
										 |  |  | 		res, err := objAPI.ListObjects(GlobalContext, minioMetaBucket, | 
					
						
							| 
									
										
										
										
											2020-01-10 18:35:06 +08:00
										 |  |  | 			minioConfigPrefix, marker, "", maxObjectList) | 
					
						
							| 
									
										
										
										
											2019-11-02 06:53:16 +08:00
										 |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		for _, obj := range res.Objects { | 
					
						
							|  |  |  | 			var ( | 
					
						
							|  |  |  | 				cdata    []byte | 
					
						
							|  |  |  | 				cencdata []byte | 
					
						
							|  |  |  | 			) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-10 00:30:02 +08:00
										 |  |  | 			cdata, err = readConfig(GlobalContext, objAPI, obj.Name) | 
					
						
							| 
									
										
										
										
											2019-11-02 06:53:16 +08:00
										 |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				return err | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 			var data []byte | 
					
						
							| 
									
										
										
										
											2019-11-02 06:53:16 +08:00
										 |  |  | 			// Is rotating of creds requested?
 | 
					
						
							|  |  |  | 			if activeCredOld.IsValid() { | 
					
						
							| 
									
										
										
										
											2019-11-12 04:01:21 +08:00
										 |  |  | 				data, err = decryptData(cdata, activeCredOld, globalActiveCred) | 
					
						
							| 
									
										
										
										
											2019-11-02 06:53:16 +08:00
										 |  |  | 				if err != nil { | 
					
						
							|  |  |  | 					if err == madmin.ErrMaliciousData { | 
					
						
							| 
									
										
										
										
											2019-11-12 04:01:21 +08:00
										 |  |  | 						return config.ErrInvalidRotatingCredentialsBackendEncrypted(nil) | 
					
						
							| 
									
										
										
										
											2019-11-02 06:53:16 +08:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2019-11-12 04:01:21 +08:00
										 |  |  | 					return err | 
					
						
							| 
									
										
										
										
											2019-11-02 06:53:16 +08:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2019-11-12 04:01:21 +08:00
										 |  |  | 			} else { | 
					
						
							|  |  |  | 				data = cdata | 
					
						
							| 
									
										
										
										
											2019-11-02 06:53:16 +08:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-12 10:42:10 +08:00
										 |  |  | 			if !utf8.Valid(data) { | 
					
						
							| 
									
										
										
										
											2020-01-10 18:35:06 +08:00
										 |  |  | 				_, err = decryptData(data, globalActiveCred) | 
					
						
							|  |  |  | 				if err == nil { | 
					
						
							|  |  |  | 					// Config is already encrypted with right keys
 | 
					
						
							|  |  |  | 					continue | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				return errors.New("config data not in plain-text form or encrypted") | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			cencdata, err = madmin.EncryptData(globalActiveCred.String(), data) | 
					
						
							| 
									
										
										
										
											2019-11-02 06:53:16 +08:00
										 |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				return err | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-10 00:30:02 +08:00
										 |  |  | 			if err = saveConfig(GlobalContext, objAPI, obj.Name, cencdata); err != nil { | 
					
						
							| 
									
										
										
										
											2019-11-02 06:53:16 +08:00
										 |  |  | 				return err | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if !res.IsTruncated { | 
					
						
							|  |  |  | 			break | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		marker = res.NextMarker | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-10 18:35:06 +08:00
										 |  |  | 	if encrypted && globalActiveCred.IsValid() && activeCredOld.IsValid() { | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 		logger.Info("Rotation complete, please make sure to unset MINIO_ACCESS_KEY_OLD and MINIO_SECRET_KEY_OLD envs") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-10 00:30:02 +08:00
										 |  |  | 	return saveConfig(GlobalContext, objAPI, backendEncryptedFile, backendEncryptedMigrationComplete) | 
					
						
							| 
									
										
										
										
											2019-11-02 06:53:16 +08:00
										 |  |  | } |