2023-04-28 15:24:14 -04:00
// Copyright (c) 2015-2023 MinIO, Inc.
2021-04-18 15:41:13 -04:00
//
// 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/>.
2020-04-14 15:46:37 -04:00
package api
import (
"encoding/json"
"errors"
2023-02-27 13:10:45 -05:00
"fmt"
2024-03-27 21:08:07 -04:00
"math"
2020-04-14 15:46:37 -04:00
"strconv"
2020-06-04 17:58:34 -04:00
"strings"
2020-04-14 15:46:37 -04:00
"time"
2021-06-01 17:59:40 -04:00
"github.com/minio/minio/internal/config"
2024-05-24 19:05:23 -04:00
"github.com/minio/pkg/v3/env"
2020-04-14 15:46:37 -04:00
)
2020-06-04 17:58:34 -04:00
// API sub-system constants
2020-04-14 15:46:37 -04:00
const (
2023-12-07 19:22:00 -05:00
apiRequestsMax = "requests_max"
apiRequestsDeadline = "requests_deadline"
apiClusterDeadline = "cluster_deadline"
apiCorsAllowOrigin = "cors_allow_origin"
apiRemoteTransportDeadline = "remote_transport_deadline"
apiListQuorum = "list_quorum"
apiReplicationPriority = "replication_priority"
apiReplicationMaxWorkers = "replication_max_workers"
2024-07-12 10:57:31 -04:00
apiReplicationMaxLWorkers = "replication_max_lrg_workers"
2023-12-07 19:22:00 -05:00
2021-10-04 13:52:28 -04:00
apiTransitionWorkers = "transition_workers"
apiStaleUploadsCleanupInterval = "stale_uploads_cleanup_interval"
apiStaleUploadsExpiry = "stale_uploads_expiry"
apiDeleteCleanupInterval = "delete_cleanup_interval"
2022-01-17 11:34:14 -05:00
apiDisableODirect = "disable_odirect"
2023-07-31 03:12:53 -04:00
apiODirect = "odirect"
2022-02-14 12:19:01 -05:00
apiGzipObjects = "gzip_objects"
2023-04-28 15:24:14 -04:00
apiRootAccess = "root_access"
2023-06-20 20:38:59 -04:00
apiSyncEvents = "sync_events"
2024-03-14 21:07:19 -04:00
apiObjectMaxVersions = "object_max_versions"
2021-04-24 00:58:45 -04:00
2024-07-12 10:57:31 -04:00
EnvAPIRequestsMax = "MINIO_API_REQUESTS_MAX"
EnvAPIRequestsDeadline = "MINIO_API_REQUESTS_DEADLINE"
EnvAPIClusterDeadline = "MINIO_API_CLUSTER_DEADLINE"
EnvAPICorsAllowOrigin = "MINIO_API_CORS_ALLOW_ORIGIN"
EnvAPIRemoteTransportDeadline = "MINIO_API_REMOTE_TRANSPORT_DEADLINE"
EnvAPITransitionWorkers = "MINIO_API_TRANSITION_WORKERS"
EnvAPIListQuorum = "MINIO_API_LIST_QUORUM"
EnvAPISecureCiphers = "MINIO_API_SECURE_CIPHERS" // default config.EnableOn
EnvAPIReplicationPriority = "MINIO_API_REPLICATION_PRIORITY"
EnvAPIReplicationMaxWorkers = "MINIO_API_REPLICATION_MAX_WORKERS"
EnvAPIReplicationMaxLWorkers = "MINIO_API_REPLICATION_MAX_LRG_WORKERS"
2021-10-04 13:52:28 -04:00
EnvAPIStaleUploadsCleanupInterval = "MINIO_API_STALE_UPLOADS_CLEANUP_INTERVAL"
EnvAPIStaleUploadsExpiry = "MINIO_API_STALE_UPLOADS_EXPIRY"
EnvAPIDeleteCleanupInterval = "MINIO_API_DELETE_CLEANUP_INTERVAL"
EnvDeleteCleanupInterval = "MINIO_DELETE_CLEANUP_INTERVAL"
2023-07-31 03:12:53 -04:00
EnvAPIODirect = "MINIO_API_ODIRECT"
2022-01-17 11:34:14 -05:00
EnvAPIDisableODirect = "MINIO_API_DISABLE_ODIRECT"
2022-02-14 12:19:01 -05:00
EnvAPIGzipObjects = "MINIO_API_GZIP_OBJECTS"
2023-07-31 03:12:53 -04:00
EnvAPIRootAccess = "MINIO_API_ROOT_ACCESS" // default config.EnableOn
2023-06-20 20:38:59 -04:00
EnvAPISyncEvents = "MINIO_API_SYNC_EVENTS" // default "off"
2024-03-14 21:07:19 -04:00
EnvAPIObjectMaxVersions = "MINIO_API_OBJECT_MAX_VERSIONS"
EnvAPIObjectMaxVersionsLegacy = "_MINIO_OBJECT_MAX_VERSIONS"
2020-04-14 15:46:37 -04:00
)
2020-09-23 12:14:33 -04:00
// Deprecated key and ENVs
const (
2022-09-24 19:20:28 -04:00
apiReadyDeadline = "ready_deadline"
apiReplicationWorkers = "replication_workers"
apiReplicationFailedWorkers = "replication_failed_workers"
2020-09-23 12:14:33 -04:00
)
2020-04-14 15:46:37 -04:00
// DefaultKVS - default storage class config
var (
DefaultKVS = config . KVS {
config . KV {
Key : apiRequestsMax ,
Value : "0" ,
} ,
config . KV {
Key : apiRequestsDeadline ,
Value : "10s" ,
} ,
2020-05-23 20:38:39 -04:00
config . KV {
2020-09-23 12:14:33 -04:00
Key : apiClusterDeadline ,
2020-05-23 20:38:39 -04:00
Value : "10s" ,
} ,
2020-06-04 17:58:34 -04:00
config . KV {
Key : apiCorsAllowOrigin ,
Value : "*" ,
} ,
2020-09-12 02:03:08 -04:00
config . KV {
Key : apiRemoteTransportDeadline ,
Value : "2h" ,
} ,
2020-11-02 20:21:56 -05:00
config . KV {
Key : apiListQuorum ,
2021-09-02 20:45:30 -04:00
Value : "strict" ,
2020-11-02 20:21:56 -05:00
} ,
2021-02-02 06:15:06 -05:00
config . KV {
2022-09-24 19:20:28 -04:00
Key : apiReplicationPriority ,
Value : "auto" ,
2021-04-24 00:58:45 -04:00
} ,
2023-12-07 19:22:00 -05:00
config . KV {
Key : apiReplicationMaxWorkers ,
Value : "500" ,
} ,
2024-07-12 10:57:31 -04:00
config . KV {
Key : apiReplicationMaxLWorkers ,
Value : "10" ,
} ,
2021-08-12 01:23:56 -04:00
config . KV {
Key : apiTransitionWorkers ,
Value : "100" ,
} ,
2021-10-04 13:52:28 -04:00
config . KV {
Key : apiStaleUploadsCleanupInterval ,
Value : "6h" ,
} ,
config . KV {
Key : apiStaleUploadsExpiry ,
Value : "24h" ,
} ,
config . KV {
Key : apiDeleteCleanupInterval ,
Value : "5m" ,
} ,
2022-01-17 11:34:14 -05:00
config . KV {
2024-01-04 18:07:17 -05:00
Key : apiDisableODirect ,
Value : "" ,
HiddenIfEmpty : true ,
2023-07-31 03:12:53 -04:00
} ,
config . KV {
Key : apiODirect ,
Value : config . EnableOn ,
2022-01-17 11:34:14 -05:00
} ,
2022-02-14 12:19:01 -05:00
config . KV {
Key : apiGzipObjects ,
2023-07-31 03:12:53 -04:00
Value : config . EnableOff ,
2022-02-14 12:19:01 -05:00
} ,
2023-04-28 15:24:14 -04:00
config . KV {
Key : apiRootAccess ,
2023-07-31 03:12:53 -04:00
Value : config . EnableOn ,
2023-04-28 15:24:14 -04:00
} ,
2023-06-20 20:38:59 -04:00
config . KV {
Key : apiSyncEvents ,
2023-07-31 03:12:53 -04:00
Value : config . EnableOff ,
2023-06-20 20:38:59 -04:00
} ,
2024-03-14 21:07:19 -04:00
config . KV {
Key : apiObjectMaxVersions ,
2024-03-27 21:08:07 -04:00
Value : "9223372036854775807" ,
2024-03-14 21:07:19 -04:00
} ,
2020-04-14 15:46:37 -04:00
}
)
// Config storage class configuration
type Config struct {
2021-10-04 13:52:28 -04:00
RequestsMax int ` json:"requests_max" `
RequestsDeadline time . Duration ` json:"requests_deadline" `
ClusterDeadline time . Duration ` json:"cluster_deadline" `
CorsAllowOrigin [ ] string ` json:"cors_allow_origin" `
RemoteTransportDeadline time . Duration ` json:"remote_transport_deadline" `
ListQuorum string ` json:"list_quorum" `
2022-09-24 19:20:28 -04:00
ReplicationPriority string ` json:"replication_priority" `
2023-12-07 19:22:00 -05:00
ReplicationMaxWorkers int ` json:"replication_max_workers" `
2024-07-12 10:57:31 -04:00
ReplicationMaxLWorkers int ` json:"replication_max_lrg_workers" `
2021-10-04 13:52:28 -04:00
TransitionWorkers int ` json:"transition_workers" `
StaleUploadsCleanupInterval time . Duration ` json:"stale_uploads_cleanup_interval" `
StaleUploadsExpiry time . Duration ` json:"stale_uploads_expiry" `
DeleteCleanupInterval time . Duration ` json:"delete_cleanup_interval" `
2023-07-31 03:12:53 -04:00
EnableODirect bool ` json:"enable_odirect" `
2022-02-14 12:19:01 -05:00
GzipObjects bool ` json:"gzip_objects" `
2023-04-28 15:24:14 -04:00
RootAccess bool ` json:"root_access" `
2023-06-20 20:38:59 -04:00
SyncEvents bool ` json:"sync_events" `
2024-03-27 21:08:07 -04:00
ObjectMaxVersions int64 ` json:"object_max_versions" `
2020-04-14 15:46:37 -04:00
}
// UnmarshalJSON - Validate SS and RRS parity when unmarshalling JSON.
func ( sCfg * Config ) UnmarshalJSON ( data [ ] byte ) error {
type Alias Config
aux := & struct {
* Alias
} {
Alias : ( * Alias ) ( sCfg ) ,
}
return json . Unmarshal ( data , & aux )
}
// LookupConfig - lookup api config and override with valid environment settings if any.
func LookupConfig ( kvs config . KVS ) ( cfg Config , err error ) {
2023-06-22 13:04:02 -04:00
deprecatedKeys := [ ] string {
apiReadyDeadline ,
"extend_list_cache_life" ,
apiReplicationWorkers ,
apiReplicationFailedWorkers ,
2024-03-18 18:25:32 -04:00
"expiry_workers" ,
2020-04-14 15:46:37 -04:00
}
2023-06-08 18:50:06 -04:00
disableODirect := env . Get ( EnvAPIDisableODirect , kvs . Get ( apiDisableODirect ) ) == config . EnableOn
2023-07-31 03:12:53 -04:00
enableODirect := env . Get ( EnvAPIODirect , kvs . Get ( apiODirect ) ) == config . EnableOn
2023-06-08 18:50:06 -04:00
gzipObjects := env . Get ( EnvAPIGzipObjects , kvs . Get ( apiGzipObjects ) ) == config . EnableOn
rootAccess := env . Get ( EnvAPIRootAccess , kvs . Get ( apiRootAccess ) ) == config . EnableOn
cfg = Config {
2023-07-31 03:12:53 -04:00
EnableODirect : enableODirect || ! disableODirect ,
GzipObjects : gzipObjects ,
RootAccess : rootAccess ,
2023-06-08 18:50:06 -04:00
}
2023-07-15 15:15:06 -04:00
var corsAllowOrigin [ ] string
corsList := env . Get ( EnvAPICorsAllowOrigin , kvs . Get ( apiCorsAllowOrigin ) )
if corsList == "" {
2023-06-22 13:04:02 -04:00
corsAllowOrigin = [ ] string { "*" } // defaults to '*'
2023-07-15 15:15:06 -04:00
} else {
corsAllowOrigin = strings . Split ( corsList , "," )
for _ , cors := range corsAllowOrigin {
if cors == "" {
return cfg , errors . New ( "invalid cors value" )
}
}
2023-06-22 13:04:02 -04:00
}
cfg . CorsAllowOrigin = corsAllowOrigin
if err = config . CheckValidKeys ( config . APISubSys , kvs , DefaultKVS , deprecatedKeys ... ) ; err != nil {
return cfg , err
}
2020-04-14 15:46:37 -04:00
// Check environment variables parameters
2022-02-21 18:50:45 -05:00
requestsMax , err := strconv . Atoi ( env . Get ( EnvAPIRequestsMax , kvs . GetWithDefault ( apiRequestsMax , DefaultKVS ) ) )
2020-04-14 15:46:37 -04:00
if err != nil {
return cfg , err
}
2023-06-08 18:50:06 -04:00
cfg . RequestsMax = requestsMax
2020-04-14 15:46:37 -04:00
if requestsMax < 0 {
return cfg , errors . New ( "invalid API max requests value" )
}
2022-02-21 18:50:45 -05:00
requestsDeadline , err := time . ParseDuration ( env . Get ( EnvAPIRequestsDeadline , kvs . GetWithDefault ( apiRequestsDeadline , DefaultKVS ) ) )
2020-04-14 15:46:37 -04:00
if err != nil {
return cfg , err
}
2023-06-08 18:50:06 -04:00
cfg . RequestsDeadline = requestsDeadline
2020-04-14 15:46:37 -04:00
2022-02-21 18:50:45 -05:00
clusterDeadline , err := time . ParseDuration ( env . Get ( EnvAPIClusterDeadline , kvs . GetWithDefault ( apiClusterDeadline , DefaultKVS ) ) )
2020-05-23 20:38:39 -04:00
if err != nil {
return cfg , err
}
2023-06-08 18:50:06 -04:00
cfg . ClusterDeadline = clusterDeadline
2020-05-23 20:38:39 -04:00
2022-02-21 18:50:45 -05:00
remoteTransportDeadline , err := time . ParseDuration ( env . Get ( EnvAPIRemoteTransportDeadline , kvs . GetWithDefault ( apiRemoteTransportDeadline , DefaultKVS ) ) )
2020-09-12 02:03:08 -04:00
if err != nil {
return cfg , err
}
2023-06-08 18:50:06 -04:00
cfg . RemoteTransportDeadline = remoteTransportDeadline
2020-09-12 02:03:08 -04:00
2022-02-21 18:50:45 -05:00
listQuorum := env . Get ( EnvAPIListQuorum , kvs . GetWithDefault ( apiListQuorum , DefaultKVS ) )
2020-11-02 20:21:56 -05:00
switch listQuorum {
2023-12-29 18:52:41 -05:00
case "strict" , "optimal" , "reduced" , "disk" , "auto" :
2020-11-02 20:21:56 -05:00
default :
2023-06-08 18:50:06 -04:00
return cfg , fmt . Errorf ( "invalid value %v for list_quorum: will default to 'strict'" , listQuorum )
2020-11-02 20:21:56 -05:00
}
2023-06-08 18:50:06 -04:00
cfg . ListQuorum = listQuorum
2020-11-02 20:21:56 -05:00
2022-09-24 19:20:28 -04:00
replicationPriority := env . Get ( EnvAPIReplicationPriority , kvs . GetWithDefault ( apiReplicationPriority , DefaultKVS ) )
switch replicationPriority {
case "slow" , "fast" , "auto" :
default :
2023-02-27 13:10:45 -05:00
return cfg , fmt . Errorf ( "invalid value %v for replication_priority" , replicationPriority )
2021-04-24 00:58:45 -04:00
}
2023-06-08 18:50:06 -04:00
cfg . ReplicationPriority = replicationPriority
2023-12-07 19:22:00 -05:00
replicationMaxWorkers , err := strconv . Atoi ( env . Get ( EnvAPIReplicationMaxWorkers , kvs . GetWithDefault ( apiReplicationMaxWorkers , DefaultKVS ) ) )
if err != nil {
return cfg , err
}
if replicationMaxWorkers <= 0 || replicationMaxWorkers > 500 {
return cfg , config . ErrInvalidReplicationWorkersValue ( nil ) . Msg ( "Number of replication workers should be between 1 and 500" )
}
cfg . ReplicationMaxWorkers = replicationMaxWorkers
2024-07-12 10:57:31 -04:00
replicationMaxLWorkers , err := strconv . Atoi ( env . Get ( EnvAPIReplicationMaxLWorkers , kvs . GetWithDefault ( apiReplicationMaxLWorkers , DefaultKVS ) ) )
if err != nil {
return cfg , err
}
if replicationMaxLWorkers <= 0 || replicationMaxLWorkers > 10 {
return cfg , config . ErrInvalidReplicationWorkersValue ( nil ) . Msg ( "Number of replication workers for transfers >=128MiB should be between 1 and 10 per node" )
}
cfg . ReplicationMaxLWorkers = replicationMaxLWorkers
2022-02-21 18:50:45 -05:00
transitionWorkers , err := strconv . Atoi ( env . Get ( EnvAPITransitionWorkers , kvs . GetWithDefault ( apiTransitionWorkers , DefaultKVS ) ) )
2021-08-12 01:23:56 -04:00
if err != nil {
return cfg , err
}
2023-06-08 18:50:06 -04:00
cfg . TransitionWorkers = transitionWorkers
2021-08-12 01:23:56 -04:00
2021-10-04 13:52:28 -04:00
v := env . Get ( EnvAPIDeleteCleanupInterval , kvs . Get ( apiDeleteCleanupInterval ) )
if v == "" {
2022-02-21 18:50:45 -05:00
v = env . Get ( EnvDeleteCleanupInterval , kvs . GetWithDefault ( apiDeleteCleanupInterval , DefaultKVS ) )
2021-10-04 13:52:28 -04:00
}
deleteCleanupInterval , err := time . ParseDuration ( v )
if err != nil {
return cfg , err
}
2023-06-08 18:50:06 -04:00
cfg . DeleteCleanupInterval = deleteCleanupInterval
2021-10-04 13:52:28 -04:00
2022-02-21 18:50:45 -05:00
staleUploadsCleanupInterval , err := time . ParseDuration ( env . Get ( EnvAPIStaleUploadsCleanupInterval , kvs . GetWithDefault ( apiStaleUploadsCleanupInterval , DefaultKVS ) ) )
2021-10-04 13:52:28 -04:00
if err != nil {
return cfg , err
}
2023-06-08 18:50:06 -04:00
cfg . StaleUploadsCleanupInterval = staleUploadsCleanupInterval
2021-10-04 13:52:28 -04:00
2022-02-21 18:50:45 -05:00
staleUploadsExpiry , err := time . ParseDuration ( env . Get ( EnvAPIStaleUploadsExpiry , kvs . GetWithDefault ( apiStaleUploadsExpiry , DefaultKVS ) ) )
2021-10-04 13:52:28 -04:00
if err != nil {
return cfg , err
}
2023-06-08 18:50:06 -04:00
cfg . StaleUploadsExpiry = staleUploadsExpiry
2021-10-04 13:52:28 -04:00
2023-06-20 20:38:59 -04:00
cfg . SyncEvents = env . Get ( EnvAPISyncEvents , kvs . Get ( apiSyncEvents ) ) == config . EnableOn
2024-03-14 21:07:19 -04:00
maxVerStr := env . Get ( EnvAPIObjectMaxVersions , "" )
if maxVerStr == "" {
2024-03-27 21:08:07 -04:00
maxVerStr = env . Get ( EnvAPIObjectMaxVersionsLegacy , kvs . Get ( apiObjectMaxVersions ) )
2024-03-14 21:07:19 -04:00
}
2024-03-27 21:08:07 -04:00
if maxVerStr != "" {
maxVersions , err := strconv . ParseInt ( maxVerStr , 10 , 64 )
if err != nil {
return cfg , err
}
if maxVersions <= 0 {
return cfg , fmt . Errorf ( "invalid object max versions value: %v" , maxVersions )
}
cfg . ObjectMaxVersions = maxVersions
} else {
cfg . ObjectMaxVersions = math . MaxInt64
2024-03-14 21:07:19 -04:00
}
2023-06-08 18:50:06 -04:00
return cfg , nil
2020-04-14 15:46:37 -04:00
}