Repository navigation
Normalize the tenant apex and platform root host at the write site #3328
Description
Problem
The tenant apex (namespace.cozystack.io/host) and the platform root host (_cluster.root-host) are free-form values with no lowercase validation anywhere. packages/apps/tenant/values.schema.json declares host as a bare {"type": "string"}, and TenantGatewaySpec.Apex in api/gateway/v1alpha1/tenantgateway_types.go carries no kubebuilder pattern. A mixed-case value therefore reaches the platform, and each consumer has to cope with it independently.
#3208 normalizes the reader side: the tenant hostname ValidatingAdmissionPolicies lowercase both operands of every comparison, so admission follows DNS case semantics. That fix stands on its own — the host label can be set out-of-band by a trusted caller, so the policies must stay defensive regardless of what any writer does. But the writer still emits the un-normalized value, and two consumers downstream do not cope with it.
What breaks on a mixed-case apex
gatewayv1.Hostname (gateway-api v1.4.1, apis/v1/shared_types.go) carries +kubebuilder:validation:Pattern=^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ — lowercase only. The TenantGateway reconciler builds listeners from the apex verbatim (Hostname("*." + tgw.Spec.Apex)), so a mixed-case apex makes the Gateway CREATE fail CRD validation and the tenant ends up with no Gateway at all.
The same reconciler dedups child apexes by exact string before adding them as SANs to the parent wildcard Certificate. Its own comment states the dedup is there because cert-manager rejects duplicates — and a pure case difference defeats it, in precisely the state a mixed-case apex produces.
Proposal
Normalize once, at the write site, so the label, _namespace.host, and TenantGateway.spec.apex all agree: lowercase $computedHost where the tenant namespace template writes the label (packages/apps/tenant/templates/namespace.yaml), and lowercase the root host where it is templated. Keep the reader-side normalization from #3208 as fail-closed defense — the two are complementary, not redundant.
Alternatively a validation pattern on tenant.spec.host and TenantGatewaySpec.Apex would reject the bad input at the edge instead of silently rewriting it. Worth picking deliberately: rejecting is louder, normalizing is friendlier to an operator who typed a capital letter.
Activity
fix(cozystack-basics): normalize tenant hostname VAP comparisons with…
github-actions commentedon Sep 15, 2026
This issue has had no activity for 60 days and was marked
lifecycle/stale.It will be closed in 14 days unless commented or labelled
lifecycle/frozen.