docs: add plan for sanitizing listener names
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,9 @@
|
|||||||
|
# Execution: Sanitize listener names derived from certificate DNS names
|
||||||
|
|
||||||
|
Plan: `docs/plans/2026-10-08-2046-listener-name-sanitize.md`
|
||||||
|
|
||||||
|
- [x] Step 0 — Save and commit the plan
|
||||||
|
- [ ] Step 1 — Regression tests first
|
||||||
|
- [ ] Step 2 — Fix
|
||||||
|
- [ ] Step 3 — Docs
|
||||||
|
- [ ] Step 4 — Ship
|
||||||
@@ -0,0 +1,111 @@
|
|||||||
|
# Plan: Sanitize listener names derived from certificate DNS names
|
||||||
|
|
||||||
|
**Created:** 2026-10-08 20:46 CEST
|
||||||
|
|
||||||
|
## Context
|
||||||
|
|
||||||
|
The operator in the home-lab cluster fails every reconcile of
|
||||||
|
`kube-system/wildcard-home-hrajfrisbee`:
|
||||||
|
|
||||||
|
```
|
||||||
|
spec.listeners[4].name: Invalid value: "auto-wildcard-home-hrajfrisbee-*-home-hrajfrisbee-cz":
|
||||||
|
should match '^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$'
|
||||||
|
```
|
||||||
|
|
||||||
|
`listenerNameFor` (`internal/gateway/patch.go:137`) only replaces dots in the DNS
|
||||||
|
name, so `*.home.hrajfrisbee.cz` puts a `*` into the listener name. Gateway API
|
||||||
|
listener names are `SectionName`: lowercase alphanumerics, `-` and `.`, each
|
||||||
|
dot-separated label starting and ending alphanumeric, max 253 chars. Because the
|
||||||
|
patch replaces the whole listeners array, this one name blocks every other
|
||||||
|
certificate on `cilium-gateway` too.
|
||||||
|
|
||||||
|
Outcome: any DNS name cert-manager accepts yields a valid listener name, and names
|
||||||
|
that are valid today do not change (no listener churn on existing Gateways).
|
||||||
|
|
||||||
|
Lands on `feat/house-conventions` (decided), in the same MR as the conventions port.
|
||||||
|
|
||||||
|
## Design
|
||||||
|
|
||||||
|
Only the DNS-name part is rewritten; the listener `Hostname` keeps the original
|
||||||
|
value (`*.home.hrajfrisbee.cz` is a valid Gateway hostname).
|
||||||
|
|
||||||
|
`listenerNameFor(prefix, certName, dnsName)` in `internal/gateway/patch.go`:
|
||||||
|
|
||||||
|
1. Sanitize the DNS name with a new unexported `sanitizeDNSName`:
|
||||||
|
- lowercase;
|
||||||
|
- a leading `*` label becomes `wildcard` (`*.example.com` → `wildcard-example-com`);
|
||||||
|
- `.` becomes `-` (as today);
|
||||||
|
- any other character outside `[a-z0-9-]` becomes `-`;
|
||||||
|
- trim leading and trailing `-`.
|
||||||
|
2. Name is `prefix + certName + "-" + sanitized`, as today.
|
||||||
|
3. If longer than 253: cut to 244, trim trailing `-` and `.`, append `-` plus the
|
||||||
|
first 8 hex chars of the SHA-256 of the untruncated name. This replaces the
|
||||||
|
current blind `name[:253]`, which can end in `-` (invalid) and makes long names
|
||||||
|
collide.
|
||||||
|
|
||||||
|
Result for the failing cert:
|
||||||
|
`auto-wildcard-home-hrajfrisbee-wildcard-home-hrajfrisbee-cz`.
|
||||||
|
|
||||||
|
Not changed here (stay on the backlog): collisions between distinct inputs that
|
||||||
|
sanitize to the same name (e.g. `*.x.com` and `wildcard.x.com` in one cert, or the
|
||||||
|
same cert name in two namespaces), uppercase in the listener `Hostname`, and the
|
||||||
|
other items in `docs/reviews/`.
|
||||||
|
|
||||||
|
## Steps
|
||||||
|
|
||||||
|
### Step 0 — Save and commit the plan
|
||||||
|
|
||||||
|
Copy to `docs/plans/2026-10-08-2046-listener-name-sanitize.md`, create the paired
|
||||||
|
execution log, commit alone.
|
||||||
|
|
||||||
|
### Step 1 — Regression tests first
|
||||||
|
|
||||||
|
In `internal/gateway/patch_test.go`, extend `TestListenerNameFor_sanitizesDots`
|
||||||
|
(rename to `TestListenerNameFor_validSectionName`) with cases, each asserting the
|
||||||
|
exact name and that it matches the `SectionName` pattern and length:
|
||||||
|
|
||||||
|
- `*.home.hrajfrisbee.cz` with cert `wildcard-home-hrajfrisbee` (the production case);
|
||||||
|
- uppercase DNS name;
|
||||||
|
- a character outside the allowed set;
|
||||||
|
- a name over 253 chars: result is ≤ 253, valid, ends with the hash suffix, and two
|
||||||
|
long inputs sharing a 253-char prefix produce different names;
|
||||||
|
- existing plain names unchanged (already in the table).
|
||||||
|
|
||||||
|
Add a wildcard case to `TestBuildListenersFromCertificates_names` and assert in
|
||||||
|
`_listenerFields` style that the hostname stays `*.example.com`. Run and confirm the
|
||||||
|
new cases fail before the fix.
|
||||||
|
|
||||||
|
### Step 2 — Fix
|
||||||
|
|
||||||
|
Implement the design in `internal/gateway/patch.go` (stdlib only: `strings`,
|
||||||
|
`crypto/sha256`, `encoding/hex`). Update the function comment.
|
||||||
|
|
||||||
|
### Step 3 — Docs
|
||||||
|
|
||||||
|
- `CLAUDE.md`: Gotchas — drop the wildcard half of "a single bad listener blocks the
|
||||||
|
whole Gateway" (collisions remain); Architecture — describe the name as sanitized.
|
||||||
|
- `docs/flows.md` §7 and §10 item 7: wildcard and truncation rows updated.
|
||||||
|
- `docs/reviews/…-house-conventions.md` is not touched (it predates this).
|
||||||
|
|
||||||
|
### Step 4 — Ship
|
||||||
|
|
||||||
|
`make check` and `go test -race ./...`, then `/ship` (pushes
|
||||||
|
`feat/house-conventions`) and open the MR with `tea pr create`. Tick Step 7 of the
|
||||||
|
conventions execution log in the same commit.
|
||||||
|
|
||||||
|
## Verification
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go test -race -run 'TestListenerNameFor|TestBuildListeners' -v ./internal/gateway/
|
||||||
|
make check
|
||||||
|
```
|
||||||
|
|
||||||
|
Live, after you merge the MR:
|
||||||
|
|
||||||
|
1. `/release` → tag `v0.1.0`; CI builds and moves `:latest`.
|
||||||
|
2. `kubectl -n gateway-cert-operator-system rollout restart deploy/gateway-cert-operator`
|
||||||
|
(the Deployment pins `:latest`, so it does not roll on its own).
|
||||||
|
3. The "Reconciler error" for `wildcard-home-hrajfrisbee` stops, and
|
||||||
|
`kubectl -n kube-system get gateway cilium-gateway -o jsonpath='{.spec.listeners[*].name}'`
|
||||||
|
lists `auto-wildcard-home-hrajfrisbee-wildcard-home-hrajfrisbee-cz`.
|
||||||
|
4. Then the CHANGELOG entries for both the conventions port and this fix.
|
||||||
Reference in New Issue
Block a user