chore(stdiscosrv): reduce allocations in cert handling

This commit is contained in:
Jakob Borg 2024-09-09 08:24:09 +02:00
parent 822b6ac36b
commit f9b72330a8
No known key found for this signature in database
2 changed files with 29 additions and 10 deletions

View File

@ -367,7 +367,7 @@ func certificateBytes(req *http.Request) ([]byte, error) {
} }
bs = pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: hdr}) bs = pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: hdr})
} else if hdr := req.Header.Get("X-Forwarded-Tls-Client-Cert"); hdr != "" { } else if cert := req.Header.Get("X-Forwarded-Tls-Client-Cert"); cert != "" {
// Traefik 2 passtlsclientcert // Traefik 2 passtlsclientcert
// //
// The certificate is in PEM format, maybe with URL encoding // The certificate is in PEM format, maybe with URL encoding
@ -375,19 +375,36 @@ func certificateBytes(req *http.Request) ([]byte, error) {
// statements. We need to decode, reinstate the newlines every 64 // statements. We need to decode, reinstate the newlines every 64
// character and add statements for the PEM decoder // character and add statements for the PEM decoder
if strings.Contains(hdr, "%") { if strings.Contains(cert, "%") {
if unesc, err := url.QueryUnescape(hdr); err == nil { if unesc, err := url.QueryUnescape(cert); err == nil {
hdr = unesc cert = unesc
} }
} }
for i := 64; i < len(hdr); i += 65 { const (
hdr = hdr[:i] + "\n" + hdr[i:] header = "-----BEGIN CERTIFICATE-----"
footer = "-----END CERTIFICATE-----"
)
var b bytes.Buffer
b.Grow(len(header) + 1 + len(cert) + len(cert)/64 + 1 + len(footer) + 1)
b.WriteString(header)
b.WriteByte('\n')
for i := 0; i < len(cert); i += 64 {
end := i + 64
if end > len(cert) {
end = len(cert)
}
b.WriteString(cert[i:end])
b.WriteByte('\n')
} }
hdr = "-----BEGIN CERTIFICATE-----\n" + hdr b.WriteString(footer)
hdr += "\n-----END CERTIFICATE-----\n" b.WriteByte('\n')
bs = []byte(hdr)
bs = b.Bytes()
} }
if bs == nil { if bs == nil {

View File

@ -15,6 +15,7 @@ import (
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
"os" "os"
"regexp"
"strings" "strings"
"testing" "testing"
@ -122,6 +123,7 @@ func BenchmarkAPIRequests(b *testing.B) {
if err != nil { if err != nil {
b.Fatal(err) b.Fatal(err)
} }
certBs = regexp.MustCompile(`---[^\n]+---\n`).ReplaceAll(certBs, nil)
certString := string(strings.ReplaceAll(string(certBs), "\n", " ")) certString := string(strings.ReplaceAll(string(certBs), "\n", " "))
devID := protocol.NewDeviceID(crt.Certificate[0]) devID := protocol.NewDeviceID(crt.Certificate[0])
@ -132,7 +134,7 @@ func BenchmarkAPIRequests(b *testing.B) {
url := srv.URL + "/v2/?device=" + devIDString url := srv.URL + "/v2/?device=" + devIDString
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
req, _ := http.NewRequest(http.MethodPost, url, strings.NewReader(`{"addresses":["tcp://10.10.10.10:42000"]}`)) req, _ := http.NewRequest(http.MethodPost, url, strings.NewReader(`{"addresses":["tcp://10.10.10.10:42000"]}`))
req.Header.Set("X-Ssl-Cert", certString) req.Header.Set("X-Forwarded-Tls-Client-Cert", certString)
resp, err := http.DefaultClient.Do(req) resp, err := http.DefaultClient.Do(req)
if err != nil { if err != nil {
b.Fatal(err) b.Fatal(err)