Skip to main content

Authentication & RBAC

OSAPI uses JWT bearer tokens for authentication and fine-grained resource:verb permissions for authorization. Every API endpoint (except health probes) requires a valid token.

How It Works

JWT Signing

OSAPI uses HMAC-SHA256 (HS256) symmetric signing. The same signing_key is used to both create and verify tokens:

osapi token generate ──[signs with signing_key]──> JWT
Client ──[sends JWT]──> API Server ──[verifies with signing_key]──> Allow/Deny

Only someone who knows the signing key can create valid tokens. If the signing key is compromised, rotate it immediately -- all previously issued tokens become invalid.

Token Structure

A token carries three pieces of authorization data:

  • Roles (roles claim, required) -- one or more of admin, write, read
  • Permissions (permissions claim, optional) -- direct resource:verb grants that override role expansion
  • Subject (sub claim) -- user identity for audit logging

Generate tokens with the CLI. See CLI Reference for usage and examples, or the API Reference for the REST endpoints.

Permission Resolution

When a request arrives, the middleware resolves the caller's effective permissions:

Roles and Permissions

Built-in roles expand to these default permissions:

RolePermissions
adminagent:read, agent:write, node:read, node:write, network:read, network:write, job:read, job:write, health:read, audit:read, command:execute, file:read, file:write, docker:read, docker:write, docker:execute, cron:read, cron:write, sysctl:read, sysctl:write, ntp:read, ntp:write, timezone:read, timezone:write, power:execute, process:read, process:execute, user:read, user:write, package:read, package:write, log:read, certificate:read, certificate:write, service:read, service:write
writeagent:read, node:read, node:write, network:read, network:write, job:read, job:write, health:read, file:read, file:write, docker:read, docker:write, cron:read, cron:write, sysctl:read, sysctl:write, ntp:read, ntp:write, timezone:read, timezone:write, process:read, user:read, user:write, package:read, package:write, log:read, certificate:read, certificate:write, service:read, service:write
readagent:read, node:read, network:read, job:read, health:read, file:read, docker:read, cron:read, sysctl:read, ntp:read, timezone:read, process:read, user:read, package:read, log:read, certificate:read, service:read

Custom Roles

Define custom roles in the configuration to create new role names or override default permission mappings:

controller:
api:
security:
roles:
ops:
permissions:
- node:read
- health:read
netadmin:
permissions:
- network:read
- network:write
- health:read

Configuration

controller:
api:
security:
# HS256 signing key (REQUIRED)
# Generate with: openssl rand -hex 32
signing_key: '<64-char hex string>'

client:
security:
# JWT for client requests (REQUIRED)
# Generate with: osapi token generate
bearer_token: '<jwt>'

See Configuration for the full reference including custom roles and CORS settings.

Agent-Level Authentication (PKI)

JWT-based auth secures the REST API between clients and the controller. For agent-level trust -- ensuring that only approved agents process jobs and that jobs originate from a trusted controller -- OSAPI provides an optional PKI enrollment system.

When PKI is enabled, each agent generates an Ed25519 key pair and submits an enrollment request. An administrator accepts or rejects the request, establishing cryptographic trust. The controller signs jobs with its private key, and agents verify the signature before processing.

PKI is complementary to JWT auth: JWTs authenticate API callers, while PKI authenticates the agent-controller relationship over NATS. See Agent Identity & PKI for full details.