-
Notifications
You must be signed in to change notification settings - Fork 1
/
tls.go
120 lines (97 loc) · 3.01 KB
/
tls.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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
package transport
import (
"crypto/tls"
"fmt"
"time"
"github.com/effective-security/porto/pkg/crlcache"
"github.com/effective-security/porto/pkg/tlsconfig"
"github.com/pkg/errors"
)
// TLSInfo provides TLS configuration
type TLSInfo struct {
CertFile string
KeyFile string
ClientCAFile string
TrustedCAFile string
ClientAuthType tls.ClientAuthType
CRLVerifier crlcache.Verifier
InsecureSkipVerify bool
SkipClientSANVerify bool
// ServerName ensures the cert matches the given host in case of discovery / virtual hosting
ServerName string
// HandshakeFailure is optionally called when a connection fails to handshake. The
// connection will be closed immediately afterwards.
HandshakeFailure func(*tls.Conn, error)
// CipherSuites is a list of supported cipher suites.
// If empty, Go auto-populates it by default.
// Note that cipher suites are prioritized in the given order.
CipherSuites []string
// AllowedCN is a CN which must be provided by a client.
AllowedCN string
// AllowedHostname is an IP address or hostname that must match the TLS
// certificate provided by a client.
AllowedHostname string
// EmptyCN indicates that the cert must have empty CN.
// If true, ClientConfig() will return an error for a cert with non empty CN.
EmptyCN bool
tlsCfg *tls.Config
tlsReloader *tlsconfig.KeypairReloader
}
func (info *TLSInfo) String() string {
return fmt.Sprintf("cert=%s, key=%s, trusted-ca=%s, client-ca=%s, client-cert-auth=%d",
info.CertFile, info.KeyFile, info.TrustedCAFile, info.ClientCAFile, int(info.ClientAuthType))
}
// Empty returns true if TLS info is empty
func (info *TLSInfo) Empty() bool {
return info.CertFile == "" || info.KeyFile == ""
}
// Close the resources
func (info *TLSInfo) Close() {
if info.tlsReloader != nil {
info.tlsReloader.Close()
info.tlsReloader = nil
}
if info.tlsCfg != nil {
info.tlsCfg = nil
}
}
// Config returns tls.Config
func (info *TLSInfo) Config() *tls.Config {
return info.tlsCfg
}
// ServerTLSWithReloader returns tls.Config with reloader
func (info *TLSInfo) ServerTLSWithReloader() (*tls.Config, error) {
var err error
if info.tlsCfg != nil {
return info.tlsCfg, nil
}
info.tlsCfg, err = tlsconfig.NewServerTLSFromFiles(
info.CertFile,
info.KeyFile,
info.TrustedCAFile,
info.ClientCAFile,
info.ClientAuthType)
if err != nil {
return nil, err
}
if len(info.tlsCfg.Certificates) > 0 &&
info.tlsCfg.Certificates[0].Leaf != nil &&
info.tlsCfg.Certificates[0].Leaf.NotAfter.Before(time.Now()) {
return nil, errors.Errorf("tls: certificate has expired")
}
if err = tlsconfig.UpdateCipherSuites(info.tlsCfg, info.CipherSuites); err != nil {
return nil, err
}
logger.Infof(info.String())
info.tlsReloader, err = tlsconfig.NewKeypairReloader(
"",
info.CertFile,
info.KeyFile,
5*time.Minute)
if err != nil {
return nil, err
}
// TODO: tlsloader.WithOCSPStaple(cfg.OCSPFile)
info.tlsCfg.GetCertificate = info.tlsReloader.GetKeypairFunc()
return info.tlsCfg, nil
}