> ## Documentation Index
> Fetch the complete documentation index at: https://docs.inviolet.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Cloudflare (Gateway + Logpush)

> Block LLM bypass with Cloudflare Gateway and stream Gateway DNS logs into Inviolet — the two directions of one Cloudflare integration.

Cloudflare is Inviolet's **reference network integration**, and the only vendor
where both directions work end to end:

* **Enforce (SWG):** Cloudflare Gateway blocks direct LLM access on enrolled
  devices, forcing agents and users through the governed path.
* **Observe (CASB):** Cloudflare Logpush streams Gateway DNS logs into Inviolet,
  so bypass volume and per-user attribution show up in the product.

You can run either half on its own, but together they both *stop* bypass and
*measure* it.

<Note>
  Everything below was validated live against a real Cloudflare Zero Trust
  account. Where Cloudflare behaves differently than you'd expect (e.g. it can't
  match request headers), that's called out — those are the lessons that shaped
  this setup.
</Note>

## Prerequisites

* A **Cloudflare Zero Trust** account ([one.dash.cloudflare.com](https://one.dash.cloudflare.com/)) — the free plan (≤50 seats) is enough.
* The **Cloudflare One / WARP client** on the machines whose LLM traffic you want
  governed — **agent hosts** (for API bypass) and **user endpoints** (for the
  browser/UI case). Gateway only sees traffic from enrolled devices.
* For enrollment: a **device-enrollment policy** (Settings → WARP Client → Device
  enrollment permissions → add an *Allow* rule for your users/emails). A fresh
  org has none, and enrollment fails with "Enrollment request is invalid" until
  you add one.

<Tip>
  Email one-time-PIN login is enough for **per-user attribution** — the user's
  email lands in the Gateway logs. A full IdP (Okta/Entra/Google) only adds group
  membership and SSO; it isn't required to identify who made a request.
</Tip>

## Part A — Enforcement (Cloudflare Gateway)

### Why DNS-layer, domain-based blocking

Two findings from live testing shaped this, and they're worth knowing so the
rules make sense:

1. **Gateway can't match a request header.** The natural idea — "block LLM API
   calls missing the `X-Inviolet-Fingerprint` header" — fails: Gateway's filter
   engine has no `http.request.headers` field (`apply` returns *"unknown field"*).
   And without TLS inspection, HTTP policies don't evaluate HTTPS at all.
2. **LLM traffic sprawls across subdomains** — `api.`/`cdn.`/`auth.openai.com`,
   `a-api.anthropic.com`, `oaistatic.com`, `oaistatsig.com`, … An exact-hostname
   list misses most of it.

So Inviolet enforces at the **DNS layer**, matching on **domains** (which catch
every subdomain) — this works without TLS inspection, which the live test
confirmed is on by default for enrolled devices.

### The two rules

* **Block direct LLM API access** — DNS-block the LLM API domains (`openai.com`,
  `anthropic.com`, …). Because Gateway fronts the *agent's* egress (not
  Inviolet's), this stops agents from calling the API directly and forces them
  through Inviolet; Inviolet's own mediated calls resolve from Inviolet's infra
  and are unaffected.
* **Block consumer UIs** — DNS-block `chatgpt.com`, `claude.ai`, `gemini.google.com`,
  `copilot.microsoft.com`, so humans can't use ungoverned web UIs.

### Deploy — terraform (recommended)

Use the `inviolet-swg-cloudflare` module. **Start in log-only mode** so you can
confirm the rules fire before anything is blocked:

```bash theme={"dark"}
terraform -chdir=terraform-modules/inviolet-swg-cloudflare init
terraform -chdir=terraform-modules/inviolet-swg-cloudflare apply \
  -var="cloudflare_account_id=<YOUR_ACCOUNT_ID>" \
  -var="policy_fail_action=allow"   # allow = log-only; flip to "block" to enforce
```

Your **Account ID** is in the dashboard URL (`dash.cloudflare.com/<account-id>`)
or the Account Home sidebar. You'll need a Cloudflare **API token** in
`CLOUDFLARE_API_TOKEN` with **Account → Zero Trust → Edit** (create it at
My Profile → API Tokens → Create Custom Token).

<Warning>
  `policy_fail_action = "block"` blocks direct LLM access on **every enrolled
  device** — including your own laptop if it's enrolled. Run in `allow` first,
  confirm the matches, and roll out block mode to agent hosts / your fleet rather
  than an admin's working machine.
</Warning>

### Deploy — dashboard (alternative)

Zero Trust → **Gateway → Firewall policies** → create two **DNS** policies:
Action *Block* (or *Allow* to log-only), matching the LLM domains and the
consumer-UI domains respectively. Or match Cloudflare's built-in
**"Artificial Intelligence"** application category (auto-maintained).

### Verify

1. Connect WARP on a test device.
2. Generate traffic — open `chatgpt.com`, or `curl https://api.openai.com`.
3. Zero Trust → **Logs → Gateway → DNS query logs**, filter for `openai`.
4. You should see the query with **Policy** = `Inviolet-block-direct-llm-api` and
   the user's email. In `allow` mode the query is *matched* but permitted (logged,
   not blocked) — proof the rule catches the right traffic before you enforce.

## Part B — Observability (Cloudflare → Inviolet)

To make Inviolet **see** the traffic (bypass volume + attribution), get the
Gateway DNS logs in. **How depends on your Cloudflare plan:**

| Cloudflare plan           | Log export path into Inviolet                                                                                                  |
| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| **Enterprise**            | **Logpush** (per-event, automated) — the recommended path, below                                                               |
| **Free / Pro / Business** | No Logpush. Aggregated volume via the **GraphQL Analytics API** (if available on your Zero Trust plan), or dashboard-view-only |

<Warning>
  **Logpush requires Cloudflare Enterprise.** On Free/Pro there is no automated
  log-export path — enforcement (Part A) still works, but Inviolet can't ingest the
  logs without Enterprise Logpush or the analytics API. Cloudflare has **no pull
  API for raw Gateway logs** either (`gateway/audit_logs/*` returns 404).
</Warning>

### Enterprise — Logpush

Cloudflare *pushes* NDJSON log batches to an Inviolet endpoint (not a polling
connector, since there's no pull API).

### 1. The Inviolet endpoint

Inviolet exposes an ingestion endpoint:

```
POST https://app.inviolet.ai/api/v1/telemetry/cloudflare-logpush?org=<ORG_ID>&header_Authorization=Bearer%20<SECRET>
```

* `org` — your Inviolet organization id.
* `<SECRET>` — the shared value set as `CLOUDFLARE_LOGPUSH_SECRET` on the Inviolet
  side. Cloudflare Logpush strips `header_*` query params and re-sends them as
  HTTP headers, so this becomes the bearer auth the endpoint checks.

### 2. Create the Logpush job

Zero Trust → **Logs → Logpush → Add a Logpush job**:

* **Dataset:** **Gateway DNS**
* **Destination:** **HTTP** → paste the endpoint URL above
* Cloudflare runs an **ownership challenge** against the endpoint — it validates
  automatically.
* **Fields:** `Datetime, QueryName, Email, DeviceName, DeviceID, SrcIP, ResolverDecision, MatchedPolicyName`
* **Format:** NDJSON · **Enable**

### 3. Verify

With WARP connected and the job enabled, generate LLM traffic. After a few
minutes (Logpush batches + \~30–90s Gateway log lag), the queries appear in
Inviolet as `casb-cloudflare-{openai,anthropic,google}` events with the user's
email — feeding the bypass-volume signal.

## What you get

|                                   | Enforcement (Gateway) | Observability (Logpush) |
| --------------------------------- | --------------------- | ----------------------- |
| Stops direct LLM access           | ✅                     | —                       |
| Blocks consumer UIs               | ✅                     | —                       |
| Sees bypass volume in Inviolet    | —                     | ✅                       |
| Per-user + per-device attribution | ✅ (logs)              | ✅ (into Inviolet)       |
| Requires TLS inspection           | No                    | No                      |
| Requires WARP on egress devices   | Yes                   | Yes                     |

## Notes

* **WARP is the only client requirement** — nothing Inviolet-specific is installed
  on the device beyond the standard Cloudflare One client (or a network-level
  tunnel). The Inviolet SDK lives in the *agent app*, not on the device.
* The fingerprint header proves **org + agent mediation**, not the end user — user
  attribution here comes from Cloudflare's device identity, not the fingerprint.
