github.com/minio/minio@v0.0.0-20240328213742-3f72439b8a27/internal/config/browser/browser.go (about) 1 // Copyright (c) 2015-2023 MinIO, Inc. 2 // 3 // This file is part of MinIO Object Storage stack 4 // 5 // This program is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Affero General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // This program is distributed in the hope that it will be useful 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Affero General Public License for more details. 14 // 15 // You should have received a copy of the GNU Affero General Public License 16 // along with this program. If not, see <http://www.gnu.org/licenses/>. 17 18 package browser 19 20 import ( 21 "fmt" 22 "strconv" 23 "sync" 24 25 "github.com/minio/minio/internal/config" 26 "github.com/minio/pkg/v2/env" 27 ) 28 29 // Browser sub-system constants 30 const ( 31 // browserCSPPolicy setting name for Content-Security-Policy response header value 32 browserCSPPolicy = "csp_policy" 33 // browserHSTSSeconds setting name for Strict-Transport-Security response header, amount of seconds for 'max-age' 34 browserHSTSSeconds = "hsts_seconds" 35 // browserHSTSIncludeSubdomains setting name for Strict-Transport-Security response header 'includeSubDomains' flag (true or false) 36 browserHSTSIncludeSubdomains = "hsts_include_subdomains" 37 // browserHSTSPreload setting name for Strict-Transport-Security response header 'preload' flag (true or false) 38 browserHSTSPreload = "hsts_preload" 39 // browserReferrerPolicy setting name for Referrer-Policy response header 40 browserReferrerPolicy = "referrer_policy" 41 42 EnvBrowserCSPPolicy = "MINIO_BROWSER_CONTENT_SECURITY_POLICY" 43 EnvBrowserHSTSSeconds = "MINIO_BROWSER_HSTS_SECONDS" 44 EnvBrowserHSTSIncludeSubdomains = "MINIO_BROWSER_HSTS_INCLUDE_SUB_DOMAINS" 45 EnvBrowserHSTSPreload = "MINIO_BROWSER_HSTS_PRELOAD" 46 EnvBrowserReferrerPolicy = "MINIO_BROWSER_REFERRER_POLICY" 47 ) 48 49 // DefaultKVS - default storage class config 50 var ( 51 DefaultKVS = config.KVS{ 52 config.KV{ 53 Key: browserCSPPolicy, 54 Value: "default-src 'self' 'unsafe-eval' 'unsafe-inline';", 55 }, 56 config.KV{ 57 Key: browserHSTSSeconds, 58 Value: "0", 59 }, 60 config.KV{ 61 Key: browserHSTSIncludeSubdomains, 62 Value: config.EnableOff, 63 }, 64 config.KV{ 65 Key: browserHSTSPreload, 66 Value: config.EnableOff, 67 }, 68 config.KV{ 69 Key: browserReferrerPolicy, 70 Value: "strict-origin-when-cross-origin", 71 }, 72 } 73 ) 74 75 // configLock is a global lock for browser config 76 var configLock sync.RWMutex 77 78 // Config storage class configuration 79 type Config struct { 80 CSPPolicy string `json:"csp_policy"` 81 HSTSSeconds int `json:"hsts_seconds"` 82 HSTSIncludeSubdomains bool `json:"hsts_include_subdomains"` 83 HSTSPreload bool `json:"hsts_preload"` 84 ReferrerPolicy string `json:"referrer_policy"` 85 } 86 87 // Update Updates browser with new config 88 func (browseCfg *Config) Update(newCfg Config) { 89 configLock.Lock() 90 defer configLock.Unlock() 91 browseCfg.CSPPolicy = newCfg.CSPPolicy 92 browseCfg.HSTSSeconds = newCfg.HSTSSeconds 93 browseCfg.HSTSIncludeSubdomains = newCfg.HSTSIncludeSubdomains 94 browseCfg.HSTSPreload = newCfg.HSTSPreload 95 browseCfg.ReferrerPolicy = newCfg.ReferrerPolicy 96 } 97 98 // LookupConfig - lookup api config and override with valid environment settings if any. 99 func LookupConfig(kvs config.KVS) (cfg Config, err error) { 100 cspPolicy := env.Get(EnvBrowserCSPPolicy, kvs.GetWithDefault(browserCSPPolicy, DefaultKVS)) 101 hstsSeconds, err := strconv.Atoi(env.Get(EnvBrowserHSTSSeconds, kvs.GetWithDefault(browserHSTSSeconds, DefaultKVS))) 102 if err != nil { 103 return cfg, err 104 } 105 106 hstsIncludeSubdomains := env.Get(EnvBrowserHSTSIncludeSubdomains, kvs.GetWithDefault(browserHSTSIncludeSubdomains, DefaultKVS)) == config.EnableOn 107 hstsPreload := env.Get(EnvBrowserHSTSPreload, kvs.Get(browserHSTSPreload)) == config.EnableOn 108 109 referrerPolicy := env.Get(EnvBrowserReferrerPolicy, kvs.GetWithDefault(browserReferrerPolicy, DefaultKVS)) 110 switch referrerPolicy { 111 case "no-referrer", "no-referrer-when-downgrade", "origin", "origin-when-cross-origin", "same-origin", "strict-origin", "strict-origin-when-cross-origin", "unsafe-url": 112 cfg.ReferrerPolicy = referrerPolicy 113 default: 114 return cfg, fmt.Errorf("invalid value %v for %s", referrerPolicy, browserReferrerPolicy) 115 } 116 117 cfg.CSPPolicy = cspPolicy 118 cfg.HSTSSeconds = hstsSeconds 119 cfg.HSTSIncludeSubdomains = hstsIncludeSubdomains 120 cfg.HSTSPreload = hstsPreload 121 122 return cfg, nil 123 } 124 125 // GetCSPolicy - Get the Content security Policy 126 func (browseCfg *Config) GetCSPolicy() string { 127 configLock.RLock() 128 defer configLock.RUnlock() 129 return browseCfg.CSPPolicy 130 } 131 132 // GetHSTSSeconds - Get the Content security Policy 133 func (browseCfg *Config) GetHSTSSeconds() int { 134 configLock.RLock() 135 defer configLock.RUnlock() 136 return browseCfg.HSTSSeconds 137 } 138 139 // IsHSTSIncludeSubdomains - is HSTS 'includeSubdomains' directive enabled 140 func (browseCfg *Config) IsHSTSIncludeSubdomains() string { 141 configLock.RLock() 142 defer configLock.RUnlock() 143 if browseCfg.HSTSSeconds > 0 && browseCfg.HSTSIncludeSubdomains { 144 return config.EnableOn 145 } 146 return config.EnableOff 147 } 148 149 // IsHSTSPreload - is HSTS 'preload' directive enabled 150 func (browseCfg *Config) IsHSTSPreload() string { 151 configLock.RLock() 152 defer configLock.RUnlock() 153 if browseCfg.HSTSSeconds > 0 && browseCfg.HSTSPreload { 154 return config.EnableOn 155 } 156 return config.EnableOff 157 } 158 159 // GetReferPolicy - Get the ReferPolicy 160 func (browseCfg *Config) GetReferPolicy() string { 161 configLock.RLock() 162 defer configLock.RUnlock() 163 return browseCfg.ReferrerPolicy 164 }