Skip to content

AI Functions RBAC Enforcement

AKKO ships 21 Trino scalar functions (ai_sentiment, ai_pii, ai_embed, ai_parse_document, etc.) that forward calls to the AI Service. Because Trino's OPA authorizer does not fire ExecuteFunction on plugin scalar UDFs, RBAC is enforced in the AI Service middleware, not in OPA directly.

Enforcement flow

Trino query: SELECT ai_sentiment('hello') FROM ...
Trino plugin (trino-ai-functions) forwards:
   Authorization: Bearer ${AKKO_AI_SERVICE_TOKEN}
   X-Trino-User: <caller>
   X-Akko-Ai-Function: ai_sentiment
AI Service middleware (docker/ai-service/app.py):
   1. Validate Bearer token against Secret akko-trino-ai
   2. Resolve caller's realm role via Keycloak admin API (cached 300s)
   3. Check the RBAC matrix: is ai_sentiment allowed for this role?
   4. ALLOW → execute + metrics + audit log
      DENY  → return 403 + metrics + audit log

RBAC matrix (17 text functions + 4 unstructured)

Function akko-admin akko-engineer akko-analyst akko-steward akko-viewer
ai_sentiment
ai_classify
ai_summarize
ai_translate
ai_entities
ai_anomaly
ai_sql
ai_risk
ai_pii
ai_sensitivity
ai_language
ai_keywords
ai_ask
ai_embed
ai_parse_document
ai_transcribe
ai_describe_image
ai_ocr
ai_cache_clear (admin)
ai_cb_reset (admin)
ai_stats

Viewers get zero AI functions — any call returns HTTP 403.

Activation

Enforcement is gated by two Helm values. Both default to false for dev convenience; production deployments MUST set them to true.

akko-ai-service:
  serviceToken:
    enabled: true        # Trino plugin must present a shared Bearer token
    secretName: akko-trino-ai
    secretKey: service-token
  rbac:
    enabled: true
    keycloakUrl: "http://akko-akko-keycloak:8080"
    keycloakRealm: akko
    userRoleCacheTtlSeconds: 300

The akko-trino-ai Secret is auto-generated by helm/akko/templates/secrets.yaml and reused across upgrades via lookup. The same token is injected into the Trino deployment as AKKO_AI_SERVICE_TOKEN so the plugin can authenticate.

Testing

# As viewer (dave) → expected 403
kubectl exec -n akko svc/akko-trino -- \
  trino --user dave --execute "SELECT ai_sentiment('test')"
# Error: Access Denied: role 'akko-viewer' not permitted for function 'ai_sentiment'

# As analyst (carol) → expected success
kubectl exec -n akko svc/akko-trino -- \
  trino --user carol --execute "SELECT ai_sentiment('test')"
# => POSITIVE

# Admin function → viewer denied
kubectl exec -n akko svc/akko-trino -- \
  trino --user alice --execute "SELECT ai_cache_clear()"
# => OK
kubectl exec -n akko svc/akko-trino -- \
  trino --user bob --execute "SELECT ai_cache_clear()"
# Error: admin-only function

Playwright E2E test: tests/playwright/rbac-ai-functions.spec.ts verifies the full matrix against a live cluster.

Observability

Prometheus counters (exposed by AI Service /metrics):

  • akko_ai_rbac_allowed_total{function,role}
  • akko_ai_rbac_denied_total{reason,function,role}

Audit log (structured JSON in stdout → logs layer/logs layer):

{
  "audit_type": "AI_RBAC",
  "decision": "DENY",
  "user": "dave",
  "role": "akko-viewer",
  "function": "ai_sentiment",
  "reason": "role_not_permitted",
  "timestamp": "2026-04-19T14:22:07Z"
}

Troubleshooting

Symptom Likely cause Fix
All calls succeed from viewer rbac.enabled=false or serviceToken.enabled=false Flip both to true in values-<env>.yaml, helm upgrade
All calls return 401 Secret akko-trino-ai missing or Trino not reading it Check kubectl describe deploy/akko-trino-coordinator for env AKKO_AI_SERVICE_TOKEN
All calls return 403 for valid roles Keycloak admin creds invalid → fallback default_role Check AI Service logs for kc_admin_login_failed, rotate creds
Audit log empty logs layer (or logs layer) not collecting stdout Verify promtail/vector targets AI Service pods