Cloudflare Tunnel — Architectuur
De Cloudflare Zero Trust laag bestaat uit twee tunnels per omgeving (dev en prod), een WAF met OWASP managed ruleset op alle automate365.cloud subdomains, en per-user Cloudflare Access policies. GitHub Actions runners verbinden via Cloudflare WARP en passeren dezelfde WAF en Access laag als reguliere medewerkers.
Overzicht
WAF en Access
WAF + OWASP managed ruleset is actief globaal op alle
automate365.cloudsubdomains (app.*,dev.*,api.*,api.dev.*).Cloudflare Access (Zero Trust) staat voor de tunnels met per-user policies. Access policies beperken welke gebruikers api- en app-endpoints bereiken — de NSG's op de bestemming laten technisch meer toe; Access begrenst per identiteit.
GitHub Actions runners zijn cloud-hosted en verbinden via Cloudflare WARP, waardoor ze dezelfde WAF en Access laag doorlopen als overige medewerkers.
Twee tunnels per omgeving
Tunnel | Hosting | Routes |
|---|---|---|
Tunnel B — Portal sidecar |
|
|
Tunnel A — Container App |
| Beheerverkeer: SCM/Kudu, Redis-beheer, SQL-beheer |
De Portal Management webapp heeft vier host-bindings tegelijk: app.*, dev.*, api.* en api.dev.*. Verkeer op api.* komt dus aan op de Portal-webapp, niet op de API-webapp. De Portal stuurt dit verkeer via z'n outbound subnet (snet-portal-out) via de eigen Private Endpoint (snet-portal-in) terug naar zichzelf als self-loop, en vandaar via snet-portal-out → snet-webapi-in naar de API-webapp voor server-side API-calls.
De API-webapp heeft geen cloudflared sidecar — verwijderd uit de live-omgeving en uit Bicep voor alle omgevingen.
Ingress-diagram
Azure Container App — resourcedetails
Veld | Dev | Prod |
|---|---|---|
Container App Environment |
|
|
Container App |
|
|
Image |
| idem |
Startup args |
| idem |
Replicas | 2 (HA) | 2 (HA) |
Workload profile | Consumption | Consumption |
Subnet |
|
|
Managed Identity | User-assigned (voor KV secret-toegang) | idem |
Ingress | Geen (outbound-only) | idem |
Tunnel-token | KV secret | idem |
Bicep |
| idem |
NSG-hardening
Alle 11 subnets hebben een Network Security Group. De regels zijn gedefinieerd in Infrastructure/Src/Modules/Networking/SubnetHardening.bicep en worden aangeroepen vanuit main.bicep.
NSG-flows per subnet
Eén diagram per source-subnet. De NSG-regeldetails per destination-subnet staan verderop in NSG-regels per subnet.
snet-cftunnel-out — Cloudflare Tunnel Container App
snet-portal-out — Portal WebApp outbound
snet-webapi-out — API WebApp outbound
snet-autosign-out — Autosign Function outbound
NSG-regels per subnet
snet-sql-in — *-Automate-Net-SqlIn-Nsg-Weu
Richting | Protocol | Poort | Bron | Actie |
|---|---|---|---|---|
Inbound | TCP | 1433 |
| Allow |
Inbound | TCP | 1433 |
| Allow |
Inbound | TCP | 1433 |
| Allow |
Inbound | Any | Any | VirtualNetwork | Deny |
snet-redis-in — *-Automate-Net-RedisIn-Nsg-Weu
Richting | Protocol | Poort | Bron | Actie |
|---|---|---|---|---|
Inbound | TCP | 10000 |
| Allow |
Inbound | TCP | 10000 |
| Allow |
Inbound | TCP | 10000 |
| Allow |
Inbound | Any | Any | VirtualNetwork | Deny |
snet-webapi-in — *-Automate-Net-WebApiIn-Nsg-Weu
Richting | Protocol | Poort | Bron | Actie |
|---|---|---|---|---|
Inbound | TCP | 443 |
| Allow |
Inbound | TCP | 443 |
| Allow |
Inbound | TCP | 443 |
| Allow |
Inbound | Any | Any | VirtualNetwork | Deny |
snet-portal-in — *-Automate-Net-PortalIn-Nsg-Weu
Richting | Protocol | Poort | Bron | Actie |
|---|---|---|---|---|
Inbound | TCP | 443 |
| Allow |
Inbound | TCP | 443 |
| Allow |
Inbound | Any | Any | VirtualNetwork | Deny |
snet-keyvault-in — *-Automate-Net-KeyVaultIn-Nsg-Weu
Richting | Protocol | Poort | Bron | Actie |
|---|---|---|---|---|
Inbound | TCP | 443 |
| Allow |
Inbound | TCP | 443 |
| Allow |
Inbound | TCP | 443 |
| Allow |
Inbound | Any | Any | VirtualNetwork | Deny |
snet-storage-in — *-Automate-Net-StorageIn-Nsg-Weu
Richting | Protocol | Poort | Bron | Actie |
|---|---|---|---|---|
Inbound | TCP | 443 |
| Allow |
Inbound | TCP | 443 |
| Allow |
Inbound | TCP | 443 |
| Allow |
Inbound | Any | Any | VirtualNetwork | Deny |
snet-autosign-in — *-Automate-Net-AutosignIn-Nsg-Weu
Richting | Protocol | Poort | Bron | Actie |
|---|---|---|---|---|
Inbound | TCP | 443 |
| Allow |
Inbound | Any | Any | VirtualNetwork | Deny |
snet-portal-out — *-Automate-Net-PortalOut-Nsg-Weu
Richting | Protocol | Poort | Doel | Actie |
|---|---|---|---|---|
Outbound | TCP | 443 |
| Allow |
Outbound | TCP | 443 |
| Allow |
Outbound | TCP | 10000 |
| Allow |
Outbound | TCP | 443 |
| Allow |
Outbound | TCP | 443 |
| Allow |
Outbound | Any | Any | VirtualNetwork | Deny |
snet-webapi-out — *-Automate-Net-WebApiOut-Nsg-Weu
Richting | Protocol | Poort | Doel | Actie |
|---|---|---|---|---|
Outbound | TCP | 1433 |
| Allow |
Outbound | TCP | 10000 |
| Allow |
Outbound | TCP | 443 |
| Allow |
Outbound | TCP | 443 |
| Allow |
Outbound | TCP | 443 |
| Allow |
Outbound | Any | Any | VirtualNetwork | Deny |
snet-autosign-out — *-Automate-Net-AutosignOut-Nsg-Weu
Richting | Protocol | Poort | Doel | Actie |
|---|---|---|---|---|
Outbound | TCP | 1433 |
| Allow |
Outbound | Any | Any | VirtualNetwork | Deny |
snet-cftunnel-out — *-Automate-Net-CfTunnelOut-Nsg-Weu
Richting | Protocol | Poort | Doel | Actie |
|---|---|---|---|---|
Outbound | Any | Any | VirtualNetwork | Allow |
Outbound | TCP | 443 | Internet | Allow |
Ontwerpkeuzes
Portal heeft geen directe SQL-toegang
De NSG op snet-portal-out staat geen outbound-verbinding toe naar snet-sql-in. De Portal verwerkt alle databewerkingen via de API. De SignatureDb connection string die in WebApp.bicep op de Portal is geconfigureerd, is daarmee niet-functioneel vanuit het netwerk — dit is een verwachte configuratie.
API stuurt nooit terug naar Portal
De NSG op snet-webapi-out blokkeert outbound verkeer naar snet-portal-in. De API belt nooit terug naar de Portal.
Self-loop Portal-out → Portal-in is verplicht
Wanneer publicNetworkAccess: Disabled is ingesteld op een App Service met een Private Endpoint, belt de App Service runtime zichzelf aan via de Private Endpoint hostname (<webapp>.privatelink.azurewebsites.net). Dit geldt voor Blazor Server circuit-verbindingen en interne health checks.
Zonder de Allow-regel snet-portal-out → snet-portal-in:443 resulteert dit in een 502 via de Cloudflare-tunnel. De App Service start op, maar requests via de tunnel mislukken door de geblokkeerde self-loop. De NSG-blokkade is niet direct zichtbaar als zodanig en manifesteert zich als een 502 op de Cloudflare-tunnel.
IaC — actuele status
Alle NSG's, het subnet snet-cftunnel-out, en de Container App zijn in Bicep gecodeerd:
Component | Bicep-locatie |
|---|---|
11 NSG-modules |
|
Subnet |
|
Container App Environment + Container App |
|
Aanroep CFTunnel + SubnetHardening |
|
Portal sidecar (dev-only) |
|
Operationele procedures
Tunnel-logs inzien
Log Analytics query:
QUIC-waarschuwingen
cloudflared logt regelmatig:
Dit zijn geen indicatoren van een probleem. cloudflared herverbindt continu via meerdere edge-verbindingen (QUIC en HTTP/2). Bij een 502 via de tunnel: onderzoek eerst de Private Endpoint bereikbaarheid, NSG-regels (met name de self-loop Allow), en de App Service gezondheid — niet de cloudflared container zelf.
Token roteren
Het tunnel-token staat in Key Vault als secret CFTunnelToken. Na rotatie in het Cloudflare Zero Trust-dashboard:
Update KV secret
CFTunnelTokenmet de nieuwe waarde.Restart de Container App (of wacht op replica-recycle).