Skip to content

Commit

Permalink
Cache a certificate loaded from disk in the StaticCertManager
Browse files Browse the repository at this point in the history
  • Loading branch information
kpumuk committed Sep 24, 2024
1 parent 3643d9e commit d1a33c6
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 1 deletion.
9 changes: 8 additions & 1 deletion internal/server/cert.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@ type CertManager interface {
GetCertificate(hello *tls.ClientHelloInfo) (*tls.Certificate, error)
}

// StaticCertManager is a certificate manager that loads certificates from disk.
type StaticCertManager struct {
tlsCertificateFilePath string
tlsPrivateKeyFilePath string
cert *tls.Certificate
}

func NewStaticCertManager(tlsCertificateFilePath, tlsPrivateKeyFilePath string) *StaticCertManager {
Expand All @@ -22,6 +24,10 @@ func NewStaticCertManager(tlsCertificateFilePath, tlsPrivateKeyFilePath string)
}

func (m *StaticCertManager) GetCertificate(*tls.ClientHelloInfo) (*tls.Certificate, error) {
if m.cert != nil {
return m.cert, nil
}

slog.Info(
"Loading custom TLS certificate",
"tls-certificate-path", m.tlsCertificateFilePath,
Expand All @@ -32,6 +38,7 @@ func (m *StaticCertManager) GetCertificate(*tls.ClientHelloInfo) (*tls.Certifica
if err != nil {
return nil, err
}
m.cert = &cert

return &cert, nil
return m.cert, nil
}
75 changes: 75 additions & 0 deletions internal/server/cert_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package server

import (
"crypto/tls"
"os"
"testing"

"github.com/stretchr/testify/require"
)

const certPem = `-----BEGIN CERTIFICATE-----
MIIBhTCCASugAwIBAgIQIRi6zePL6mKjOipn+dNuaTAKBggqhkjOPQQDAjASMRAw
DgYDVQQKEwdBY21lIENvMB4XDTE3MTAyMDE5NDMwNloXDTE4MTAyMDE5NDMwNlow
EjEQMA4GA1UEChMHQWNtZSBDbzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABD0d
7VNhbWvZLWPuj/RtHFjvtJBEwOkhbN/BnnE8rnZR8+sbwnc/KhCk3FhnpHZnQz7B
5aETbbIgmuvewdjvSBSjYzBhMA4GA1UdDwEB/wQEAwICpDATBgNVHSUEDDAKBggr
BgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MCkGA1UdEQQiMCCCDmxvY2FsaG9zdDo1
NDUzgg4xMjcuMC4wLjE6NTQ1MzAKBggqhkjOPQQDAgNIADBFAiEA2zpJEPQyz6/l
Wf86aX6PepsntZv2GYlA5UpabfT2EZICICpJ5h/iI+i341gBmLiAFQOyTDT+/wQc
6MF9+Yw1Yy0t
-----END CERTIFICATE-----`

const keyPem = `-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIIrYSSNQFaA2Hwf1duRSxKtLYX5CB04fSeQ6tF1aY/PuoAoGCCqGSM49
AwEHoUQDQgAEPR3tU2Fta9ktY+6P9G0cWO+0kETA6SFs38GecTyudlHz6xvCdz8q
EKTcWGekdmdDPsHloRNtsiCa697B2O9IFA==
-----END EC PRIVATE KEY-----`

func TestCertificateLoading(t *testing.T) {
certPath, keyPath, err := prepareTestCertificateFiles()
require.NoError(t, err)
defer os.Remove(certPath)
defer os.Remove(keyPath)

manager := NewStaticCertManager(certPath, keyPath)
cert, err := manager.GetCertificate(&tls.ClientHelloInfo{})
require.NoError(t, err)
require.NotNil(t, cert)
}

func TestCachesLoadedCertificate(t *testing.T) {
certPath, keyPath, err := prepareTestCertificateFiles()
require.NoError(t, err)
defer os.Remove(certPath)
defer os.Remove(keyPath)

manager := NewStaticCertManager(certPath, keyPath)
cert1, err := manager.GetCertificate(&tls.ClientHelloInfo{})
require.NoError(t, err)
require.NotNil(t, cert1)

os.Remove(certPath)
os.Remove(keyPath)

cert2, err := manager.GetCertificate(&tls.ClientHelloInfo{})
require.Equal(t, cert1, cert2)
}

func prepareTestCertificateFiles() (string, string, error) {
certFile, err := os.CreateTemp("", "example-cert-*.pem")
if err != nil {
return "", "", err
}
defer certFile.Close()
certFile.Write([]byte(certPem))

keyFile, err := os.CreateTemp("", "example-key-*.pem")
if err != nil {
return "", "", err
}
defer keyFile.Close()
keyFile.Write([]byte(keyPem))

return certFile.Name(), keyFile.Name(), nil
}

0 comments on commit d1a33c6

Please sign in to comment.