storj.io/minio@v0.0.0-20230509071714-0cbc90f649b1/cmd/config.go (about)

     1  /*
     2   * MinIO Cloud Storage, (C) 2018 MinIO, Inc.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package cmd
    18  
    19  import (
    20  	"context"
    21  	"encoding/json"
    22  	"path"
    23  	"sort"
    24  	"strings"
    25  	"unicode/utf8"
    26  
    27  	jsoniter "github.com/json-iterator/go"
    28  
    29  	"storj.io/minio/cmd/config"
    30  	"storj.io/minio/pkg/kms"
    31  	"storj.io/minio/pkg/madmin"
    32  )
    33  
    34  const (
    35  	minioConfigPrefix = "config"
    36  
    37  	kvPrefix = ".kv"
    38  
    39  	// Captures all the previous SetKV operations and allows rollback.
    40  	minioConfigHistoryPrefix = minioConfigPrefix + "/history"
    41  
    42  	// MinIO configuration file.
    43  	minioConfigFile = "config.json"
    44  )
    45  
    46  func listServerConfigHistory(ctx context.Context, objAPI ObjectLayer, withData bool, count int) (
    47  	[]madmin.ConfigHistoryEntry, error) {
    48  
    49  	var configHistory []madmin.ConfigHistoryEntry
    50  
    51  	// List all kvs
    52  	marker := ""
    53  	for {
    54  		res, err := objAPI.ListObjects(ctx, minioMetaBucket, minioConfigHistoryPrefix, marker, "", maxObjectList)
    55  		if err != nil {
    56  			return nil, err
    57  		}
    58  		for _, obj := range res.Objects {
    59  			cfgEntry := madmin.ConfigHistoryEntry{
    60  				RestoreID:  strings.TrimSuffix(path.Base(obj.Name), kvPrefix),
    61  				CreateTime: obj.ModTime, // ModTime is createTime for config history entries.
    62  			}
    63  			if withData {
    64  				data, err := readConfig(ctx, objAPI, obj.Name)
    65  				if err != nil {
    66  					return nil, err
    67  				}
    68  				if GlobalKMS != nil {
    69  					data, err = config.DecryptBytes(GlobalKMS, data, kms.Context{
    70  						obj.Bucket: path.Join(obj.Bucket, obj.Name),
    71  					})
    72  					if err != nil {
    73  						return nil, err
    74  					}
    75  				}
    76  				cfgEntry.Data = string(data)
    77  			}
    78  			configHistory = append(configHistory, cfgEntry)
    79  			count--
    80  			if count == 0 {
    81  				break
    82  			}
    83  		}
    84  		if !res.IsTruncated {
    85  			// We are done here
    86  			break
    87  		}
    88  		marker = res.NextMarker
    89  	}
    90  	sort.Slice(configHistory, func(i, j int) bool {
    91  		return configHistory[i].CreateTime.Before(configHistory[j].CreateTime)
    92  	})
    93  	return configHistory, nil
    94  }
    95  
    96  func delServerConfigHistory(ctx context.Context, objAPI ObjectLayer, uuidKV string) error {
    97  	historyFile := pathJoin(minioConfigHistoryPrefix, uuidKV+kvPrefix)
    98  	_, err := objAPI.DeleteObject(ctx, minioMetaBucket, historyFile, ObjectOptions{})
    99  	return err
   100  }
   101  
   102  func readServerConfigHistory(ctx context.Context, objAPI ObjectLayer, uuidKV string) ([]byte, error) {
   103  	historyFile := pathJoin(minioConfigHistoryPrefix, uuidKV+kvPrefix)
   104  	data, err := readConfig(ctx, objAPI, historyFile)
   105  	if err != nil {
   106  		return nil, err
   107  	}
   108  
   109  	if GlobalKMS != nil {
   110  		data, err = config.DecryptBytes(GlobalKMS, data, kms.Context{
   111  			minioMetaBucket: path.Join(minioMetaBucket, historyFile),
   112  		})
   113  	}
   114  	return data, err
   115  }
   116  
   117  func saveServerConfigHistory(ctx context.Context, objAPI ObjectLayer, kv []byte) error {
   118  	uuidKV := mustGetUUID() + kvPrefix
   119  	historyFile := pathJoin(minioConfigHistoryPrefix, uuidKV)
   120  
   121  	if GlobalKMS != nil {
   122  		var err error
   123  		kv, err = config.EncryptBytes(GlobalKMS, kv, kms.Context{
   124  			minioMetaBucket: path.Join(minioMetaBucket, historyFile),
   125  		})
   126  		if err != nil {
   127  			return err
   128  		}
   129  	}
   130  	return saveConfig(ctx, objAPI, historyFile, kv)
   131  }
   132  
   133  func saveServerConfig(ctx context.Context, objAPI ObjectLayer, cfg interface{}) error {
   134  	data, err := json.Marshal(cfg)
   135  	if err != nil {
   136  		return err
   137  	}
   138  
   139  	var configFile = path.Join(minioConfigPrefix, minioConfigFile)
   140  	if GlobalKMS != nil {
   141  		data, err = config.EncryptBytes(GlobalKMS, data, kms.Context{
   142  			minioMetaBucket: path.Join(minioMetaBucket, configFile),
   143  		})
   144  		if err != nil {
   145  			return err
   146  		}
   147  	}
   148  	return saveConfig(ctx, objAPI, configFile, data)
   149  }
   150  
   151  func readServerConfig(ctx context.Context, objAPI ObjectLayer) (config.Config, error) {
   152  	configFile := path.Join(minioConfigPrefix, minioConfigFile)
   153  	data, err := readConfig(ctx, objAPI, configFile)
   154  	if err != nil {
   155  		// Config not found for some reason, allow things to continue
   156  		// by initializing a new fresh config in safe mode.
   157  		if err == errConfigNotFound && newObjectLayerFn() == nil {
   158  			return newServerConfig(), nil
   159  		}
   160  		return nil, err
   161  	}
   162  
   163  	if GlobalKMS != nil && !utf8.Valid(data) {
   164  		data, err = config.DecryptBytes(GlobalKMS, data, kms.Context{
   165  			minioMetaBucket: path.Join(minioMetaBucket, configFile),
   166  		})
   167  		if err != nil {
   168  			return nil, err
   169  		}
   170  	}
   171  
   172  	var srvCfg = config.New()
   173  	var json = jsoniter.ConfigCompatibleWithStandardLibrary
   174  	if err = json.Unmarshal(data, &srvCfg); err != nil {
   175  		return nil, err
   176  	}
   177  
   178  	// Add any missing entries
   179  	return srvCfg.Merge(), nil
   180  }
   181  
   182  // ConfigSys - config system.
   183  type ConfigSys struct{}
   184  
   185  // NewConfigSys - creates new config system object.
   186  func NewConfigSys() *ConfigSys {
   187  	return &ConfigSys{}
   188  }