Module 7: Authorization and Policy Enforcement
Identity answers who — policy answers what they can do
3 hours. 2 hands-on labs. Free course module.
Learning Objectives
- Understand authentication vs authorization in zero trust
- Write Rego policies with Open Policy Agent (OPA)
- Implement identity-aware authorization with SPIFFE IDs
- Integrate OPA with Envoy for runtime policy enforcement
Why This Matters
Authentication tells you WHO is making a request. Without authorization, authenticated services can access anything. OPA with SPIFFE IDs gives you fine-grained, testable, version-controlled authorization — the critical layer between "identified" and "permitted."
Lesson Content
Authentication tells you who is making a request. Authorization tells you what they are allowed to do. SPIFFE handles authentication (via SVIDs). This module adds the authorization layer using Open Policy Agent (OPA).
Authentication vs Authorization
- Authentication (SPIFFE/SPIRE): "This request is from spiffe://example.org/ns/default/sa/orders-api"
- Authorization (OPA): "The orders-api service is allowed to GET /api/orders but NOT DELETE /api/users"
Open Policy Agent (OPA)
OPA is a CNCF graduated project that provides policy-as-code. Policies are written in Rego, a declarative language designed for structured data.
# Basic Rego policy
package authz
default allow = false
# Allow the orders service to read orders
allow {
input.source_spiffe_id == "spiffe://example.org/ns/default/sa/orders-api"
input.request_method == "GET"
startswith(input.request_path, "/api/orders")
}
# Allow the admin service full access
allow {
input.source_spiffe_id == "spiffe://example.org/ns/default/sa/admin"
}
# Deny everything else (default allow = false)
Envoy External Authorization
Envoy proxy can check every request against OPA before forwarding it to the backend service. The flow is: client connects with mTLS (Envoy terminates, extracts SPIFFE ID), Envoy sends the request details and SPIFFE ID to OPA, OPA evaluates the Rego policy and returns allow/deny, and Envoy either forwards the request or returns 403 Forbidden.
Context-Aware Authorization
Beyond simple SPIFFE ID matching, policies can consider the HTTP method and path, request headers, time of day, source namespace and environment, and custom claims in JWT-SVIDs.
Policy Testing
# Test your policies before deploying
# test_authz.rego
package authz
test_orders_api_can_read {
allow with input as {
"source_spiffe_id": "spiffe://example.org/ns/default/sa/orders-api",
"request_method": "GET",
"request_path": "/api/orders/123"
}
}
test_orders_api_cannot_delete_users {
not allow with input as {
"source_spiffe_id": "spiffe://example.org/ns/default/sa/orders-api",
"request_method": "DELETE",
"request_path": "/api/users/456"
}
}
# Run tests: opa test . -v
Real-World Use Cases
- API endpoint authorization — which services can call which endpoints
- Data access control — limiting which services can read sensitive data
- Multi-tenant isolation — ensuring tenant A services cannot access tenant B data
- Compliance enforcement — automated policy checks for regulatory requirements
Production Notes
- Always test Rego policies with opa test before deploying. Include both positive and negative test cases.
- Start with broad allow rules, then tighten incrementally. A deny-all start causes outages.
- Version your Rego policies in Git and deploy them through CI/CD, just like application code.
Common Mistakes
- Writing overly permissive policies that allow everything initially and never tightening
- Not testing policies before deploying — broken policies block legitimate traffic
- Putting authorization logic in application code instead of a policy engine
- Confusing OPA with a firewall — OPA makes decisions, Envoy enforces them
Think Like an Engineer
- Should authorization policies be centralized (one OPA instance) or distributed (per-service OPA)?
- How do you handle policy updates without restarting services?
- What is the performance impact of calling OPA on every request?
- How do you audit authorization decisions for compliance?
Key Terms
- OPA
- Open Policy Agent — CNCF graduated policy engine
- Rego
- Declarative policy language used by OPA
- ext_authz
- Envoy external authorization filter that calls OPA
- RBAC
- Role-Based Access Control
- ABAC
- Attribute-Based Access Control
Hands-On Labs
-
Writing Basic Rego Policies
Learn Rego syntax by writing and testing authorization policies.
- Write a Rego policy that allows specific SPIFFE IDs
- Write test cases for the policy
- Run opa test and verify all tests pass
- Experiment with more complex rules
-
Integrating OPA with Envoy
Deploy OPA as an Envoy external authorization filter.
- Deploy OPA as a sidecar alongside Envoy
- Configure Envoy ext_authz filter to call OPA
- Deploy two services with different SPIFFE IDs
- Verify that policies correctly allow/deny requests
Key Takeaways
- Authentication (who) and authorization (what) are separate concerns
- OPA provides policy-as-code with the Rego language
- Envoy ext_authz integrates OPA into the request path transparently
- Policies should be tested like code — use opa test
- SPIFFE IDs in policies enable fine-grained service-to-service authorization