Skip to main content

Documentation Index

Fetch the complete documentation index at: https://notes.kodekloud.com/llms.txt

Use this file to discover all available pages before exploring further.

In this lesson we demonstrate how Istio Ambient mode affects workload security, mTLS enforcement, and AuthorizationPolicy behavior. You’ll see how namespace labeling, PeerAuthentication, waypoints, and SPIFFE principals interact in Ambient mode. The flow:
  • Verify Istio control-plane components (including ztunnel used by Ambient mode).
  • Deploy a long-running curl client in the test namespace.
  • Deploy a HelloWorld app in a hello namespace, label it for Ambient mode, and enforce global mTLS with a PeerAuthentication.
  • Show how namespace labeling affects connectivity under mTLS in Ambient mode.
  • Demonstrate how layer‑7 AuthorizationPolicy requires a waypoint in Ambient mode and why policies should use service-account principals (SPIFFE) instead of namespace-based sources.
All examples use corrected command syntax and concise console output snippets to illustrate expected results.

Verify Istio control-plane and create a test pod

First, ensure the Istio control plane and Ambient components are running. In Ambient mode you should see a ztunnel pod in the istio-system namespace:
kubectl get pods -n istio-system
# Example output:
# NAME                              READY   STATUS    RESTARTS   AGE
# istio-cni-node-zr8pb              1/1     Running   0          57s
# istiod-6b854648cc-ppq86           1/1     Running   0          65s
# ztunnel-9wjg7                     1/1     Running   0          51s
Create a long-running curl pod in the test namespace to act as a client:
kubectl run curl --image=curlimages/curl -n test --restart=Never --command -- sleep infinity
# pod/curl created
Confirm the client exists and is ready:
kubectl get pods -n test
# NAME   READY   STATUS    RESTARTS   AGE
# curl   1/1     Running   0          5s

Deploy HelloWorld into a namespace labeled for Ambient mode

From your demo folder, label the hello namespace for Ambient dataplane mode and apply the HelloWorld manifest (helloworld.yaml):
cd demo/

ls -l
# total 12
kubectl label namespace hello istio.io/dataplane-mode=ambient
kubectl apply -f helloworld.yaml -n hello
# service/helloworld created
# deployment.apps/helloworld-v1 created
# deployment.apps/helloworld-v2 created
Verify the HelloWorld pods and service:
kubectl get pods -n hello
# NAME                           READY   STATUS    RESTARTS   AGE
# helloworld-v1-...              1/1     Running   0          9s
kubectl get svc -n hello
# NAME         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)     AGE
# helloworld   ClusterIP   10.100.96.89   <none>        5000/TCP    13s

Enforce global mTLS (PeerAuthentication)

Create a cluster-wide PeerAuthentication in istio-system to require strict mTLS:
# global-pa.yaml
apiVersion: security.istio.io/v1
kind: PeerAuthentication
metadata:
  name: default
  namespace: istio-system
spec:
  mtls:
    mode: STRICT
Apply it:
kubectl apply -f global-pa.yaml
# peerauthentication.security.istio.io/default created
Verify the PeerAuthentication exists:
kubectl get peerauthentications -A
# NAMESPACE     NAME      AGE
# istio-system  default   10s

Test connectivity from the test pod

Try to reach the HelloWorld service from the curl pod in the test namespace:
kubectl exec -n test -it curl -- curl -I http://helloworld.hello.svc.cluster.local:5000/hello
# curl: (56) Recv failure: Connection reset by peer
Why this fails:
  • The hello namespace is labeled for Ambient mode and is subject to strict mTLS.
  • The test namespace is not labeled for Ambient mode and therefore is not participating in the Ambient dataplane (ztunnel identity/mTLS path). The identity/mTLS mismatch results in a connection reset.
To fix the mismatch, label the test namespace for Ambient:
kubectl label namespace test istio.io/dataplane-mode=ambient
# namespace/test labeled
Retry the request from the curl pod:
kubectl exec -n test -it curl -- curl -I http://helloworld.hello.svc.cluster.local:5000/hello
# HTTP/1.1 200 OK
# ...
Namespaces that should participate in Istio Ambient features must be labeled with istio.io/dataplane-mode=ambient. Without this label, Istio’s Ambient dataplane (ztunnel identity, mTLS path, etc.) will not be used and connectivity requiring mTLS will fail.

AuthorizationPolicy in Ambient mode — layer‑7 requires a waypoint

Layer‑7 (HTTP) AuthorizationPolicy enforcement in Ambient mode is performed by a waypoint proxy. A sidecar-style, namespace-based AuthorizationPolicy that relies on source namespaces will not behave the same in Ambient mode for L7 rules. Create a namespace-based policy (sidecar-like) that attempts to allow GETs from the test namespace:
# hw.yaml  (sidecar-like / namespace-based example)
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
  name: hello-world-authz
  namespace: hello
spec:
  selector:
    matchLabels:
      app: helloworld
  action: ALLOW
  rules:
  - from:
    - source:
        namespaces: ["test"]
    to:
    - operation:
        methods: ["GET"]
Apply it:
kubectl apply -f hw.yaml
# authorizationpolicy.security.istio.io/hello-world-authz created
Now test from the curl pod:
kubectl exec -n test -it curl -- curl -I http://helloworld.hello.svc.cluster.local:5000/hello
# curl: (22) The requested URL returned error: 503 Service Unavailable
Explanation:
  • The policy contains layer‑7 HTTP rules. In Ambient mode, L7 enforcement happens at the waypoint proxy, which is the L7 enforcement point.
  • Without configuring a waypoint for the namespace, the enforcement point and routing expected by the policy are not in place, so the request can result in a 503 Service Unavailable as the waypoint-based path is not available or not allowing the request.
To enable L7 waypoint enforcement, install a waypoint proxy and label the namespace to use it:
# Install a waypoint proxy for workloads in the hello namespace
istioctl waypoint apply -n hello

# Label the hello namespace to use the waypoint
kubectl label namespace hello istio.io/waypoint=enabled
# Verify the waypoint pod shows up alongside app pods
kubectl get pods -n hello
# NAME                                 READY   STATUS    RESTARTS   AGE
# helloworld-v1-...                    1/1     Running   0          2m
# helloworld-v2-...                    1/1     Running   0          2m
# waypoint-proxy-xxxxx                 1/1     Running   0          1m
Retry the request from the test pod:
kubectl exec -n test -it curl -- curl -I http://helloworld.hello.svc.cluster.local:5000/hello
# HTTP/1.1 503 Service Unavailable
# ...
The 503 now indicates that layer‑7 authorization is being evaluated at the waypoint, and the current AuthorizationPolicy does not grant the request. In Ambient mode you must be more explicit about principals.

Use service-account principals (SPIFFE) in AuthorizationPolicy for Ambient

In Ambient mode, AuthorizationPolicy should reference exact principals (service accounts) using the SPIFFE format rather than relying solely on namespaces. Create a policy that allows traffic only from the default service account in the test namespace using the SPIFFE principal format cluster.local/ns/<namespace>/sa/<serviceaccount>:
# hw-v2.yaml  (Ambient-friendly: allow by service account principal)
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
  name: hello-world-authz-v2
  namespace: hello
spec:
  selector:
    matchLabels:
      app: helloworld
  action: ALLOW
  rules:
  - from:
    - source:
        principals: ["cluster.local/ns/test/sa/default"]
    to:
    - operation:
        methods: ["GET"]
Notes:
  • Every namespace has a default service account unless you explicitly create or replace it. In production, create specific service accounts per workload for least privilege.
  • Using SPIFFE principals gives precise control over allowed workload identities.
Apply the new policy:
kubectl apply -f hw-v2.yaml
# authorizationpolicy.security.istio.io/hello-world-authz-v2 created
Test from the curl pod (which uses the default SA in test):
kubectl exec -n test -it curl -- curl -I http://helloworld.hello.svc.cluster.local:5000/hello
# HTTP/1.1 200 OK
# ...
The request succeeds because the principal cluster.local/ns/test/sa/default is explicitly allowed.

Verify denying other namespaces / service accounts

Create a new namespace web, label it for Ambient, and attempt the same request from a pod there. The default SA in web has a different SPIFFE principal and should be denied by the above policy:
kubectl create namespace web
kubectl label namespace web istio.io/dataplane-mode=ambient
# Create a simple nginx pod in the web namespace to test requests
kubectl run nginx --image=nginx -n web --restart=Never --command -- sleep infinity
# Install curl inside the nginx pod (Debian-based image commands shown for example)
kubectl exec -n web -it nginx -- apt-get update -qq && apt-get install -y -qq curl

# Try to curl HelloWorld from the web namespace
kubectl exec -n web -it nginx -- curl -I http://helloworld.hello.svc.cluster.local:5000/hello
# HTTP/1.1 403 Forbidden
# ...
You receive 403 Forbidden because the request principal (cluster.local/ns/web/sa/default) is not allowed by hello-world-authz-v2. If you remove the AuthorizationPolicy, access will be allowed again (assuming mTLS and dataplane labels are correct):
kubectl delete -f hw-v2.yaml
# authorizationpolicy.security.istio.io "hello-world-authz-v2" deleted

Recap and best practices

  • Label namespaces with istio.io/dataplane-mode=ambient so workloads participate in the Ambient dataplane (ztunnel).
  • Enforce mTLS cluster-wide with a PeerAuthentication (e.g., mtls: STRICT). Non-ambient namespaces will fail to connect to ambient workloads if they are not labeled to participate.
  • Layer‑7 (HTTP) AuthorizationPolicy enforcement in Ambient mode uses a waypoint proxy; install a waypoint and label the namespace (istio.io/waypoint=enabled) to enable waypoint-based L7 enforcement.
  • In Ambient mode, AuthorizationPolicy should be written to match exact principals (SPIFFE identities) instead of relying solely on source namespaces:
    • Use principals in this format: cluster.local/ns/<namespace>/sa/<serviceaccount>.
  • For production, create and use distinct service accounts per workload (avoid using default) so policies can be precise and follow least-privilege principles.
TopicRecommendationExample
Namespace participationLabel for Ambient dataplanekubectl label namespace hello istio.io/dataplane-mode=ambient
mTLS enforcementUse global PeerAuthentication (STRICT)See global-pa.yaml above
L7 enforcementInstall and enable waypoint for the namespaceistioctl waypoint apply -n hello and kubectl label namespace hello istio.io/waypoint=enabled
AuthorizationPolicy identityUse SPIFFE principals (service accounts)cluster.local/ns/test/sa/default
Summary: Ambient mode changes identity and policy semantics compared to sidecar mode. Label namespaces to participate in the ambient dataplane, use waypoints for L7 enforcement, and author AuthorizationPolicy rules using SPIFFE principals (service accounts) for precise access control in a zero‑trust model.

Watch Video

Practice Lab