Auth & Admin
Principals, API keys, roles, and the auth introspection endpoints.
The admin surface manages identities (principals), credentials (API keys), and permission sets (roles). Two introspection routes at /auth/* let callers inspect the permissions a workflow requires.
All /admin/* routes here require either admin:principals:read|manage or admin:roles:read|manage depending on the operation. The built-in admin role grants *.
Principals
Principals model identities. Two types: user (typically external, OIDC-backed) and service_account (typically Flux-internal, API-key-backed). The external_issuer defaults to flux.
GET /admin/principals
List principals.
- Query:
?type=user|service_account(optional). - Permission:
admin:principals:read. - Response:
[{ "id", "subject", "type", "external_issuer", "display_name", "enabled", "roles" }, ...].
POST /admin/principals
Create a principal.
- Body (
PrincipalCreateRequest):{"type", "subject", "external_issuer?", "display_name?", "roles": [...]}. - Permission:
admin:principals:manage. - Status: 201 on success; 409 if a principal with the same
(subject, external_issuer)already exists. - Response: the new principal record.
GET /admin/principals/{subject}
Look up a principal.
- Query:
?issuer=<external_issuer>(defaults toflux). - Permission:
admin:principals:read. - Response: the principal record.
- 404: not found.
PATCH /admin/principals/{subject}
Update a principal’s display_name or enabled flag.
- Body (
PrincipalUpdateRequest): any of{"display_name", "enabled"}. - Query:
?issuer=.... - Permission:
admin:principals:manage. - Response: updated record.
DELETE /admin/principals/{subject}
Remove a principal.
- Query:
?issuer=...,?force=trueto delete even when there are active dependencies. - Permission:
admin:principals:manage. - Response:
{"status": "success", "message": "..."}.
POST /admin/principals/{subject}/enable
Toggle the enabled flag on. Equivalent to PATCH with {"enabled": true} but cheaper for shell-style calls.
- Permission:
admin:principals:manage.
POST /admin/principals/{subject}/disable
Toggle the enabled flag off.
- Permission:
admin:principals:manage.
POST /admin/principals/{subject}/roles
Grant a role to a principal.
- Body (
RoleGrantRequest):{"role": "<role_name>"}. - Query:
?issuer=.... - Permission:
admin:principals:manage. - Response:
{"status": "success", "role": "<role_name>"}.
DELETE /admin/principals/{subject}/roles/{role_name}
Revoke a role.
- Query:
?issuer=.... - Permission:
admin:principals:manage.
API keys
API keys belong to a service-account principal. Creating a key for a user principal returns 400.
POST /admin/principals/{subject}/keys
Mint a new API key. The plaintext key is returned exactly once.
- Body (
APIKeyRequest):{"name": "ci-runner", "expires_in_days": 90}(expires_in_daysis optional; omit for no expiry). - Query:
?issuer=.... - Permission:
admin:principals:manage. - Status: 201.
- Response:
{"key": "<plaintext>"}. Store it immediately — the server only retains the hash. - 400: principal is not a service account.
GET /admin/principals/{subject}/keys
List the keys (metadata only) issued to a principal.
- Query:
?issuer=.... - Permission:
admin:principals:read. - Response:
[{ "name", "prefix", "expires_at", "created_at" }, ...]. Only the prefix is exposed; the full key is never returned by list.
DELETE /admin/principals/{subject}/keys/{key_name}
Revoke a key by its name.
- Query:
?issuer=.... - Permission:
admin:principals:manage. - Response:
{"status": "success", "message": "Key '<name>' revoked"}.
Roles
Built-in roles (admin, operator, viewer, worker) cannot be modified or deleted.
GET /admin/roles
List all roles.
- Permission:
admin:roles:read. - Response:
[{ "name", "permissions", "built_in" }, ...].
GET /admin/roles/{name}
Show one role.
- Permission:
admin:roles:read.
POST /admin/roles
Create a custom role.
- Body (
RoleRequest):{"name": "...", "permissions": ["workflow:default:*:read", ...]}. - Permission:
admin:roles:manage. - 409: a role with that name already exists.
PATCH /admin/roles/{name}
Add or remove permissions on a custom role.
- Body (
RoleUpdateRequest):{"add_permissions": [...], "remove_permissions": [...]}. - Permission:
admin:roles:manage. - 400: attempting to modify a built-in role.
DELETE /admin/roles/{name}
Delete a custom role.
- Permission:
admin:roles:manage. - 400: built-in role.
POST /admin/roles/{name}/clone
Clone an existing role into a new name. Convenient for forking a built-in role into a customisable copy.
- Body (
RoleCloneRequest):{"new_name": "..."}. - Permission:
admin:roles:manage. - 409: target name already exists.
Auth introspection
GET /auth/permissions
List the permissions required to read and run workflows.
- Query:
?workflow=<ref>to scope to one workflow; omit for a map keyed bynamespace/name. - Auth: any authenticated identity.
- Response: array of permission strings (single workflow) or
{ "ns/name": [perms...] }(whole catalog). The permissions are the union of the workflow’s read permission plus anything its metadata declares (e.g.secret_requestsaddadmin:secrets:read, etc.).
POST /auth/test-token
Validate a bearer token without using it for a real request. Useful for CI diagnostics.
- Body:
{"token": "<bearer>"}. - Permission:
admin:*. - Rate limit: 10 requests per minute per client.
- Response:
{"valid": bool, "subject": "...", "roles": [...], "permissions": [...]}. Invalid tokens return{"valid": false, "error": "..."}.
Provider notes
- API key:
Authorization: Bearer <prefix>.<secret>(the dot-separated form lets the server pick the key row by prefix). Lookup is constant-time once the row is loaded. - OIDC: any standard JWT bearer; the issuer must match
[flux.security.auth.oidc].issuer. The subject from the token is matched against a principal withexternal_issuer = <oidc_issuer>and the samesubject. Unknown subjects are rejected. - Bootstrap token: only
POST /workers/registeraccepts it. Surface the current value withflux server bootstrap-token. - Execution token: minted by the server when a run is scheduled, embedded into the SSE payload, and used by the worker on callbacks. Short-lived; not intended for direct use.