RBAC Role Assignment

Audience: operators managing access control for the AutonomyOps CLI.

Background

AutonomyOps RBAC is file-backed (JSON store) and enforcement is ON by default. No environment variable is required to activate enforcement — it is active from the first command run on any new installation.

To disable enforcement (not recommended outside of migration or testing):

export AUTONOMY_RBAC_ENFORCEMENT=0   # or =false

When enforcement is active, each command checks the operator identity (from AUTONOMY_OPERATOR) against the RBAC store at AUTONOMY_RBAC_DIR. Denied actions emit an auth.access.denied audit event.

Bootstrap mode

When enforcement is ON but the RBAC store has no assignments (fresh install or deliberately empty store), the guard enters bootstrap mode:

  • rbac role assign is allowed so the first operator assignment can be created.

  • Every other guarded action is denied with instructions to run the bootstrap.

  • An auth.bootstrap.access audit event is emitted for every bootstrap-allowed action.

Bootstrap mode is transient. As soon as any assignment exists in the store, the guard switches to full enforcement for all subsequent calls.

Break-glass path

In genuine emergencies where RBAC assignments cannot be consulted, operators can activate break-glass mode:

export AUTONOMY_RBAC_BREAK_GLASS=1
export AUTONOMY_OPERATOR=<identity>  # required — break-glass without identity is still denied

Break-glass mode:

  • Allows all guarded actions regardless of assignments.

  • Emits an auth.break_glass.used audit event for every allowed action.

  • Requires both env vars to be set simultaneously.

  • Is auditable: every use appears in the audit trail.

Break-glass must not be used as a convenience shortcut. Every use is logged.


1. Predefined roles

Role

Type

Intended for

operator

predefined

Fleet operators: fleet grid, activation timeline, telemetry viewer

analyst

predefined

All operator views plus WAL inspection, bundle builder, release channel reads

auditor

predefined

All views, full audit history, cert inspection (cert:read), signature verification, and RBAC administration

integrator

predefined

Policy eval viewer, simulation sandbox, all operator views

These roles are available without a role create call. Custom roles can be created with role create.


2. Available permissions

The following 14 permissions are recognized:

Permission

Grants access to

fleet:read

HA status, quorum status, rollout plan list/describe

activation:read

Activation timeline events

telemetry:read

OTel event stream

lock:read

BLAKE3 fingerprint chain

release_channel:read

Release channel viewer (read-only)

wal:read

WAL buffer inspection

policy_eval:read

Policy evaluation results

audit_history:read

Full audit history (auditor only)

signature:verify

Re-run BLAKE3 verify on artifacts

bundle:build

Bundle builder UI (produces download only)

cert:read

Certificate list and check-revocation (read-only cert inspection; included in auditor)

cert:manage

Certificate issue, rotate, revoke, and CRL sync (mutation; requires a custom role)

rbac:manage

RBAC role creation and role assignment

simulation:run

Policy simulation sandbox


3. Bootstrap a new installation

On a fresh installation, the RBAC store is empty and the guard is in bootstrap mode. Run rbac role assign to seed the store with an RBAC manager:

export AUTONOMY_OPERATOR=first-op@example.com
export AUTONOMY_RBAC_DIR=/etc/autonomy/rbac

autonomy rbac role assign \
  --role auditor \
  --subject first-op@example.com \
  --reason "initial bootstrap access manager"

After this assignment, full enforcement applies and the same identity can assign a least-privilege day-to-day role such as operator to itself or others. Any attempt to run other commands before this step will fail with:

rbac: RBAC store has no assignments; run bootstrap first:
  autonomy rbac role assign --role operator --subject "<identity>"
To skip RBAC (not recommended): set AUTONOMY_RBAC_ENFORCEMENT=0
For emergency access: set AUTONOMY_RBAC_BREAK_GLASS=1 with AUTONOMY_OPERATOR set

4. Create a custom role

autonomy rbac role create \
  --name release-manager \
  --permissions "fleet:read,audit_history:read" \
  --description "Release review audit visibility" \
  [--rbac-dir /etc/autonomy/rbac]

Constraints:

  • Role names must not be: admin, superuser, root, or system (CONSTRAINT C-07).

  • Permissions must be from the recognized list above.


5. List roles

autonomy rbac role list [--output json] [--rbac-dir /etc/autonomy/rbac]

Example output (text):

NAME              TYPE        ASSIGNMENTS  PERMISSIONS
operator          predefined  3            fleet:read, activation:read, telemetry:read
analyst           predefined  1            fleet:read, activation:read, telemetry:read, ...
auditor           predefined  2            fleet:read, ..., audit_history:read, signature:verify, rbac:manage
integrator        predefined  1            fleet:read, ..., policy_eval:read, simulation:run
release-manager   custom      0            fleet:read, audit_history:read

6. Assign an operator to a role

autonomy rbac role assign \
  --role operator \
  --subject alice@example.com \
  --by ops-lead@example.com \
  --reason "day-to-day fleet visibility" \
  [--rbac-dir /etc/autonomy/rbac]

Audit event emitted: auth.role.assigned.

An operator can be assigned to multiple roles. The effective permission set is the union of all assigned roles’ permissions.

To delegate RBAC administration after bootstrap, assign the auditor role (which includes rbac:manage) to the operator responsible for access control:

autonomy rbac role assign \
  --role auditor \
  --subject security-admin@example.com \
  --by first-op@example.com \
  --reason "delegate RBAC administration"

7. Verify enforcement

With AUTONOMY_OPERATOR and AUTONOMY_RBAC_DIR set:

# Should succeed (fleet:read required; alice has operator role)
export AUTONOMY_OPERATOR=alice@example.com
autonomy ha status --orchestrator-url "$AUTONOMY_ORCHESTRATOR_URL"

# Should be denied (audit_history:read required; alice has operator role only)
autonomy audit query --audit-dir "$AUTONOMY_AUDIT_DIR"
# Error: rbac: operator "alice@example.com" is not authorized to perform "audit query"
#        (requires permission "audit_history:read")
# Audit event: auth.access.denied

No AUTONOMY_RBAC_ENFORCEMENT variable is needed — enforcement is on by default.



9. Break-glass emergency access

When RBAC assignments cannot be consulted (corrupted store, lost access during incident):

export AUTONOMY_RBAC_BREAK_GLASS=1
export AUTONOMY_OPERATOR=oncall@example.com

# All commands now pass the RBAC check, with mandatory audit events
autonomy ha status --orchestrator-url "$AUTONOMY_ORCHESTRATOR_URL"
# Audit event: auth.break_glass.used (emitted for EVERY command)

After the incident, verify the break-glass events were captured:

autonomy audit query \
  --audit-dir "$AUTONOMY_AUDIT_DIR" \
  --event-type auth.break_glass.used \
  --output json

Unset the break-glass variables when done:

unset AUTONOMY_RBAC_BREAK_GLASS
# Re-verify enforcement is restored:
autonomy ha status --orchestrator-url "$AUTONOMY_ORCHESTRATOR_URL"
# If alice does not have fleet:read, this should now be denied again.

Known gaps

  • No rbac role check command: Determining an operator’s effective permissions requires manual JSON filtering. A autonomy rbac role check --operator NAME command is a follow-on item.

  • No assignment revocation: Once a role is assigned, it cannot be unassigned via the CLI. Revocation requires manually editing the JSON store at AUTONOMY_RBAC_DIR.

  • No multi-tenancy: All operators and roles share the same JSON store. Namespace isolation between teams is not implemented.

  • RBAC store is not replicated: The RBAC JSON store at AUTONOMY_RBAC_DIR is local to each node. In a multi-node deployment, role assignments must be synchronized out of band (e.g. via configuration management or a shared filesystem).

  • Enforcement is session-scoped: AUTONOMY_RBAC_ENFORCEMENT=0 disables enforcement for the duration of the shell session only. There is no system-wide persistent toggle.