Access control

Namespaces, ownership, the seeded RBAC roles, and Grants: who can see, change, SSH into, and read your resources.

Ringleader’s access model has three layers: namespaces (the tenancy boundary), ownership (you control what you create), and Grants (explicit, per-object sharing). RBAC roles decide what verbs you hold in a namespace; ownership narrows the write verbs to your own objects; Grants selectively widen access to specific peers.

Above the namespace sits the organization — the company a namespace belongs to. It is what makes “admin of every namespace in Acme” expressible as a single grant.

Namespaces & onboarding

A namespace is the unit of tenancy: a team or business unit. Every resource lives in one, and cross-references stay within it. Every namespace rolls up to exactly one organization.

The control plane does not create a namespace eagerly. On your first login it decides where you land, once, by this precedence:

  1. A pre-assignment by an operator: a shared namespace, into which you are bound as namespace-member.
  2. A verified, auto-join company domain: if your email domain is verified for an organization that allows auto-join, you land in that organization’s shared namespace as a namespace-member — no operator involvement. See Organizations.
  3. Otherwise, a personal namespace derived from your email with a short random suffix (e.g. alice-acme-com-k3f9x2), into which you are bound as namespace-admin: full control of everything in it. You are also made the org-admin of the personal organization it rolls up to, so a solo signup can administer their own tenancy — register a trust anchor, author a service account — with no operator acting first. This applies to the personal branch only: someone auto-joined into a company’s org under case 2 is an ordinary member of it.

In a shared namespace (cases 1 and 2) you fully control your own resources and can read your teammates’, but cannot modify or delete theirs.

When you omit -n, the CLI targets the namespace you pinned with rl namespace use, else your origin’s spec.defaultNamespace, else the reserved local.

Ownership: personal resources

Workstation, Secret, and WorkstationConfig are owner-scoped personal kinds: like a Unix file, you own what you create. On every write the control plane stamps the owner from your verified identity (a client can’t forge it). The consequence for a namespace-member:

  • You may create, update, and delete your own workstations, secrets, and configs.
  • Peers may get/list them (reads are open within the namespace) but cannot update or delete them.
  • A WorkstationConfig is the one exception on the read side: it has no per-object access gate, so an admin-authored shared config is referenceable by any member’s workstation while members still own the configs they author.

A namespace-admin (personal namespaces, and admins of shared ones) is not owner-restricted: they manage every object in the namespace, whoever created it.

The built-in roles

The built-in roles define what a subject may do. They are predefined by Ringleader (not something you author), so their meaning is consistent everywhere, and they form a ladder: each rung contains the one below it.

RoleWho gets itWhat it grants
namespace-memberYou, in a shared namespaceget/list/watch on everything in the namespace; owner-scoped create/update/delete on workstations, secrets, workstationconfigs, grants; plus create/update/delete on your device-local localbindings and sshkeys.
namespace-adminYou, in your personal namespace; admins of a shared oneEverything a member has, plus create/update/delete across the namespace’s kinds — workstations, configs, secrets, grants, ssh keys, bindings, cloud identities, and the namespace’s own roles and role bindings — for any owner, not just your own. It is a curated set, not a blanket wildcard.
org-adminAn organization’s administratorsEverything a namespace-admin has, in their organization’s namespaces, plus the organization’s own structure: its namespaces, its org-scoped roles, and its CloudAccounts. Confined to their own organization.
node-ownerEvery authenticated userOwner-scoped management of your own device records (nodeinfos).
public-infoEvery authenticated userget/list/watch on namespaces, organizations and their domains, and role definitions and org role bindings — so you can see who administers your org. The user roster is deliberately not included.
global-adminRingleader operators (break-glass)Full access to everything, everywhere — the only role that holds the wildcard.

Two limits hold for every rung below global-admin:

  • No role grants access on a secret it does not own. An administrator owns a Secret’s object lifecycle — they can delete it — but reading a plaintext they do not own still requires ownership or an explicit Grant.
  • No role can escalate itself. You cannot bind a subject (including yourself) to permissions you do not already hold.

How a role reaches you

A role is just a rule set. What decides where it applies is the binding that carries it:

BindingReaches
RoleBinding (namespaced)One namespace.
OrgRoleBinding (cluster-scoped, carries spec.org)Every namespace of one organization, including ones created later — plus that org’s own structure (its namespaces, org roles, cloud accounts, and user roster).
GlobalRoleBinding (cluster-scoped)Everywhere. Operators only.

A binding may reference a built-in GlobalRole, a namespaced Role, or an org-scoped OrgRole. An OrgRoleBinding’s reach over cluster-scoped objects is confined to the org’s own — it can never grant a verb on another org’s objects, or on global roles.

Inspect what you actually hold at each origin with:

rl auth status --show-access

The access verb & secrets

Reading a Secret’s values (not just its redacted projection) is gated by a distinct access verb: the same verb that admits objects which consume the secret (a ${secret:NAME} reference, a git source’s credentialRef, a Tailscale authKeyRef). You hold access on your own secrets automatically; a Grant with rights: [access] extends it to a peer.

rl secret get db --reveal    # requires the access right

Grants: explicit per-object sharing

A Grant is a namespaced kind that opens a single owned object to specific subjects. It is the only way a peer gains:

  • SSH access to a workstation you own (rights: [ssh]), or
  • value access to a secret you own (rights: [access]).

There is no namespace-wide SSH fan-out: SSH to a workstation is ownership (automatic) + Grants (explicit), nothing else.

Create and revoke Grants with the share/unshare commands rather than hand-writing them:

rl workstation share my-box --with user:alice@acme.com
rl workstation unshare my-box --with user:alice@acme.com

Grant spec

apiVersion: core.ringleader.dev/v1
kind: Grant
metadata:
  name: my-box-to-alice
  namespace: dev
spec:
  target:
    kind: Workstation       # Workstation | Secret
    matchName: my-box       # exact name, or "*" for every object of the kind
  subjects:
    - user:alice@acme.com   # beneficiaries
  rights:
    - ssh                   # ssh (Workstation) | access (Secret)
FieldTypeDescription
target.kindstringRequired. Workstation or Secret.
target.matchNamestringExact object name, or * for every object of the kind. (Exactly one of matchName/matchLabels.)
target.matchLabelsmapSelect potentially many targets by label.
subjects[]stringBeneficiaries (user:…, sa:…, workload:…, node:…; system:authenticated is admin-only).
rights[]stringssh for a Workstation, access for a Secret.

Owner scope vs. admin scope

Every Grant carries a scope, set by the control plane from the rights you actually held when you created it, never trusted from the client:

  • owner: created by share/unshare. It lights up a target only while you still own it, so a Grant can never hand out more than you could yourself.
  • admin: created by admin grant. It can reach any object in the namespace, and requires namespace-admin rights.

This “a Grant never grants more than its creator could grant directly” rule is re-checked continuously, so a Grant automatically stops applying if you lose ownership of its target.

See also