2023-04-28 12:24:14 -07:00
// Copyright (c) 2015-2023 MinIO, Inc.
2021-04-18 12:41:13 -07: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 20:46:37 +01:00
package api
import (
"encoding/json"
"errors"
2023-02-27 10:10:45 -08:00
"fmt"
2024-03-27 18:08:07 -07:00
"math"
2020-04-14 20:46:37 +01:00
"strconv"
2020-06-04 14:58:34 -07:00
"strings"
2020-04-14 20:46:37 +01:00
"time"
2021-06-01 14:59:40 -07:00
"github.com/minio/minio/internal/config"
2024-05-24 16:05:23 -07:00
"github.com/minio/pkg/v3/env"
2020-04-14 20:46:37 +01:00
)
2020-06-04 14:58:34 -07:00
// API sub-system constants
2020-04-14 20:46:37 +01:00
const (
2023-12-07 16:22:00 -08:00
apiRequestsMax = "requests_max"
apiClusterDeadline = "cluster_deadline"
apiCorsAllowOrigin = "cors_allow_origin"
apiRemoteTransportDeadline = "remote_transport_deadline"
apiListQuorum = "list_quorum"
apiReplicationPriority = "replication_priority"
apiReplicationMaxWorkers = "replication_max_workers"
2024-07-12 07:57:31 -07:00
apiReplicationMaxLWorkers = "replication_max_lrg_workers"
2023-12-07 16:22:00 -08:00
2021-10-04 10:52:28 -07:00
apiTransitionWorkers = "transition_workers"
apiStaleUploadsCleanupInterval = "stale_uploads_cleanup_interval"
apiStaleUploadsExpiry = "stale_uploads_expiry"
apiDeleteCleanupInterval = "delete_cleanup_interval"
2022-01-17 08:34:14 -08:00
apiDisableODirect = "disable_odirect"
2023-07-31 00:12:53 -07:00
apiODirect = "odirect"
2022-02-14 09:19:01 -08:00
apiGzipObjects = "gzip_objects"
2023-04-28 12:24:14 -07:00
apiRootAccess = "root_access"
2023-06-21 06:08:59 +05:30
apiSyncEvents = "sync_events"
2024-03-14 18:07:19 -07:00
apiObjectMaxVersions = "object_max_versions"
2021-04-23 21:58:45 -07:00
2024-07-12 07:57:31 -07: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 10:52:28 -07: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 00:12:53 -07:00
EnvAPIODirect = "MINIO_API_ODIRECT"
2022-01-17 08:34:14 -08:00
EnvAPIDisableODirect = "MINIO_API_DISABLE_ODIRECT"
2022-02-14 09:19:01 -08:00
EnvAPIGzipObjects = "MINIO_API_GZIP_OBJECTS"
2023-07-31 00:12:53 -07:00
EnvAPIRootAccess = "MINIO_API_ROOT_ACCESS" // default config.EnableOn
2023-06-21 06:08:59 +05:30
EnvAPISyncEvents = "MINIO_API_SYNC_EVENTS" // default "off"
2024-03-14 18:07:19 -07:00
EnvAPIObjectMaxVersions = "MINIO_API_OBJECT_MAX_VERSIONS"
EnvAPIObjectMaxVersionsLegacy = "_MINIO_OBJECT_MAX_VERSIONS"
2020-04-14 20:46:37 +01:00
)
2020-09-23 09:14:33 -07:00
// Deprecated key and ENVs
const (
2022-09-24 16:20:28 -07:00
apiReadyDeadline = "ready_deadline"
2024-08-16 01:43:49 -07:00
apiRequestsDeadline = "requests_deadline"
2022-09-24 16:20:28 -07:00
apiReplicationWorkers = "replication_workers"
apiReplicationFailedWorkers = "replication_failed_workers"
2020-09-23 09:14:33 -07:00
)
2020-04-14 20:46:37 +01:00
// DefaultKVS - default storage class config
var (
DefaultKVS = config . KVS {
config . KV {
Key : apiRequestsMax ,
Value : "0" ,
} ,
2020-05-23 17:38:39 -07:00
config . KV {
2020-09-23 09:14:33 -07:00
Key : apiClusterDeadline ,
2020-05-23 17:38:39 -07:00
Value : "10s" ,
} ,
2020-06-04 14:58:34 -07:00
config . KV {
Key : apiCorsAllowOrigin ,
Value : "*" ,
} ,
2020-09-11 23:03:08 -07:00
config . KV {
Key : apiRemoteTransportDeadline ,
Value : "2h" ,
} ,
2020-11-02 17:21:56 -08:00
config . KV {
Key : apiListQuorum ,
2021-09-02 17:45:30 -07:00
Value : "strict" ,
2020-11-02 17:21:56 -08:00
} ,
2021-02-02 03:15:06 -08:00
config . KV {
2022-09-24 16:20:28 -07:00
Key : apiReplicationPriority ,
Value : "auto" ,
2021-04-23 21:58:45 -07:00
} ,
2023-12-07 16:22:00 -08:00
config . KV {
Key : apiReplicationMaxWorkers ,
Value : "500" ,
} ,
2024-07-12 07:57:31 -07:00
config . KV {
Key : apiReplicationMaxLWorkers ,
Value : "10" ,
} ,
2021-08-11 22:23:56 -07:00
config . KV {
Key : apiTransitionWorkers ,
Value : "100" ,
} ,
2021-10-04 10:52:28 -07:00
config . KV {
Key : apiStaleUploadsCleanupInterval ,
Value : "6h" ,
} ,
config . KV {
Key : apiStaleUploadsExpiry ,
Value : "24h" ,
} ,
config . KV {
Key : apiDeleteCleanupInterval ,
Value : "5m" ,
} ,
2022-01-17 08:34:14 -08:00
config . KV {
2024-01-04 15:07:17 -08:00
Key : apiDisableODirect ,
Value : "" ,
HiddenIfEmpty : true ,
2023-07-31 00:12:53 -07:00
} ,
config . KV {
Key : apiODirect ,
Value : config . EnableOn ,
2022-01-17 08:34:14 -08:00
} ,
2022-02-14 09:19:01 -08:00
config . KV {
Key : apiGzipObjects ,
2023-07-31 00:12:53 -07:00
Value : config . EnableOff ,
2022-02-14 09:19:01 -08:00
} ,
2023-04-28 12:24:14 -07:00
config . KV {
Key : apiRootAccess ,
2023-07-31 00:12:53 -07:00
Value : config . EnableOn ,
2023-04-28 12:24:14 -07:00
} ,
2023-06-21 06:08:59 +05:30
config . KV {
Key : apiSyncEvents ,
2023-07-31 00:12:53 -07:00
Value : config . EnableOff ,
2023-06-21 06:08:59 +05:30
} ,
2024-03-14 18:07:19 -07:00
config . KV {
Key : apiObjectMaxVersions ,
2024-03-27 18:08:07 -07:00
Value : "9223372036854775807" ,
2024-03-14 18:07:19 -07:00
} ,
2020-04-14 20:46:37 +01:00
}
)
// Config storage class configuration
type Config struct {
2021-10-04 10:52:28 -07:00
RequestsMax int ` json:"requests_max" `
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 16:20:28 -07:00
ReplicationPriority string ` json:"replication_priority" `
2023-12-07 16:22:00 -08:00
ReplicationMaxWorkers int ` json:"replication_max_workers" `
2024-07-12 07:57:31 -07:00
ReplicationMaxLWorkers int ` json:"replication_max_lrg_workers" `
2021-10-04 10:52:28 -07: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 00:12:53 -07:00
EnableODirect bool ` json:"enable_odirect" `
2022-02-14 09:19:01 -08:00
GzipObjects bool ` json:"gzip_objects" `
2023-04-28 12:24:14 -07:00
RootAccess bool ` json:"root_access" `
2023-06-21 06:08:59 +05:30
SyncEvents bool ` json:"sync_events" `
2024-03-27 18:08:07 -07:00
ObjectMaxVersions int64 ` json:"object_max_versions" `
2020-04-14 20:46:37 +01: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 10:04:02 -07:00
deprecatedKeys := [ ] string {
apiReadyDeadline ,
2024-08-16 01:43:49 -07:00
apiRequestsDeadline ,
2023-06-22 10:04:02 -07:00
"extend_list_cache_life" ,
apiReplicationWorkers ,
apiReplicationFailedWorkers ,
2024-03-18 15:25:32 -07:00
"expiry_workers" ,
2020-04-14 20:46:37 +01:00
}
2023-06-08 15:50:06 -07:00
disableODirect := env . Get ( EnvAPIDisableODirect , kvs . Get ( apiDisableODirect ) ) == config . EnableOn
2023-07-31 00:12:53 -07:00
enableODirect := env . Get ( EnvAPIODirect , kvs . Get ( apiODirect ) ) == config . EnableOn
2023-06-08 15:50:06 -07:00
gzipObjects := env . Get ( EnvAPIGzipObjects , kvs . Get ( apiGzipObjects ) ) == config . EnableOn
rootAccess := env . Get ( EnvAPIRootAccess , kvs . Get ( apiRootAccess ) ) == config . EnableOn
cfg = Config {
2023-07-31 00:12:53 -07:00
EnableODirect : enableODirect || ! disableODirect ,
GzipObjects : gzipObjects ,
RootAccess : rootAccess ,
2023-06-08 15:50:06 -07:00
}
2023-07-16 03:15:06 +08:00
var corsAllowOrigin [ ] string
corsList := env . Get ( EnvAPICorsAllowOrigin , kvs . Get ( apiCorsAllowOrigin ) )
if corsList == "" {
2023-06-22 10:04:02 -07:00
corsAllowOrigin = [ ] string { "*" } // defaults to '*'
2023-07-16 03:15:06 +08:00
} else {
corsAllowOrigin = strings . Split ( corsList , "," )
for _ , cors := range corsAllowOrigin {
if cors == "" {
return cfg , errors . New ( "invalid cors value" )
}
}
2023-06-22 10:04:02 -07:00
}
cfg . CorsAllowOrigin = corsAllowOrigin
if err = config . CheckValidKeys ( config . APISubSys , kvs , DefaultKVS , deprecatedKeys ... ) ; err != nil {
return cfg , err
}
2020-04-14 20:46:37 +01:00
// Check environment variables parameters
2022-02-22 05:20:45 +05:30
requestsMax , err := strconv . Atoi ( env . Get ( EnvAPIRequestsMax , kvs . GetWithDefault ( apiRequestsMax , DefaultKVS ) ) )
2020-04-14 20:46:37 +01:00
if err != nil {
return cfg , err
}
2023-06-08 15:50:06 -07:00
cfg . RequestsMax = requestsMax
2020-04-14 20:46:37 +01:00
if requestsMax < 0 {
return cfg , errors . New ( "invalid API max requests value" )
}
2022-02-22 05:20:45 +05:30
clusterDeadline , err := time . ParseDuration ( env . Get ( EnvAPIClusterDeadline , kvs . GetWithDefault ( apiClusterDeadline , DefaultKVS ) ) )
2020-05-23 17:38:39 -07:00
if err != nil {
return cfg , err
}
2023-06-08 15:50:06 -07:00
cfg . ClusterDeadline = clusterDeadline
2020-05-23 17:38:39 -07:00
2022-02-22 05:20:45 +05:30
remoteTransportDeadline , err := time . ParseDuration ( env . Get ( EnvAPIRemoteTransportDeadline , kvs . GetWithDefault ( apiRemoteTransportDeadline , DefaultKVS ) ) )
2020-09-11 23:03:08 -07:00
if err != nil {
return cfg , err
}
2023-06-08 15:50:06 -07:00
cfg . RemoteTransportDeadline = remoteTransportDeadline
2020-09-11 23:03:08 -07:00
2022-02-22 05:20:45 +05:30
listQuorum := env . Get ( EnvAPIListQuorum , kvs . GetWithDefault ( apiListQuorum , DefaultKVS ) )
2020-11-02 17:21:56 -08:00
switch listQuorum {
2023-12-29 15:52:41 -08:00
case "strict" , "optimal" , "reduced" , "disk" , "auto" :
2020-11-02 17:21:56 -08:00
default :
2023-06-08 15:50:06 -07:00
return cfg , fmt . Errorf ( "invalid value %v for list_quorum: will default to 'strict'" , listQuorum )
2020-11-02 17:21:56 -08:00
}
2023-06-08 15:50:06 -07:00
cfg . ListQuorum = listQuorum
2020-11-02 17:21:56 -08:00
2022-09-24 16:20:28 -07:00
replicationPriority := env . Get ( EnvAPIReplicationPriority , kvs . GetWithDefault ( apiReplicationPriority , DefaultKVS ) )
switch replicationPriority {
case "slow" , "fast" , "auto" :
default :
2023-02-27 10:10:45 -08:00
return cfg , fmt . Errorf ( "invalid value %v for replication_priority" , replicationPriority )
2021-04-23 21:58:45 -07:00
}
2023-06-08 15:50:06 -07:00
cfg . ReplicationPriority = replicationPriority
2023-12-07 16:22:00 -08: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 07:57:31 -07: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-22 05:20:45 +05:30
transitionWorkers , err := strconv . Atoi ( env . Get ( EnvAPITransitionWorkers , kvs . GetWithDefault ( apiTransitionWorkers , DefaultKVS ) ) )
2021-08-11 22:23:56 -07:00
if err != nil {
return cfg , err
}
2023-06-08 15:50:06 -07:00
cfg . TransitionWorkers = transitionWorkers
2021-08-11 22:23:56 -07:00
2021-10-04 10:52:28 -07:00
v := env . Get ( EnvAPIDeleteCleanupInterval , kvs . Get ( apiDeleteCleanupInterval ) )
if v == "" {
2022-02-22 05:20:45 +05:30
v = env . Get ( EnvDeleteCleanupInterval , kvs . GetWithDefault ( apiDeleteCleanupInterval , DefaultKVS ) )
2021-10-04 10:52:28 -07:00
}
deleteCleanupInterval , err := time . ParseDuration ( v )
if err != nil {
return cfg , err
}
2023-06-08 15:50:06 -07:00
cfg . DeleteCleanupInterval = deleteCleanupInterval
2021-10-04 10:52:28 -07:00
2022-02-22 05:20:45 +05:30
staleUploadsCleanupInterval , err := time . ParseDuration ( env . Get ( EnvAPIStaleUploadsCleanupInterval , kvs . GetWithDefault ( apiStaleUploadsCleanupInterval , DefaultKVS ) ) )
2021-10-04 10:52:28 -07:00
if err != nil {
return cfg , err
}
2023-06-08 15:50:06 -07:00
cfg . StaleUploadsCleanupInterval = staleUploadsCleanupInterval
2021-10-04 10:52:28 -07:00
2022-02-22 05:20:45 +05:30
staleUploadsExpiry , err := time . ParseDuration ( env . Get ( EnvAPIStaleUploadsExpiry , kvs . GetWithDefault ( apiStaleUploadsExpiry , DefaultKVS ) ) )
2021-10-04 10:52:28 -07:00
if err != nil {
return cfg , err
}
2023-06-08 15:50:06 -07:00
cfg . StaleUploadsExpiry = staleUploadsExpiry
2021-10-04 10:52:28 -07:00
2023-06-21 06:08:59 +05:30
cfg . SyncEvents = env . Get ( EnvAPISyncEvents , kvs . Get ( apiSyncEvents ) ) == config . EnableOn
2024-03-14 18:07:19 -07:00
maxVerStr := env . Get ( EnvAPIObjectMaxVersions , "" )
if maxVerStr == "" {
2024-03-27 18:08:07 -07:00
maxVerStr = env . Get ( EnvAPIObjectMaxVersionsLegacy , kvs . Get ( apiObjectMaxVersions ) )
2024-03-14 18:07:19 -07:00
}
2024-03-27 18:08:07 -07: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 18:07:19 -07:00
}
2023-06-08 15:50:06 -07:00
return cfg , nil
2020-04-14 20:46:37 +01:00
}