[Backport release-1.6] fix(tenant): skip Cilium policies on isp-hosted without Cilium (#5080)

## What this PR does

Backport of #4710 to release-1.6.

- The traces-central templates do not exist on release-1.6, so their
hunks and the matching unit-test assertions are dropped, a test case
that relied on a main-only cozy-lib change uses `_cluster: {}` instead.

### Screenshots

Not a UI change.

### Downstream repositories

- [x] No downstream repository is affected by this change
- [ ] [cozystack/website](https://github.com/cozystack/website) -
follow-up:
- [ ]
[cozystack/terraform-provider-cozystack](https://github.com/cozystack/terraform-provider-cozystack)
- follow-up:
- [ ]
[cozystack/ansible-cozystack](https://github.com/cozystack/ansible-cozystack)
- follow-up:
- [ ] [cozystack/ccp](https://github.com/cozystack/ccp) - follow-up:
- [ ] [cozystack/talm](https://github.com/cozystack/talm) - follow-up:
- [ ] [cozystack/cozyhr](https://github.com/cozystack/cozyhr) -
follow-up:
- [ ] [cozystack/cozy-proxy](https://github.com/cozystack/cozy-proxy) -
follow-up:
- [ ]
[cozystack/cozystack-telemetry-server](https://github.com/cozystack/cozystack-telemetry-server)
- follow-up:
- [ ]
[cozystack/external-apps-example](https://github.com/cozystack/external-apps-example)
- follow-up:
- [ ] [cozystack/examples](https://github.com/cozystack/examples) -
follow-up:

### Release note

```release-note
fix(tenant): the tenant chart no longer fails to install on the isp-hosted variants when the host has no Cilium. There, the Cilium network policies are created only if the host serves the Cilium policy API; otherwise tenants get no network isolation from Cozystack. Other variants are unchanged.
```
This commit is contained in:
myasnikovdaniil authored and GitHub committed 2026-10-23 20:00:52 +05:00
commit 2f820f7e6a
6 files changed
+87

No files matched your search

+1
View File
@@ -93,6 +93,7 @@ Actors are decomposed by **trust boundary**: two components are distinct actors
- **Upstream-only vulnerabilities** not introduced or worsened by Cozystack packaging or defaults.
- **Ingress-side isolation of tenant pods.** Tenant-pod ingress is open to `world` and `cluster`, so a tenant pod is reachable by any in-cluster peer whose own egress permits it (platform components) or by a workload not governed by Cozystack's tenant egress policies. Cross-tenant isolation is enforced on the *egress* side, not tenant-pod ingress.
- **Blocking cross-tenant reachability through externally-exposed services.** If a tenant publishes a LoadBalancer external IP, another tenant can reach it via `world` egress.
- **Network isolation between tenants on a hosted cluster without Cilium.** On the `isp-hosted` and `isp-hosted-slim` variants the CNI belongs to the host, and tenant Cilium policies are created only if the host serves the Cilium policy API. Without it, tenants get no network isolation from Cozystack, and isolating them is up to the host.
- **Noisy-neighbour / side-channel** guarantees for co-located tenant pods beyond namespace scoping (and, for tenant Kubernetes/VMs, virtualization).
- Acting as an **egress firewall**: tenant workloads may egress to `world` by default.
- Supporting **pre-release builds and end-of-life versions**.
+1
View File
@@ -83,6 +83,7 @@ The following are explicitly out of scope for the platform's security guarantees
- **Upstream-only vulnerabilities** that Cozystack packaging and defaults do not introduce or worsen.
- **Ingress-side isolation of tenant pods.** Tenant-pod ingress is open to the `world` and `cluster` entities, so a tenant pod is reachable by any in-cluster peer whose own egress permits it (platform components) and by a workload not governed by Cozystack's tenant egress policies (e.g. a privileged or system pod). Cross-tenant isolation is enforced on the *egress* side, not on tenant-pod ingress.
- **Blocking cross-tenant reachability through externally-exposed services.** If a tenant publishes a LoadBalancer with an external IP, another tenant can reach it via `world` egress.
- **Network isolation between tenants on a hosted cluster without Cilium.** On the `isp-hosted` and `isp-hosted-slim` variants the CNI belongs to the host, and the tenant chart creates its Cilium policies only if the host serves the Cilium policy API (`packages/apps/tenant/templates/_helpers.tpl`, helper `tenant.ciliumPolicies`). Without it, tenants get no network isolation from Cozystack, and isolating them is up to the host.
- **Noisy-neighbour and side-channel guarantees** for co-located tenant pods beyond namespace scoping (and, for tenant Kubernetes/VMs, virtualization). Co-located pods are not claimed to be side-channel isolated.
- **Acting as an egress firewall.** Tenant workloads are allowed egress to `world` by default (`packages/apps/tenant/templates/networkpolicy.yaml`).
- **Supporting pre-release builds and end-of-life versions** (`SECURITY.md`).
+4
View File
@@ -70,6 +70,10 @@ tenant-u1
└── postgres-db1
```
### Network isolation
Tenant network isolation is enforced with Cilium network policies. On the `isp-hosted` and `isp-hosted-slim` platform variants the CNI belongs to the host, so these policies are created only if the host serves the Cilium policy API when the tenant is installed or updated. On a host without Cilium, tenants get no network isolation from Cozystack, and isolating them is up to the host. If Cilium appears on the host later, the policies are created on the tenant's next chart or values change, not automatically.
## Parameters
### Common parameters
@@ -92,3 +92,16 @@ false
{{- if .Values.gateway -}}true{{- else -}}false{{- end -}}
{{- end -}}
{{- end -}}
{{- /* Every variant but the isp-hosted ones installs Cilium itself, so the
policies render unconditionally there: a CRD missing at render time
must fail the install, not leave the tenant unisolated for good, since
helm-controller does not re-render a release when discovery changes.
isp-hosted runs on the host's CNI, which may or may not be Cilium. */ -}}
{{- define "tenant.ciliumPolicies" -}}
{{- if not (has (include "cozy-lib.bundle-name" .) (list "isp-hosted" "isp-hosted-slim")) -}}
true
{{- else if and (.Capabilities.APIVersions.Has "cilium.io/v2/CiliumNetworkPolicy") (.Capabilities.APIVersions.Has "cilium.io/v2/CiliumClusterwideNetworkPolicy") -}}
true
{{- end -}}
{{- end -}}
@@ -1,3 +1,4 @@
{{- if include "tenant.ciliumPolicies" . }}
---
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
@@ -274,3 +275,4 @@ spec:
- toEndpoints:
- matchLabels:
cozystack.io/service: ingress
{{- end }}
@@ -0,0 +1,66 @@
suite: tenant Cilium policies follow the platform variant's CNI
templates:
- templates/networkpolicy.yaml
release:
name: tenant-ktj
namespace: tenant-root
tests:
- it: renders no Cilium objects on isp-hosted without the cilium.io API
set:
_cluster:
bundle-name: isp-hosted
asserts:
- hasDocuments:
count: 0
- it: renders no Cilium objects on isp-hosted-slim without the cilium.io API
set:
_cluster:
bundle-name: isp-hosted-slim
asserts:
- hasDocuments:
count: 0
- it: renders no Cilium objects on isp-hosted when only one Cilium kind is served
set:
_cluster:
bundle-name: isp-hosted
capabilities:
apiVersions:
- cilium.io/v2/CiliumNetworkPolicy
asserts:
- hasDocuments:
count: 0
- it: renders the Cilium policies on isp-hosted when the host runs Cilium
set:
_cluster:
bundle-name: isp-hosted
capabilities:
apiVersions:
- cilium.io/v2/CiliumNetworkPolicy
- cilium.io/v2/CiliumClusterwideNetworkPolicy
asserts: &policiesRendered
- template: templates/networkpolicy.yaml
documentSelector:
path: metadata.name
value: allow-internal-communication
isKind:
of: CiliumNetworkPolicy
- template: templates/networkpolicy.yaml
documentSelector:
path: metadata.name
value: tenant-ktj-ingress
isKind:
of: CiliumClusterwideNetworkPolicy
- it: renders the Cilium policies on a Cilium variant even when the API is not discoverable
set:
_cluster:
bundle-name: isp-full
asserts: *policiesRendered
- it: renders the Cilium policies when the platform injected no bundle-name
set:
_cluster: {}
asserts: *policiesRendered