AutoMate Technisch Help

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.cloud subdomains (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

cloudflared sitecontainer op de Portal Management webapp (production-slot + Staging-slot)

app.automate365.cloud, dev.automate365.cloud, api.automate365.cloud, api.dev.automate365.cloud

Tunnel A — Container App

*-Automate-Conn-CFTunnel-CA-Weu in Container App Environment *-Automate-Conn-CFTunnel-CAE-Weu; image cloudflare/cloudflared:latest, 2 replicas, Consumption profile, subnet snet-cftunnel-out

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 VNet (per env)

Cloudflare Zero Trust

API WebApp — publicNetworkAccess: Disabled

Portal Management WebApp — publicNetworkAccess: Disabled

snet-cftunnel-out

WARP

self-loop voor api.*
portal-out → portal-in

server-side call
portal-out → webapi-in

Eindgebruiker

Medewerker / Admin

GitHub Actions runner
cloud-hosted

WAF + OWASP managed ruleset
globaal op alle automate365.cloud subdomains

Cloudflare Access
per-user policies — alleen api en app endpoints

WARP tunnel
GitHub runners route hierdoor

Tunnel B — Portal sidecar
app.* / dev.* / api.* / api.dev.*

Tunnel A — Container App
SCM, Redis-beheer, SQL-beheer

cloudflared CA — 2 replicas

cloudflared sidecar per slot

Blazor runtime
host-binding: app.* + api.*

FastEndpoints runtime

snet-portal-in PE

snet-webapi-in PE

Azure Container App — resourcedetails

Veld

Dev

Prod

Container App Environment

D-Automate-Conn-CFTunnel-CAE-Weu

P-Automate-Conn-CFTunnel-CAE-Weu

Container App

d-automate-conn-cftunnel-ca-weu

p-automate-conn-cftunnel-ca-weu

Image

cloudflare/cloudflared:latest

idem

Startup args

tunnel run

idem

Replicas

2 (HA)

2 (HA)

Workload profile

Consumption

Consumption

Subnet

snet-cftunnel-out — 10.36.11.0/24, delegated Microsoft.App/environments

10.32.11.0/24

Managed Identity

User-assigned (voor KV secret-toegang)

idem

Ingress

Geen (outbound-only)

idem

Tunnel-token

KV secret CFTunnelToken

idem

Bicep

Infrastructure/Src/Modules/MainComponents/CFTunnel.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

443

443

443

1433

10000

443

443

snet-cftunnel-out

snet-portal-in

snet-webapi-in

snet-autosign-in

snet-sql-in

snet-redis-in

snet-keyvault-in

snet-storage-in

snet-portal-out — Portal WebApp outbound

443 (self-loop)

443

10000

443

443

snet-portal-out

snet-portal-in

snet-webapi-in

snet-redis-in

snet-keyvault-in

snet-storage-in

snet-webapi-out — API WebApp outbound

1433

443 (self-loop)

10000

443

443

snet-webapi-out

snet-sql-in

snet-webapi-in

snet-redis-in

snet-keyvault-in

snet-storage-in

snet-autosign-out — Autosign Function outbound

1433

snet-autosign-out

snet-sql-in

NSG-regels per subnet

snet-sql-in*-Automate-Net-SqlIn-Nsg-Weu

Richting

Protocol

Poort

Bron

Actie

Inbound

TCP

1433

snet-cftunnel-out

Allow

Inbound

TCP

1433

snet-autosign-out

Allow

Inbound

TCP

1433

snet-webapi-out

Allow

Inbound

Any

Any

VirtualNetwork

Deny

snet-redis-in*-Automate-Net-RedisIn-Nsg-Weu

Richting

Protocol

Poort

Bron

Actie

Inbound

TCP

10000

snet-cftunnel-out

Allow

Inbound

TCP

10000

snet-webapi-out

Allow

Inbound

TCP

10000

snet-portal-out

Allow

Inbound

Any

Any

VirtualNetwork

Deny

snet-webapi-in*-Automate-Net-WebApiIn-Nsg-Weu

Richting

Protocol

Poort

Bron

Actie

Inbound

TCP

443

snet-portal-out

Allow

Inbound

TCP

443

snet-cftunnel-out

Allow

Inbound

TCP

443

snet-webapi-out (self)

Allow

Inbound

Any

Any

VirtualNetwork

Deny

snet-portal-in*-Automate-Net-PortalIn-Nsg-Weu

Richting

Protocol

Poort

Bron

Actie

Inbound

TCP

443

snet-portal-out (self-loop)

Allow

Inbound

TCP

443

snet-cftunnel-out

Allow

Inbound

Any

Any

VirtualNetwork

Deny

snet-keyvault-in*-Automate-Net-KeyVaultIn-Nsg-Weu

Richting

Protocol

Poort

Bron

Actie

Inbound

TCP

443

snet-portal-out

Allow

Inbound

TCP

443

snet-webapi-out

Allow

Inbound

TCP

443

snet-cftunnel-out

Allow

Inbound

Any

Any

VirtualNetwork

Deny

snet-storage-in*-Automate-Net-StorageIn-Nsg-Weu

Richting

Protocol

Poort

Bron

Actie

Inbound

TCP

443

snet-portal-out

Allow

Inbound

TCP

443

snet-webapi-out

Allow

Inbound

TCP

443

snet-cftunnel-out

Allow

Inbound

Any

Any

VirtualNetwork

Deny

snet-autosign-in*-Automate-Net-AutosignIn-Nsg-Weu

Richting

Protocol

Poort

Bron

Actie

Inbound

TCP

443

snet-cftunnel-out uitsluitend

Allow

Inbound

Any

Any

VirtualNetwork

Deny

snet-portal-out*-Automate-Net-PortalOut-Nsg-Weu

Richting

Protocol

Poort

Doel

Actie

Outbound

TCP

443

snet-webapi-in

Allow

Outbound

TCP

443

snet-portal-in (self-loop)

Allow

Outbound

TCP

10000

snet-redis-in

Allow

Outbound

TCP

443

snet-keyvault-in

Allow

Outbound

TCP

443

snet-storage-in

Allow

Outbound

Any

Any

VirtualNetwork

Deny

snet-webapi-out*-Automate-Net-WebApiOut-Nsg-Weu

Richting

Protocol

Poort

Doel

Actie

Outbound

TCP

1433

snet-sql-in

Allow

Outbound

TCP

10000

snet-redis-in

Allow

Outbound

TCP

443

snet-webapi-in (self)

Allow

Outbound

TCP

443

snet-keyvault-in

Allow

Outbound

TCP

443

snet-storage-in

Allow

Outbound

Any

Any

VirtualNetwork

Deny

snet-autosign-out*-Automate-Net-AutosignOut-Nsg-Weu

Richting

Protocol

Poort

Doel

Actie

Outbound

TCP

1433

snet-sql-in uitsluitend

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

Infrastructure/Src/Modules/Networking/SubnetHardening.bicep

Subnet snet-cftunnel-out

Infrastructure/Src/main.bicep — subnets-array index 10

Container App Environment + Container App

Infrastructure/Src/Modules/MainComponents/CFTunnel.bicep

Aanroep CFTunnel + SubnetHardening

Infrastructure/Src/main.bicep (modules deploy-cftunnel, deploy-subnet-hardening)

Portal sidecar (dev-only)

Infrastructure/Src/Modules/Portal/WebApp.bicep — parameter deployCloudflaredSidecar (environmentLetter == 'D')

Operationele procedures

Tunnel-logs inzien

az containerapp logs show \ --resource-group D-Automate-Conn-CFTunnel-CAE-Weu \ --name d-automate-conn-cftunnel-ca-weu \ --follow

Log Analytics query:

ContainerAppConsoleLogs_CL | where ContainerAppName_s == "d-automate-conn-cftunnel-ca-weu" | project TimeGenerated, Log_s | order by TimeGenerated desc

QUIC-waarschuwingen

cloudflared logt regelmatig:

WARN QUIC connection to Cloudflare edge failed, falling back to HTTP/2 WARN Connection with edge closed INFO Registered tunnel connection ...

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:

  1. Update KV secret CFTunnelToken met de nieuwe waarde.

  2. Restart de Container App (of wacht op replica-recycle).

Last modified: 11 June 2026