Authorization policies with ztunnel
Apply Layer 4 authorization policies with ztunnel in ambient mesh to control which workloads can communicate with each other.
The ztunnel proxy enforces authorization policy at Layer 4 (L4). Because ztunnel operates at L4, only L4 attributes from Istio’s authorization policies are supported.
A waypoint proxy can enforce both L4 and L7 policy. See Choosing enforcement points for guidance on where to apply L4 policy when you also deploy waypoints.
Kubernetes network policies continue to work alongside ztunnel if your cluster has a CNI plugin that supports them, providing additional defense-in-depth.
Policy enforcement using ztunnel
When a workload is enrolled in ambient mesh, the ztunnel enforces authorization policy at the receiving (server-side) ztunnel in the path of a connection.
A basic L4 authorization policy looks like the following. This example policy uses a selector to allow traffic from the curl service account to pods labeled app: httpbin in the default namespace.
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: allow-curl-to-httpbin
namespace: default
spec:
selector:
matchLabels:
app: httpbin
action: ALLOW
rules:
- from:
- source:
principals:
- cluster.local/ns/ambient-demo/sa/curlWhen no authorization policy is provisioned, all traffic is allowed by default. Once a policy is provisioned, pods targeted by the policy only permit explicitly allowed traffic. In this example, pods labeled app: httpbin allow connections only from cluster.local/ns/ambient-demo/sa/curl. All other traffic is denied.
You can verify that the policy is attached by checking the status field.
kubectl get authorizationpolicy allow-curl-to-httpbin -n default -o yamlstatus:
conditions:
- lastTransitionTime: "2024-12-13T08:22:40.876269340Z"
message: attached to ztunnel
reason: Accepted
status: "True"
type: ZtunnelAcceptedTargeting policies
The scope of an authorization policy is determined by the namespace that the policy object resides in, and an optional selector1. Policies in the Istio root namespace (typically istio-system) target all namespaces. Policies in any other namespace target only that namespace.
Allowed policy attributes
Authorization policy rules can contain source (from), operation (to), and condition (when) clauses.
The following attributes can be used in policies enforced by ztunnel.
| Type | Attribute | Positive match | Negative match |
|---|---|---|---|
| Source | Peer identity | principals | notPrincipals |
| Source | Namespace | namespaces | notNamespaces |
| Source | IP block | ipBlocks | notIpBlocks |
| Operation | Destination port | ports | notPorts |
| Condition | Source IP | source.ip | n/a |
| Condition | Source namespace | source.namespace | n/a |
| Condition | Source identity | source.principal | n/a |
| Condition | Remote IP | destination.ip | n/a |
| Condition | Remote port | destination.port | n/a |
Use of disallowed policy attributes
Ztunnel operates at L4 and cannot enforce L7 attributes. If a policy with L7 attribute rules is targeted at a ztunnel, it fails safe:
DENYpolicies with L7 attributes are enforced without their HTTP components.ALLOWpolicies with L7 attributes are empty and never match.
In both cases, the result is more restrictive than requested.
The following example extends the previous policy with an HTTP method check (an L7 attribute), intending to allow only GET requests from the curl service account to httpbin. Because ztunnel cannot enforce the method match, the ALLOW rule never matches, and all connections, including those from curl, are denied.
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: allow-curl-to-httpbin
spec:
selector:
matchLabels:
app: httpbin
action: ALLOW
rules:
- from:
- source:
principals:
- cluster.local/ns/ambient-demo/sa/curl
to:
- operation:
methods: ["GET"]The connection attempt fails.
command terminated with exit code 56The status field confirms the policy was accepted, but fails safe.
status:
conditions:
- lastTransitionTime: "2024-12-13T09:18:42.451009757Z"
message: ztunnel does not support HTTP attributes (found: methods). In
ambient mode you must use a waypoint proxy to enforce HTTP rules. Within an
ALLOW policy, rules matching HTTP attributes are omitted. This will be more
restrictive than requested.
reason: UnsupportedValue
status: "True"
type: ZtunnelAcceptedDefault DENY
Set up a default DENY policy to deny all traffic by default, then explicitly allow only the traffic that you want to permit. If you miss a condition, traffic is unexpectedly denied rather than unexpectedly allowed.
The following policy creates a default deny for all L4 traffic in the default namespace. With no spec rules, no traffic matches any allow rule, and ztunnel denies all incoming connections:
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: default-deny
namespace: default
spec:
{}If you use waypoints, also configure a default deny for waypoints.
Choosing enforcement points when waypoints are used
When a waypoint proxy is added to a workload, you have two possible enforcement points for L4 policy2.
Apply policies at the earliest enforcement point that can handle them. In most cases, once you add a waypoint, it becomes the ideal enforcement point.
Without a waypoint, traffic arrives at the destination ztunnel with the identity of the source workload.
Waypoints do not impersonate the source workload identity. With a waypoint in the traffic path, the destination ztunnel sees traffic with the waypoint’s identity, not the source identity.
This means that when you have a waypoint installed, the ideal enforcement point shifts. Even for L4-only policies, if you depend on the source identity, attach the policy to the waypoint. A ztunnel policy should also target the workload to enforce that in-mesh traffic must arrive from the waypoint.
Peer authentication
Istio’s peer authentication policies, which configure mutual TLS (mTLS) modes, are supported by ztunnel.
The default policy for ambient mode is PERMISSIVE, which allows pods to accept both mTLS-encrypted traffic (from within the mesh) and plain text traffic (from outside). Enabling STRICT mode means pods only accept mTLS-encrypted traffic.
The DISABLE mode is not supported in ambient mesh and is ignored. ztunnel and HBONE require mTLS.