Skip to main content
Version: 0.1.0

Users, roles & permissions

This page covers operator login, roles, and permissions for Padas UI, the console. Operators sign in to the console; the console then reaches the engine using credentials from enrollment (not a token pasted into Cores). See Security and Cores.

Related: Security · REST API Reference · Motion Engine TOML · Cores · Monitoring · Troubleshooting & Logs · Glossary · Run a sample pipeline · Install Padas Motion


Overview

ConcernRuntime behavior
Human authenticationPOST /auth/login validates credentials (local users.json or LDAP bind); success issues session cookies (access_token / refresh_token).
Route-level authorizationProtected console routes require a valid session. Role checks use admin and user only.
Session lifecycleShort-lived access token + refresh path; expired access may be renewed via refresh cookie until logout or secret rotation.
console as authorization boundaryconsole pages and APIs check the signed-in operator’s role before mutating configuration.
Human vs service identityOperator login controls who may use the console. Enrollment controls how the console may call the engine—separate layers (Security).

Initial admin bootstrap and first login

First-run flow: after licensing, the console creates empty {PADAS_UI_HOME}/data/security/users.json and secret.json if missing. Until users.local is non-empty, the sign-in surface shows System Not Initialized. GET /auth/init and POST /auth/init are reachable without a session—treat them as bootstrap attack surface on untrusted networks.

Why /auth/init matters: it is the only supported path to create the first local user with roles: ['admin']. GET /auth/init returns { "initialized": false } until a user exists; POST /auth/init accepts name, username, password, email and always assigns admin. If any user already exists → 409 Conflict. Operational hardening: after bootstrap, restrict /auth/init to a trusted network (ingress allowlist, reverse proxy ACL, or private admin VLAN).

JWT secret implications: secret.json defines signing trust for all future sessions. Loss or rotation without coordinated re-login invalidates existing sessions—plan secret rotation as a global sign-out event (see Operational identity management).

users.json persistence: bootstrap appends the first local user; subsequent CRUD goes through authenticated admin routes. Treat {PADAS_UI_HOME}/data/security/ as sensitive. Backup/restore: restore users.json and secret.json together—mismatched pairs break session verification.

curl -sS https://UI_HOST:9000/auth/init

curl -sS -X POST https://UI_HOST:9000/auth/init \
-H "Content-Type: application/json" \
-d '{"name":"Ops Admin","username":"admin1","password":"YourComplexPass1","email":"admin1@example.com"}'

After first login, enroll each engine (Installation — padas-motion), then register host and port under Configurations → Cores (Cores).


In the UI: session menu, profile, and password

Header menu (role in context)

The header shows username and an Administrator badge when the session includes the admin role. This reflects the same roles array used for route authorization—not a separate privilege channel.

Home: user avatar menu with admin username, Administrator badge, Profile, Change password, Logout
Runtime session: user label, role badge, and account actions from the header.

User profile

Profile shows Name, Username, E-Mail, and Roles from users.json for local users. LDAP-backed users see the same shape after bind—the console still issues a local session carrying roles. This screen mirrors persisted identity; it does not grant privilege by itself.

User Profile: Name, Username, E-Mail, Roles fields and Change Password button
User Profile: fields map to persisted identity; roles drive console access.

Change password

Change password is local-user self-service. A successful update changes the stored hash in users.json; existing sessions may remain valid until expiry—password rotation does not instantly revoke all sessions unless you also rotate secret.json or restart with session invalidation. LDAP directory passwords are not managed through this modal; use IdP flows.

Change Password modal with password fields and Update password / Cancel
Self-service password update for the current local user.

Roles and console access

Runtime RBAC uses two role strings only: admin and user. Protected routes declare which roles may call them. Missing session → 401 Unauthorized; wrong role → 403 Forbidden.

Surfaceadmin onlyadmin + user
Licensesverify, list, add, delete
Users / LDAP / audit logslist, CRUD
POST /logs (client log ingest)
Registry create/update/delete, bulk delete
Registry GET
Management deploy / start / stop / restart
Monitoring, captures, POST /test/run

Why the engine does not enforce console roles: The engine authorizes HTTP API calls with service authentication from enrollment—not the operator’s console role. A signed-in operator can trigger console actions that call the engine only when enrollment and Cores registration are correct.

Current product limitations:

  • POST /auth/users (admin) currently creates new local users with admin role only—least-privilege user creation via API is not supported yet.
  • LDAP sign-in assigns admin for authorization today—directory groups do not map to user yet.

Security implications:

TopicBehavior
Enrolled engine accessAfter enrollment, deploy and monitoring use the service identity on the engine host; console roles gate who may trigger those actions.
console compromiseHost-level compromise of PADAS_UI_HOME exposes secret.json, users.json, registry DB, and enroll registry—effective authority includes configuration deploy to enrolled Cores.
RBAC scopeNo fine-grained resource ABAC; no per-Core segregation by role—authorization is route-wide.

Multiple local users

Accounts live under users.jsonlocal array entries with username, password hash, roles, and profile fields.

Admin / user role model: user can read registry and run deploy/monitor flows per route table; admin additionally manages users, LDAP settings, licenses, audit exports, and destructive registry operations. Prefer named operators over shared admin accounts where policy requires accountability.

Audit: mutating console API calls record the signed-in operator; correlate with Monitoring for incident review.


LDAP directory sign-in

When LDAP is configured, POST /auth/login can bind against the directory. Successful bind issues the same session cookies as local login—the browser never stores directory credentials for subsequent requests.

Role mapping: every LDAP session is admin-equivalent for authorization today. Identity provider trust: the console trusts the directory for password verification; directory outage surfaces as login failures, not engine errors.

Operational deployment: use LDAPS/TLS to the IdP, lock down LDAP config backups, and document fallback to a local admin during IdP incidents.


Runtime identity flow

StepBehavior
Browser loginOperator submits username / password to POST /auth/login.
Credential checkLocal users.json or LDAP bind.
Session issuanceHTTP-only cookies carry signed access and refresh tokens.
Request authenticationProtected routes verify session signature and expiry.
Role authorizationRoute checks roles against allowed list.
Engine API mediationThe console calls the engine on behalf of signed-in operators using enrollment credentials—not the operator’s session cookie.

Trust boundaries and authorization model

BoundaryEnforcement
Browser ↔ consoleOperator session cookies + role checks on console routes.
console ↔ engineService authentication from enrollment; the engine does not enforce console roles.
Session vs engine BearerSession = operator to console; engine Bearer = direct API automation on the engine host—separate trust boundaries (Security).
Human identity vs service identityOperator accounts vs enrollment on each engine.
Delegated authorityThe console uses server-side enroll material for actions that call the engine—operators do not hold engine secrets in the browser.

Operational identity management

  • Password rotation: updates users.json; outstanding sessions may persist until expiry—plan maintenance windows.
  • Admin account hygiene: avoid long-lived shared admin accounts.
  • Bootstrap recovery: fresh install with empty users.local vs 409 on populated data—never mix prod data/security/ with lab secret.json casually.
  • Secret rotation: new secret.json invalidates all sessions—every operator must re-login.
  • console migration: move {PADAS_UI_HOME}/data/security/ atomically with the registry DB and data/security/s2s/ enroll state.
  • Backup sensitivity: users.json, secret.json, registry DB, and enroll registry hold operational identity—encrypt backups and restrict restore RBAC.

Security considerations and troubleshooting

SymptomLikely cause
Expired session401 on protected routes; refresh or re-login required.
Cookie / session issuesBrowser blocked cookies, wrong console origin, or refresh mismatch.
Invalid role errors403—session lacks required admin / user.
LDAP bind failuresDirectory unreachable, bad bind DN/password, or TLS to IdP failing.
Bootstrap conflicts (409)POST /auth/init when a user already exists—expected guard.
Corrupted users.jsonJSON parse failures or manual edit errors—restore from backup.
Lost secret.jsonCannot verify sessions; restore secrets backup or regenerate and force global re-login.
Auth redirect loopsClient repeatedly hitting protected routes without valid cookie—check reverse proxy cookie forwarding.
Stale sessions after role changesSession still carries old roles until re-issue—re-login or wait for access token expiry.

Deeper triage: Troubleshooting & Logs.