mirror of https://github.com/minio/minio.git
175 lines
5.9 KiB
Go
175 lines
5.9 KiB
Go
// 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/v3/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'; script-src 'self' https://unpkg.com; connect-src 'self' https://unpkg.com;",
|
|
},
|
|
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) {
|
|
cfg = Config{
|
|
CSPPolicy: env.Get(EnvBrowserCSPPolicy, kvs.GetWithDefault(browserCSPPolicy, DefaultKVS)),
|
|
HSTSSeconds: 0,
|
|
HSTSIncludeSubdomains: true,
|
|
HSTSPreload: true,
|
|
ReferrerPolicy: "strict-origin-when-cross-origin",
|
|
}
|
|
|
|
if err = config.CheckValidKeys(config.BrowserSubSys, kvs, DefaultKVS); err != nil {
|
|
return cfg, err
|
|
}
|
|
|
|
hstsIncludeSubdomains := env.Get(EnvBrowserHSTSIncludeSubdomains, kvs.GetWithDefault(browserHSTSIncludeSubdomains, DefaultKVS)) == config.EnableOn
|
|
hstsPreload := env.Get(EnvBrowserHSTSPreload, kvs.Get(browserHSTSPreload)) == config.EnableOn
|
|
|
|
hstsSeconds, err := strconv.Atoi(env.Get(EnvBrowserHSTSSeconds, kvs.GetWithDefault(browserHSTSSeconds, DefaultKVS)))
|
|
if err != nil {
|
|
return cfg, err
|
|
}
|
|
|
|
cfg.HSTSSeconds = hstsSeconds
|
|
cfg.HSTSIncludeSubdomains = hstsIncludeSubdomains
|
|
cfg.HSTSPreload = hstsPreload
|
|
|
|
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)
|
|
}
|
|
|
|
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
|
|
}
|