package tls import ( "crypto/tls" "fmt" "strings" "testing" "time" "github.com/patrickmn/go-cache" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/traefik/traefik/v3/pkg/safe" ) func TestGetBestCertificate(t *testing.T) { // TODO Add tests for defaultCert testCases := []struct { desc string domainToCheck string dynamicCert string expectedCert string uppercase bool }{ { desc: "Empty Store, returns no certs", domainToCheck: "snitest.com", dynamicCert: "", expectedCert: "", }, { desc: "Best Match with no corresponding", domainToCheck: "snitest.com", dynamicCert: "snitest.org", expectedCert: "", }, { desc: "Best Match", domainToCheck: "snitest.com", dynamicCert: "snitest.com", expectedCert: "snitest.com", }, { desc: "Best Match with dynamic wildcard", domainToCheck: "www.snitest.com", dynamicCert: "*.snitest.com", expectedCert: "*.snitest.com", }, { desc: "Best Match with dynamic wildcard only, case insensitive", domainToCheck: "bar.www.snitest.com", dynamicCert: "*.www.snitest.com", expectedCert: "*.www.snitest.com", uppercase: true, }, } for _, test := range testCases { t.Run(test.desc, func(t *testing.T) { t.Parallel() dynamicMap := map[string]*CertificateData{} if test.dynamicCert != "" { cert, err := loadTestCert(test.dynamicCert, test.uppercase) require.NoError(t, err) dynamicMap[strings.ToLower(test.dynamicCert)] = cert } store := &CertificateStore{ DynamicCerts: safe.New(dynamicMap), CertCache: cache.New(1*time.Hour, 10*time.Minute), } var expected *CertificateData if test.expectedCert != "" { cert, err := loadTestCert(test.expectedCert, test.uppercase) require.NoError(t, err) expected = cert } clientHello := &tls.ClientHelloInfo{ ServerName: test.domainToCheck, } actual := store.GetBestCertificate(clientHello) assert.Equal(t, expected, actual) }) } } func loadTestCert(certName string, uppercase bool) (*CertificateData, error) { replacement := "wildcard" if uppercase { replacement = "uppercase_wildcard" } staticCert, err := tls.LoadX509KeyPair( fmt.Sprintf("../../integration/fixtures/https/%s.cert", strings.ReplaceAll(certName, "*", replacement)), fmt.Sprintf("../../integration/fixtures/https/%s.key", strings.ReplaceAll(certName, "*", replacement)), ) if err != nil { return nil, err } return &CertificateData{ Certificate: &staticCert, }, nil }