Cloudflare

On Cloudflare, enforcement runs in a Worker on your own zone with mTLS enabled for the protected hostname. The Worker verifies the signed manifest, re-validates the client leaf against the signed bundle and runs the same deny-by-default policy as every Mutual Trust enforcer.

Documentation menu

Pair and deploy the Worker

Pair, load secrets, deploy
mt-enforcer pair --connector cloudflare-worker --api https://api.mutualtrust.io --state ./mt-state mt-enforcer credentials --state ./mt-state > creds.json npx wrangler kv namespace create MT_STATE # put the id in wrangler.jsonc npx wrangler secret bulk creds.json -c services/gateway/cloudflare-worker/wrangler.jsonc && rm creds.json npx wrangler deploy -c services/gateway/cloudflare-worker/wrangler.jsonc
services/gateway/cloudflare-worker/wrangler.jsonc
{ // Mutual Trust gateway Worker: deploy on YOUR Cloudflare zone, in front of your origin. // Prerequisites (dashboard: SSL/TLS → Client Certificates, or API Shield → mTLS): // - enable mTLS for the protected hostname so Cloudflare requests a client certificate; // - do NOT add a WAF rule that blocks on cf.tls_client_auth.cert_verified unless you have // uploaded the space CA (BYOCA): this Worker validates the chain against the signed bundle. // Pair and load secrets (either command produces the same JSON): // mt gateway pair --print-credentials --api https://api.mutualtrust.io --out creds.json // mt-enforcer pair --connector cloudflare-worker --api https://api.mutualtrust.io --state ./mt-state && mt-enforcer credentials --state ./mt-state > creds.json // npx wrangler secret bulk creds.json -c services/gateway/cloudflare-worker/wrangler.jsonc && rm creds.json // Secrets set that way: MT_GATEWAY_ID, MT_TENANT_ID, MT_SERVICE_ID, MT_ENVIRONMENT, MT_CREDENTIAL, // MT_POLICY_KID, MT_POLICY_JWK, MT_GATEWAY_KEY. Optional secret: MT_ORIGIN_SECRET. "$schema": "../../../node_modules/wrangler/config-schema.json", "name": "mt-gateway-orders", "main": "src/worker.ts", "compatibility_date": "2025-10-01", "compatibility_flags": ["nodejs_compat"], "workers_dev": false, "preview_urls": false, "routes": [{ "pattern": "orders-api.example.com/*", "zone_name": "example.com" }], "vars": { "MT_API": "https://api.mutualtrust.io" // "ORIGIN_URL": "https://origin.internal.example.com" // unset → the zone's configured origin // "MT_REQUIRE_CF_VERIFIED": "true" // only if the space CA is uploaded (BYOCA) }, // Last verified manifest + high-water mark, so cold isolates enforce immediately and never // accept an older revision. Create with: npx wrangler kv namespace create MT_STATE "kv_namespaces": [{ "binding": "MT_STATE", "id": "<kv-namespace-id>" }], // Refresh + ACK even when idle, and flush receipts. "triggers": { "crons": ["* * * * *"] }, "observability": { "enabled": true } }

The Worker source is services/gateway/cloudflare-worker (also linked from services/enforcer/integrations/cloudflare).

What the Worker does

  • Reads the full leaf from request.cf.tlsClientAuth.certRFC9440 and cross-checks it with Cloudflare's fingerprint of the handshake certificate.
  • Re-validates the leaf against the signed bundle and applies the manifest deny set, so revocation does not depend on uploaded CAs.
  • Caches the verified manifest and high-water mark in KV, so cold isolates enforce at once and never accept an older revision; refreshes on the manifest cadence and from a one-minute cron.
  • Strips identity headers, forwards x-mt-principal, x-mt-grant and x-mt-request-id (and x-mt-origin-auth when MT_ORIGIN_SECRET is set), and sends signed acknowledgments and receipts.

In-path alternative

With Cloudflare's client-certificate forwarding enabled, origin requests carry Cf-Client-Cert-Der-Base64; run the enforcer in front of the origin with mt-enforcer proxy --peer-source forwarded --format cloudflare --trusted-proxies <Cloudflare IP ranges>, and authenticate the Cloudflare-to-origin hop (Authenticated Origin Pulls) so only Cloudflare reaches it.