LLM RBAC — Role-Based Access Control for AI models¶
AKKO maps the 5 AKKO platform roles (akko-admin, akko-engineer,
akko-analyst, akko-user, akko-viewer) to LiteLLM model access groups
and quotas, centralising the AI access matrix in a single ConfigMap
that is exposed via the Cockpit UI under Governance → LLM Access Matrix.
Default matrix¶
| Role | Chat (qwen2.5:3b) | Embed (nomic) | Code (qwen-coder) | GPU (vLLM) | Daily quota | Rate limit |
|---|---|---|---|---|---|---|
akko-admin |
✅ | ✅ | ✅ | ✅ | unlimited | unlimited |
akko-engineer |
✅ | ✅ | ✅ | ❌ | 50 k tokens | 120 req/min |
akko-analyst |
✅ | ✅ | ❌ | ❌ | 20 k tokens | 60 req/min |
akko-user |
✅ | ❌ | ❌ | ❌ | 5 k tokens | 30 req/min |
akko-viewer |
❌ | ❌ | ❌ | ❌ | none | — |
Source: helm/akko/charts/akko-cockpit/templates/configmap-llm-rbac.yaml
(rendered ConfigMap akko-llm-rbac in namespace akko).
Architecture¶
Cockpit UI (Governance → LLM Access tab)
│
▼
GET /api/cockpit/llm-rbac.json ← served by nginx cockpit from mounted ConfigMap
│
├── read by browser → renders the matrix (read-only)
│
└── write: GitOps only — edit the Helm-templated ConfigMap, commit, push,
let CI re-deploy. No runtime mutation endpoint. This avoids the
need for a K8s ServiceAccount with patch-ConfigMap rights inside
the cockpit, and keeps every change auditable in Git history.
File layout¶
| File | Role |
|---|---|
helm/akko/charts/akko-cockpit/templates/configmap-llm-rbac.yaml |
Source of truth (Helm-templated) |
helm/akko/charts/akko-cockpit/templates/deployment.yaml |
Mounts ConfigMap at /usr/share/nginx/html/api/cockpit/llm-rbac.json |
branding/cockpit/index.html |
Governance page with matrix UI (Sprint 15.5) |
branding/cockpit/app.js |
loadLlmRbac() fetches the JSON + renders |
Using the matrix from code¶
From a notebook (jupyter-alice)¶
import os
import requests
# LiteLLM respects the access_groups based on the bearer token user
resp = requests.post(
f"http://akko-akko-litellm:4000/chat/completions",
headers={"Authorization": f"Bearer {os.environ['LITELLM_USER_KEY']}"},
json={"model": "akko-chat", "messages": [{"role": "user", "content": "hi"}]}
)
If the user's role doesn't match the model's access_groups, LiteLLM returns
403 Forbidden with a message indicating the missing group.
From Trino (via ai_*() functions)¶
-- The ai_service middleware passes the Trino user's Keycloak role to LiteLLM.
-- A user with role akko-viewer gets an empty result (no model access).
SELECT akko_ai_sentiment(comment) FROM reviews LIMIT 10;
From Claude Desktop (via MCP)¶
MCP Trino server propagates the user's role via HTTP header. The LiteLLM gateway enforces it the same way.
Modifying the matrix¶
Via GitOps (recommended — prod)¶
Edit helm/akko/charts/akko-cockpit/templates/configmap-llm-rbac.yaml →
commit → push → CI auto-deploy → ConfigMap updated.
Via Cockpit UI (Sprint 15.5, admin only — read-only view)¶
- Sign in as
alice(akko-admin) - Navigate to Governance → LLM Access tab
- The full matrix renders: 4 models × 5 roles, with quotas and rate limits per role
- To change the matrix, edit the Helm ConfigMap and push (GitOps only — no runtime edits)
The read-only design is deliberate: every change goes through code review and
lands as a Git commit, so access-control history is auditable forever. The
configmap-llm-rbac.yaml file is the single source of truth.
Adding a new model¶
- Edit
helm/examples/values-dev.yaml— add the model toakko-litellm.config.model_list - Edit
helm/akko/charts/akko-cockpit/templates/configmap-llm-rbac.yaml— add the model tomodelssection with its defaultaccess_groups - Commit + push → CI deploy
- LiteLLM picks up the new model automatically; matrix shows the new column
Auditing LLM usage¶
Every LLM call is logged in logs layer by the AI Service middleware:
{service="ai-service"} |= "llm_call" | json | line_format
"{{.user}} {{.model}} {{.status}} tokens={{.tokens}}"
Dashboard Dashboards LLM Usage by Role (planned Sprint 15.7) shows: - Tokens/hour per role - Top 10 users by volume - Error rate per model - Cost estimate (when commercial models are added)
Emergency lockout¶
Set a role to access_groups: [] to immediately deny all LLM access for that
role, without changing Keycloak or redeploying services:
kubectl edit configmap akko-llm-rbac -n akko
# Find "akko-analyst" → set "access_groups": []
# Save → LiteLLM reload → effective immediately
See also¶
- Cockpit v2 roadmap: repo privé
akko-technical-map/roadmap/master-roadmap-2026-04-14.md(section Sprint 16) - RBAC model (5 roles)
- LiteLLM config