Envoy/Istio Integration
| Field | Value |
|---|---|
| Document ID | ASCEND-SDK-005 |
| Version | 1.0.0 |
| Last Updated | December 19, 2025 |
| Author | Ascend Engineering Team |
| Publisher | OW-KAI Technologies Inc. |
| Classification | Enterprise Client Documentation |
| Compliance | SOC 2 CC6.1/CC6.2, PCI-DSS 7.1/8.3, HIPAA 164.312, NIST 800-53 AC-2/SI-4 |
Reading Time: 15 minutes | Skill Level: Advanced
Overview
The ASCEND Envoy ext_authz service provides AI governance for Envoy proxy and Istio service mesh deployments. All service-to-service traffic can be governed without code changes.
Architecture
┌─────────────────────────────────────────────────────────────────────┐
│ ENVOY/ISTIO ARCHITECTURE │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ AI │ │ Envoy │ │ Backend │ │
│ │ Agent │───────▶│ Proxy │───────▶│ Service │ │
│ │ │ │ (Sidecar) │ │ │ │
│ └─────────┘ └──────┬──────┘ └─────────────┘ │
│ │ │
│ │ gRPC ext_authz │
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ ASCEND │ │
│ │ ext_authz │ │
│ │ Service │ │
│ │ │ │
│ │ Go gRPC │ │
│ │ Server │ │
│ └──────┬──────┘ │
│ │ │
│ │ HTTP/HTTPS │
│ ▼ │
│ ┌─────────────┐ │
│ │ ASCEND │ │
│ │ Platform │ │
│ └─────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────┘
Prerequisites
- Kubernetes 1.21+
- Envoy 1.20+ or Istio 1.12+
- ASCEND API key
Deployment
Kubernetes Deployment
# Source: ascend-envoy-authz/deploy/kubernetes/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: ascend-authz
namespace: ascend-system
spec:
replicas: 3
selector:
matchLabels:
app: ascend-authz
template:
metadata:
labels:
app: ascend-authz
spec:
containers:
- name: ascend-authz
image: owkai/ascend-envoy-authz:latest
ports:
- containerPort: 9001
name: grpc
- containerPort: 8080
name: health
env:
- name: ASCEND_API_KEY
valueFrom:
secretKeyRef:
name: ascend-secrets
key: api-key
- name: ASCEND_API_URL
value: "https://pilot.owkai.app"
- name: ENVIRONMENT
value: "production"
- name: FAIL_OPEN
value: "false"
- name: CACHE_TTL
value: "60s"
- name: LOG_LEVEL
value: "info"
resources:
requests:
memory: "64Mi"
cpu: "100m"
limits:
memory: "256Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health
port: health
initialDelaySeconds: 5
readinessProbe:
httpGet:
path: /ready
port: health
initialDelaySeconds: 5
---
apiVersion: v1
kind: Service
metadata:
name: ascend-authz
namespace: ascend-system
spec:
selector:
app: ascend-authz
ports:
- port: 9001
name: grpc
targetPort: grpc
- port: 8080
name: health
targetPort: health
Secrets
apiVersion: v1
kind: Secret
metadata:
name: ascend-secrets
namespace: ascend-system
type: Opaque
stringData:
api-key: "owkai_your_key_here"
Helm Chart
# Install from ECR Public OCI Registry
helm install ascend-authz oci://public.ecr.aws/d2x6s8u5/ascend-authz \
--version 1.0.0 \
--namespace ascend-system \
--create-namespace \
--set apiKey="owkai_your_key_here" \
--set environment=production
Package Info: ascend-authz on ECR Public | Version: 1.0.0
Envoy Configuration
ext_authz Filter
# envoy.yaml
static_resources:
listeners:
- name: listener_0
address:
socket_address:
address: 0.0.0.0
port_value: 8080
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefix: ingress_http
http_filters:
# ASCEND ext_authz filter
- name: envoy.filters.http.ext_authz
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz
grpc_service:
envoy_grpc:
cluster_name: ascend-authz
timeout: 5s
transport_api_version: V3
failure_mode_allow: false
with_request_body:
max_request_bytes: 8192
allow_partial_message: true
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
clusters:
- name: ascend-authz
type: STRICT_DNS
lb_policy: ROUND_ROBIN
typed_extension_protocol_options:
envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
"@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions
explicit_http_config:
http2_protocol_options: {}
load_assignment:
cluster_name: ascend-authz
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: ascend-authz.ascend-system.svc.cluster.local
port_value: 9001
Istio Configuration
AuthorizationPolicy
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: ascend-ext-authz
namespace: istio-system
spec:
selector:
matchLabels:
app: istio-ingressgateway
action: CUSTOM
provider:
name: ascend-authz
rules:
- to:
- operation:
notPaths:
- "/health"
- "/metrics"
MeshConfig Extension Provider
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
meshConfig:
extensionProviders:
- name: ascend-authz
envoyExtAuthzGrpc:
service: ascend-authz.ascend-system.svc.cluster.local
port: 9001
timeout: 5s
failOpen: false
Configuration Options
| Option | Default | Description |
|---|---|---|
ASCEND_API_KEY | Required | ASCEND API key |
ASCEND_API_URL | https://pilot.owkai.app | API endpoint |
ENVIRONMENT | production | Environment name |
FAIL_OPEN | false | Allow on error |
CACHE_TTL | 60s | Cache duration |
AGENT_ID_HEADER | x-ascend-agent-id | Header for agent ID |
DEFAULT_AGENT_ID | - | Default agent if missing |
REQUIRE_AGENT_ID | true | Require agent header |
LOG_LEVEL | info | Logging level |
LOG_DECISIONS | true | Log all decisions |
BLOCK_ON_PENDING | true | Block pending approvals |
EXCLUDED_PATHS | /health,/metrics | Paths to skip |
DATA_SENSITIVITY | internal | Default data class |
Handler Implementation
// Source: ascend-envoy-authz/internal/authz/handler.go:70
func (h *Handler) Check(ctx context.Context, req *authv3.CheckRequest) (*authv3.CheckResponse, error) {
// Extract HTTP request attributes
httpReq := req.GetAttributes().GetRequest().GetHttp()
// Check path exclusions
if mapper.IsPathExcluded(path, h.config.ExcludedPaths) {
return h.allowResponse(nil), nil
}
// Extract agent ID from headers
agentID := h.extractAgentID(httpReq.GetHeaders())
if agentID == "" && h.config.RequireAgentID {
return h.denyResponse("Missing agent ID", codes.Unauthenticated, nil), nil
}
// Map request to ASCEND action
action := mapper.MapCheckRequest(req, agentID, h.config.Environment)
// Check cache
if cached := h.getFromCache(cacheKey); cached != nil {
return h.buildResponse(cached), nil
}
// Call ASCEND API
decision, err := h.client.EvaluateAction(ctx, action)
if err != nil {
// FAIL SECURE
if h.config.FailOpen {
return h.allowResponse(map[string]string{"x-ascend-status": "error-allowed"}), nil
}
return h.denyResponse("Governance unavailable", codes.Unavailable, nil), nil
}
// Cache approved decisions
if decision.IsApproved() {
h.setCache(cacheKey, decision)
}
return h.buildResponse(decision), nil
}
Response Headers
The service adds these headers to allowed requests:
// Source: ascend-envoy-authz/internal/authz/handler.go:197
func (h *Handler) allowResponse(headers map[string]string) *authv3.CheckResponse {
headers["x-ascend-status"] = "approved"
headers["x-ascend-action-id"] = fmt.Sprintf("%d", decision.ActionID)
headers["x-ascend-risk-score"] = fmt.Sprintf("%.1f", decision.RiskScore)
headers["x-ascend-risk-level"] = decision.RiskLevel
// ...
}
Fail Secure Design
// Source: ascend-envoy-authz/internal/authz/handler.go:130
// FAIL SECURE: Deny on error unless fail_open is configured
if h.config.FailOpen {
h.logger.Warn("Fail open enabled, allowing request despite error")
return h.allowResponse(map[string]string{
"x-ascend-status": "error-allowed",
"x-ascend-error": err.Error(),
}), nil
}
return h.denyResponse(
"Governance service unavailable",
codes.Unavailable,
map[string]string{"x-ascend-error": "service_unavailable"},
), nil
Caching
The service maintains an in-memory cache for approved decisions:
// Source: ascend-envoy-authz/internal/authz/handler.go:296
type cacheEntry struct {
decision *ascend.Decision
expiresAt time.Time
}
func (h *Handler) getFromCache(key string) *ascend.Decision {
h.cacheMu.RLock()
defer h.cacheMu.RUnlock()
entry, ok := h.cache[key]
if !ok || time.Now().After(entry.expiresAt) {
return nil
}
return entry.decision
}
Health Checks
// Health endpoint: GET /health
// Ready endpoint: GET /ready
Health check integration:
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 5
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
Monitoring
Prometheus Metrics
The service exposes Prometheus metrics:
| Metric | Type | Description |
|---|---|---|
ascend_authz_requests_total | Counter | Total requests |
ascend_authz_decisions | Counter | Decisions by status |
ascend_authz_latency_seconds | Histogram | Request latency |
ascend_authz_cache_hits | Counter | Cache hit count |
ascend_authz_api_errors | Counter | API errors |
ServiceMonitor
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: ascend-authz
spec:
selector:
matchLabels:
app: ascend-authz
endpoints:
- port: health
path: /metrics
Logging
Structured JSON logging:
{
"level": "info",
"component": "authz_handler",
"agent_id": "my-agent-001",
"action_type": "api.read",
"status": "approved",
"risk_score": 3.5,
"risk_level": "low",
"action_id": 12345,
"latency_ms": 45,
"cached": false
}
Testing
Local Testing
# Build and run
go build -o ascend-authz ./cmd/server
./ascend-authz
# Test with grpcurl
grpcurl -plaintext \
-d '{"attributes":{"request":{"http":{"method":"GET","path":"/api/data","headers":{"x-ascend-agent-id":"test"}}}}}' \
localhost:9001 envoy.service.auth.v3.Authorization/Check
Integration Testing
# Deploy to Kubernetes
kubectl apply -f deploy/kubernetes/
# Test through Envoy
curl -H "X-Ascend-Agent-ID: test-agent" \
http://your-envoy-endpoint/api/data
Troubleshooting
| Issue | Cause | Solution |
|---|---|---|
| All requests denied | Invalid API key | Check secret |
| gRPC connection errors | Wrong port/service | Verify cluster config |
| High latency | No caching | Set CACHE_TTL |
| Pod CrashLoopBackOff | Missing env vars | Check deployment |
Best Practices
- Use 3+ replicas for high availability
- Set resource limits to prevent noisy neighbors
- Enable caching for production workloads
- Monitor error rates with Prometheus
- Use PodDisruptionBudget for updates
Next Steps
- Kong Plugin — For Kong Gateway
- AWS Lambda — For API Gateway
- Smart Rules — Create custom rules
Document Version: 1.0.0 | Last Updated: December 2025