fix: produce valid listener names for wildcard and unusual DNS names
A DNS name like *.home.hrajfrisbee.cz put "*" into the listener name; the API server rejected the patch, which blocked every certificate on that Gateway. - lowercase the DNS part, spell "*" as "wildcard", map other characters outside [a-z0-9] to "-" - names over 253 chars are cut and get a hash suffix instead of a blind cut - names that were valid before are unchanged Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
package gateway
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -272,7 +274,20 @@ func TestListenersEqual_managedFields(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestListenerNameFor_sanitizesDots(t *testing.T) {
|
||||
// sectionNamePattern is the Gateway API SectionName validation rule.
|
||||
var sectionNamePattern = regexp.MustCompile(`^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$`)
|
||||
|
||||
func assertValidSectionName(t *testing.T, name string) {
|
||||
t.Helper()
|
||||
if len(name) > 253 {
|
||||
t.Errorf("name is %d chars, limit is 253", len(name))
|
||||
}
|
||||
if !sectionNamePattern.MatchString(name) {
|
||||
t.Errorf("name %q is not a valid SectionName", name)
|
||||
}
|
||||
}
|
||||
|
||||
func TestListenerNameFor_validSectionName(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := []struct {
|
||||
@@ -284,14 +299,57 @@ func TestListenerNameFor_sanitizesDots(t *testing.T) {
|
||||
{name: "dots become dashes", certName: "web", dnsName: "app.example.com", want: "auto-web-app-example-com"},
|
||||
{name: "single label", certName: "web", dnsName: "localhost", want: "auto-web-localhost"},
|
||||
{name: "existing dashes are kept", certName: "my-cert", dnsName: "my-app.example.com", want: "auto-my-cert-my-app-example-com"},
|
||||
{
|
||||
name: "wildcard label is spelled out",
|
||||
certName: "wildcard-home-hrajfrisbee",
|
||||
dnsName: "*.home.hrajfrisbee.cz",
|
||||
want: "auto-wildcard-home-hrajfrisbee-wildcard-home-hrajfrisbee-cz",
|
||||
},
|
||||
{name: "uppercase is lowered", certName: "web", dnsName: "App.Example.COM", want: "auto-web-app-example-com"},
|
||||
{name: "other characters become dashes", certName: "web", dnsName: "my_app.example.com", want: "auto-web-my-app-example-com"},
|
||||
{name: "trailing dot is dropped", certName: "web", dnsName: "app.example.com.", want: "auto-web-app-example-com"},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
if got := listenerNameFor(testPrefix, tc.certName, tc.dnsName); got != tc.want {
|
||||
got := listenerNameFor(testPrefix, tc.certName, tc.dnsName)
|
||||
if got != tc.want {
|
||||
t.Errorf("listenerNameFor() = %q, want %q", got, tc.want)
|
||||
}
|
||||
assertValidSectionName(t, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestListenerNameFor_longNames(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// 62 dashes right where the name is cut, so a blind cut would end in "-".
|
||||
shared := strings.Repeat("a", 200) + strings.Repeat("-", 62)
|
||||
first := listenerNameFor(testPrefix, "web", shared+"x.example.com")
|
||||
second := listenerNameFor(testPrefix, "web", shared+"y.example.com")
|
||||
|
||||
assertValidSectionName(t, first)
|
||||
assertValidSectionName(t, second)
|
||||
if first == second {
|
||||
t.Errorf("two long DNS names sharing a prefix got the same listener name %q", first)
|
||||
}
|
||||
if again := listenerNameFor(testPrefix, "web", shared+"x.example.com"); again != first {
|
||||
t.Errorf("name is not deterministic: %q then %q", first, again)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildListenersFromCertificates_wildcard(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
got := BuildListenersFromCertificates(
|
||||
[]cmv1.Certificate{cert("default", "wild", "wild-tls", "*.example.com")}, testPrefix)
|
||||
if len(got) != 1 {
|
||||
t.Fatalf("got %d listeners, want 1", len(got))
|
||||
}
|
||||
assertValidSectionName(t, string(got[0].Name))
|
||||
if got[0].Hostname == nil || *got[0].Hostname != "*.example.com" {
|
||||
t.Errorf("hostname = %v, want the wildcard kept as *.example.com", got[0].Hostname)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user