I've been running Cloudflare Access in front of a suite of internal applications for about 18 months now, and for the most part, it's been a game-changer for our zero-trust implementation. The integration with our IdP (Okta) is seamless, the user experience is clean, and the performance is excellent. We've successfully replaced a clunky, VPN-dependent model for over 200 developers and support staff.
However, we recently hit a significant snag during our annual SOC 2 audit. The auditors requested detailed, application-specific access logs covering a 90-day period. They wanted to see not just *that* someone authenticated, but exactly *which* application they accessed, the specific path or subdomain, and the final outcome (allow/deny). This is where Access's reporting and logging capabilities fell dramatically short.
The primary issue is the granularity—or lack thereof—in the available logs and reports. While you can pull event logs from the Dashboard or via the GraphQL API, correlating a specific login event to a specific Access application is a manual, frustrating process.
For example, here's a typical log entry from the `gatewayEvents` dataset in the GraphQL API. Note the `application` field:
```graphql
{
"action": "allow",
"datetime": "2024-01-15T10:23:45Z",
"destinationIP": "192.0.2.1",
"email": "[email protected]",
"application": "a1b2c3d4e5f6g7h8"
}
```
That `application` field is a UUID. To map it to a human-readable application name (e.g., "Internal Jenkins"), you must make a separate API call to the `accessApplications` endpoint and cross-reference the IDs. For a 90-day period with thousands of events, this becomes a massive data engineering task. There is no built-in report that simply shows "User X accessed Application Y at Time Z."
The limitations I encountered are:
* **No Consolidated Per-App Dashboard:** The "Access" section in Analytics shows aggregate metrics but doesn't allow you to drill down into a single application's traffic and user list over a custom time range.
* **Audit Log Opaqueness:** The Audit Log in the Zero Trust dashboard provides admin action trails but not end-user application access events.
* **API-Driven Workarounds:** The only way to build the required report was to write a script that:
1. Pulled all `gatewayEvents` for the date range.
2. Extracted unique `application` UUIDs.
3. Fetched all `accessApplications` to build a UUID-to-name map.
4. Joined the datasets and filtered for our specific apps.
This process is not only inefficient but also incurs additional Logpull costs at scale. For a product built on the principle of zero-trust and security, this lack of transparent, readily available application-level auditing is a serious oversight. It forces organizations into a reactive, script-heavy posture for compliance reporting, which is the exact opposite of the operational simplicity Cloudflare typically offers.
I'm curious if others in the community have faced similar audit or reporting challenges and what your workflows look like. Have you built custom dashboards in SIEM tools, or are you using a third-party layer on top of Cloudflare's APIs? The product feels 95% complete, but this missing 5% is critical for enterprise governance.
-- alex
That last part about correlating login events to a specific application really hits home. We faced a similar issue when our security team needed to audit access to a specific, sensitive admin tool among the dozen we have behind Access.
We ended up having to export the raw logs and write a script to join data from different tables, essentially matching session IDs across datasets. It worked, but it felt absurd to need that level of manual work for a core compliance need. It makes me wonder, is the per-app reporting gap a design choice for simplicity, or just an oversight they plan to fix?
We went through that exact script-building exercise last year. Your feeling that it's absurd is spot on. It's a significant time investment just to answer a basic audit question like "who accessed our billing portal last quarter?"
While I'd lean toward calling it an oversight, I've found their API does expose the necessary fields - it's just not surfaced in the dashboard. The workaround is sustainable once built, but it shouldn't be necessary for a product at this scale. I'd recommend submitting a feature request directly to their team, as volume of user feedback often dictates their roadmap priorities.
—Anita
You're totally right about the granularity issue. We had auditors ask for the same thing, and it was like pulling teeth to map a user's session to the specific app they actually landed on.
The upside is that once you build that initial script or workflow using the GraphQL API, you can re-run it pretty easily for future audits. But having to build it at all for a core compliance need feels like a miss for such a polished product otherwise.
Have you looked at using a log forwarder to ship everything to a SIEM? It adds another step, but then you can build the reports once and keep them on hand.
Automate all the things
Yeah, the SIEM forwarder is the real workaround here. We send all our Access logs to Datadog, and I built a dashboard that groups events by application hostname. It took a day to set up, but now I can just screenshot it for audits.
The annoying part is the cost creep. Ingesting all those logs isn't free, and now I'm managing yet another dashboard. For a premium product, it's weird that this reporting isn't just built in.
cost first, then scale
Yep, you've put your finger on the exact compliance gap. It's not a design choice, it's an oversight in their reporting layer. The data exists in the event logs, but the dashboard aggregates it away for a "cleaner" view.
You can pull what you need via the API. The real issue is that every mature procurement process now demands baked-in audit trails. Building a script is a fine tactical fix, but it becomes a permanent, undocumented liability in your stack.
I make detailed logging a non-negotiable line item in every vendor's security exhibit now. If they can't show me the report, the feature doesn't exist.
I hit the same wall during our ISO 27001 audit. >correlating a specific login event to a specific Access application is a manual, frustrating process. It is. I found the session IDs are key, but the logs don't map them back to the app name in the UI, only to the underlying hostname. Did you have to cross-reference the application configuration JSON to make sense of it, or was there another trick?
Yep, cross-referencing the app config was the only trick we found too. That manual mapping step is the real time sink.
What made it extra tricky for us was when a single internal app had multiple associated hostnames or paths - the logs just show the hostname, not the friendly "Billing Portal" name we all use. It meant keeping a separate spreadsheet just to translate for the auditors.
I'm hoping they add the app name as a field you can pull from the API soon. Until then, the config JSON is your best friend, even if it's a clunky one.
That manual mapping step through the configuration JSON is precisely where the process breaks down from an audit integrity perspective. You're now maintaining a separate, external source of truth that must be perfectly synchronized with your live Access configuration. Any drift, like an app rename or a new hostname added last Tuesday, immediately invalidates your historical log mapping.
This creates a significant operational liability. Your audit trail's accuracy depends on a manual spreadsheet discipline that the product itself should enforce. The data model clearly supports this relationship, but the reporting abstraction deliberately obscures it for dashboard simplicity.
A truly frustrating corner case is when dealing with deleted applications. If you remove an app from your configuration, you lose the key entirely for mapping those historical logs, unless you've been meticulous about archiving every config version.
Data doesn't lie, but folks sometimes do.