docs: update API.md with service account onboarding guide
CI / Vet, test, build (push) Canceled after 3m20s
CI / Build and push image (push) Canceled after 0s

- Add roles-based auth for service accounts
- Document client_credentials flow
- Add onboarding steps for new services
- Clarify user vs service auth models
This commit is contained in:
Admin Bot
2026-09-03 19:27:16 -07:00
parent a8bb6a4ffa
commit f154c5993a
+96 -9
View File
@@ -633,17 +633,104 @@ Authentik tokens include these custom claims:
}
```
### Capabilities (RBAC)
### Service Account Auth (Recommended for Services)
The `permissions` claim contains capabilities. Gateway checks these:
Service accounts use **roles** stored in user attributes. Simpler than groups.
| Capability | Required for | Granted to |
|------------|--------------|------------|
| `llm:inference` | `/v1/chat/completions`, `/v1/embeddings`, `/v1/rerank` | llm-admins, llm-users |
| `memory:read` | Memory queries | memory-users, memory-writers, poimen-memory-admins |
| `memory:write` | Memory ingest | memory-writers, poimen-memory-admins |
| `memory:admin` | Memory admin ops | poimen-memory-admins |
| `*` | Everything | homelab-admins |
**JWT claims (client_credentials flow):**
```json
{
"azp": "portfolio-agent",
"roles": ["llm:inference", "memory:read"]
}
```
**Gateway checks `roles` claim:**
```go
if hasRole(claims.Roles, "llm:inference") {
// allow
}
```
**Available roles:**
| Role | Grants access to |
|------|------------------|
| `llm:inference` | `/v1/chat/completions`, `/v1/embeddings`, `/v1/rerank` |
| `memory:read` | Memory queries |
| `memory:write` | Memory ingest |
| `s3:read` | S3/MinIO read |
| `s3:write` | S3/MinIO write |
---
### Onboarding a New Service
1. **Add to provisioning script** (`homelab/scripts/iam/authentik-provision.py`):
```python
SERVICE_ACCOUNTS = {
# ... existing ...
"my-new-service": {
"roles": ["llm:inference", "memory:read"], # what APIs it can call
"attributes": {
"memory_projects": ["my-project"], # optional: memory access scope
"memory_visibility": "public",
},
"secret_ns": "my-namespace", # k8s namespace for credentials
"secret_name": "my-service-oidc", # k8s secret name
},
}
```
2. **Run provisioning:**
```bash
export AUTHENTIK_BOOTSTRAP_TOKEN=$(kubectl -n iam get secret authentik-secrets \
-o jsonpath='{.data.AUTHENTIK_BOOTSTRAP_TOKEN}' | base64 -d)
python3 scripts/iam/authentik-provision.py
```
3. **Use credentials in your service:**
```bash
# Credentials stored in k8s secret
kubectl -n my-namespace get secret my-service-oidc -o yaml
# Contains: CLIENT_ID, CLIENT_SECRET, TOKEN_URL, ISSUER
# Get token
TOKEN=$(curl -s -X POST $TOKEN_URL \
-d "grant_type=client_credentials" \
-d "client_id=$CLIENT_ID" \
-d "client_secret=$CLIENT_SECRET" \
-d "scope=openid roles" | jq -r '.access_token')
# Call API
curl -H "Authorization: Bearer $TOKEN" https://api.riotpiao.com/v1/models
```
---
### User Auth (Groups → Permissions)
Human users use **groups** which map to **permissions**. Used for browser-based apps.
**JWT claims (authorization_code flow):**
```json
{
"groups": ["homelab-admins", "llm-admins"],
"permissions": ["*", "llm:inference", "llm:read", "llm:write"]
}
```
| Group | Permissions granted |
|-------|---------------------|
| `homelab-admins` | `*` (everything) |
| `llm-admins` | `llm:inference`, `llm:read`, `llm:write` |
| `llm-users` | `llm:inference` |
| `memory-users` | `memory:read` |
| `memory-writers` | `memory:read`, `memory:write` |
| `poimen-memory-admins` | `memory:*`, `memory:admin` |
**Memory-specific claims:**