-
Notifications
You must be signed in to change notification settings - Fork 134
/
cached_certificate.go
122 lines (99 loc) · 2.64 KB
/
cached_certificate.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
121
122
package certs
import (
"crypto/tls"
"os"
"sync"
"time"
log "github.com/sirupsen/logrus"
"github.com/armadaproject/armada/internal/common/armadacontext"
)
type CachedCertificateService struct {
certPath string
keyPath string
fileInfoLock sync.Mutex
certFileInfo os.FileInfo
keyFileInfo os.FileInfo
certificateLock sync.Mutex
certificate *tls.Certificate
refreshInterval time.Duration
}
func NewCachedCertificateService(certPath string, keyPath string, refreshInternal time.Duration) *CachedCertificateService {
cert := &CachedCertificateService{
certPath: certPath,
keyPath: keyPath,
certificateLock: sync.Mutex{},
fileInfoLock: sync.Mutex{},
refreshInterval: refreshInternal,
}
// Initialise the certificate
err := cert.refresh()
if err != nil {
panic(err)
}
return cert
}
func (c *CachedCertificateService) GetCertificate() *tls.Certificate {
c.certificateLock.Lock()
defer c.certificateLock.Unlock()
return c.certificate
}
func (c *CachedCertificateService) updateCertificate(certificate *tls.Certificate) {
c.certificateLock.Lock()
defer c.certificateLock.Unlock()
c.certificate = certificate
}
func (c *CachedCertificateService) Run(ctx *armadacontext.Context) {
ticker := time.NewTicker(c.refreshInterval)
for {
select {
case <-ctx.Done():
return
case <-ticker.C:
err := c.refresh()
if err != nil {
log.WithError(err).Errorf("failed refreshing certificate from files cert: %s key: %s", c.certPath, c.keyPath)
}
}
}
}
func (c *CachedCertificateService) refresh() error {
updatedCertFileInfo, err := os.Stat(c.certPath)
if err != nil {
return err
}
updatedKeyFileInfo, err := os.Stat(c.keyPath)
if err != nil {
return err
}
modified := false
if c.certFileInfo == nil || updatedCertFileInfo.ModTime().After(c.certFileInfo.ModTime()) {
modified = true
}
if c.keyFileInfo == nil || updatedKeyFileInfo.ModTime().After(c.keyFileInfo.ModTime()) {
modified = true
}
if modified {
log.Infof("refreshing certificate from files cert: %s key: %s", c.certPath, c.keyPath)
certFileData, err := os.ReadFile(c.certPath)
if err != nil {
return err
}
keyFileData, err := os.ReadFile(c.keyPath)
if err != nil {
return err
}
cert, err := tls.X509KeyPair(certFileData, keyFileData)
if err != nil {
return err
}
c.updateData(updatedCertFileInfo, updatedKeyFileInfo, &cert)
}
return nil
}
func (c *CachedCertificateService) updateData(certFileInfo os.FileInfo, keyFileInfo os.FileInfo, newCert *tls.Certificate) {
c.fileInfoLock.Lock()
defer c.fileInfoLock.Unlock()
c.certFileInfo = certFileInfo
c.keyFileInfo = keyFileInfo
c.updateCertificate(newCert)
}