PeerAuthentication
mTLS mode between sidecars. STRICT,
PERMISSIVE, DISABLE. Scope: mesh (in
istio-system), namespace, or workload via
selector. Migrating to STRICT: first
mesh-wide PERMISSIVE, then switch namespace by namespace.
apiVersion: security.istio.io/v1
kind: PeerAuthentication
metadata: {name: default, namespace: prod}
spec:
mtls: {mode: STRICT}
---
# Port exception (spec only, own name): NLB check
spec:
selector: {matchLabels: {app: legacy}}
mtls: {mode: STRICT}
portLevelMtls:
8080: {mode: PERMISSIVE}
AuthorizationPolicy
L7 access control. Order: CUSTOM (ext authz) →
DENY → ALLOW (default action);
AUDIT only marks requests for an audit plugin. No ALLOW policy on a workload = allow
all. spec: {} (ALLOW, no rules) denies everything;
rules: [{}] matches every request. Rules OR, fields in a
rule AND. 1.31+: source.trustDomains.
Ambient: without targetRefs (selector
or namespace-wide), ztunnel enforces it, L4 only; L7 rules need a
waypoint and targetRefs. ztunnel skips L7 attributes:
ALLOW with them denies, DENY with only them blocks
nothing. Behind a waypoint, the destination ztunnel
sees the waypoint’s identity.
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata: {name: reviews-allow, namespace: prod}
spec:
selector: {matchLabels: {app: reviews}}
action: ALLOW
rules:
- from:
- source:
principals:
- cluster.local/ns/prod/sa/productpage
to:
- operation:
methods: [GET]
paths: ["/reviews/*"]
when:
- key: request.auth.claims[groups]
values: ["reader", "admin"]
RequestAuthentication (JWT)
Validates the JWT and fills request.auth.* for the
AuthorizationPolicy. Important: without an
additional DENY policy with notRequestPrincipals=["*"],
unauthenticated requests can still get through.
Ambient: attach both to a waypoint via
targetRefs; ztunnel ignores this L7-only DENY, so
without a waypoint it blocks nothing.
apiVersion: security.istio.io/v1
kind: RequestAuthentication
metadata: {name: jwt, namespace: prod}
spec:
selector: {matchLabels: {app: api}}
jwtRules:
- issuer: "https://auth.example.com"
jwksUri: "https://auth.example.com/jwks"
audiences: ["api.example.com"]
forwardOriginalToken: true
Identity
SPIFFE URI spiffe://<trust>/ns/<ns>/sa/<sa>.
Trust domain defaults to cluster.local; all clusters of
one mesh share it (or list each other in
trustDomainAliases), only the cluster name is unique.
Workload certs: 24 h TTL (SECRET_TTL), istio-agent
renews at half-life (SECRET_GRACE_PERIOD_RATIO=0.5),
issued by the istiod CA.