Fleet Roles and Permissions
Fleet gives each operator a named role. Each role holds a fixed set of permissions. Give each operator the lowest role that fits the job. Do not share one token between operators.
This page covers Fleet roles only. It does not cover roles for ssg CLI operators or the local daemon dashboard token. Those are outside Fleet.
Source of truth
The table on this page comes from the BUILTIN_PERMISSIONS map in the Fleet source file sigmashake-fleet/src/lib/permissions.ts. The Permission type is in sigmashake-fleet/src/types.ts. If this page and the code disagree, the code is correct.
Built-in roles
Fleet has four built-in roles. They are listed here from the lowest rank to the highest rank.
| Role | Rank | Purpose | Permissions held |
|---|---|---|---|
member | 1 | Read-only access to the organization | 7 |
auditor | 2 | Read access plus audit, compliance, and SIEM read access | 12 |
policy_author | 3 | Read access plus policy write access | 9 |
org_admin | 4 | Full control of the organization | 26 |
org_adminholds every permission.- The sets do not form one chain.
auditorholdsaudit:verify,audit:export,compliance:read, andsiem:read.policy_authorholds none of them. policy_authorranks aboveauditor. A route that checks only the rank letspolicy_authorpass anauditorcheck. A route that checks a permission string still needs the matching string.
Permission matrix
A permission has the form resource:action. A check is exact. Fleet does not use wildcards.
yes means the role holds the permission. no means it does not.
The last column shows whether a Fleet route checks the permission string. Other Fleet routes check the role rank only. For those routes, the permission string does not change the result.
| Permission | member | auditor | policy_author | org_admin | Checked by permission |
|---|---|---|---|---|---|
org:read | yes | yes | yes | yes | yes |
org:write | no | no | no | yes | yes |
team:read | yes | yes | yes | yes | no |
team:write | no | no | no | yes | no |
policy:read | yes | yes | yes | yes | no |
policy:write | no | no | yes | yes | no |
policy:approve | no | no | no | yes | no |
audit:read | no | yes | yes | yes | yes |
audit:verify | no | yes | no | yes | yes |
audit:export | no | yes | no | yes | yes |
agent:read | yes | yes | yes | yes | no |
agent:write | no | no | no | yes | no |
agent:revoke | no | no | no | yes | no |
member:read | yes | yes | yes | yes | no |
member:write | no | no | no | yes | no |
sa:read | no | no | no | yes | no |
sa:write | no | no | no | yes | no |
alert:read | no | no | no | yes | no |
alert:write | no | no | no | yes | no |
compliance:read | no | yes | no | yes | no |
compliance:generate | no | no | no | yes | no |
dashboard:read | yes | yes | yes | yes | no |
role:read | yes | yes | yes | yes | yes |
role:write | no | no | no | yes | yes |
siem:read | no | yes | no | yes | yes |
siem:admin | no | no | no | yes | yes |
Nine permissions are checked by permission string today: org:read, org:write, audit:read, audit:verify, audit:export, role:read, role:write, siem:read, and siem:admin. The audit, role, organization database, and SIEM routes use these checks. The SIEM routes need siem:read to view destinations and siem:admin to change them.
How Fleet resolves permissions
- Fleet reads the role of the user in the organization from the membership record.
- If the user has no membership, the permission set is empty.
- If the user holds a custom role, the permission set is the permission list of that custom role. A custom role that no longer exists gives an empty set.
- If the role is a built-in role, the permission set is the fixed set in the matrix above.
- If the role is not found, the permission set is empty.
A request without a required permission gets a 403 response. A request without a user identity gets a 401 response.
Custom roles
A user who holds role:write can define a custom role. Among the built-in roles, only org_admin holds role:write. A custom role has a name, a slug, and a list of permission strings.
- The slug uses 2 to 32 characters. Allowed characters are lowercase letters, digits, underscore, and hyphen.
- Each permission string must be a valid
Permissionvalue. - A slug that equals a built-in role slug is rejected with a 409 response.
- A caller cannot grant a permission that the caller does not hold. Fleet rejects the request with a 403 response and lists the permissions that the caller lacks.
- The rank of a custom role comes only from its permissions. Fleet finds the highest built-in role whose full permission set the custom role holds. If the custom role does not hold the full set of even the
memberrole, it has no built-in rank. - The free-form
rankfield of a custom role is never used for access. - A custom role is stored next to the base role
member.
Known limits
- Seventeen of the 26 permission strings are not checked by any route today. A custom role that holds one of them gains no extra access from it.
- A permission check and a rank check can disagree on one route. A user must pass both checks on that route.
- This page does not describe roles outside Fleet.