Istio Quickstart
Get your first 403 in under 5 minutes with Istio service mesh.
Prerequisites
- Kubernetes cluster with Istio installed
- kubectl configured
- istioctl (optional, for debugging)
Verify Istio is running:
kubectl get pods -n istio-system
Steps
1. Deploy Tenuo Authorizer
kubectl apply -f https://raw.githubusercontent.com/tenuo-ai/tenuo/main/docs/quickstart/istio/tenuo.yaml
2. Configure Istio ExtensionProvider
kubectl patch configmap istio -n istio-system --type merge \
--patch-file https://raw.githubusercontent.com/tenuo-ai/tenuo/main/docs/quickstart/istio/mesh-config.yaml
kubectl rollout restart deployment/istiod -n istio-system
3. Deploy Test App
kubectl apply -f https://raw.githubusercontent.com/tenuo-ai/tenuo/main/docs/quickstart/istio/httpbin.yaml
This deploys httpbin with an AuthorizationPolicy that routes requests to Tenuo.
4. Wait for Pods
kubectl wait --for=condition=ready pod -l app=httpbin --timeout=60s
5. Port Forward
kubectl port-forward svc/httpbin 8080:8000 &
6. Test Without Warrant
curl -i http://localhost:8080/get
Expected:
HTTP/1.1 403 Forbidden
x-tenuo-deny-reason: missing_warrant
7. Test With Warrant
For demo purposes, the authorizer accepts a test warrant. In production, warrants come from your control plane.
# Demo warrant (pre-signed)
WARRANT="eyJ0eXAiOiJKV1QiLCJhbGciOiJFZERTQSJ9..."
curl -i -H "X-Tenuo-Warrant: $WARRANT" http://localhost:8080/get
See the Kubernetes Guide for issuing real warrants.
Architecture
Client --> Istio Sidecar --> Tenuo Authorizer --> httpbin
| |
| (verify) |
|<---------------+
|
+--> (forward if 200)
- Request arrives at httpbin’s Istio sidecar
- AuthorizationPolicy triggers external auth to Tenuo
- Tenuo verifies warrant
- Sidecar forwards to httpbin only if authorized
AuthorizationPolicy
The policy applies Tenuo auth to specific paths:
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: tenuo-authz
spec:
selector:
matchLabels:
app: httpbin
action: CUSTOM
provider:
name: tenuo-ext-authz
rules:
- to:
- operation:
paths: ["/api/*", "/get", "/post"]
Troubleshooting
Check AuthorizationPolicy:
kubectl get authorizationpolicy
istioctl x authz check deploy/httpbin
Check authorizer logs:
kubectl logs -n tenuo-system -l app=tenuo-authorizer --tail=20
Check Istio sidecar logs:
kubectl logs -l app=httpbin -c istio-proxy --tail=20
Verify ExtensionProvider:
kubectl get configmap istio -n istio-system -o yaml | grep -A10 extensionProviders
Envoy vs Istio
| Aspect | Envoy | Istio |
|---|---|---|
| Setup | Direct Envoy config | ExtensionProvider + AuthorizationPolicy |
| Granularity | Per-listener | Per-workload, per-path |
| Dependencies | Just Envoy | Full service mesh |
| Best for | Simple proxy | Existing Istio users |
Multi-hop Delegation Chains
X-Tenuo-Warrant accepts both a single warrant and a full delegation chain. The authorizer automatically distinguishes between the two: a chain is a CBOR array of warrants base64url-encoded as a single value; a single warrant is a CBOR-encoded warrant base64url-encoded directly.
For service-to-service calls within a mesh, each service that needs to delegate to a downstream service should:
- Receive the chain in
X-Tenuo-Warrant - Derive a narrower warrant from its own leaf token
- Append the derived token to the chain and re-encode it
- Forward the updated chain to the downstream service in
X-Tenuo-Warrant
The downstream service’s Istio sidecar forwards the header to Tenuo, which verifies the full chain offline — every link from root to leaf — with no network calls.
Next Steps
- Envoy Quickstart - Standalone proxy alternative
- Kubernetes Guide - Production patterns
- Proxy Configurations - Full Istio config reference
Clean Up
kubectl delete -f https://raw.githubusercontent.com/tenuo-ai/tenuo/main/docs/quickstart/istio/httpbin.yaml
kubectl delete -f https://raw.githubusercontent.com/tenuo-ai/tenuo/main/docs/quickstart/istio/tenuo.yaml