Skip to content

Authorization#

Perses uses a Role-based access control (RBAC) system to regulate access to resources based on user roles.
The RBAC API includes four kinds of resources: GlobalRole, Role, GlobalRoleBinding, and RoleBinding.
The RBAC implementation in Perses is heavily inspired by Kubernetes' RBAC model.

Role and GlobalRole#

An RBAC Role or GlobalRole defines a set of permissions (rules). Permissions are purely additive, meaning there are no "deny" permissions.

  • A Role specifies permissions within a specific project. The project must be defined when the Role is created.
  • A GlobalRole applies to resources globally and is not limited to a project scope.

Role Example#

This example defines a Role in the "MySuperProject" project that grants edit access to dashboards:

kind: Role
metadata:
  name: dashboard-editor
  project: MySuperProject
spec:
  permissions:
    - actions: ["edit"]
      scopes: ["Dashboard"]

Global Role example#

A GlobalRole can grant access to both global resources (e.g., global datasources, global variables, users) and project-specific resources (like dashboards) across all projects.

Here is an example of a GlobalRole that grants edit access to variables across all projects:

kind: GlobalRole
metadata:
  name: variable-editor
spec:
  permissions:
    - actions: ["edit"]
      scopes: ["Variable"]

RoleBinding and GlobalRoleBinding#

A role binding grants the permissions defined in a role to a user or set of users. It holds a list of subjects (users or teams) and a reference to the role being granted. A RoleBinding grants permissions within a specific project whereas a GlobalRoleBinding grants that access global-wide.

A RoleBinding may reference any Role in the same project. Similarly, a GlobalRoleBinding can reference any GlobalRole.

RoleBinding example#

Here is an example of a RoleBinding that grants the "dashboard-editor" Role to the user "jane" within the "MySuperProject" project. This allows "jane" to edit dashboards in the "MySuperProject" project.

kind: RoleBinding
metadata:
  name: edit-dashboards
  project: MySuperProject
spec:
  role: dashboard-editor
  subjects:
    - kind: User
      name: jane

GlobalRoleBinding example#

Here is an example of a GlobalRoleBinding that grants the "variable-editor" GlobalRole to the user "jane" within all projects. This allows "jane" to edit variables in all projects.

kind: GlobalRoleBinding
metadata:
  name: edit-variables
spec:
  role: variable-editor
  subjects:
    - kind: User
      name: jane

RoleBinding and GlobalRoleBinding update restriction#

After you create a binding, you cannot change the Role or GlobalRole that it refers to. If you try to change a binding's role, you get a validation error. If you do want to change the role for a binding, you need to remove the binding object and create a replacement.

There are two reasons for this restriction:

  • Making role immutable allows granting someone update permission on an existing binding object, so that they can manage the list of subjects, without being able to change the role that is granted to those subjects.
  • A binding to a different role is a fundamentally different binding. Requiring a binding to be deleted/recreated in order to change the role reference ensures the full list of subjects in the binding is intended to be granted the new role (as opposed to enabling or accidentally modifying only the role reference without verifying all of the existing subjects should be given the new role's permissions).

Referring to resources#

In Perses API, resources are identified and accessed using a string, corresponding to the name in the metadata. You can also refer to all resources using the wildcard * character. Here is an example for granting edit permissions to all resources in all projects:

kind: GlobalRole
metadata:
  name: admin-editor
spec:
  permissions:
    - actions: ["edit"]
      scopes: ["*"]

RBAC Synchro#

Roles and RoleBindings of an user are stored in the user's JWT. If Perses is deployed with multiple instances, Perses RBAC roles and role bindings cache need to be synchronized/replicated between all instances. To do that there are multiple mechanisms:

  • cache is refreshed every X minutes
  • cache is refreshed if roles and role bindings retrieve from the user's JWT are different from the cache
  • cache is refreshed when a new role is created, edited or deleted
  • cache is refreshed when a new rolebinding is created, edited or deleted