From 825b39a2df9e61ae14ffdb176c47b172a343c10a Mon Sep 17 00:00:00 2001 From: Jakob Date: Wed, 24 Jun 2026 09:45:10 +0200 Subject: [PATCH] feat(api): validate advertiseAddress is an IP and clarify its docs (#1202) advertiseAddress is passed verbatim to the API server's --advertise-address flag, which only accepts an IP address. A DNS name was silently admitted and only surfaced as a tenant API server CrashLoopBackOff ("failed to parse IP"), three layers removed from the misconfiguration. Add a CEL validation (consistent with the existing isCIDR rules on serviceCidr/podCidr in the same struct) so the value is rejected at admission time, and clarify the field documentation: it must be an IP, it feeds --advertise-address, and the supported way to use a hostname is a DNS record pointing at a stable VIP plus networkProfile.certSANs. Closes #1197 Signed-off-by: Jakob Hahn Co-authored-by: Claude --- api/v1alpha1/tenantcontrolplane_types.go | 15 +++++++++++---- ...aji.clastix.io_tenantcontrolplanes_spec.yaml | 17 +++++++++++++---- .../kamaji.clastix.io_tenantcontrolplanes.yaml | 17 +++++++++++++---- docs/content/reference/api.md | 14 ++++++++++---- 4 files changed, 47 insertions(+), 16 deletions(-) diff --git a/api/v1alpha1/tenantcontrolplane_types.go b/api/v1alpha1/tenantcontrolplane_types.go index 96b8c15..100949c 100644 --- a/api/v1alpha1/tenantcontrolplane_types.go +++ b/api/v1alpha1/tenantcontrolplane_types.go @@ -31,10 +31,17 @@ type NetworkProfileSpec struct { // Address where API server will be exposed. // In the case of LoadBalancer Service, this can be empty in order to use the exposed IP provided by the cloud controller manager. Address string `json:"address,omitempty"` - // AdvertiseAddress is the address advertised to tenant-side consumers (workers, konnectivity). - // When set, the management address is used for CAPI and status reporting, while this address - // is used for kubeadm ControlPlaneEndpoint, cluster-info, and admin.conf. - // Both addresses are included in the API server certificate SANs. + // AdvertiseAddress is the IP address advertised to tenant-side consumers (workers, konnectivity). + // It is passed to the API server's --advertise-address flag and used for the kubeadm + // ControlPlaneEndpoint, cluster-info, and admin.conf; when set, the management address is used + // for CAPI and status reporting. Both addresses are included in the API server certificate SANs. + // + // This must be an IP address, not a DNS name: --advertise-address and the in-tenant "kubernetes" + // Service endpoints only accept IPs. To expose the control plane under a hostname, point a DNS + // record at a stable VIP and add the hostname to networkProfile.certSANs; for L7/hostname exposure + // see spec.controlPlane.ingress / spec.controlPlane.gateway (mind the TLS-passthrough caveats for + // client-certificate authentication). + //+kubebuilder:validation:XValidation:rule="self == '' || isIP(self)",message="advertiseAddress must be a valid IP address" AdvertiseAddress string `json:"advertiseAddress,omitempty"` // The default domain name used for DNS resolution within the cluster. //+kubebuilder:default="cluster.local" diff --git a/charts/kamaji-crds/hack/kamaji.clastix.io_tenantcontrolplanes_spec.yaml b/charts/kamaji-crds/hack/kamaji.clastix.io_tenantcontrolplanes_spec.yaml index f493647..5304d13 100644 --- a/charts/kamaji-crds/hack/kamaji.clastix.io_tenantcontrolplanes_spec.yaml +++ b/charts/kamaji-crds/hack/kamaji.clastix.io_tenantcontrolplanes_spec.yaml @@ -8545,11 +8545,20 @@ versions: type: string advertiseAddress: description: |- - AdvertiseAddress is the address advertised to tenant-side consumers (workers, konnectivity). - When set, the management address is used for CAPI and status reporting, while this address - is used for kubeadm ControlPlaneEndpoint, cluster-info, and admin.conf. - Both addresses are included in the API server certificate SANs. + AdvertiseAddress is the IP address advertised to tenant-side consumers (workers, konnectivity). + It is passed to the API server's --advertise-address flag and used for the kubeadm + ControlPlaneEndpoint, cluster-info, and admin.conf; when set, the management address is used + for CAPI and status reporting. Both addresses are included in the API server certificate SANs. + + This must be an IP address, not a DNS name: --advertise-address and the in-tenant "kubernetes" + Service endpoints only accept IPs. To expose the control plane under a hostname, point a DNS + record at a stable VIP and add the hostname to networkProfile.certSANs; for L7/hostname exposure + see spec.controlPlane.ingress / spec.controlPlane.gateway (mind the TLS-passthrough caveats for + client-certificate authentication). type: string + x-kubernetes-validations: + - message: advertiseAddress must be a valid IP address + rule: self == '' || isIP(self) allowAddressAsExternalIP: description: |- AllowAddressAsExternalIP will include tenantControlPlane.Spec.NetworkProfile.Address in the section of diff --git a/charts/kamaji/crds/kamaji.clastix.io_tenantcontrolplanes.yaml b/charts/kamaji/crds/kamaji.clastix.io_tenantcontrolplanes.yaml index b74dbb8..431bd97 100644 --- a/charts/kamaji/crds/kamaji.clastix.io_tenantcontrolplanes.yaml +++ b/charts/kamaji/crds/kamaji.clastix.io_tenantcontrolplanes.yaml @@ -8553,11 +8553,20 @@ spec: type: string advertiseAddress: description: |- - AdvertiseAddress is the address advertised to tenant-side consumers (workers, konnectivity). - When set, the management address is used for CAPI and status reporting, while this address - is used for kubeadm ControlPlaneEndpoint, cluster-info, and admin.conf. - Both addresses are included in the API server certificate SANs. + AdvertiseAddress is the IP address advertised to tenant-side consumers (workers, konnectivity). + It is passed to the API server's --advertise-address flag and used for the kubeadm + ControlPlaneEndpoint, cluster-info, and admin.conf; when set, the management address is used + for CAPI and status reporting. Both addresses are included in the API server certificate SANs. + + This must be an IP address, not a DNS name: --advertise-address and the in-tenant "kubernetes" + Service endpoints only accept IPs. To expose the control plane under a hostname, point a DNS + record at a stable VIP and add the hostname to networkProfile.certSANs; for L7/hostname exposure + see spec.controlPlane.ingress / spec.controlPlane.gateway (mind the TLS-passthrough caveats for + client-certificate authentication). type: string + x-kubernetes-validations: + - message: advertiseAddress must be a valid IP address + rule: self == '' || isIP(self) allowAddressAsExternalIP: description: |- AllowAddressAsExternalIP will include tenantControlPlane.Spec.NetworkProfile.Address in the section of diff --git a/docs/content/reference/api.md b/docs/content/reference/api.md index b0a1be0..1daec4f 100644 --- a/docs/content/reference/api.md +++ b/docs/content/reference/api.md @@ -47869,10 +47869,16 @@ In the case of LoadBalancer Service, this can be empty in order to use the expos advertiseAddress string - AdvertiseAddress is the address advertised to tenant-side consumers (workers, konnectivity). -When set, the management address is used for CAPI and status reporting, while this address -is used for kubeadm ControlPlaneEndpoint, cluster-info, and admin.conf. -Both addresses are included in the API server certificate SANs.
+ AdvertiseAddress is the IP address advertised to tenant-side consumers (workers, konnectivity). +It is passed to the API server's --advertise-address flag and used for the kubeadm +ControlPlaneEndpoint, cluster-info, and admin.conf; when set, the management address is used +for CAPI and status reporting. Both addresses are included in the API server certificate SANs. + +This must be an IP address, not a DNS name: --advertise-address and the in-tenant "kubernetes" +Service endpoints only accept IPs. To expose the control plane under a hostname, point a DNS +record at a stable VIP and add the hostname to networkProfile.certSANs; for L7/hostname exposure +see spec.controlPlane.ingress / spec.controlPlane.gateway (mind the TLS-passthrough caveats for +client-certificate authentication).
false