879 lines · 28.8 KB · Go
RawDownload
// Copyright (c) 2015-2021 MinIO, Inc.//// 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/>. package cmd import (	"context"	"errors"	"fmt"	"strings"	"sync" 	"github.com/minio/madmin-go"	"github.com/minio/minio/internal/config"	"github.com/minio/minio/internal/config/api"	"github.com/minio/minio/internal/config/cache"	"github.com/minio/minio/internal/config/callhome"	"github.com/minio/minio/internal/config/compress"	"github.com/minio/minio/internal/config/dns"	"github.com/minio/minio/internal/config/etcd"	"github.com/minio/minio/internal/config/heal"	xldap "github.com/minio/minio/internal/config/identity/ldap"	"github.com/minio/minio/internal/config/identity/openid"	idplugin "github.com/minio/minio/internal/config/identity/plugin"	xtls "github.com/minio/minio/internal/config/identity/tls"	"github.com/minio/minio/internal/config/notify"	"github.com/minio/minio/internal/config/policy/opa"	polplugin "github.com/minio/minio/internal/config/policy/plugin"	"github.com/minio/minio/internal/config/scanner"	"github.com/minio/minio/internal/config/storageclass"	"github.com/minio/minio/internal/config/subnet"	"github.com/minio/minio/internal/crypto"	xhttp "github.com/minio/minio/internal/http"	"github.com/minio/minio/internal/kms"	"github.com/minio/minio/internal/logger"	"github.com/minio/pkg/env") func initHelp() {	kvs := map[string]config.KVS{		config.EtcdSubSys:           etcd.DefaultKVS,		config.CacheSubSys:          cache.DefaultKVS,		config.CompressionSubSys:    compress.DefaultKVS,		config.IdentityLDAPSubSys:   xldap.DefaultKVS,		config.IdentityOpenIDSubSys: openid.DefaultKVS,		config.IdentityTLSSubSys:    xtls.DefaultKVS,		config.IdentityPluginSubSys: idplugin.DefaultKVS,		config.PolicyOPASubSys:      opa.DefaultKVS,		config.PolicyPluginSubSys:   polplugin.DefaultKVS,		config.SiteSubSys:           config.DefaultSiteKVS,		config.RegionSubSys:         config.DefaultRegionKVS,		config.APISubSys:            api.DefaultKVS,		config.CredentialsSubSys:    config.DefaultCredentialKVS,		config.LoggerWebhookSubSys:  logger.DefaultLoggerWebhookKVS,		config.AuditWebhookSubSys:   logger.DefaultAuditWebhookKVS,		config.AuditKafkaSubSys:     logger.DefaultAuditKafkaKVS,		config.HealSubSys:           heal.DefaultKVS,		config.ScannerSubSys:        scanner.DefaultKVS,		config.SubnetSubSys:         subnet.DefaultKVS,		config.CallhomeSubSys:       callhome.DefaultKVS,	}	for k, v := range notify.DefaultNotificationKVS {		kvs[k] = v	}	if globalIsErasure {		kvs[config.StorageClassSubSys] = storageclass.DefaultKVS	}	config.RegisterDefaultKVS(kvs) 	// Captures help for each sub-system	helpSubSys := config.HelpKVS{		config.HelpKV{			Key:         config.SiteSubSys,			Description: "label the server and its location",		},		config.HelpKV{			Key:         config.CacheSubSys,			Description: "add caching storage tier",		},		config.HelpKV{			Key:         config.CompressionSubSys,			Description: "enable server side compression of objects",		},		config.HelpKV{			Key:         config.EtcdSubSys,			Description: "federate multiple clusters for IAM and Bucket DNS",		},		config.HelpKV{			Key:             config.IdentityOpenIDSubSys,			Description:     "enable OpenID SSO support",			MultipleTargets: true,		},		config.HelpKV{			Key:         config.IdentityLDAPSubSys,			Description: "enable LDAP SSO support",		},		config.HelpKV{			Key:         config.IdentityTLSSubSys,			Description: "enable X.509 TLS certificate SSO support",		},		config.HelpKV{			Key:         config.IdentityPluginSubSys,			Description: "enable Identity Plugin via external hook",		},		config.HelpKV{			Key:         config.PolicyPluginSubSys,			Description: "enable Access Management Plugin for policy enforcement",		},		config.HelpKV{			Key:         config.APISubSys,			Description: "manage global HTTP API call specific features, such as throttling, authentication types, etc.",		},		config.HelpKV{			Key:         config.HealSubSys,			Description: "manage object healing frequency and bitrot verification checks",		},		config.HelpKV{			Key:         config.ScannerSubSys,			Description: "manage namespace scanning for usage calculation, lifecycle, healing and more",		},		config.HelpKV{			Key:             config.LoggerWebhookSubSys,			Description:     "send server logs to webhook endpoints",			MultipleTargets: true,		},		config.HelpKV{			Key:             config.AuditWebhookSubSys,			Description:     "send audit logs to webhook endpoints",			MultipleTargets: true,		},		config.HelpKV{			Key:             config.AuditKafkaSubSys,			Description:     "send audit logs to kafka endpoints",			MultipleTargets: true,		},		config.HelpKV{			Key:             config.NotifyWebhookSubSys,			Description:     "publish bucket notifications to webhook endpoints",			MultipleTargets: true,		},		config.HelpKV{			Key:             config.NotifyAMQPSubSys,			Description:     "publish bucket notifications to AMQP endpoints",			MultipleTargets: true,		},		config.HelpKV{			Key:             config.NotifyKafkaSubSys,			Description:     "publish bucket notifications to Kafka endpoints",			MultipleTargets: true,		},		config.HelpKV{			Key:             config.NotifyMQTTSubSys,			Description:     "publish bucket notifications to MQTT endpoints",			MultipleTargets: true,		},		config.HelpKV{			Key:             config.NotifyNATSSubSys,			Description:     "publish bucket notifications to NATS endpoints",			MultipleTargets: true,		},		config.HelpKV{			Key:             config.NotifyNSQSubSys,			Description:     "publish bucket notifications to NSQ endpoints",			MultipleTargets: true,		},		config.HelpKV{			Key:             config.NotifyMySQLSubSys,			Description:     "publish bucket notifications to MySQL databases",			MultipleTargets: true,		},		config.HelpKV{			Key:             config.NotifyPostgresSubSys,			Description:     "publish bucket notifications to Postgres databases",			MultipleTargets: true,		},		config.HelpKV{			Key:             config.NotifyESSubSys,			Description:     "publish bucket notifications to Elasticsearch endpoints",			MultipleTargets: true,		},		config.HelpKV{			Key:             config.NotifyRedisSubSys,			Description:     "publish bucket notifications to Redis datastores",			MultipleTargets: true,		},		config.HelpKV{			Key:         config.SubnetSubSys,			Type:        "string",			Description: "set subnet config for the cluster e.g. api key",			Optional:    true,		},		config.HelpKV{			Key:         config.CallhomeSubSys,			Type:        "string",			Description: "enable callhome for the cluster",			Optional:    true,		},	} 	if globalIsErasure {		helpSubSys = append(helpSubSys, config.HelpKV{})		copy(helpSubSys[2:], helpSubSys[1:])		helpSubSys[1] = config.HelpKV{			Key:         config.StorageClassSubSys,			Description: "define object level redundancy",		}	} 	helpMap := map[string]config.HelpKVS{		"":                          helpSubSys, // Help for all sub-systems.		config.SiteSubSys:           config.SiteHelp,		config.RegionSubSys:         config.RegionHelp,		config.APISubSys:            api.Help,		config.StorageClassSubSys:   storageclass.Help,		config.EtcdSubSys:           etcd.Help,		config.CacheSubSys:          cache.Help,		config.CompressionSubSys:    compress.Help,		config.HealSubSys:           heal.Help,		config.ScannerSubSys:        scanner.Help,		config.IdentityOpenIDSubSys: openid.Help,		config.IdentityLDAPSubSys:   xldap.Help,		config.IdentityTLSSubSys:    xtls.Help,		config.IdentityPluginSubSys: idplugin.Help,		config.PolicyOPASubSys:      opa.Help,		config.PolicyPluginSubSys:   polplugin.Help,		config.LoggerWebhookSubSys:  logger.Help,		config.AuditWebhookSubSys:   logger.HelpWebhook,		config.AuditKafkaSubSys:     logger.HelpKafka,		config.NotifyAMQPSubSys:     notify.HelpAMQP,		config.NotifyKafkaSubSys:    notify.HelpKafka,		config.NotifyMQTTSubSys:     notify.HelpMQTT,		config.NotifyNATSSubSys:     notify.HelpNATS,		config.NotifyNSQSubSys:      notify.HelpNSQ,		config.NotifyMySQLSubSys:    notify.HelpMySQL,		config.NotifyPostgresSubSys: notify.HelpPostgres,		config.NotifyRedisSubSys:    notify.HelpRedis,		config.NotifyWebhookSubSys:  notify.HelpWebhook,		config.NotifyESSubSys:       notify.HelpES,		config.SubnetSubSys:         subnet.HelpSubnet,		config.CallhomeSubSys:       callhome.HelpCallhome,	} 	config.RegisterHelpSubSys(helpMap) 	// save top-level help for deprecated sub-systems in a separate map.	deprecatedHelpKVMap := map[string]config.HelpKV{		config.RegionSubSys: {			Key:         config.RegionSubSys,			Description: "[DEPRECATED - use `site` instead] label the location of the server",		},		config.PolicyOPASubSys: {			Key:         config.PolicyOPASubSys,			Description: "[DEPRECATED - use `policy_plugin` instead] enable external OPA for policy enforcement",		},	} 	config.RegisterHelpDeprecatedSubSys(deprecatedHelpKVMap)} var (	// globalServerConfig server config.	globalServerConfig   config.Config	globalServerConfigMu sync.RWMutex) func validateSubSysConfig(s config.Config, subSys string, objAPI ObjectLayer) error {	switch subSys {	case config.CredentialsSubSys:		if _, err := config.LookupCreds(s[config.CredentialsSubSys][config.Default]); err != nil {			return err		}	case config.SiteSubSys:		if _, err := config.LookupSite(s[config.SiteSubSys][config.Default], s[config.RegionSubSys][config.Default]); err != nil {			return err		}	case config.APISubSys:		if _, err := api.LookupConfig(s[config.APISubSys][config.Default]); err != nil {			return err		}	case config.StorageClassSubSys:		if globalIsErasure {			if objAPI == nil {				return errServerNotInitialized			}			for _, setDriveCount := range objAPI.SetDriveCounts() {				if _, err := storageclass.LookupConfig(s[config.StorageClassSubSys][config.Default], setDriveCount); err != nil {					return err				}			}		}	case config.CacheSubSys:		if _, err := cache.LookupConfig(s[config.CacheSubSys][config.Default]); err != nil {			return err		}	case config.CompressionSubSys:		compCfg, err := compress.LookupConfig(s[config.CompressionSubSys][config.Default])		if err != nil {			return err		} 		if objAPI != nil {			if compCfg.Enabled && !objAPI.IsCompressionSupported() {				return fmt.Errorf("Backend does not support compression")			}		}	case config.HealSubSys:		if _, err := heal.LookupConfig(s[config.HealSubSys][config.Default]); err != nil {			return err		}	case config.ScannerSubSys:		if _, err := scanner.LookupConfig(s[config.ScannerSubSys][config.Default]); err != nil {			return err		}	case config.EtcdSubSys:		etcdCfg, err := etcd.LookupConfig(s[config.EtcdSubSys][config.Default], globalRootCAs)		if err != nil {			return err		}		if etcdCfg.Enabled {			etcdClnt, err := etcd.New(etcdCfg)			if err != nil {				return err			}			etcdClnt.Close()		}	case config.IdentityOpenIDSubSys:		if _, err := openid.LookupConfig(s,			NewGatewayHTTPTransport(), xhttp.DrainBody, globalSite.Region); err != nil {			return err		}	case config.IdentityLDAPSubSys:		cfg, err := xldap.Lookup(s[config.IdentityLDAPSubSys][config.Default], globalRootCAs)		if err != nil {			return err		}		if cfg.Enabled {			conn, cerr := cfg.Connect()			if cerr != nil {				return cerr			}			conn.Close()		}	case config.IdentityTLSSubSys:		if _, err := xtls.Lookup(s[config.IdentityTLSSubSys][config.Default]); err != nil {			return err		}	case config.IdentityPluginSubSys:		if _, err := idplugin.LookupConfig(s[config.IdentityPluginSubSys][config.Default],			NewGatewayHTTPTransport(), xhttp.DrainBody, globalSite.Region); err != nil {			return err		}	case config.SubnetSubSys:		if _, err := subnet.LookupConfig(s[config.SubnetSubSys][config.Default], nil); err != nil {			return err		}	case config.CallhomeSubSys:		if _, err := callhome.LookupConfig(s[config.CallhomeSubSys][config.Default]); err != nil {			return err		}	case config.PolicyOPASubSys:		// In case legacy OPA config is being set, we treat it as if the		// AuthZPlugin is being set.		subSys = config.PolicyPluginSubSys		fallthrough	case config.PolicyPluginSubSys:		if ppargs, err := polplugin.LookupConfig(s[config.PolicyPluginSubSys][config.Default],			NewGatewayHTTPTransport(), xhttp.DrainBody); err != nil {			return err		} else if ppargs.URL == nil {			// Check if legacy opa is configured.			if _, err := opa.LookupConfig(s[config.PolicyOPASubSys][config.Default],				NewGatewayHTTPTransport(), xhttp.DrainBody); err != nil {				return err			}		}	default:		if config.LoggerSubSystems.Contains(subSys) {			if err := logger.ValidateSubSysConfig(s, subSys); err != nil {				return err			}		}	} 	if config.NotifySubSystems.Contains(subSys) {		if err := notify.TestSubSysNotificationTargets(GlobalContext, s, NewGatewayHTTPTransport(), globalNotificationSys.ConfiguredTargetIDs(), subSys); err != nil {			return err		}	}	return nil} func validateConfig(s config.Config, subSys string) error {	objAPI := newObjectLayerFn() 	// We must have a global lock for this so nobody else modifies env while we do.	defer env.LockSetEnv()() 	// Disable merging env values with config for validation.	env.SetEnvOff() 	// Enable env values to validate KMS.	defer env.SetEnvOn()	if subSys != "" {		return validateSubSysConfig(s, subSys, objAPI)	} 	// No sub-system passed. Validate all of them.	for _, ss := range config.SubSystems.ToSlice() {		if err := validateSubSysConfig(s, ss, objAPI); err != nil {			return err		}	} 	return nil} func lookupConfigs(s config.Config, objAPI ObjectLayer) {	ctx := GlobalContext 	var err error	if !globalActiveCred.IsValid() {		// Env doesn't seem to be set, we fallback to lookup creds from the config.		globalActiveCred, err = config.LookupCreds(s[config.CredentialsSubSys][config.Default])		if err != nil {			logger.LogIf(ctx, fmt.Errorf("Invalid credentials configuration: %w", err))		}	} 	dnsURL, dnsUser, dnsPass, err := env.LookupEnv(config.EnvDNSWebhook)	if err != nil {		if globalIsGateway {			logger.FatalIf(err, "Unable to initialize remote webhook DNS config")		} else {			logger.LogIf(ctx, fmt.Errorf("Unable to initialize remote webhook DNS config %w", err))		}	}	if err == nil && dnsURL != "" {		globalDNSConfig, err = dns.NewOperatorDNS(dnsURL,			dns.Authentication(dnsUser, dnsPass),			dns.RootCAs(globalRootCAs))		if err != nil {			if globalIsGateway {				logger.FatalIf(err, "Unable to initialize remote webhook DNS config")			} else {				logger.LogIf(ctx, fmt.Errorf("Unable to initialize remote webhook DNS config %w", err))			}		}	} 	etcdCfg, err := etcd.LookupConfig(s[config.EtcdSubSys][config.Default], globalRootCAs)	if err != nil {		if globalIsGateway {			logger.FatalIf(err, "Unable to initialize etcd config")		} else {			logger.LogIf(ctx, fmt.Errorf("Unable to initialize etcd config: %w", err))		}	} 	if etcdCfg.Enabled {		if globalEtcdClient == nil {			globalEtcdClient, err = etcd.New(etcdCfg)			if err != nil {				if globalIsGateway {					logger.FatalIf(err, "Unable to initialize etcd config")				} else {					logger.LogIf(ctx, fmt.Errorf("Unable to initialize etcd config: %w", err))				}			}		} 		if len(globalDomainNames) != 0 && !globalDomainIPs.IsEmpty() && globalEtcdClient != nil {			if globalDNSConfig != nil {				// if global DNS is already configured, indicate with a warning, incase				// users are confused.				logger.LogIf(ctx, fmt.Errorf("DNS store is already configured with %s, not using etcd for DNS store", globalDNSConfig))			} else {				globalDNSConfig, err = dns.NewCoreDNS(etcdCfg.Config,					dns.DomainNames(globalDomainNames),					dns.DomainIPs(globalDomainIPs),					dns.DomainPort(globalMinioPort),					dns.CoreDNSPath(etcdCfg.CoreDNSPath),				)				if err != nil {					if globalIsGateway {						logger.FatalIf(err, "Unable to initialize DNS config")					} else {

Lines 1–500 of 879.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t