Skip to content

Commit fe098cf

Browse files
authored
Merge pull request ghostunnel#679 from ghostunnel/claude/review-next-priorities-gzd8k
Extract baseCertificate struct to deduplicate shared methods
2 parents aab8fb6 + 0a302dd commit fe098cf

4 files changed

Lines changed: 32 additions & 81 deletions

File tree

certloader/certificate.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,36 @@ package certloader
1919
import (
2020
"crypto/tls"
2121
"crypto/x509"
22+
"sync/atomic"
2223
)
2324

25+
// baseCertificate holds cached certificate and trust store pointers shared by
26+
// concrete Certificate types. Embed it and implement only Reload().
27+
type baseCertificate struct {
28+
cachedCertificate atomic.Pointer[tls.Certificate]
29+
cachedCertPool atomic.Pointer[x509.CertPool]
30+
}
31+
32+
// GetCertificate retrieves the actual underlying tls.Certificate.
33+
func (b *baseCertificate) GetCertificate(clientHello *tls.ClientHelloInfo) (*tls.Certificate, error) {
34+
return b.cachedCertificate.Load(), nil
35+
}
36+
37+
// GetClientCertificate retrieves the certificate for mTLS client authentication.
38+
func (b *baseCertificate) GetClientCertificate(certInfo *tls.CertificateRequestInfo) (*tls.Certificate, error) {
39+
return b.cachedCertificate.Load(), nil
40+
}
41+
42+
// GetTrustStore returns the most up-to-date version of the trust store / CA bundle.
43+
func (b *baseCertificate) GetTrustStore() *x509.CertPool {
44+
return b.cachedCertPool.Load()
45+
}
46+
47+
// GetIdentifier returns an identifier for the certificate for logging.
48+
func (b *baseCertificate) GetIdentifier() string {
49+
return b.cachedCertificate.Load().Leaf.Subject.String()
50+
}
51+
2452
// Certificate wraps a TLS certificate and supports reloading at runtime.
2553
type Certificate interface {
2654
// Reload will reload the certificate and private key. Subsequent calls

certloader/certstore_enabled.go

Lines changed: 1 addition & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,12 @@ import (
2424
"fmt"
2525
"log"
2626
"sort"
27-
"sync/atomic"
2827

2928
"github.com/ghostunnel/ghostunnel/certstore"
3029
)
3130

3231
type certstoreCertificate struct {
32+
baseCertificate
3333
// Common name or serial number of keychain identity
3434
commonNameOrSerial string
3535
// Issuer name of keychain identity
@@ -38,10 +38,6 @@ type certstoreCertificate struct {
3838
caBundlePath string
3939
// Require use of hardware token?
4040
requireToken bool
41-
// Cached *tls.Certificate
42-
cachedCertificate atomic.Pointer[tls.Certificate]
43-
// Cached *x509.CertPool
44-
cachedCertPool atomic.Pointer[x509.CertPool]
4541
// Added logger, useful for certstore logging
4642
logger *log.Logger
4743
}
@@ -162,27 +158,6 @@ func (c *certstoreCertificate) Reload() error {
162158
return nil
163159
}
164160

165-
// GetIdentifier returns an identifier for the certificate for logging.
166-
func (c *certstoreCertificate) GetIdentifier() string {
167-
cert, _ := c.GetCertificate(nil)
168-
return cert.Leaf.Subject.String()
169-
}
170-
171-
// GetCertificate retrieves the actual underlying tls.Certificate.
172-
func (c *certstoreCertificate) GetCertificate(clientHello *tls.ClientHelloInfo) (*tls.Certificate, error) {
173-
return c.cachedCertificate.Load(), nil
174-
}
175-
176-
// GetClientCertificate retrieves the actual underlying tls.Certificate.
177-
func (c *certstoreCertificate) GetClientCertificate(certInfo *tls.CertificateRequestInfo) (*tls.Certificate, error) {
178-
return c.cachedCertificate.Load(), nil
179-
}
180-
181-
// GetTrustStore returns the most up-to-date version of the trust store / CA bundle.
182-
func (c *certstoreCertificate) GetTrustStore() *x509.CertPool {
183-
return c.cachedCertPool.Load()
184-
}
185-
186161
func serializeChain(chain []*x509.Certificate) [][]byte {
187162
out := [][]byte{}
188163
for _, cert := range chain {

certloader/keystore.go

Lines changed: 1 addition & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@ import (
2222
"crypto/x509"
2323
"encoding/pem"
2424
"fmt"
25-
"sync/atomic"
2625
)
2726

2827
type keystoreCertificate struct {
28+
baseCertificate
2929
// Keystore or PEM files path
3030
keystorePaths []string
3131
// Password for keystore (may be empty)
@@ -34,10 +34,6 @@ type keystoreCertificate struct {
3434
caBundlePath string
3535
// File format indicator (e.g. "PEM", "PKCS12", "JCEKS", "DER", or "" for auto-detect)
3636
format string
37-
// Cached *tls.Certificate
38-
cachedCertificate atomic.Pointer[tls.Certificate]
39-
// Cached *x509.CertPool
40-
cachedCertPool atomic.Pointer[x509.CertPool]
4137
}
4238

4339
// CertificateFromPEMFiles creates a reloadable certificate from a set of PEM files.
@@ -105,24 +101,3 @@ func (c *keystoreCertificate) Reload() error {
105101

106102
return nil
107103
}
108-
109-
// GetIdentifier returns an identifier for the certificate for logging.
110-
func (c *keystoreCertificate) GetIdentifier() string {
111-
cert, _ := c.GetCertificate(nil)
112-
return cert.Leaf.Subject.String()
113-
}
114-
115-
// GetCertificate retrieves the actual underlying tls.Certificate.
116-
func (c *keystoreCertificate) GetCertificate(clientHello *tls.ClientHelloInfo) (*tls.Certificate, error) {
117-
return c.cachedCertificate.Load(), nil
118-
}
119-
120-
// GetClientCertificate retrieves the actual underlying tls.Certificate.
121-
func (c *keystoreCertificate) GetClientCertificate(certInfo *tls.CertificateRequestInfo) (*tls.Certificate, error) {
122-
return c.cachedCertificate.Load(), nil
123-
}
124-
125-
// GetTrustStore returns the most up-to-date version of the trust store / CA bundle.
126-
func (c *keystoreCertificate) GetTrustStore() *x509.CertPool {
127-
return c.cachedCertPool.Load()
128-
}

certloader/pkcs11_enabled.go

Lines changed: 2 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -20,24 +20,19 @@ package certloader
2020

2121
import (
2222
"crypto/tls"
23-
"crypto/x509"
2423
"log"
25-
"sync/atomic"
2624

2725
pkcs11key "github.com/letsencrypt/pkcs11key/v4"
2826
)
2927

3028
type pkcs11Certificate struct {
29+
baseCertificate
3130
// Certificate chain corresponding to key
3231
certificatePath string
3332
// Root CA bundle path
3433
caBundlePath string
3534
// Params for loading key from a PKCS#11 module
3635
modulePath, tokenLabel, pin string
37-
// Cached *tls.Certificate
38-
cachedCertificate atomic.Pointer[tls.Certificate]
39-
// Cached *x509.CertPool
40-
cachedCertPool atomic.Pointer[x509.CertPool]
4136
// Added logger, useful for PKCS#11 logging
4237
logger *log.Logger
4338
}
@@ -84,9 +79,8 @@ func (c *pkcs11Certificate) Reload() error {
8479
// Reuse previously loaded PKCS11 private key if we already have it.
8580
// We want to avoid reloading the key every time the cert reloads, as it's
8681
// a potentially expensive operation that calls out into a shared library.
87-
if c.cachedCertificate.Load() != nil {
82+
if old := c.cachedCertificate.Load(); old != nil {
8883
c.logger.Printf("pkcs11: re-using previously cached private key handle from module")
89-
old, _ := c.GetCertificate(nil)
9084
certAndKey.PrivateKey = old.PrivateKey
9185
} else {
9286
c.logger.Printf("pkcs11: loading private key for given certificate from module")
@@ -107,24 +101,3 @@ func (c *pkcs11Certificate) Reload() error {
107101

108102
return nil
109103
}
110-
111-
// GetIdentifier returns an identifier for the certificate for logging.
112-
func (c *pkcs11Certificate) GetIdentifier() string {
113-
cert, _ := c.GetCertificate(nil)
114-
return cert.Leaf.Subject.String()
115-
}
116-
117-
// GetCertificate retrieves the actual underlying tls.Certificate.
118-
func (c *pkcs11Certificate) GetCertificate(clientHello *tls.ClientHelloInfo) (*tls.Certificate, error) {
119-
return c.cachedCertificate.Load(), nil
120-
}
121-
122-
// GetClientCertificate retrieves the actual underlying tls.Certificate.
123-
func (c *pkcs11Certificate) GetClientCertificate(certInfo *tls.CertificateRequestInfo) (*tls.Certificate, error) {
124-
return c.cachedCertificate.Load(), nil
125-
}
126-
127-
// GetTrustStore returns the most up-to-date version of the trust store / CA bundle.
128-
func (c *pkcs11Certificate) GetTrustStore() *x509.CertPool {
129-
return c.cachedCertPool.Load()
130-
}

0 commit comments

Comments
 (0)