1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
|
package tls
import (
"crypto/tls"
"fmt"
"sort"
"strings"
)
// GetCertificateFunc returns the certificate to be used for given domain
type GetCertificateFunc func(*tls.ClientHelloInfo) (*tls.Certificate, error)
var (
preferredCipherSuites = []uint16{
tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
tls.TLS_AES_128_GCM_SHA256,
tls.TLS_AES_256_GCM_SHA384,
tls.TLS_CHACHA20_POLY1305_SHA256,
}
// AllTLSVersions has all supported flag values
AllTLSVersions = map[string]uint16{
"": 0, // Default value in tls.Config
"tls1.2": tls.VersionTLS12,
"tls1.3": tls.VersionTLS13,
}
)
// FlagUsage returns string with explanation how to use the CLI flag
func FlagUsage(minOrMax string) string {
versions := []string{}
for version := range AllTLSVersions {
if version != "" {
versions = append(versions, fmt.Sprintf("%q", version))
}
}
sort.Strings(versions)
return fmt.Sprintf("Specifies the "+minOrMax+"imum SSL/TLS version, supported values are %s", strings.Join(versions, ", "))
}
// Create returns tls.Config for given app configuration
func Create(cert, key []byte, getCertificate GetCertificateFunc, insecureCiphers bool, tlsMinVersion uint16, tlsMaxVersion uint16) (*tls.Config, error) {
// set MinVersion to fix gosec: G402
tlsConfig := &tls.Config{GetCertificate: getCertificate, MinVersion: tls.VersionTLS12}
err := configureCertificate(tlsConfig, cert, key)
if err != nil {
return nil, err
}
if !insecureCiphers {
configureTLSCiphers(tlsConfig)
}
tlsConfig.MinVersion = tlsMinVersion
tlsConfig.MaxVersion = tlsMaxVersion
return tlsConfig, nil
}
// ValidateTLSVersions returns error if the provided TLS versions config values are not valid
func ValidateTLSVersions(min, max string) error {
tlsMin, tlsMinOk := AllTLSVersions[min]
tlsMax, tlsMaxOk := AllTLSVersions[max]
if !tlsMinOk {
return fmt.Errorf("invalid minimum TLS version: %s", min)
}
if !tlsMaxOk {
return fmt.Errorf("invalid maximum TLS version: %s", max)
}
if tlsMin > tlsMax && tlsMax > 0 {
return fmt.Errorf("invalid maximum TLS version: %s; should be at least %s", max, min)
}
return nil
}
func configureCertificate(tlsConfig *tls.Config, cert, key []byte) error {
certificate, err := tls.X509KeyPair(cert, key)
if err != nil {
return err
}
tlsConfig.Certificates = []tls.Certificate{certificate}
return nil
}
func configureTLSCiphers(tlsConfig *tls.Config) {
tlsConfig.PreferServerCipherSuites = true
tlsConfig.CipherSuites = preferredCipherSuites
}
|