1
1
package saltboot
2
2
3
3
import (
4
+ "crypto/tls"
4
5
"fmt"
5
6
"io/ioutil"
6
7
"log"
@@ -12,17 +13,22 @@ import (
12
13
)
13
14
14
15
const (
15
- httpsEnabledKey = "SALTBOOT_HTTPS_ENABLED"
16
- portKey = "SALTBOOT_PORT"
17
- defaultPort = 7070
18
- httpsPortKey = "SALTBOOT_HTTPS_PORT"
19
- defaultHttpsPort = 7071
20
- httpsCertFileKey = "SALTBOOT_HTTPS_CERT_FILE"
21
- defaultHttpsCertFile = "/etc/certs/cluster.pem"
22
- httpsKeyFileKey = "SALTBOOT_HTTPS_KEY_FILE"
23
- defaultHttpsKeyFile = "/etc/certs/cluster-key.pem"
24
- httpsCaCertFileKey = "SALTBOOT_HTTPS_CACERT_FILE"
25
- defaultHttpsCaCertFileKey = "/etc/certs/ca.pem"
16
+ httpsEnabledKey = "SALTBOOT_HTTPS_ENABLED"
17
+ portKey = "SALTBOOT_PORT"
18
+ defaultPort = 7070
19
+ httpsPortKey = "SALTBOOT_HTTPS_PORT"
20
+ defaultHttpsPort = 7071
21
+ httpsCertFileKey = "SALTBOOT_HTTPS_CERT_FILE"
22
+ defaultHttpsCertFile = "/etc/certs/cluster.pem"
23
+ httpsKeyFileKey = "SALTBOOT_HTTPS_KEY_FILE"
24
+ defaultHttpsKeyFile = "/etc/certs/cluster-key.pem"
25
+ httpsCaCertFileKey = "SALTBOOT_HTTPS_CACERT_FILE"
26
+ defaultHttpsCaCertFile = "/etc/certs/ca.pem"
27
+ minTlsVersionKey = "SALTBOOT_MIN_TLS_VERSION"
28
+ defaultMinTlsVersion = tls .VersionTLS12
29
+ maxTlsVersionKey = "SALTBOOT_MAX_TLS_VERSION"
30
+ defaultMaxTlsVersion = tls .VersionTLS13
31
+ cipherSuitesKey = "SALTBOOT_CIPHER_SUITES"
26
32
27
33
userKey = "SALTBOOT_USER"
28
34
passwdKey = "SALTBOOT_PASSWORD"
@@ -31,10 +37,49 @@ const (
31
37
defaultConfigLoc = "/etc/salt-bootstrap/security-config.yml"
32
38
)
33
39
40
+ var tlsVersionMap = map [string ]uint16 {
41
+ "1.0" : tls .VersionTLS10 ,
42
+ "1.1" : tls .VersionTLS11 ,
43
+ "1.2" : tls .VersionTLS12 ,
44
+ "1.3" : tls .VersionTLS13 ,
45
+ }
46
+
47
+ /**
48
+ * This slice matches the list of cipher suites specified in https://pkg.go.dev/crypto/tls@go1.14.3#pkg-constants
49
+ * Only the TLS 1.0-1.2 cipher suites are listed, since according to the go documentation "...TLS 1.3 ciphersuites are not configurable."
50
+ */
51
+ var cipherSuiteMap = map [string ]uint16 {
52
+ "TLS_RSA_WITH_RC4_128_SHA" : tls .TLS_RSA_WITH_RC4_128_SHA ,
53
+ "TLS_RSA_WITH_3DES_EDE_CBC_SHA" : tls .TLS_RSA_WITH_3DES_EDE_CBC_SHA ,
54
+ "TLS_RSA_WITH_AES_128_CBC_SHA" : tls .TLS_RSA_WITH_AES_128_CBC_SHA ,
55
+ "TLS_RSA_WITH_AES_256_CBC_SHA" : tls .TLS_RSA_WITH_AES_256_CBC_SHA ,
56
+ "TLS_RSA_WITH_AES_128_CBC_SHA256" : tls .TLS_RSA_WITH_AES_128_CBC_SHA256 ,
57
+ "TLS_RSA_WITH_AES_128_GCM_SHA256" : tls .TLS_RSA_WITH_AES_128_GCM_SHA256 ,
58
+ "TLS_RSA_WITH_AES_256_GCM_SHA384" : tls .TLS_RSA_WITH_AES_256_GCM_SHA384 ,
59
+ "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA" : tls .TLS_ECDHE_ECDSA_WITH_RC4_128_SHA ,
60
+ "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA" : tls .TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA ,
61
+ "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA" : tls .TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA ,
62
+ "TLS_ECDHE_RSA_WITH_RC4_128_SHA" : tls .TLS_ECDHE_RSA_WITH_RC4_128_SHA ,
63
+ "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA" : tls .TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA ,
64
+ "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA" : tls .TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA ,
65
+ "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA" : tls .TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA ,
66
+ "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256" : tls .TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 ,
67
+ "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256" : tls .TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 ,
68
+ "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" : tls .TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 ,
69
+ "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" : tls .TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 ,
70
+ "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384" : tls .TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 ,
71
+ "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384" : tls .TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 ,
72
+ "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256" : tls .TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 ,
73
+ "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256" : tls .TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 ,
74
+ }
75
+
34
76
type HttpsConfig struct {
35
- CertFile string `json:"certFile" yaml:"certFile"`
36
- KeyFile string `json:"keyFile" yaml:"keyFile"`
37
- CaCertFile string `json:"caCertFile" yaml:"caCertFile"`
77
+ CertFile string `json:"certFile" yaml:"certFile"`
78
+ KeyFile string `json:"keyFile" yaml:"keyFile"`
79
+ CaCertFile string `json:"caCertFile" yaml:"caCertFile"`
80
+ MinTlsVersion uint16 `json:"minTlsVersion" yaml:"minTlsVersion"`
81
+ MaxTlsVersion uint16 `json:"maxTlsVersion" yaml:"maxTlsVersion"`
82
+ CipherSuites []uint16 `json:"cipherSuites" yaml:"cipherSuites"`
38
83
}
39
84
40
85
type SecurityConfig struct {
@@ -43,6 +88,19 @@ type SecurityConfig struct {
43
88
SignVerifyKey string `json:"signKey" yaml:"signKey"`
44
89
}
45
90
91
+ func defaultCipherSuites () []uint16 {
92
+ return []uint16 {
93
+ tls .TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 ,
94
+ tls .TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 ,
95
+ tls .TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 ,
96
+ tls .TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 ,
97
+ tls .TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA ,
98
+ tls .TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA ,
99
+ tls .TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA ,
100
+ tls .TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA ,
101
+ }
102
+ }
103
+
46
104
func defaultSecurityConfigLoc () string {
47
105
return defaultConfigLoc
48
106
}
@@ -107,9 +165,9 @@ func GetHttpsConfig() HttpsConfig {
107
165
certFileStr := os .Getenv (httpsCertFileKey )
108
166
keyFileStr := os .Getenv (httpsKeyFileKey )
109
167
caCertFileStr := os .Getenv (httpsCaCertFileKey )
110
- log . Printf ( "[GetHttpsConfig] %s: %s" , httpsCertFileKey , certFileStr )
111
- log . Printf ( "[GetHttpsConfig] %s: %s" , httpsKeyFileKey , keyFileStr )
112
- log . Printf ( "[GetHttpsConfig] %s: %s" , httpsCaCertFileKey , caCertFileStr )
168
+ minTlsVersionStr := os . Getenv ( minTlsVersionKey )
169
+ maxTlsVersionStr := os . Getenv ( maxTlsVersionKey )
170
+ cipherSuitesStr := os . Getenv ( cipherSuitesKey )
113
171
114
172
if certFileStr == "" {
115
173
httpsConfig .CertFile = defaultHttpsCertFile
@@ -124,11 +182,43 @@ func GetHttpsConfig() HttpsConfig {
124
182
httpsConfig .KeyFile = keyFileStr
125
183
}
126
184
if caCertFileStr == "" {
127
- httpsConfig .CaCertFile = defaultHttpsCaCertFileKey
128
- log .Printf ("[GetHttpsConfig] using default ca cert file: %s" , defaultHttpsCaCertFileKey )
185
+ httpsConfig .CaCertFile = defaultHttpsCaCertFile
186
+ log .Printf ("[GetHttpsConfig] using default ca cert file: %s" , defaultHttpsCaCertFile )
129
187
} else {
130
188
httpsConfig .CaCertFile = caCertFileStr
131
189
}
190
+ if minTlsVersionStr == "" {
191
+ httpsConfig .MinTlsVersion = defaultMinTlsVersion
192
+ log .Printf ("[GetHttpsConfig] using default min TLS version: %s" , tlsVersionToString (defaultMinTlsVersion ))
193
+ } else {
194
+ minTlsVersion , valid := tlsVersionMap [minTlsVersionStr ]
195
+ if ! valid {
196
+ log .Fatalf ("[GetHttpsConfig] The specified TLS version is not a valid TLS version: %s" , minTlsVersionStr )
197
+ }
198
+ httpsConfig .MinTlsVersion = minTlsVersion
199
+ }
200
+ if maxTlsVersionStr == "" {
201
+ httpsConfig .MaxTlsVersion = defaultMaxTlsVersion
202
+ log .Printf ("[GetHttpsConfig] using default max TLS version: %s" , tlsVersionToString (defaultMaxTlsVersion ))
203
+ } else {
204
+ maxTlsVersion , valid := tlsVersionMap [maxTlsVersionStr ]
205
+ if ! valid {
206
+ log .Fatalf ("[GetHttpsConfig] The specified TLS version is not a valid TLS version: %s" , maxTlsVersionStr )
207
+ }
208
+ httpsConfig .MaxTlsVersion = maxTlsVersion
209
+ }
210
+ if cipherSuitesStr == "" {
211
+ httpsConfig .CipherSuites = defaultCipherSuites ()
212
+ log .Printf ("[GetHttpsConfig] using default list of cipher suites: %s" , MapUint16ToString (defaultCipherSuites (), cipherSuiteToString ))
213
+ } else {
214
+ httpsConfig .CipherSuites = MapStringToUint16 (strings .Split (cipherSuitesStr , "," ), func (s string ) uint16 {
215
+ cipherSuite , valid := cipherSuiteMap [s ]
216
+ if ! valid {
217
+ log .Fatalf ("[GetHttpsConfig] The specified cipher suite is not a valid cipher suite: %s" , s )
218
+ }
219
+ return cipherSuite
220
+ })
221
+ }
132
222
return httpsConfig
133
223
}
134
224
@@ -158,6 +248,24 @@ func GetConcatenatedCertFilePath(httpsConfig HttpsConfig) (string, error) {
158
248
return tmpFile .Name (), nil
159
249
}
160
250
251
+ func tlsVersionToString (tlsVersion uint16 ) string {
252
+ for str , constant := range tlsVersionMap {
253
+ if constant == tlsVersion {
254
+ return str
255
+ }
256
+ }
257
+ return fmt .Sprintf ("(0x%04x)" , tlsVersion )
258
+ }
259
+
260
+ func cipherSuiteToString (cipherSuite uint16 ) string {
261
+ for str , constant := range cipherSuiteMap {
262
+ if constant == cipherSuite {
263
+ return str
264
+ }
265
+ }
266
+ return fmt .Sprintf ("(0x%04x)" , cipherSuite )
267
+ }
268
+
161
269
func DetermineSecurityDetails (getEnv func (key string ) string , securityConfig func () string ) (* SecurityConfig , error ) {
162
270
var config SecurityConfig
163
271
configLoc := strings .TrimSpace (getEnv (configLocKey ))
0 commit comments