NIST 800-207 calls them the Policy Engine and Policy Enforcement Point. In practice you will encounter half a dozen different engines and a dozen kinds of enforcement points. This lesson maps the landscape.
The Decision Plane
A policy engine answers one question billions of times a day: given this principal, this resource, this action, and this context — allow or deny (and what additional steps)?
The decision can be:
- Allow
- Allow with step-up (MFA challenge, approval workflow)
- Allow with constraints (read-only, no download, time-limited)
- Deny
The signal set: principal identity, group/role membership, device posture, network location, time, behavioural risk, threat intelligence, application sensitivity, requested action.
IdP-Native Engines
For user-to-application access (north-south), the identity provider's own policy engine is the dominant pattern.
| IdP | Engine |
|---|---|
| Microsoft Entra ID | Conditional Access + Continuous Access Evaluation |
| Okta | Sign-on policies, Authentication policies, Device Trust |
| Google Workspace | Context-Aware Access |
| Ping Identity | PingOne policies + DaVinci flows |
These engines plug into the federation flow: every SAML / OIDC sign-in is evaluated. Continuous evaluation (CAE in Entra) revokes access mid-session when signals change (password reset, leaked credential, device non-compliant).
Configuration is declarative. A typical Conditional Access policy:
Name: Require compliant device for Finance apps
Assignments:
Users: group "Finance"
Cloud apps: "SAP Finance", "Workday", "Stripe Dashboard"
Conditions:
User risk: low or medium
Locations: not "blocked countries"
Access controls:
Grant: Require compliant device AND Require phishing-resistant MFA
Session controls:
Sign-in frequency: 4 hours
Use app-enforced restrictions
Application-Level Authorisation
IdP policies decide whether to let you into the app. Inside the app, you still need fine-grained authorisation — "User X may read order Y because they are the account owner."
The historical mess: ad-hoc if user.role == 'admin' checks scattered through the codebase. The Zero Trust pattern is to externalise authorisation into a policy engine.
Open Policy Agent (OPA) and Rego
OPA is a CNCF graduated project, the most widely adopted general-purpose policy engine. Policies are written in Rego:
# package authz
allow {
input.user.id == input.resource.owner
}
allow {
input.user.role == "admin"
input.action != "delete"
}
Applications send a small JSON input ("can user U do action A on resource R") and get back an allow/deny. OPA is embedded as a sidecar, library, or central service. The same engine evaluates Kubernetes admission (via OPA Gatekeeper), Terraform plans (via conftest), API gateway decisions, and microservice authorisation.
AWS Cedar
Cedar is the policy language behind Amazon Verified Permissions and Verified Access. Designed for SaaS-style RBAC + ABAC:
permit (
principal in Group::"sales",
action == Action::"viewReport",
resource
) when {
resource.region == principal.region
};
Cedar is more constrained than Rego, which makes it more analysable — you can ask "does this policy ever allow X" with formal guarantees. Good fit for SaaS authorisation; not yet as broadly tooled as OPA.
Other engines worth knowing
- Oso / Permit.io / Aserto — managed authorisation for application developers
- Warrant, OpenFGA — Zanzibar-style relationship-based access control (the model Google Drive uses)
- Kyverno — Kubernetes-native policy as YAML (alternative to OPA Gatekeeper for the cluster admission case)
Enforcement Points
Wherever traffic is intercepted, a PEP applies the decision. The same engine often feeds many PEPs.
| Layer | Enforcement points |
|---|---|
| Identity / SSO | IdP federation flow |
| API edge | API gateway (Kong, Apigee, AWS API Gateway), Envoy with ext_authz |
| Service mesh | Sidecar / proxy with AuthorizationPolicy |
| Cluster admission | Kubernetes admission webhooks (Gatekeeper, Kyverno) |
| Database | Row/column-level security (Postgres RLS, Snowflake), permissions.cloud, immutable proxies |
| Network / ZTNA | ZTNA broker, secure web gateway |
| Endpoint | EDR / MDM |
ZTNA — Zero Trust Network Access
ZTNA is the specific category of product that replaces VPNs for user-to-application access. The pattern:
- The user authenticates to a ZTNA broker (a SaaS service).
- The broker evaluates identity, device posture, and context.
- If allowed, the broker establishes an authenticated, encrypted tunnel directly to the application (not the network).
- The application is invisible to anyone who is not authorised — no DNS, no IP reachability.
This is BeyondCorp commoditised. Compared to a VPN:
- No "I'm in" — every connection is per-app, not per-network
- Applications are not exposed to the internet
- Authorisation is identity- and context-based, not IP-based
- Often clientless (browser-based) for partner / contractor access
Major ZTNA products:
- Cloudflare Access (part of Cloudflare One)
- Zscaler Private Access (ZPA)
- Netskope Private Access
- Palo Alto Prisma Access
- Twingate, Tailscale (mesh-VPN approaches that meet many ZTNA principles)
- Microsoft Entra Private Access / Microsoft Entra Internet Access
For pure HTTPS apps you may not need a dedicated ZTNA at all — exposing the app behind a reverse proxy (e.g., Cloudflare Tunnel, AWS Verified Access, Azure App Proxy) plus Conditional Access can be enough.
Policy as Code
At scale, point-and-click policy is unmaintainable. The mature pattern is policy as code:
- Policy stored in git, versioned, peer-reviewed via PR
- Unit tests (Rego unit tests, Cedar policy tests, Conditional Access policy mock evaluation)
- CI pipelines push to the engine — never manual changes in production
- Drift detection — anything changed outside git is flagged
- Pre-deployment dry-run (Conditional Access "report-only" mode, OPA decision logs in non-blocking mode)
Treat policy as you treat application code: write tests, deploy through CI, monitor in production.
Observability of Decisions
Every allow and deny is a security event. Ship:
- Sign-in logs from the IdP
- OPA decision logs to the SIEM
- ZTNA access logs
- Admission controller decisions
Correlate with the SIEM. Tune policies based on observed deny rates and user friction. A successful Zero Trust deployment ends up with a measurable "denial reasons" dashboard that the security team reviews weekly.
The Picture
Behind every successful request in a mature Zero Trust deployment: an identity provider verified the user, the device posture engine confirmed the laptop was compliant, the ZTNA broker brokered the connection, the API gateway evaluated an OPA policy, the database enforced row-level security, and every decision was logged. That is six policy decisions for one HTTP request — none of which the user noticed.
The final lesson puts it all together into a practical adoption roadmap.