RBAC policies in Workload Credentials
Access control in Pathfinder
Role-based access control (RBAC) is a new Pathfinder platform capability. Every product built on Pathfinder shares one policy language, one policy API, one set of principals, and one policy lifecycle. What each product contributes is its own resource types, roles, and actions.
This guide covers the platform model first, then Workload Credentials (WLC), a product that uses it. Cedar identifiers make the boundary explicit: Pathfinder:: names platform concepts, WorkloadCredentials:: names the product's.
Pathfinder RBAC
Overview
Access is denied by default: a principal can perform only the actions it has been explicitly granted, on the resources those grants name.
There are two ways to grant access:
-
Assign a built-in role in the Role and Group Management view of the Administration console. A built-in role is assigned to a group, and every member of that group inherits it. This is the broad option: a single assignment grants a whole level of access across the product.
-
Write a policy through the policy API. A policy grants a principal, down to an individual user, a specific set of actions on a specific resource. This is the fine-grained option, for access too narrow for a built-in role to express.
Policies are declarative and idempotent, so applying the same one twice produces the same grant.
Principals
A principal is the identity a policy grants to. All principals are platform identities in the Pathfinder:: namespace.
| Principal | Cedar form |
|---|---|
| User | Pathfinder::User::Email::"[email protected]" |
| Workload (machine or service identity) | Pathfinder::Workload::Id::"<workload-uuid>" |
| Group | Pathfinder::Group::"devops-team" |
| Role | Pathfinder::Role::"secrets-admin" |
Policies and how they take effect
A policy is a Cedar document naming one principal, one or more actions, and one resource.
A policy takes effect in two phases:
1. WRITE (immediate)
The policy is submitted.
the engine authorizes the caller, validates the document, stores it
returns 202 Accepted (stored, but granting nothing yet)
2. BIND (moments later, automatic)
A background pipeline resolves the resource path to a concrete
resource, compiles the grant, and writes it into the authorization
graph. The grant is now live.
Two timing rules follow from this:
- A policy may name a resource that does not exist yet; it binds automatically once that resource is created.
- A policy for a principal with no access to the product is rejected on submit, so the principal must be enabled for the product first.
The policy API
Policies are managed at https://api.beyondtrust.io/platform/iam. Every request requires a bearer token.
| Method | Path | Purpose |
|---|---|---|
PUT | /policies/{name} | Create or replace a policy |
GET | /policies/{name} | Read a policy and its status |
GET | /policies | List policies |
DELETE | /policies/{name} | Revoke a policy |
A policy is identified by {name}. PUT is create-or-replace: submitting an existing name updates it in place.
The request body is raw Cedar text with Content-Type: text/plain, and it begins with a @siteId("<site-uuid>") annotation naming the site the policy applies to.
Here is an example written to a file named alice-admin.cedar:
@siteId("11111111-1111-1111-1111-111111111111")
permit(
principal == Pathfinder::User::Email::"[email protected]",
action == Pathfinder::Action::"Admin",
resource is WorkloadCredentials::Product
);
Then submit it with PUT:
curl -sS -X PUT https://api.beyondtrust.io/platform/iam/policies/alice-admin \
-H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: text/plain' \
--data-binary @alice-admin.cedarA successful submit returns 202 Accepted. GET /policies/{name} reports status, which reaches ACTIVE once bound, or WAITING_FOR_RESOURCE while the named resource does not yet exist. DELETE /policies/{name} revokes it.
A policy document must satisfy the following:
-
Exactly one
permitstatement.forbidand conditional clauses (when/unless) are not supported. -
principal ==a single principal from Section 2. -
action ==a single action, oraction in [ ... ]for several. -
resource ==a path-addressed resource, orresource is <Product>for a product-wide grant. -
Fully qualified names, with PascalCase action ids.
Product roles
Every Pathfinder product exposes a standard set of roles at the product scope, granted through the Pathfinder::Action namespace with the product as the resource.
| Role | Action id | Grants |
|---|---|---|
| Admin | Pathfinder::Action::"Admin" | Full control of the product in the site |
| Standard User | Pathfinder::Action::"StandardUser" | Sign in and open the home page; the home listing is empty until access is granted |
| Auditor | Pathfinder::Action::"Auditor" | Read and list across the product, and its audit views |
| Viewer | Pathfinder::Action::"Viewer" | Product-wide read |
A user enabled for a product automatically receives a baseline, typically Standard User. Any access beyond that baseline is granted explicitly, either by assigning a built-in role or by writing a policy such as this one for product administration:
@siteId("11111111-1111-1111-1111-111111111111")
permit(
principal == Pathfinder::User::Email::"[email protected]",
action == Pathfinder::Action::"Admin",
resource is WorkloadCredentials::Product
);
Grants come at two granularities. A role bundles a whole level of access, whether one of the product roles here or a resource role a product defines, while a fine-grained action grants a single capability.
Identities, groups, and roles
Identities, groups, and role assignments are managed in the Role and Group Management view of the Administration console, separately from the policy API.
The model is simple: a role holds permissions, a role is assigned to a group, and a group contains users, so a user receives a role's access through the groups they belong to.
User groups
A group links users to roles. You create a group, add users as members, and assign it one or more roles, and every member then holds those roles.

The User Management page with the User Groups tab selected.

The User Group Details page for a group.
Role Management
Each product publishes built-in roles, scoped to the product in a site. For example, for Workload Credentials these are Product Admin, Product Standard User, Product Auditor, and Product Viewer, the product roles. Assign a built-in role to a group to grant it to that group's members.

The User Management page with the Roles Management tab selected.
A policy can also name a group or a role as its principal, so the fine-grained path builds on these same groups and roles. A principal must have some product access before a policy can apply to it, which a built-in role provides through a group; until then, a policy naming it is rejected.
Workload Credentials
Workload Credentials (WLC) is a product built on Pathfinder RBAC. It uses the policy language, API, principals, lifecycle, and product roles from Part 1. This part documents the resource types, roles, and actions WLC adds.
Resources
WLC resources are addressed by path. Folders, secrets, and dynamic secrets form a hierarchy: a folder contains subfolders, secrets, and dynamic secrets, and a grant on a folder is inherited by everything beneath it. Integrations sit outside this tree, attaching directly to the product. Because the product is the root, a product-scoped grant covers every resource in it.
| Resource | Cedar form |
|---|---|
| Product (the WLC instance in a site) | WorkloadCredentials::Product (referenced with resource is, no id) |
| Folder | WorkloadCredentials::Folder::"/prod" |
| Secret | WorkloadCredentials::Secret::"/prod/db-password" |
| Dynamic secret | WorkloadCredentials::DynamicSecret::"/prod/db-dynamic" |
| Integration | WorkloadCredentials::Integration::"/aws/prod" |
Roles
WLC defines three roles that apply to its resources, in addition to the product roles in Section 5. Owner on a folder cascades to everything beneath it, and Admin on the product cascades to the entire product.
| Role | Action id | Grants | Assignable on |
|---|---|---|---|
| Owner | Owner | Read, browse, create, update, delete, restore, tags, and all of the above on nested resources | Folder, Secret, Dynamic secret, Integration |
| Viewer | Viewer | Read values and metadata, browse and list contents; no writes | Folder, Secret, Dynamic secret, Integration |
| Lister | Lister | Browse and list names; no reading of values | Folder, Dynamic secret, Integration, Product |
Action reference
Each action grants a single capability and is checked on the object in the "Checked on" column. Create actions are checked on the parent folder, not on the item being created.
Static secrets
| To do this | Action ID | Checked on |
|---|---|---|
| Read a secret's value | ReadSecret | The secret |
| Read a secret's metadata | ReadSecretMetadata | The secret |
| Create a secret | CreateSecret | The parent folder |
| Update a secret | UpdateSecret | The secret |
| Delete a secret | DeleteSecret | The secret |
| Permanently destroy a secret | DestroySecret | The secret |
| Restore a secret | RestoreSecret | The secret |
| Add tags | WriteSecretTags | The secret |
| Remove tags | DeleteSecretTags | The secret |
Folders
| To do this | Action ID | Checked on |
|---|---|---|
| Browse a folder's contents | ListFolderContents | The folder, or the product at the root |
| Read a folder's metadata | ReadFolderMetadata | The folder |
| Create a subfolder | CreateFolder | The parent folder |
| Delete a folder | DeleteFolder | The folder |
| Destroy a folder | DestroyFolder | The folder |
| Recursively destroy a folder | ForceDestroyFolder | The folder |
| Restore a folder | RestoreFolder | The folder |
| Add tags | WriteFolderTags | The folder |
| Remove tags | DeleteFolderTags | The folder |
Integrations
| To do this | Action ID | Checked on |
|---|---|---|
| List integrations | ListIntegrations | The product |
| Create an integration | CreateIntegration | The product |
| Read an integration | ReadIntegration | The integration |
| Read an integration's metadata | ReadIntegrationMetadata | The integration |
| Update an integration | UpdateIntegration | The integration |
| Delete an integration | DeleteIntegration | The integration |
| Add tags | WriteIntegrationTags | The integration |
| Remove tags | DeleteIntegrationTags | The integration |
| List dynamic secrets under an integration | ListDynamicSecrets | The integration |
Dynamic secrets and leases
| To do this | Action ID | Checked on |
|---|---|---|
| Read a dynamic secret's definition | ReadDynamicSecret | The dynamic secret |
| Read a dynamic secret's metadata | ReadDynamicSecretMetadata | The dynamic secret |
| Create a dynamic secret | CreateDynamicSecret | The parent folder |
| Update a dynamic secret | UpdateDynamicSecret | The dynamic secret |
| Delete a dynamic secret | DeleteDynamicSecret | The dynamic secret |
| Destroy a dynamic secret | DestroyDynamicSecret | The dynamic secret |
| Restore a dynamic secret | RestoreDynamicSecret | The dynamic secret |
| Generate a credential | GenerateDynamicCredential | The dynamic secret |
| List leases | ListLeases | The dynamic secret |
| Read a lease | ReadLease | The dynamic secret |
| Revoke a lease | RevokeLease | The dynamic secret |
| Add tags | WriteDynamicSecretTags | The dynamic secret |
| Remove tags | DeleteDynamicSecretTags | The dynamic secret |
Permission dependencies
- Listing and reading are separate permissions. Seeing items in a folder requires browse (
ListFolderContents) on the container, and each item is then filtered by whether the principal has any access to it. A principal granted onlyReadSecreton one secret can read that secret by its path, but the secret does not appear when browsing its folder unless the principal also has browse on the folder. An empty listing means no reachable items, not an empty folder. To grant read plus browse of a whole branch, useVieweron the folder; to grant browsing without reading values, useLister. - Create is checked on the parent.
CreateSecret,CreateFolder, andCreateDynamicSecretare checked on the parent folder, or on the product at the root, andCreateIntegrationis checked on the product. - Write access does not grant discoverability. A principal can hold a write grant on an item that does not appear in listings; the item stays reachable by path.
- Generating a credential is a product-level capability.
GenerateDynamicCredentialis held by every product Standard User and Admin, and it can also be granted directly on a single dynamic secret. A resourceOwnergrant, such as owner of the containing folder, does not include it: generating credentials requires the Standard User or Admin product role, or a directGenerateDynamicCredentialgrant. - Inspecting and revoking leases is separate from generating. Reading and revoking individual leases (
ReadLease,RevokeLease) belong toOwner, so a principal can generate credentials without being able to inspect or revoke existing ones.
Grants cascade down only. A grant on/prodapplies to/prod/db-passwordand every subfolder, while a grant on/prod/db-passwordapplies to nothing above or beside it.
Recipes
Full control of a folder branch:
@siteId("<site-uuid>")
permit(
principal == Pathfinder::Group::"payments-team",
action == WorkloadCredentials::Action::"Owner",
resource == WorkloadCredentials::Folder::"/payments"
);
Read-only, browsable access to a branch:
@siteId("<site-uuid>")
permit(
principal == Pathfinder::Group::"payments-readers",
action == WorkloadCredentials::Action::"Viewer",
resource == WorkloadCredentials::Folder::"/payments"
);
A workload that can generate credentials for one dynamic secret and nothing else:
@siteId("<site-uuid>")
permit(
principal == Pathfinder::Workload::Id::"<workload-uuid>",
action == WorkloadCredentials::Action::"GenerateDynamicCredential",
resource == WorkloadCredentials::DynamicSecret::"/prod/db-dynamic"
);
WLC administrator for the whole site:
@siteId("<site-uuid>")
permit(
principal == Pathfinder::User::Email::"[email protected]",
action == Pathfinder::Action::"Admin",
resource is WorkloadCredentials::Product
);
Troubleshooting
| Symptom | Cause | Resolution |
|---|---|---|
403 on a list call | The principal lacks browse on the container | Grant Viewer, Lister, or Owner on the folder, or confirm the product baseline |
| A listing omits items known to exist | Items are filtered to what the principal can reach | Expected; grant access to the items or the container |
| A policy was submitted but access did not change | The named resource does not exist yet | Check GET /policies/{name}; the grant binds when the resource is created |
| A policy is rejected on submit | The principal has no access to the WLC product | Enable the principal for the product, then resubmit |
Updated about 16 hours ago