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.
Pair and deploy the Worker
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{
// 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.certRFC9440and 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-grantandx-mt-request-id(andx-mt-origin-authwhenMT_ORIGIN_SECRETis 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.