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 (
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
@@ -132,16 +134,38 @@ func listenerMap(listeners []gwapiv1.Listener) map[string]listenerKey {
|
||||
return m
|
||||
}
|
||||
|
||||
// maxSectionNameLen is the Gateway API limit for listener names.
|
||||
const maxSectionNameLen = 253
|
||||
|
||||
// listenerNameFor generates a deterministic listener name from cert name and DNS name.
|
||||
// Truncates to stay within Gateway API's 253-char limit for section names.
|
||||
// The result is a valid Gateway API SectionName: names that would exceed the limit
|
||||
// are cut and get a hash of the full name appended, so distinct long names stay distinct.
|
||||
func listenerNameFor(prefix, certName, dnsName string) string {
|
||||
// Replace dots with dashes for DNS names, combine with cert name.
|
||||
sanitized := strings.ReplaceAll(dnsName, ".", "-")
|
||||
name := fmt.Sprintf("%s%s-%s", prefix, certName, sanitized)
|
||||
if len(name) > 253 {
|
||||
name = name[:253]
|
||||
name := strings.TrimRight(fmt.Sprintf("%s%s-%s", prefix, certName, sanitizeDNSName(dnsName)), "-.")
|
||||
if len(name) <= maxSectionNameLen {
|
||||
return name
|
||||
}
|
||||
return name
|
||||
sum := sha256.Sum256([]byte(name))
|
||||
suffix := "-" + hex.EncodeToString(sum[:4])
|
||||
return strings.TrimRight(name[:maxSectionNameLen-len(suffix)], "-.") + suffix
|
||||
}
|
||||
|
||||
// sanitizeDNSName maps a certificate DNS name onto the characters allowed in a
|
||||
// listener name. A wildcard label is spelled out so "*.example.com" and
|
||||
// "example.com" stay distinct.
|
||||
func sanitizeDNSName(dnsName string) string {
|
||||
var b strings.Builder
|
||||
for _, r := range strings.ToLower(dnsName) {
|
||||
switch {
|
||||
case r >= 'a' && r <= 'z', r >= '0' && r <= '9':
|
||||
b.WriteRune(r)
|
||||
case r == '*':
|
||||
b.WriteString("wildcard")
|
||||
default:
|
||||
b.WriteByte('-')
|
||||
}
|
||||
}
|
||||
return strings.Trim(b.String(), "-")
|
||||
}
|
||||
|
||||
func ptrTo[T any](v T) *T {
|
||||
|
||||
Reference in New Issue
Block a user