forked from cloudflare/cfssl
-
Notifications
You must be signed in to change notification settings - Fork 0
/
listener.go
116 lines (99 loc) · 2.65 KB
/
listener.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
package transport
import (
"crypto/tls"
"net"
"time"
"github.com/cloudflare/cfssl/log"
)
// A Listener is a TCP network listener for TLS-secured connections.
type Listener struct {
*Transport
net.Listener
}
// Listen sets up a new server. If an error is returned, it means
// the server isn't ready to begin listening.
func Listen(address string, tr *Transport) (*Listener, error) {
var err error
l := &Listener{Transport: tr}
config, err := tr.getConfig()
if err != nil {
return nil, err
}
l.Listener, err = tls.Listen("tcp", address, config)
return l, err
}
func (tr *Transport) getConfig() (*tls.Config, error) {
if tr.ClientTrustStore != nil {
log.Info("using client auth")
return tr.TLSClientAuthServerConfig()
}
log.Info("not using client auth")
return tr.TLSServerConfig()
}
// PollInterval is how often to check whether a new certificate has
// been found.
var PollInterval = 30 * time.Second
func pollWait(target time.Time) {
for {
<-time.After(PollInterval)
if time.Now().After(target) {
break
}
}
}
// AutoUpdate will automatically update the listener. If a non-nil
// certUpdates chan is provided, it will receive timestamps for
// reissued certificates. If errChan is non-nil, any errors that occur
// in the updater will be passed along.
func (l *Listener) AutoUpdate(certUpdates chan<- time.Time, errChan chan<- error) {
defer func() {
if r := recover(); r != nil {
log.Criticalf("AutoUpdate panicked: %v", r)
}
}()
for {
// Wait until it's time to update the certificate.
target := time.Now().Add(l.Lifespan())
if PollInterval == 0 {
<-time.After(l.Lifespan())
} else {
pollWait(target)
}
// Keep trying to update the certificate until it's
// ready.
for {
log.Debug("refreshing certificate")
err := l.RefreshKeys()
if err == nil {
break
}
delay := l.Transport.Backoff.Duration()
log.Debugf("failed to update certificate, will try again in %s", delay)
if errChan != nil {
errChan <- err
}
<-time.After(delay)
}
if certUpdates != nil {
certUpdates <- time.Now()
}
config, err := l.getConfig()
if err != nil {
log.Debug("immediately after getting a new certificate, the Transport is reporting errors: %v", err)
if errChan != nil {
errChan <- err
}
}
address := l.Listener.Addr().String()
lnet := l.Listener.Addr().Network()
l.Listener, err = tls.Listen(lnet, address, config)
if err != nil {
log.Debug("immediately after getting a new certificate, the Transport is reporting errors: %v", err)
if errChan != nil {
errChan <- err
}
}
log.Debug("listener: auto update of certificate complete")
l.Transport.Backoff.Reset()
}
}