mirror of
https://github.com/minio/minio.git
synced 2024-12-24 22:25:54 -05:00
Support to store browser config settings (#18631)
* csp_policy * hsts_seconds * hsts_include_subdomains * hsts_preload * referrer_policy
This commit is contained in:
parent
c1cae51fb5
commit
8f13c8c3bf
@ -178,6 +178,23 @@ func minioConfigToConsoleFeatures() {
|
|||||||
os.Setenv("CONSOLE_MINIO_REGION", globalSite.Region)
|
os.Setenv("CONSOLE_MINIO_REGION", globalSite.Region)
|
||||||
os.Setenv("CONSOLE_CERT_PASSWD", env.Get("MINIO_CERT_PASSWD", ""))
|
os.Setenv("CONSOLE_CERT_PASSWD", env.Get("MINIO_CERT_PASSWD", ""))
|
||||||
|
|
||||||
|
// This section sets Browser (console) stored config
|
||||||
|
if valueSCP := globalBrowserConfig.GetCSPolicy(); valueSCP != "" {
|
||||||
|
os.Setenv("CONSOLE_SECURE_CONTENT_SECURITY_POLICY", valueSCP)
|
||||||
|
}
|
||||||
|
|
||||||
|
if hstsSeconds := globalBrowserConfig.GetHSTSSeconds(); hstsSeconds > 0 {
|
||||||
|
isubdom := globalBrowserConfig.IsHSTSIncludeSubdomains()
|
||||||
|
isprel := globalBrowserConfig.IsHSTSPreload()
|
||||||
|
os.Setenv("CONSOLE_SECURE_STS_SECONDS", strconv.Itoa(hstsSeconds))
|
||||||
|
os.Setenv("CONSOLE_SECURE_STS_INCLUDE_SUB_DOMAINS", isubdom)
|
||||||
|
os.Setenv("CONSOLE_SECURE_STS_PRELOAD", isprel)
|
||||||
|
}
|
||||||
|
|
||||||
|
if valueRefer := globalBrowserConfig.GetReferPolicy(); valueRefer != "" {
|
||||||
|
os.Setenv("CONSOLE_SECURE_REFERRER_POLICY", valueRefer)
|
||||||
|
}
|
||||||
|
|
||||||
globalSubnetConfig.ApplyEnv()
|
globalSubnetConfig.ApplyEnv()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,6 +24,8 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/minio/minio/internal/config/browser"
|
||||||
|
|
||||||
"github.com/minio/madmin-go/v3"
|
"github.com/minio/madmin-go/v3"
|
||||||
"github.com/minio/minio/internal/config"
|
"github.com/minio/minio/internal/config"
|
||||||
"github.com/minio/minio/internal/config/api"
|
"github.com/minio/minio/internal/config/api"
|
||||||
@ -74,6 +76,7 @@ func initHelp() {
|
|||||||
config.DriveSubSys: drive.DefaultKVS,
|
config.DriveSubSys: drive.DefaultKVS,
|
||||||
config.CacheSubSys: cache.DefaultKVS,
|
config.CacheSubSys: cache.DefaultKVS,
|
||||||
config.BatchSubSys: batch.DefaultKVS,
|
config.BatchSubSys: batch.DefaultKVS,
|
||||||
|
config.BrowserSubSys: browser.DefaultKVS,
|
||||||
}
|
}
|
||||||
for k, v := range notify.DefaultNotificationKVS {
|
for k, v := range notify.DefaultNotificationKVS {
|
||||||
kvs[k] = v
|
kvs[k] = v
|
||||||
@ -226,6 +229,11 @@ func initHelp() {
|
|||||||
Description: "enable cache plugin on MinIO for GET/HEAD requests",
|
Description: "enable cache plugin on MinIO for GET/HEAD requests",
|
||||||
Optional: true,
|
Optional: true,
|
||||||
},
|
},
|
||||||
|
config.HelpKV{
|
||||||
|
Key: config.BrowserSubSys,
|
||||||
|
Description: "manage Browser HTTP specific features, such as Security headers, etc.",
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
if globalIsErasure {
|
if globalIsErasure {
|
||||||
@ -273,6 +281,7 @@ func initHelp() {
|
|||||||
config.CallhomeSubSys: callhome.HelpCallhome,
|
config.CallhomeSubSys: callhome.HelpCallhome,
|
||||||
config.DriveSubSys: drive.HelpDrive,
|
config.DriveSubSys: drive.HelpDrive,
|
||||||
config.CacheSubSys: cache.Help,
|
config.CacheSubSys: cache.Help,
|
||||||
|
config.BrowserSubSys: browser.Help,
|
||||||
}
|
}
|
||||||
|
|
||||||
config.RegisterHelpSubSys(helpMap)
|
config.RegisterHelpSubSys(helpMap)
|
||||||
@ -407,6 +416,10 @@ func validateSubSysConfig(ctx context.Context, s config.Config, subSys string, o
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case config.BrowserSubSys:
|
||||||
|
if _, err := browser.LookupConfig(s[config.BrowserSubSys][config.Default]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
if config.LoggerSubSystems.Contains(subSys) {
|
if config.LoggerSubSystems.Contains(subSys) {
|
||||||
if err := logger.ValidateSubSysConfig(ctx, s, subSys); err != nil {
|
if err := logger.ValidateSubSysConfig(ctx, s, subSys); err != nil {
|
||||||
@ -689,6 +702,12 @@ func applyDynamicConfigForSubSys(ctx context.Context, objAPI ObjectLayer, s conf
|
|||||||
} else {
|
} else {
|
||||||
globalCacheConfig.Update(cacheCfg)
|
globalCacheConfig.Update(cacheCfg)
|
||||||
}
|
}
|
||||||
|
case config.BrowserSubSys:
|
||||||
|
browserCfg, err := browser.LookupConfig(s[config.BrowserSubSys][config.Default])
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Unable to apply browser config: %w", err)
|
||||||
|
}
|
||||||
|
globalBrowserConfig.Update(browserCfg)
|
||||||
}
|
}
|
||||||
globalServerConfigMu.Lock()
|
globalServerConfigMu.Lock()
|
||||||
defer globalServerConfigMu.Unlock()
|
defer globalServerConfigMu.Unlock()
|
||||||
|
@ -33,6 +33,7 @@ import (
|
|||||||
"github.com/minio/minio/internal/bpool"
|
"github.com/minio/minio/internal/bpool"
|
||||||
"github.com/minio/minio/internal/bucket/bandwidth"
|
"github.com/minio/minio/internal/bucket/bandwidth"
|
||||||
"github.com/minio/minio/internal/config"
|
"github.com/minio/minio/internal/config"
|
||||||
|
"github.com/minio/minio/internal/config/browser"
|
||||||
"github.com/minio/minio/internal/handlers"
|
"github.com/minio/minio/internal/handlers"
|
||||||
"github.com/minio/minio/internal/kms"
|
"github.com/minio/minio/internal/kms"
|
||||||
"go.uber.org/atomic"
|
"go.uber.org/atomic"
|
||||||
@ -191,6 +192,9 @@ var (
|
|||||||
// Disable redirect, default is enabled.
|
// Disable redirect, default is enabled.
|
||||||
globalBrowserRedirect bool
|
globalBrowserRedirect bool
|
||||||
|
|
||||||
|
// globalBrowserConfig Browser user configurable settings
|
||||||
|
globalBrowserConfig browser.Config
|
||||||
|
|
||||||
// This flag is set to 'true' when MINIO_UPDATE env is set to 'off'. Default is false.
|
// This flag is set to 'true' when MINIO_UPDATE env is set to 'off'. Default is false.
|
||||||
globalInplaceUpdateDisabled = false
|
globalInplaceUpdateDisabled = false
|
||||||
|
|
||||||
|
164
internal/config/browser/browser.go
Normal file
164
internal/config/browser/browser.go
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
// Copyright (c) 2015-2023 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 browser
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/minio/minio/internal/config"
|
||||||
|
"github.com/minio/pkg/v2/env"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Browser sub-system constants
|
||||||
|
const (
|
||||||
|
// browserCSPPolicy setting name for Content-Security-Policy response header value
|
||||||
|
browserCSPPolicy = "csp_policy"
|
||||||
|
// browserHSTSSeconds setting name for Strict-Transport-Security response header, amount of seconds for 'max-age'
|
||||||
|
browserHSTSSeconds = "hsts_seconds"
|
||||||
|
// browserHSTSIncludeSubdomains setting name for Strict-Transport-Security response header 'includeSubDomains' flag (true or false)
|
||||||
|
browserHSTSIncludeSubdomains = "hsts_include_subdomains"
|
||||||
|
// browserHSTSPreload setting name for Strict-Transport-Security response header 'preload' flag (true or false)
|
||||||
|
browserHSTSPreload = "hsts_preload"
|
||||||
|
// browserReferrerPolicy setting name for Referrer-Policy response header
|
||||||
|
browserReferrerPolicy = "referrer_policy"
|
||||||
|
|
||||||
|
EnvBrowserCSPPolicy = "MINIO_BROWSER_CONTENT_SECURITY_POLICY"
|
||||||
|
EnvBrowserHSTSSeconds = "MINIO_BROWSER_HSTS_SECONDS"
|
||||||
|
EnvBrowserHSTSIncludeSubdomains = "MINIO_BROWSER_HSTS_INCLUDE_SUB_DOMAINS"
|
||||||
|
EnvBrowserHSTSPreload = "MINIO_BROWSER_HSTS_PRELOAD"
|
||||||
|
EnvBrowserReferrerPolicy = "MINIO_BROWSER_REFERRER_POLICY"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DefaultKVS - default storage class config
|
||||||
|
var (
|
||||||
|
DefaultKVS = config.KVS{
|
||||||
|
config.KV{
|
||||||
|
Key: browserCSPPolicy,
|
||||||
|
Value: "default-src 'self' 'unsafe-eval' 'unsafe-inline';",
|
||||||
|
},
|
||||||
|
config.KV{
|
||||||
|
Key: browserHSTSSeconds,
|
||||||
|
Value: "0",
|
||||||
|
},
|
||||||
|
config.KV{
|
||||||
|
Key: browserHSTSIncludeSubdomains,
|
||||||
|
Value: config.EnableOff,
|
||||||
|
},
|
||||||
|
config.KV{
|
||||||
|
Key: browserHSTSPreload,
|
||||||
|
Value: config.EnableOff,
|
||||||
|
},
|
||||||
|
config.KV{
|
||||||
|
Key: browserReferrerPolicy,
|
||||||
|
Value: "strict-origin-when-cross-origin",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// configLock is a global lock for browser config
|
||||||
|
var configLock sync.RWMutex
|
||||||
|
|
||||||
|
// Config storage class configuration
|
||||||
|
type Config struct {
|
||||||
|
CSPPolicy string `json:"csp_policy"`
|
||||||
|
HSTSSeconds int `json:"hsts_seconds"`
|
||||||
|
HSTSIncludeSubdomains bool `json:"hsts_include_subdomains"`
|
||||||
|
HSTSPreload bool `json:"hsts_preload"`
|
||||||
|
ReferrerPolicy string `json:"referrer_policy"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update Updates browser with new config
|
||||||
|
func (browseCfg *Config) Update(newCfg Config) {
|
||||||
|
configLock.Lock()
|
||||||
|
defer configLock.Unlock()
|
||||||
|
browseCfg.CSPPolicy = newCfg.CSPPolicy
|
||||||
|
browseCfg.HSTSSeconds = newCfg.HSTSSeconds
|
||||||
|
browseCfg.HSTSIncludeSubdomains = newCfg.HSTSIncludeSubdomains
|
||||||
|
browseCfg.HSTSPreload = newCfg.HSTSPreload
|
||||||
|
browseCfg.ReferrerPolicy = newCfg.ReferrerPolicy
|
||||||
|
}
|
||||||
|
|
||||||
|
// LookupConfig - lookup api config and override with valid environment settings if any.
|
||||||
|
func LookupConfig(kvs config.KVS) (cfg Config, err error) {
|
||||||
|
cspPolicy := env.Get(EnvBrowserCSPPolicy, kvs.GetWithDefault(browserCSPPolicy, DefaultKVS))
|
||||||
|
hstsSeconds, err := strconv.Atoi(env.Get(EnvBrowserHSTSSeconds, kvs.GetWithDefault(browserHSTSSeconds, DefaultKVS)))
|
||||||
|
if err != nil {
|
||||||
|
return cfg, err
|
||||||
|
}
|
||||||
|
|
||||||
|
hstsIncludeSubdomains := env.Get(EnvBrowserHSTSIncludeSubdomains, kvs.GetWithDefault(browserHSTSIncludeSubdomains, DefaultKVS)) == config.EnableOn
|
||||||
|
hstsPreload := env.Get(EnvBrowserHSTSPreload, kvs.Get(browserHSTSPreload)) == config.EnableOn
|
||||||
|
|
||||||
|
referrerPolicy := env.Get(EnvBrowserReferrerPolicy, kvs.GetWithDefault(browserReferrerPolicy, DefaultKVS))
|
||||||
|
switch referrerPolicy {
|
||||||
|
case "no-referrer", "no-referrer-when-downgrade", "origin", "origin-when-cross-origin", "same-origin", "strict-origin", "strict-origin-when-cross-origin", "unsafe-url":
|
||||||
|
cfg.ReferrerPolicy = referrerPolicy
|
||||||
|
default:
|
||||||
|
return cfg, fmt.Errorf("invalid value %v for %s", referrerPolicy, browserReferrerPolicy)
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg.CSPPolicy = cspPolicy
|
||||||
|
cfg.HSTSSeconds = hstsSeconds
|
||||||
|
cfg.HSTSIncludeSubdomains = hstsIncludeSubdomains
|
||||||
|
cfg.HSTSPreload = hstsPreload
|
||||||
|
|
||||||
|
return cfg, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetCSPolicy - Get the Content security Policy
|
||||||
|
func (browseCfg *Config) GetCSPolicy() string {
|
||||||
|
configLock.RLock()
|
||||||
|
defer configLock.RUnlock()
|
||||||
|
return browseCfg.CSPPolicy
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetHSTSSeconds - Get the Content security Policy
|
||||||
|
func (browseCfg *Config) GetHSTSSeconds() int {
|
||||||
|
configLock.RLock()
|
||||||
|
defer configLock.RUnlock()
|
||||||
|
return browseCfg.HSTSSeconds
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsHSTSIncludeSubdomains - is HSTS 'includeSubdomains' directive enabled
|
||||||
|
func (browseCfg *Config) IsHSTSIncludeSubdomains() string {
|
||||||
|
configLock.RLock()
|
||||||
|
defer configLock.RUnlock()
|
||||||
|
if browseCfg.HSTSSeconds > 0 && browseCfg.HSTSIncludeSubdomains {
|
||||||
|
return config.EnableOn
|
||||||
|
}
|
||||||
|
return config.EnableOff
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsHSTSPreload - is HSTS 'preload' directive enabled
|
||||||
|
func (browseCfg *Config) IsHSTSPreload() string {
|
||||||
|
configLock.RLock()
|
||||||
|
defer configLock.RUnlock()
|
||||||
|
if browseCfg.HSTSSeconds > 0 && browseCfg.HSTSPreload {
|
||||||
|
return config.EnableOn
|
||||||
|
}
|
||||||
|
return config.EnableOff
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetReferPolicy - Get the ReferPolicy
|
||||||
|
func (browseCfg *Config) GetReferPolicy() string {
|
||||||
|
configLock.RLock()
|
||||||
|
defer configLock.RUnlock()
|
||||||
|
return browseCfg.ReferrerPolicy
|
||||||
|
}
|
60
internal/config/browser/help.go
Normal file
60
internal/config/browser/help.go
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
// Copyright (c) 2015-2023 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 browser
|
||||||
|
|
||||||
|
import "github.com/minio/minio/internal/config"
|
||||||
|
|
||||||
|
// Help template for browser feature.
|
||||||
|
var (
|
||||||
|
defaultHelpPostfix = func(key string) string {
|
||||||
|
return config.DefaultHelpPostfix(DefaultKVS, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
Help = config.HelpKVS{
|
||||||
|
config.HelpKV{
|
||||||
|
Key: browserCSPPolicy,
|
||||||
|
Description: `set Content-Security-Policy response header value` + defaultHelpPostfix(browserCSPPolicy),
|
||||||
|
Optional: true,
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
config.HelpKV{
|
||||||
|
Key: browserHSTSSeconds,
|
||||||
|
Description: `set Strict-Transport-Security 'max-age' amount of seconds value` + defaultHelpPostfix(browserHSTSSeconds),
|
||||||
|
Optional: true,
|
||||||
|
Type: "number",
|
||||||
|
},
|
||||||
|
config.HelpKV{
|
||||||
|
Key: browserHSTSIncludeSubdomains,
|
||||||
|
Description: `turn 'on' to set Strict-Transport-Security 'includeSubDomains' directive` + defaultHelpPostfix(browserHSTSIncludeSubdomains),
|
||||||
|
Optional: true,
|
||||||
|
Type: "boolean",
|
||||||
|
},
|
||||||
|
config.HelpKV{
|
||||||
|
Key: browserHSTSPreload,
|
||||||
|
Description: `turn 'on' to set Strict-Transport-Security 'preload' directive` + defaultHelpPostfix(browserHSTSPreload),
|
||||||
|
Optional: true,
|
||||||
|
Type: "boolean",
|
||||||
|
},
|
||||||
|
config.HelpKV{
|
||||||
|
Key: browserReferrerPolicy,
|
||||||
|
Description: `set Referrer-Policy response header value` + defaultHelpPostfix(browserReferrerPolicy),
|
||||||
|
Optional: true,
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
@ -119,6 +119,7 @@ const (
|
|||||||
CallhomeSubSys = madmin.CallhomeSubSys
|
CallhomeSubSys = madmin.CallhomeSubSys
|
||||||
DriveSubSys = madmin.DriveSubSys
|
DriveSubSys = madmin.DriveSubSys
|
||||||
BatchSubSys = madmin.BatchSubSys
|
BatchSubSys = madmin.BatchSubSys
|
||||||
|
BrowserSubSys = madmin.BrowserSubSys
|
||||||
|
|
||||||
// Add new constants here (similar to above) if you add new fields to config.
|
// Add new constants here (similar to above) if you add new fields to config.
|
||||||
)
|
)
|
||||||
@ -188,6 +189,7 @@ var SubSystemsDynamic = set.CreateStringSet(
|
|||||||
StorageClassSubSys,
|
StorageClassSubSys,
|
||||||
CacheSubSys,
|
CacheSubSys,
|
||||||
BatchSubSys,
|
BatchSubSys,
|
||||||
|
BrowserSubSys,
|
||||||
)
|
)
|
||||||
|
|
||||||
// SubSystemsSingleTargets - subsystems which only support single target.
|
// SubSystemsSingleTargets - subsystems which only support single target.
|
||||||
@ -209,8 +211,8 @@ var SubSystemsSingleTargets = set.CreateStringSet(
|
|||||||
SubnetSubSys,
|
SubnetSubSys,
|
||||||
CallhomeSubSys,
|
CallhomeSubSys,
|
||||||
DriveSubSys,
|
DriveSubSys,
|
||||||
CacheSubSys,
|
|
||||||
BatchSubSys,
|
BatchSubSys,
|
||||||
|
BrowserSubSys,
|
||||||
)
|
)
|
||||||
|
|
||||||
// Constant separators
|
// Constant separators
|
||||||
|
@ -82,6 +82,7 @@ const (
|
|||||||
EnvWorm = "MINIO_WORM" // legacy
|
EnvWorm = "MINIO_WORM" // legacy
|
||||||
EnvRegion = "MINIO_REGION" // legacy
|
EnvRegion = "MINIO_REGION" // legacy
|
||||||
EnvRegionName = "MINIO_REGION_NAME" // legacy
|
EnvRegionName = "MINIO_REGION_NAME" // legacy
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Expiration Token durations
|
// Expiration Token durations
|
||||||
|
Loading…
Reference in New Issue
Block a user