-
-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathauthenticationtls.go
106 lines (97 loc) · 3.06 KB
/
authenticationtls.go
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
101
102
103
104
105
106
package eredis
import (
"crypto/tls"
"crypto/x509"
"errors"
"fmt"
"os"
"path/filepath"
)
// The defaults should be a safe configuration
const defaultMinTLSVersion = tls.VersionTLS12
// Uses the default MaxVersion from "crypto/tls"
const defaultMaxTLSVersion = 0
// TLSConfig is the interface used to configure a tcp client or server from a `Config`
type TLSConfig struct {
// Enable TLS
Enabled bool
// Path to the CA cert. For a client this verifies the server certificate.
CAFile string
// Path to the TLS cert to use for TLS required connections. (optional)
CertFile string
// Path to the TLS key to use for TLS required connections. (optional)
KeyFile string
// InsecureSkipVerify will enable TLS but not verify the certificate
InsecureSkipVerify bool
// MinVersion sets the minimum TLS version that is acceptable.
// If not set, TLS 1.2 will be used. (optional)
MinVersion string
// MaxVersion sets the maximum TLS version that is acceptable.
// If not set, refer to crypto/tls for defaults. (optional)
MaxVersion string
}
func (c *TLSConfig) LoadTLSConfig() (*tls.Config, error) {
if !c.Enabled {
return nil, nil
}
var err error
var certPool *x509.CertPool
if c.CAFile != "" {
certPool, err = c.loadCert(c.CAFile)
if err != nil {
return nil, fmt.Errorf("failed to load CA CertPool: %w", err)
}
}
if (c.CertFile == "" && c.KeyFile != "") || (c.CertFile != "" && c.KeyFile == "") {
return nil, errors.New("for auth via TLS, either both certificate and key must be supplied, or neither")
}
var cert tls.Certificate
if c.CertFile != "" && c.KeyFile != "" {
cert, err = tls.LoadX509KeyPair(c.CertFile, c.KeyFile)
if err != nil {
return nil, fmt.Errorf("could not load TLS client key/certificate from %s:%s: %s", c.KeyFile, c.CertFile, err)
}
}
minVersion, err := convertVersion(c.MinVersion, defaultMinTLSVersion)
if err != nil {
return nil, fmt.Errorf("invalid TLS min_version: %w", err)
}
maxVersion, err := convertVersion(c.MaxVersion, defaultMaxTLSVersion)
if err != nil {
return nil, fmt.Errorf("invalid TLS max_version: %w", err)
}
return &tls.Config{
RootCAs: certPool,
Certificates: []tls.Certificate{cert},
InsecureSkipVerify: c.InsecureSkipVerify, //nolint:gosec
MinVersion: minVersion,
MaxVersion: maxVersion,
}, nil
}
func (c TLSConfig) loadCert(caPath string) (*x509.CertPool, error) {
caPEM, err := os.ReadFile(filepath.Clean(caPath))
if err != nil {
return nil, fmt.Errorf("failed to load CA %s: %w", caPath, err)
}
certPool := x509.NewCertPool()
if !certPool.AppendCertsFromPEM(caPEM) {
return nil, fmt.Errorf("failed to parse CA %s", caPath)
}
return certPool, nil
}
func convertVersion(version string, defaultVersion uint16) (uint16, error) {
if version == "" {
return defaultVersion, nil
}
val, ok := tlsProtocolVersions[version]
if !ok {
return 0, fmt.Errorf("unsupported TLS version: %q", version)
}
return val, nil
}
var tlsProtocolVersions = map[string]uint16{
"1.0": tls.VersionTLS10,
"1.1": tls.VersionTLS11,
"1.2": tls.VersionTLS12,
"1.3": tls.VersionTLS13,
}