Skip to main content

Envoy/Istio Integration

FieldValue
Document IDASCEND-SDK-005
Version1.0.0
Last UpdatedDecember 19, 2025
AuthorAscend Engineering Team
PublisherOW-KAI Technologies Inc.
ClassificationEnterprise Client Documentation
ComplianceSOC 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

OptionDefaultDescription
ASCEND_API_KEYRequiredASCEND API key
ASCEND_API_URLhttps://pilot.owkai.appAPI endpoint
ENVIRONMENTproductionEnvironment name
FAIL_OPENfalseAllow on error
CACHE_TTL60sCache duration
AGENT_ID_HEADERx-ascend-agent-idHeader for agent ID
DEFAULT_AGENT_ID-Default agent if missing
REQUIRE_AGENT_IDtrueRequire agent header
LOG_LEVELinfoLogging level
LOG_DECISIONStrueLog all decisions
BLOCK_ON_PENDINGtrueBlock pending approvals
EXCLUDED_PATHS/health,/metricsPaths to skip
DATA_SENSITIVITYinternalDefault 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:

MetricTypeDescription
ascend_authz_requests_totalCounterTotal requests
ascend_authz_decisionsCounterDecisions by status
ascend_authz_latency_secondsHistogramRequest latency
ascend_authz_cache_hitsCounterCache hit count
ascend_authz_api_errorsCounterAPI 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

IssueCauseSolution
All requests deniedInvalid API keyCheck secret
gRPC connection errorsWrong port/serviceVerify cluster config
High latencyNo cachingSet CACHE_TTL
Pod CrashLoopBackOffMissing env varsCheck deployment

Best Practices

  1. Use 3+ replicas for high availability
  2. Set resource limits to prevent noisy neighbors
  3. Enable caching for production workloads
  4. Monitor error rates with Prometheus
  5. Use PodDisruptionBudget for updates

Next Steps


Document Version: 1.0.0 | Last Updated: December 2025