Repository navigation
Design: permissions and custom roles #294
Description
The two role requests on #231 (written up in #293) are both "this role, but with this added or that removed". A fixed four-step ladder can't express that, and the next request will look the same. Rather than add two more hard-coded roles, move to permissions with roles as named bundles of them, so admins can build their own.
Where we are
- Four roles in a strict ladder: viewer (1) < operator (2) < poweruser (3) < admin (4). Each gets everything below it.
- About 70 checks on the server (
has_role(...)/role_level(...)), almost all insrc/api.rs. - About 50 more in the pages' own JavaScript (
roleLevel,isAdmin), deciding what to show. Those have drifted from the server: every logged-in user sees Recordings, but only poweruser and up can list them; operators see Tokens, but only poweruser and up can create one; viewers see Credentials, but saving needs operator. - OIDC groups map to a role (
group_role_mappings,rustguac map-group). User API tokens can be capped withmax_role. - Folder access (
allowed_groups/allowed_users) is a separate system that decides which connections someone sees. The role decides what they can do. That split is right and stays as it is.
Current server rules, roughly:
| Area | Needs today |
|---|---|
| List and connect to Connections, VDI containers, login scripts, credential variables | operator |
| Save own credential variables | operator |
| Ad-hoc sessions, host-key probe, quick connect | poweruser |
| Recordings and typescripts (list, play) | poweruser |
| Reports | poweruser |
| Create own API tokens | poweruser |
| Edit Connections (entries, folders, bulk, move, copy, folder config) | admin |
| Delete recordings, shadow sessions, view all sessions and thumbnails | admin |
| Users, roles, group mappings, admin tokens, audit logs, system status | admin |
Proposal
-
Permissions are the unit. A fixed list defined in code, around 15 to 20 of them. A first cut:
connections.connect,connections.adhoc,connections.edit,folders.manage_accesscredentials.self,tokens.self,docs.viewsessions.view_all,sessions.shadowrecordings.view,recordings.delete,reports.viewadmin.users,admin.roles,admin.audit,admin.system
Every server check becomes
has_perm(...). -
Roles are named bundles of permissions. The four current roles ship as built-ins that grant exactly what they grant today, so nothing changes for anyone on upgrade. Admins can add custom roles in the Admin page (e.g. "contractor", "connection editor") and map OIDC groups to them the same way as now.
-
API tokens:
max_rolebecomes "at most this role's permissions". The token gets only what both the user and the cap allow. -
/api/mereturns the caller's permission list, and the pages show or hide things from it rather than from their own role logic. pages: one navigation on every page, with the caller's role baked into the served page #274 already gives every nav link adata-min-roleattribute, so this becomes something likedata-perm="recordings.view". -
CLI:
set-roleandmap-groupaccept custom role names. Changes to roles are audited like other admin actions (headline only).
connections.adhoc covers ad-hoc connections to any host (and the host-key probe they use). It's a connection, not session management, so it sits with the connection permissions; the ad-hoc form is moving to the Connections page as well.
Staging
- Inventory (this issue): list every server and page check, give each one a permission, and write out exactly what each built-in role gets. Fix the existing nav/server mismatches here.
- Refactor with no behaviour change: move the checks to permissions with only the four built-ins. Tests pin that each built-in role allows and refuses exactly what it does today.
- Custom roles: a DB table, Admin UI to create and edit roles, and group mappings to custom roles.
- FR: two new roles, connection editor and connect-only #293: ship "connection editor" and "connect-only" as documented examples, or as extra built-ins.
Things to get right
folders.manage_accessis effectively admin. Anyone who can changeallowed_groups/allowed_userscan give themselves any folder. The UI should say so where it's granted.- No escalation through role editing. Only
admin.rolescan edit roles, and nobody can grant a permission they don't hold themselves, or change the role they're using. - Deleting a role in use. Refuse it, or reassign those users to a role the admin chooses. Never silently drop them to nothing, or worse, to a default with more access.
- Stored roles and tokens. Roles live on users, group mappings and token caps. A custom role that's renamed or deleted has to be handled in all three.
- Deny by default. A permission added in a later release is not granted to existing custom roles. Built-ins get whatever matches today's behaviour.
Not in scope
- Per-folder permissions (editor rights on some folders only). Folder access stays as it is. This could come later on top of the same permission names.
- Changing what the four built-in roles can do. That's a separate decision once permissions make it a one-line change.
Activity
entries: access rules on an entry and on each protocol