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 }