Files
rustguac/docs/api.md
T
Dave Kempe a94b743d6c Add user API tokens with role-based access and audit logging
User API tokens allow OIDC users to authenticate via bearer token for
automation and scripting. Powerusers and admins can create their own
tokens; admins can create tokens for operators. Tokens use SHA-256
hashing, optional max_role caps, optional expiry, and full audit
logging of create/revoke operations with client IPs.

- DB schema: user_api_tokens and token_audit_log tables
- Auth middleware: validates user tokens as fallback after admin keys
- API: 7 new endpoints (self-service + admin token management)
- UI: tokens.html (self-service) + admin.html token/audit sections
- Nav: Tokens link added to all pages (visible for operator+)
- Docs: API reference, security model, roles/access control updated
- Background cleanup: expired tokens + 90-day audit log retention

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-07 15:02:54 +11:00

7.4 KiB

API Reference

All API endpoints are under /api/. Authentication is via Authorization: Bearer <api-key> header, X-API-Key: <key> header, or OIDC session cookie.

Health

GET /api/health

No authentication required. Returns 200 OK when the server is running.

Sessions

POST /api/sessions

Create a new session. Requires poweruser role or higher.

SSH session (password):

{
  "session_type": "ssh",
  "hostname": "10.0.0.1",
  "port": 22,
  "username": "root",
  "password": "secret"
}

SSH session (ephemeral keypair):

{
  "session_type": "ssh",
  "hostname": "10.0.0.1",
  "username": "root",
  "generate_keypair": true
}

The response includes the public key in the banner_text field. The SSH connection is deferred until the user clicks "Continue" on the banner page.

SSH session (private key):

{
  "session_type": "ssh",
  "hostname": "10.0.0.1",
  "username": "root",
  "private_key": "-----BEGIN OPENSSH PRIVATE KEY-----\n..."
}

RDP session:

{
  "session_type": "rdp",
  "hostname": "10.0.0.1",
  "port": 3389,
  "username": "Administrator",
  "password": "secret",
  "ignore_cert": true,
  "domain": "EXAMPLE"
}

Web browser session:

{
  "session_type": "web",
  "url": "https://example.com"
}

Response:

{
  "session_id": "550e8400-e29b-41d4-a716-446655440000",
  "client_url": "/client.html?session_id=550e8400-e29b-41d4-a716-446655440000",
  "share_url": "/client.html?session_id=550e8400-e29b-41d4-a716-446655440000&key=abc123"
}

GET /api/sessions

List all sessions. Requires operator role or higher.

GET /api/sessions/:id

Get session details. Requires operator role or higher.

DELETE /api/sessions/:id

Terminate a session. Requires operator role or higher. Non-admins can only delete their own sessions.

GET /api/sessions/:id/banner

Get session banner text. Authenticates via share token (not credentials). Used for the ephemeral keypair banner display.

Recordings

GET /api/recordings

List all recording files. Requires operator role or higher.

GET /api/recordings/:name

Serve a recording file for playback. Requires operator role or higher. Filename is validated against path traversal.

DELETE /api/recordings/:name

Delete a recording file. Requires admin role.

Users (admin only)

GET /api/users

List all OIDC users.

PUT /api/users/:email/role

Set a user's role.

{
  "role": "poweruser"
}

Valid roles: admin, poweruser, operator, viewer.

DELETE /api/users/:email

Delete a user.

POST /api/users/:email/disable

Disable a user (blocks login).

POST /api/users/:email/enable

Re-enable a disabled user.

DELETE /api/users/:email/sessions

Force-logout a user by deleting all their auth sessions.

Group-to-Role Mappings (admin only)

GET /api/admin/group-mappings

List all group-to-role mappings.

POST /api/admin/group-mappings

Create a mapping.

{
  "oidc_group": "engineering",
  "role": "poweruser"
}

Returns 409 Conflict if a mapping for the group already exists.

PUT /api/admin/group-mappings/:id

Update a mapping.

{
  "oidc_group": "engineering",
  "role": "admin"
}

DELETE /api/admin/group-mappings/:id

Delete a mapping.

Address Book (requires Vault)

GET /api/addressbook/folders

List visible folders. Filtered by OIDC group membership (admins see all).

GET /api/addressbook/folders/:scope/:folder/entries

List entries in a folder. Scope is shared or instance. Requires folder group access.

POST /api/addressbook/folders/:scope/:folder/entries/:entry/connect

Create a session from an address book entry. Reads credentials from Vault server-side and creates a session. Requires operator role and folder group access.

POST /api/addressbook/folders (admin)

Create a folder.

{
  "scope": "shared",
  "name": "production",
  "allowed_groups": ["engineering", "devops"],
  "description": "Production servers"
}

PUT /api/addressbook/folders/:scope/:folder (admin)

Update folder configuration (allowed_groups, description).

DELETE /api/addressbook/folders/:scope/:folder (admin)

Delete a folder and all its entries.

POST /api/addressbook/folders/:scope/:folder/entries (admin)

Create a connection entry.

PUT /api/addressbook/folders/:scope/:folder/entries/:entry (admin)

Update a connection entry.

DELETE /api/addressbook/folders/:scope/:folder/entries/:entry (admin)

Delete a connection entry.

User API Tokens (self-service)

User API tokens allow OIDC users to authenticate via API key for automation and scripting. Tokens inherit the user's identity and are subject to role restrictions.

POST /api/me/tokens

Create a personal API token. Requires poweruser role or higher. Only available to OIDC-authenticated users (not API key admins).

{
  "name": "my-ci-token",
  "max_role": "operator",
  "expires_at": "2026-12-31T23:59:59Z"
}
  • name — required, 1-100 characters, must be unique per user
  • max_role — optional, caps the token's effective role (cannot exceed the user's current role)
  • expires_at — optional, ISO 8601 timestamp

Response:

{
  "id": 1,
  "name": "my-ci-token",
  "token": "rgu_a1b2c3d4e5f6...",
  "max_role": "operator",
  "expires_at": "2026-12-31T23:59:59Z"
}

The token field is the plaintext token — it is only returned once at creation and cannot be retrieved again.

GET /api/me/tokens

List your own tokens. Available to any OIDC user (operator+). Returns token metadata only (never the plaintext token).

DELETE /api/me/tokens/:id

Revoke one of your own tokens. Requires poweruser role or higher. The token is immediately invalidated.

User API Tokens (admin)

Admins can manage tokens for any user, including creating tokens for operators who cannot create their own.

POST /api/admin/user-tokens

Create a token for any OIDC user. Requires admin role.

{
  "email": "operator@example.com",
  "name": "operator-automation",
  "max_role": "operator",
  "expires_at": "2026-06-30T23:59:59Z"
}

Response is the same as POST /api/me/tokens.

GET /api/admin/user-tokens

List all user tokens across all users. Requires admin role.

DELETE /api/admin/user-tokens/:id

Revoke any user token. Requires admin role.

GET /api/admin/token-audit

View the token audit log. Requires admin role.

Query parameters:

  • limit — max entries to return (default: 200, max: 1000)
  • email — filter by user email

Returns an array of audit events with fields: created_at, user_email, token_name, action, ip_addr, details.

Authentication

GET /api/auth/status

No authentication required. Returns whether OIDC is enabled and the site title.

{
  "oidc_enabled": true,
  "site_title": "rustguac"
}

GET /api/me

Returns current user info. Requires authentication.

{
  "name": "User Name",
  "email": "user@example.com",
  "role": "operator",
  "groups": ["engineering"],
  "auth_type": "oidc",
  "vault_enabled": true,
  "vault_configured": true
}

GET /auth/login

Redirects to OIDC provider for authentication.

GET /auth/callback

OIDC callback endpoint. Handles token exchange, user creation/update, and session creation.

GET /auth/logout

Clears the session cookie and deletes the auth session.