Skip to main content
This lesson demonstrates authorization in Istio: after authentication (mTLS) establishes identity, AuthorizationPolicy resources determine what authenticated workloads are allowed to do. We’ll walk through a set of hands-on examples that illustrate:
  • Enforcing mTLS cluster-wide (PeerAuthentication)
  • Creating AuthorizationPolicy resources to ALLOW or DENY traffic
  • How rule scope (namespace, selector, methods, paths) affects behavior
  • The precedence of DENY over ALLOW
Prerequisites: an Istio-enabled cluster with istio-system installed and working control plane.

1. Deploy example workloads

Apply the httpbin sample used throughout this lesson:
Verify the httpbin pod is running:
Create a test namespace and enable automatic Envoy sidecar injection:
Run a simple client pod (nginx) in the test namespace — the Istio sidecar will be injected:
Get the httpbin service (note: this sample uses port 8000):
From the test pod, verify connectivity to httpbin (no policies yet):

2. Enforce mTLS cluster-wide

Create a PeerAuthentication in the istio-system namespace to enforce strict mTLS: peer_auth_global.yaml
Apply it:
With strict mTLS enforced, workloads in the mesh must present mTLS to communicate; Istio manages certificates via Citadel / Istiod.

3. Basic ALLOW policy — namespace-based, method-scoped

Create an AuthorizationPolicy that ALLOWs only GET requests from namespace test to the workload(s) in the policy scope. auth_policy_allow_test.yaml
Apply the policy and inspect:
Important: curl --head issues an HTTP HEAD request, not GET. Because this policy allows only GET, HEAD requests will be denied.
Tip: When testing method-based policies, use curl --request GET or a plain curl (defaults to GET). If you prefer HEAD behavior, include HEAD in the policy (e.g., methods: ["GET", "HEAD"]).
Update the policy to allow both GET and HEAD:
Apply the updated policy and test again; now both HEAD and GET succeed from test.

4. Namespace scoping — allow only selected namespaces

Create another namespace app, enable injection, and run a test client there:
Run a test pod in app:
A request from app will be denied by the policy that allows only test:
To permit both test and app, include both namespaces in from.source.namespaces:
Apply and verify connectivity from both namespaces succeeds.

5. DENY specific paths and the DENY warning

Create a DENY policy that blocks requests to the /delay path: auth_policy_deny.yaml
Before applying, note the API warning behavior:
Warning: A DENY rule that uses only HTTP attributes (methods, paths) can impact TCP traffic under its scope unless you explicitly specify ports. Istio will warn when you apply such a rule. To avoid unintended TCP denial, scope the policy by ports, selector, or namespace.
Apply the DENY policy:
Requests to http://httpbin.default.svc:8000/delay will now be denied, even if an ALLOW policy also matches — see DENY precedence below.

6. Scoping ALLOW policies by selector, path, and methods

For precise allow rules (e.g., allow only GET/HEAD to /get from clients in app and only for the httpbin workload), use a selector and explicit paths:
Apply the policy and test /get from a pod running in app.

7. DENY-all pattern and rule precedence

A deny-all policy example: auth_deny_all.yaml
Important behavior to remember:
  • DENY policies are evaluated before ALLOW policies. If a DENY matches, the request is rejected even if an ALLOW would also match.
  • A broad deny-all in the same scope will block traffic unless you remove it or more specifically scope other policies.
If you need to restore access after applying a deny-all, delete it:

Per-workload deny example (target productpage only)

Instead of denying cluster-wide, target a specific workload via selector: auth_deny_product.yaml
Apply it:
Now calls to productpage will return 403, while other services (e.g., httpbin) remain accessible:
View active policies:
Deny rules are evaluated before allow rules. If both DENY and ALLOW match a request, the DENY takes precedence. Use targeted DENY rules (by selector, namespace, port, or path) rather than a broad deny-all unless you intend to explicitly allow everything else.

Summary table — useful Istio security resources


Reference and additional resources

The image shows a webpage from the Istio documentation focused on "Authorization," detailing various access control methods for Istio services. It includes links for setting up access controls like HTTP traffic, TCP traffic, and JWT tokens.
The Istio AuthorizationPolicy API supports:
  • Scoping by workload (selector.matchLabels)
  • from (source: namespaces, principals, service accounts)
  • to (operation: methods, paths, ports)
  • when (conditions based on request attributes, JWT claims)
  • Actions: ALLOW, DENY, AUDIT, CUSTOM (ALLOW and DENY are most commonly used)
For authoritative documentation and examples, see the Istio Authorization Policy reference:
The image shows a webpage from Istio's documentation discussing the "Authorization Policy," which involves access control on workloads in the mesh. It outlines the use of CUSTOM, DENY, and ALLOW actions for access control.

Key takeaways

  • Authentication (mTLS) establishes identity; authorization decides what that identity may do.
  • AuthorizationPolicy is powerful but can be subtle. Pay attention to:
    • Rule scope (namespace-level vs workload selector)
    • Verb vs method differences (e.g., GET vs HEAD)
    • DENY precedence over ALLOW
    • Warnings about DENY rules with only HTTP attributes and their potential effect on TCP traffic
  • Practice common patterns: allow-by-namespace, allow-by-service-account, deny-by-path, and per-workload deny to build confidence for production and certification scenarios.

Watch Video

Practice Lab