# ============================================================================ # Per-tenant NetworkPolicy TEMPLATE — web-hosting isolation (Cl-infra-2 / Wh-C2) # ============================================================================ # GATED substrate (outside apps/, not auto-applied). Modeled on the canonical # default-deny + allowlist shape in apps/fc-devicemgmt/network-policy.yaml. # # Purpose: when a public multi-tenant site is provisioned, each tenant's pods # get a NetworkPolicy that (a) default-denies all ingress/egress, then allows # only Traefik ingress + CoreDNS + that tenant's own DB. This enforces the # cross-tenant isolation Wh-C2 verifies with negative suites. # # Replace the {{TENANT}} placeholders and apply alongside the tenant's workload # (the MySQL/PHP managers should emit this when they create a tenant, or a # templating step in apps/ should render it). Kept here as the reference shape. # ---------------------------------------------------------------------------- apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: tenant-{{TENANT}}-isolation namespace: fc-tenant-{{TENANT}} labels: app.kubernetes.io/part-of: flowercore flowercore.io/tenant-id: "{{TENANT}}" flowercore.io/created-by: bluejay-infra flowercore.io/gate: public-tls spec: podSelector: {} # all pods in the tenant namespace policyTypes: [Ingress, Egress] ingress: # Only Traefik may reach tenant pods (public traffic terminates at Traefik). - from: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: traefik-system ports: - { protocol: TCP, port: 80 } - { protocol: TCP, port: 443 } - { protocol: TCP, port: 8080 } egress: # CoreDNS resolution. - to: - namespaceSelector: {} podSelector: matchLabels: k8s-app: kube-dns ports: - { protocol: UDP, port: 53 } - { protocol: TCP, port: 53 } # This tenant's OWN MySQL only (NOT other tenants' DBs — that's the isolation). - to: - podSelector: matchLabels: flowercore.io/tenant-id: "{{TENANT}}" app.kubernetes.io/name: mysql ports: - { protocol: TCP, port: 3306 } # NOTE: deliberately NO blanket egress. Add per-tenant allowances explicitly # (object storage, mail relay, etc.) so a compromised tenant pod cannot reach # the rest of the fleet or other tenants.