Skip to content

Envoy Authz Server

This example demonstrates how to run and test the Kyverno Authorization Server in Envoy mode with a JWT-based authentication policy.

It shows how the server evaluates gRPC requests and enforces access rules using token validation.

Prerequisites

Before starting, ensure you have:

  • Docker installed and running.
  • grpcurl for sending gRPC requests.

Tip

You do not need a Kubernetes cluster — the server runs locally and loads policies directly from files.

Step 1: Create a Policy

Start by creating a simple ValidatingPolicy.

Save the following policy as quick-start.yaml in your working directory:

apiVersion: policies.kyverno.io/v1alpha1
kind: ValidatingPolicy
metadata:
  name: quick-start
spec:
  evaluation:
    mode: Envoy 
  failurePolicy: Fail 
  variables: 
  - name: authorization
    expression: object.attributes.request.http.headers[?"authorization"].orValue("").split(" ")
  - name: token
    expression: >
      size(variables.authorization) == 2 && variables.authorization[0].lowerAscii() == "bearer"
        ? jwt.Decode(variables.authorization[1], "secret")
        : null
  validations: 
  - expression: >
      variables.token == null || !variables.token.Valid
        ? envoy.Denied(401).Response()
        : null
  - expression: >
      variables.token.Claims.?role.orValue("") != "admin"
        ? envoy.Denied(403).Response()
        : null
  - expression: >
      envoy.Allowed().Response()

This policy:

  • Denies requests without a valid token (401).
  • Denies authenticated users without an admin role (403).
  • Allows admin users (200).

Step 2: Run the Envoy Authz Server

You can use Docker to start the Kyverno Authz Server and load the policy created above.

Run the following command from your terminal:

docker run --rm                                               \
  -p 9081:9081                                                \
  -v ${PWD}/quick-start.yaml:/data/policies/quick-start.yaml  \
  ghcr.io/kyverno/kyverno-authz:latest                        \
  serve envoy authz-server --kube-policy-source=false         \
  --external-policy-source file://data/policies

Info

  • The flag --external-policy-source tells the server to load policies from file://data/policies.
  • Port 9081 is exposed for HTTP requests.
  • TLS certificates are not required for this example.

Once the container starts, you should see output similar to this:

2025-11-17T12:19:18+01:00       INFO    Using namespace 'default' - consider setting explicit namespace
2025-11-17T12:19:18+01:00       INFO    GRPC Server starting... {"address": "[::]:9081", "network": "tcp"}

This confirms the server is running and listening on port 9081.

Step 3: Send Requests to the Server

Now that the server is running, you can send test requests to observe how the policy behaves.

Example 1 — Missing Authorization Header

grpcurl -plaintext -d @ localhost:9081 envoy.service.auth.v3.Authorization/Check <<EOF
{
  "attributes": {
    "request": {
      "http": {
        "headers": {
          "authorization": "empty"
        }
      }
    }
  }
}
EOF

Response:

{
  "status": {
    "code": 7
  },
  "deniedResponse": {
    "status": {
      "code": "Unauthorized"
    }
  }
}

Example 2 — Non-admin User Token

export ALICE_TOKEN="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjIyNDEwODE1MzksIm5iZiI6MTUxNDg1MTEzOSwicm9sZSI6Imd1ZXN0Iiwic3ViIjoiWVd4cFkyVT0ifQ.ja1bgvIt47393ba_WbSBm35NrUhdxM4mOVQN8iXz8lk"

grpcurl -plaintext -d @ localhost:9081 envoy.service.auth.v3.Authorization/Check <<EOF
{
  "attributes": {
    "request": {
      "http": {
        "headers": {
          "authorization": "bearer $ALICE_TOKEN"
        }
      }
    }
  }
}
EOF

Response:

{
  "status": {
    "code": 7
  },
  "deniedResponse": {
    "status": {
      "code": "Forbidden"
    }
  }
}

Example 3 — Admin User Token

export BOB_TOKEN="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjIyNDEwODE1MzksIm5iZiI6MTUxNDg1MTEzOSwicm9sZSI6ImFkbWluIiwic3ViIjoiWVd4cFkyVT0ifQ.veMeVDYlulTdieeX-jxFZ_tCmqQ_K8rwx2OktUHv5Z0"

grpcurl -plaintext -d @ localhost:9081 envoy.service.auth.v3.Authorization/Check <<EOF
{
  "attributes": {
    "request": {
      "http": {
        "headers": {
          "authorization": "bearer $BOB_TOKEN"
        }
      }
    }
  }
}
EOF

Response:

{
  "status": {},
  "okResponse": {}
}

Step 4: Summary

  1. Define a JWT-based Envoy authorization policy.
  2. Run the Kyverno Envoy Authz Server via Docker.
  3. Test requests with grpcurl and validate access control decisions.