Repository navigation
tenant chart: nested namespace labels miss ancestor tenant.cozystack.io/* labels beyond direct parent #2810
Description
Summary
When a tenant B is created under another tenant A (which itself is under tenant-root), the namespace tenant-B receives tenant.cozystack.io/tenant-A and tenant.cozystack.io/tenant-B labels, but not tenant.cozystack.io/tenant-root. This breaks the chain that egress CiliumClusterwideNetworkPolicy objects rely on and prevents the root ingress controller from proxying traffic into nested tenants.
Impact
addons.ingressNginx.hostson a nestedKubernetes(k8s-tenant) CR creates an Ingress on the root ingress class, but the root ingress controller cannot reach the proxyServicein the nested tenant namespace because thetenant-root-egressCiliumClusterwideNetworkPolicyrestricts egress to namespaces labeledtenant.cozystack.io/tenant-root.- External traffic to the host gets a TCP accept on the root ingress IP, the HTTP request is sent successfully, but the upstream connect times out. Root ingress controller logs:
upstream timed out (110: Operation timed out) while connecting to upstream, upstream: "http://10.244.x.y:30000/", host: "<configured-host>"
Repro
- Create
apps.cozystack.io/v1alpha1/TenantAintenant-rootnamespace. Resultingtenant-Anamespace correctly has bothtenant.cozystack.io/tenant-rootandtenant.cozystack.io/tenant-Alabels. - Create
apps.cozystack.io/v1alpha1/TenantBintenant-Anamespace. Resultingtenant-Bnamespace has onlytenant.cozystack.io/tenant-Aandtenant.cozystack.io/tenant-B. Missing:tenant.cozystack.io/tenant-root. - Create
apps.cozystack.io/v1alpha1/Kubernetesintenant-Bnamespace withaddons.ingressNginx.enabled: trueandaddons.ingressNginx.hosts: [foo.example.com]. - Point DNS
foo.example.comto the root ingress public IP. curl http://foo.example.com/from the internet — TCP connects, HTTP request is sent, no response.
Root cause
packages/apps/tenant/templates/namespace.yaml derives ancestor labels by splitting the parent namespace name on -:
```yaml
{{- $parts := splitList "-" .Release.Namespace }}
{{- range $i, $v := $parts }}
{{- if ne $i 0 }}
tenant.cozystack.io/{{ join "-" (slice $parts 0 (add $i 1)) }}: ""
{{- end }}
{{- end }}
```
This assumes tenant names encode the full hierarchy chain in their name (e.g. tenant-root-a-b), but the actual naming convention uses short names (tenant-a, tenant-b). So for Release.Namespace = \"tenant-a\", the loop yields only tenant.cozystack.io/tenant-a, missing tenant.cozystack.io/tenant-root (and any deeper ancestor in a 3+ level hierarchy).
Expected
Each tenant namespace should carry tenant.cozystack.io/<ancestor> labels for all ancestors up to tenant-root, so the egress/ingress policies derived from those labels grant cross-tenant traversal as the platform model intends.
Suggested fix
Read the parent namespace's existing tenant.cozystack.io/* labels via `lookup` and propagate them all, plus add the namespace's own label. Roughly:
```yaml
{{- $parentNS := lookup "v1" "Namespace" "" .Release.Namespace }}
{{- range $k, $_ := (default dict $parentNS.metadata.labels) }}
{{- if hasPrefix "tenant.cozystack.io/" $k }}
{{ $k }}: ""
{{- end }}
{{- end }}
tenant.cozystack.io/{{ $tenantName }}: ""
```
Workaround
Manually label the affected nested namespace until the chart is fixed:
```bash
kubectl label namespace tenant-b tenant.cozystack.io/tenant-root=""
```
Activity
dosubot commentedon Jun 3, 2026
This is a duplicate of #2171, which reports the same root cause — the hyphen-splitting logic in
packages/apps/tenant/templates/namespace.yamlcannot reconstruct the full ancestry chain when tenant names don't encode the hierarchy [1].The same problem affects the egress rules in
networkpolicy.yaml, which uses the identical splitting pattern to generate parent ingress access rules [2].Your suggested
lookup-based fix is essentially the same approach proposed in #2171 — read the parent namespace's existingtenant.cozystack.io/*labels and propagate them forward. That's the cleanest path since labels already encode ancestry correctly at depth 1 and the fix makes each level self-consistent by inheriting from its parent.Worth noting: PR #2470 (merged May 26, 2026) introduced a controller-based label inheritance pattern for Gateway API support (
namespace.cozystack.io/gatewaylabels) that patches descendant namespaces with ancestor information [3]. That same pattern could potentially be adapted for thetenant.cozystack.io/*labels as a more robust solution thanlookup(which only evaluates at Helm template render time and wouldn't self-heal if a parent is relabeled later).To reply, just mention @dosu.
Share context across your team and agents. Try Dosu.
lexfrei commentedon Jul 1, 2026
Duplicate of #2171 — same root cause: the hyphen-split of
.Release.Namespaceinpackages/apps/tenant/templates/namespace.yaml(still present on main). #2171 is broader (Cilium egress netpol + ancestor labels); this is the labels-only subset, and #2171 already documents this exact missing-label symptom. Consolidating on #2171.fix(tenant): inherit full ancestor label chain from parent namespace (#…
fix(platform): backfill tenant ancestor labels (backport #2912)
fix(platform): backfill tenant ancestor labels (backport #2912)