> ## 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.

# Demo Ambient Mode Securing Workloads

> Explains how Istio Ambient mode affects mTLS, AuthorizationPolicy, namespace labeling, waypoints, and using SPIFFE service account principals to secure workload communication

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:

```shell theme={null}
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:

```shell theme={null}
kubectl run curl --image=curlimages/curl -n test --restart=Never --command -- sleep infinity
# pod/curl created
```

Confirm the client exists and is ready:

```shell theme={null}
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`):

```shell theme={null}
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:

```shell theme={null}
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:

```yaml theme={null}
# global-pa.yaml
apiVersion: security.istio.io/v1
kind: PeerAuthentication
metadata:
  name: default
  namespace: istio-system
spec:
  mtls:
    mode: STRICT
```

Apply it:

```shell theme={null}
kubectl apply -f global-pa.yaml
# peerauthentication.security.istio.io/default created
```

Verify the PeerAuthentication exists:

```shell theme={null}
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:

```shell theme={null}
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:

```shell theme={null}
kubectl label namespace test istio.io/dataplane-mode=ambient
# namespace/test labeled
```

Retry the request from the `curl` pod:

```shell theme={null}
kubectl exec -n test -it curl -- curl -I http://helloworld.hello.svc.cluster.local:5000/hello
# HTTP/1.1 200 OK
# ...
```

<Callout icon="lightbulb" color="#1CB2FE">
  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.
</Callout>

## 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:

```yaml theme={null}
# 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:

```shell theme={null}
kubectl apply -f hw.yaml
# authorizationpolicy.security.istio.io/hello-world-authz created
```

Now test from the `curl` pod:

```shell theme={null}
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:

```shell theme={null}
# 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:

```shell theme={null}
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>`:

```yaml theme={null}
# 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:

```shell theme={null}
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`):

```shell theme={null}
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:

```shell theme={null}
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):

```shell theme={null}
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.

| Topic                        |                                Recommendation | Example                                                                                          |
| ---------------------------- | --------------------------------------------: | ------------------------------------------------------------------------------------------------ |
| Namespace participation      |                   Label for Ambient dataplane | `kubectl label namespace hello istio.io/dataplane-mode=ambient`                                  |
| mTLS enforcement             |        Use global PeerAuthentication (STRICT) | See `global-pa.yaml` above                                                                       |
| L7 enforcement               | Install and enable waypoint for the namespace | `istioctl waypoint apply -n hello` and `kubectl label namespace hello istio.io/waypoint=enabled` |
| AuthorizationPolicy identity |      Use SPIFFE principals (service accounts) | `cluster.local/ns/test/sa/default`                                                               |

<Callout icon="lightbulb" color="#1CB2FE">
  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.
</Callout>

## Links and references

* Istio Ambient mode concepts: [https://istio.io/latest/docs/ops/deployment/ambient/](https://istio.io/latest/docs/ops/deployment/ambient/)
* PeerAuthentication reference: [https://istio.io/latest/docs/reference/config/security/peer\_authentication/](https://istio.io/latest/docs/reference/config/security/peer_authentication/)
* AuthorizationPolicy reference: [https://istio.io/latest/docs/reference/config/security/authorization-policy/](https://istio.io/latest/docs/reference/config/security/authorization-policy/)
* Waypoint proxies: [https://istio.io/latest/docs/setup/additional-setup/waypoint/](https://istio.io/latest/docs/setup/additional-setup/waypoint/)
* SPIFFE standard: [https://spiffe.io/](https://spiffe.io/)

<CardGroup>
  <Card title="Watch Video" icon="video" cta="Learn more" href="https://learn.kodekloud.com/user/courses/istio-certified-associate/module/17ba1cac-61f4-48b6-b354-c2c735f5791d/lesson/43061c1f-8ac1-4a33-aa98-dff962f9b9ad" />

  <Card title="Practice Lab" icon="flask-conical" cta="Learn more" href="https://learn.kodekloud.com/user/courses/istio-certified-associate/module/17ba1cac-61f4-48b6-b354-c2c735f5791d/lesson/2cd41378-65b3-4710-a7f0-46fbb10c4f77" />
</CardGroup>
