Per-app egress allowlists via Cilium FQDN policies (tighten the interim 443/80 default) #13

Open
opened 2026-06-29 16:04:51 +00:00 by plat · 1 comment
Owner

Context

Apps need to call external APIs (the core "build an app with an external API" use case). The app netpol historically blocked ALL external egress. Interim fix (mcp v0.23.13, PR plat/mcp#2): the default allow-egress now permits 443/80 to any external host, excluding RFC1918 — so external-API apps work, and internal ranges (other tenants, platform services) stay unreachable.

That interim default is broad: an app may reach any external host on 443/80. The desired end-state is least-privilege per-app egress.

Proposal — Cilium FQDN egress allowlists

Adopt Cilium as the CNI and express app egress as CiliumNetworkPolicy with toFQDNs, so each app declares the exact external hosts it needs and egress is denied to everything else.

  • App declares needed hosts (e.g. in its repo config / a plat.sh/egress annotation): api.openweathermap.org, api.stripe.com, …
  • create_app / overlayManifests renders a CiliumNetworkPolicy:
    apiVersion: cilium.io/v2
    kind: CiliumNetworkPolicy
    spec:
      endpointSelector: {}
      egress:
        - toFQDNs:
            - matchName: api.openweathermap.org
          toPorts: [{ ports: [{ port: "443" }] }]
    
  • Default external egress returns to deny; only declared FQDNs are reachable.

Benefits

  • Least-privilege, auditable, per-app egress (no blanket internet access).
  • Matches our other platform deployment (Cilium, working well).

Notes / work

  • k3d default CNI (flannel) does NOT support FQDN egress → germinate must install Cilium (disable flannel via --k3s-arg "--flannel-backend=none" + --disable-network-policy, install Cilium with the DNS proxy / toFQDNs enabled).
  • Until this lands, the 443/80-excl-RFC1918 default (v0.23.13) is the interim; this issue tracks tightening it.

Surfaced live: a weather app with a synced OPENWEATHER_API_KEY could not reach OpenWeather until egress was opened; the interim default now lets it through.

## Context Apps need to call external APIs (the core "build an app with an external API" use case). The app netpol historically blocked ALL external egress. Interim fix (mcp v0.23.13, PR plat/mcp#2): the default `allow-egress` now permits **443/80 to any external host, excluding RFC1918** — so external-API apps work, and internal ranges (other tenants, platform services) stay unreachable. That interim default is broad: an app may reach **any** external host on 443/80. The desired end-state is **least-privilege per-app egress**. ## Proposal — Cilium FQDN egress allowlists Adopt Cilium as the CNI and express app egress as `CiliumNetworkPolicy` with `toFQDNs`, so each app declares the exact external hosts it needs and egress is denied to everything else. - App declares needed hosts (e.g. in its repo config / a `plat.sh/egress` annotation): `api.openweathermap.org`, `api.stripe.com`, … - `create_app` / `overlayManifests` renders a `CiliumNetworkPolicy`: ```yaml apiVersion: cilium.io/v2 kind: CiliumNetworkPolicy spec: endpointSelector: {} egress: - toFQDNs: - matchName: api.openweathermap.org toPorts: [{ ports: [{ port: "443" }] }] ``` - Default external egress returns to **deny**; only declared FQDNs are reachable. ## Benefits - Least-privilege, auditable, per-app egress (no blanket internet access). - Matches our other platform deployment (Cilium, working well). ## Notes / work - k3d default CNI (flannel) does NOT support FQDN egress → germinate must install Cilium (disable flannel via `--k3s-arg "--flannel-backend=none"` + `--disable-network-policy`, install Cilium with the DNS proxy / `toFQDNs` enabled). - Until this lands, the **443/80-excl-RFC1918 default (v0.23.13) is the interim**; this issue tracks tightening it. Surfaced live: a weather app with a synced `OPENWEATHER_API_KEY` could not reach OpenWeather until egress was opened; the interim default now lets it through.
Author
Owner

Interim is LIVE and merged: apps now default to 443/80 external egress excluding RFC1918 (mcp overlayManifests), so external-API apps work out of the box — that unblocked the core use case. This issue remains for the TIGHTENING: per-app FQDN allowlists via Cilium (the owner runs Cilium elsewhere and prefers it). Not built. Design in the issue body.

Interim is LIVE and merged: apps now default to **443/80 external egress excluding RFC1918** (mcp overlayManifests), so external-API apps work out of the box — that unblocked the core use case. This issue remains for the TIGHTENING: per-app FQDN allowlists via Cilium (the owner runs Cilium elsewhere and prefers it). Not built. Design in the issue body.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
open-platform/mitosis#13
No description provided.