Skip to content

Commit 37f5936

Browse files
committed
fix(charts): fail fast on empty tenant apex in host composition
Charts that publish a service compose their hostname as <sub>.<_namespace.host>. When the injected tenant apex is empty and no per-app host override is set, they used to emit a malformed trailing-dot hostname (e.g. "harbor.") into Ingresses, HTTPRoutes and Certificate dnsNames silently. Source the apex through cozy-lib.ns-host-required at each hostname-emitting site so the render fails with a clear message instead, matching the gateway path. Covered: harbor, postgres (external), qdrant (external), kubernetes (control-plane endpoint), vpn, seaweedfs, bootbox, monitoring (grafana, alerta, oidc client), and system/bucket (adds the cozy-lib subchart symlink it lacked). The guard is placed at the point each resource is actually emitted, so standalone renders, no-exposure tenants and the kubernetes no-etcd beacon path are unaffected. The post-delete cleanup hooks are left unguarded so an empty apex cannot block uninstall. Behavior change: a tenant with an empty injected apex and no host override that enables one of these components now fails its render (HelmRelease NotReady) instead of deploying a broken hostname. In practice the apex is always injected (root has root-host, children inherit it), so this only trips a genuinely misconfigured tenant. Signed-off-by: IvanHunters <[email protected]>
1 parent 2dc884f commit 37f5936

27 files changed

Lines changed: 167 additions & 22 deletions

File tree

‎packages/apps/harbor/templates/harbor.yaml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
{{- $host := .Values._namespace.host }}
1+
{{- $host := include "cozy-lib.ns-host-required" . }}
22
{{- $harborHost := .Values.host | default (printf "%s.%s" .Release.Name $host) }}
33

44
{{- $existingSecret := lookup "v1" "Secret" .Release.Namespace (printf "%s-credentials" .Release.Name) }}

‎packages/apps/harbor/templates/httproute.yaml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{{- $gateway := .Values._namespace.gateway | default "" }}
2-
{{- $host := .Values._namespace.host }}
2+
{{- $host := include "cozy-lib.ns-host-required" . }}
33
{{- $harborHost := .Values.host | default (printf "%s.%s" .Release.Name $host) }}
44
{{- if $gateway }}
55
apiVersion: gateway.networking.k8s.io/v1

‎packages/apps/harbor/templates/ingress.yaml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{{- $ingress := .Values._namespace.ingress }}
22
{{- $gateway := .Values._namespace.gateway | default "" }}
3-
{{- $host := .Values._namespace.host }}
3+
{{- $host := include "cozy-lib.ns-host-required" . }}
44
{{- $harborHost := .Values.host | default (printf "%s.%s" .Release.Name $host) }}
55
{{- $solver := (index .Values._cluster "solver") | default "http01" }}
66
{{- $clusterIssuer := (index .Values._cluster "issuer-name") | default "letsencrypt-prod" }}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
suite: harbor fails to render its ingress when the tenant apex is empty
2+
templates:
3+
- templates/ingress.yaml
4+
5+
release:
6+
name: harbor
7+
namespace: tenant-root
8+
9+
# harbor composes its public hostname as <release>.<_namespace.host>. When the
10+
# tenant apex is empty and no per-app host override is set, that used to emit a
11+
# malformed "harbor." host silently. cozy-lib.ns-host-required now fails the
12+
# render instead. Rendering with a valid apex must still succeed.
13+
14+
tests:
15+
- it: fails when _namespace.host is empty and no host override is set
16+
set:
17+
_namespace:
18+
host: ""
19+
ingress: tenant-root
20+
gateway: ""
21+
_cluster:
22+
issuer-name: letsencrypt-prod
23+
solver: http01
24+
asserts:
25+
- failedTemplate:
26+
errorMessage: "the tenant apex (_namespace.host) is empty and this app sets no host override, so its ingress hostname would be malformed. Set tenant.spec.host on this tenant, inherit it from a parent that has host set, or set this app's host value."
27+
28+
- it: renders when a host override is set even though the apex is empty
29+
set:
30+
host: harbor.custom.example
31+
_namespace:
32+
host: ""
33+
ingress: tenant-root
34+
gateway: ""
35+
_cluster:
36+
issuer-name: letsencrypt-prod
37+
solver: http01
38+
asserts:
39+
- equal:
40+
path: spec.rules[0].host
41+
value: harbor.custom.example
42+
43+
- it: renders normally when the apex is set
44+
set:
45+
_namespace:
46+
host: example.org
47+
ingress: tenant-root
48+
gateway: ""
49+
_cluster:
50+
issuer-name: letsencrypt-prod
51+
solver: http01
52+
asserts:
53+
- equal:
54+
path: spec.rules[0].host
55+
value: harbor.example.org

‎packages/apps/kubernetes/templates/cluster.yaml‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,6 @@
8484
{{- $podCIDR := "10.243.0.0/16" }}
8585
{{- $serviceCIDR := "10.95.0.0/16" }}
8686
{{- $ingress := .Values._namespace.ingress }}
87-
{{- $host := .Values._namespace.host }}
8887
{{- if not $etcd }}
8988
---
9089
apiVersion: v1
@@ -775,7 +774,7 @@ spec:
775774
ingress:
776775
extraAnnotations:
777776
nginx.ingress.kubernetes.io/ssl-passthrough: "true"
778-
hostname: {{ .Values.host | default (printf "%s.%s" .Release.Name $host) }}:443
777+
hostname: {{ .Values.host | default (printf "%s.%s" .Release.Name (include "cozy-lib.ns-host-required" .)) }}:443
779778
className: "{{ $ingress }}"
780779
additionalServicePorts:
781780
- name: talos-trustd

‎packages/apps/kubernetes/templates/oidc-rbac-job.yaml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
*/}}
4848
{{- $clientId := include "kubernetes.oidc.clientId" . | trim }}
4949
{{- $issuer := include "kubernetes.oidc.systemIssuerURL" . | trim }}
50-
{{- $externalHost := .Values.host | default (printf "%s.%s" .Release.Name (.Values._namespace.host)) }}
50+
{{- $externalHost := .Values.host | default (printf "%s.%s" .Release.Name (include "cozy-lib.ns-host-required" .)) }}
5151
---
5252
apiVersion: v1
5353
kind: ServiceAccount

‎packages/apps/kubernetes/tests/admin_kubeconfig_wait_test.yaml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ tests:
141141
monitoring: ""
142142
ingress: ""
143143
seaweedfs: ""
144-
host: ""
144+
host: example.org
145145
asserts:
146146
- hasDocuments:
147147
count: 1
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
suite: kubernetes apiserver endpoint guards an empty tenant apex only when it is emitted
2+
templates:
3+
- templates/cluster.yaml
4+
5+
release:
6+
name: kubernetes
7+
namespace: tenant-test
8+
9+
# cluster.yaml advertises the apiserver endpoint as <release>.<_namespace.host>
10+
# only inside the KamajiControlPlane, which is emitted when the tenant has an
11+
# etcd DataStore. cozy-lib.ns-host-required guards that one hostname, so an empty
12+
# apex fails there. The no-etcd path emits only a ConfigMap beacon and never
13+
# composes the hostname, so it must keep rendering even with an empty apex (the
14+
# parent Tenant chart populates _namespace.etcd asynchronously).
15+
16+
tests:
17+
- it: fails when the tenant has etcd but the apex is empty and no host override
18+
set:
19+
_namespace:
20+
etcd: tenant-test
21+
host: ""
22+
_cluster:
23+
cluster-domain: cozy.local
24+
version: "v1.35"
25+
asserts:
26+
- failedTemplate:
27+
errorMessage: "the tenant apex (_namespace.host) is empty and this app sets no host override, so its ingress hostname would be malformed. Set tenant.spec.host on this tenant, inherit it from a parent that has host set, or set this app's host value."
28+
29+
- it: still renders the awaiting-etcd beacon when the apex is empty and there is no etcd
30+
set:
31+
_namespace:
32+
etcd: ""
33+
host: ""
34+
_cluster:
35+
cluster-domain: cozy.local
36+
version: "v1.35"
37+
asserts:
38+
- hasDocuments:
39+
count: 1
40+
- isKind:
41+
of: ConfigMap

‎packages/apps/kubernetes/tests/substrate_proxmox_test.yaml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ release:
1414
set:
1515
_namespace:
1616
etcd: etcd-test
17+
host: example.org
1718
_cluster:
1819
cluster-domain: cozy.local
1920
version: "v1.35"

‎packages/apps/kubernetes/tests/substrate_switch_guard_test.yaml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ release:
1717
set:
1818
_namespace:
1919
etcd: etcd-test
20+
host: example.org
2021
_cluster:
2122
cluster-domain: cozy.local
2223
version: "v1.35"

0 commit comments

Comments
 (0)