7.7. Role-Based Access Control (RBAC) Model #
7.7.1. Key Concepts #
Access control in PPEM is implemented via the RBAC (Role-Based Access Control) model, which defines access restriction rules through roles and privileges. The model establishes the following basic conventions:
Object is a resource to which access should be granted or restricted.
Subject is a person (user) or an automated agent.
Privilege is a permission granting access to perform an operation with the object.
Role is a job function or title defined at the authorization level.
The basic conventions define the following extended conventions:
Access rule is a combination of a role, privileges, and their relationships.
Session is an association between a subject and a role.
One subject can have several roles.
One role can belong to several subjects.
One role can have several privileges.
One privilege can belong to several roles.
Note
Privileges are not assigned to subjects directly but are acquired by subjects through roles.
7.7.2. RBAC in PPEM #
Fundamental principles:
PPEM functionality is composed of plugins.
Each plugin helps to manage a specific resource.
Resources can be managed by basic CRUD operations: create, view, edit, and delete.
Additionally, resource management may include various RPC operations. Their names depend on the resource management operation.
Privileges allow subjects to perform certain operations. All resources are managed through privileges (basic minimum requirements):
RESOURCE\_createRESOURCE\_viewRESOURCE\_editRESOURCE\_delete
Privileges are included in roles.
Roles can be assigned to a subject both at the time of subject creation and later.
When the plugin receives a request from a subject to perform an operation, it checks the subject’s permission to access the requested operation.
Subjects (users) can create their own roles (if they have privileges) and assign these roles to other subjects.
Privileges and roles may be object-specific. This means that you can specify a role and privilege that allows access to a limited set of objects.
Binding to an object can be done at the role level (all subjects with this role have access to the object) or at the user level (only one user has access to the object).
7.7.2.1. Subjects #
The following may act as subjects:
Users. Roles are assigned to users at creation time. If roles are not explicitly specified, a default role may be assigned.
Agents. This role is assigned when creating or registering agents.
7.7.2.2. Objects #
Objects can be either resources or their representations in the repository, such as servers, agents, instances, users, and user groups.
7.7.2.3. Setting Privileges and Roles #
On the first PPEM startup, the repository initialization is performed, during which system tables are populated (privileges and roles).
During initialization, each plugin is assigned its own set of privileges, roles, and “role-privilege” associations. For example, the accounts plugin has dedicated privileges and roles for managing access to its objects. Other plugins receive their own sets of privileges and roles to control access to their respective objects.
If users are granted necessary privileges, they can create custom roles, specify privilege sets, link roles to objects, and assign custom roles to subjects.
7.7.3. Implementation #
Access privileges are implemented by the following set of tables, which are owned by the accounts plugin:
privileges: Privileges with object classes they regulate access to.roles: Roles with target object classes.role_privileges: The “role-privilege” association defines relationships between roles and privileges included in them.users: Users of the system (subjects).user_roles: The “user-role” association that defines relationships between users and roles assigned to them.user_privileges: The view that displays the “user-privilege” associations.groups: The groups of the system.group_roles: The “group-role” association defines relationships between groups and roles assigned to them.group_users: The “group-user” association defines relationships between groups and users included in them.
7.7.3.1. The privileges Table #
The table has the following fields:
id: The unique privilege ID.name: The unique privilege name.title: The privilege description.class: The class of objects to which the privilege grants access.source: The name of the plugin that sets the privilege and then performs the access check.
The table is populated by the manager using migrations. Each plugin determines its own set of privileges.
An HTTP middleware handler is used to check privileges. Creation, modification, and deletion of privileges by the user is not supported, since the privilege check is implemented in the manager code.
7.7.3.2. The roles Table #
The table has the following fields:
id: The unique role ID.name: The unique role name.title: The role description.class: The class of objects to which the privilege grants access. The field value is used as a UI hint to get privileges of the corresponding class and the list of objects of this class.source: The name of the plugin that sets the role. For custom roles, theuservalue is set.
Roles are created by the manager using migrations. The basic role set is established for the accounts plugin.
With the manager API, users can create, modify, and delete custom roles, but they cannot modify or delete roles set by the manager (system roles).
7.7.3.3. The role_privileges Table #
The table defines associations between roles and privileges and has the following fields:
id: The unique association ID.role: The role ID.privilege: The privilege ID.parametric: Specifies whether object binding is used.object: The unique ID of an arbitrary class object.
The object class is determined by the privileges.class field value. The object ID declared here restricts the privilege specified in role_privileges.privilege to a single object and allows access to the object only by members of a single role specified in role_privileges.role (access is granted to users in user_roles.user who have user_roles.role = role_privileges.role).
The combination of role, privilege, and object is a unique key with the object IS NOT NULL condition.
Note
A parameterized object-specific “role-privilege” association determines access only to a single object (when specifying object). If access is required for N objects, N entries in the role_privileges table are created.
7.7.3.4. The users Table #
The table has no RBAC-related fields. When creating a user via the manager API, you can specify a list of role IDs that will be assigned to the user.
7.7.3.5. The user_roles Table #
The table defines associations between users and roles and has the following fields:
id: The unique association ID.user: The user ID.role: The role ID.object: The unique ID of an arbitrary class object.
The object class is determined by the privileges.class field value. The object ID declared here restricts the privilege specified in role_privileges.privilege to a single object and allows access to the object by the user specified in user_roles.user.
Note
A parameterized object-specific “role-privilege” association determines access only to a single object (when specifying object). If access is required for N objects, N entries in the role_privileges table are created.
7.7.3.6. The user_privileges View #
This view shows users with their roles and privileges and makes it easier to check privileges of a specific subject:
user:user_roles.userrole:user_roles.roleprivilege:privilege.nameobject:user_roles.objectsorrole_privileges.object
7.7.3.7. The groups Table #
The table has no RBAC-related fields.
When creating a group, you can specify a list of role IDs that will be assigned to the group and, as a result, to all users included in it.
7.7.3.8. The group_roles Table #
The table defines associations between groups and roles and has the following fields:
group_id: The group ID.role_id: The role ID.object: The unique ID of an arbitrary class object.
The object class is determined by the privileges.class field value. The object ID declared here restricts the privilege specified in role_privileges.privilege to a single object and allows access to the object by the user specified in group_roles.role_id.
Note
A parameterized object-specific “group-role” association determines access only to a single object (when specifying object). If access is required for N objects, N entries in the group_roles table are created.
7.7.3.9. The group_users Table #
The table defines associations between groups and users and has the following fields:
group_id: The group ID.user_id: The user ID.
The “group-user” associations are not object-specific.
7.7.4. Object-Specific Roles #
In general, it is assumed that roles can include privileges allowing access to all objects of any class.
For finer-grained access control, you can specify both the class and the object ID in role_privileges.object. This ensures that the role and privilege apply only to the object with the specified ID. The object can be specified in multiple locations:
In
role_privileges.objectfor a role. In this case, object access is granted to all role members.In
user_roles.objectfor a user. In this case, access is granted only to a single user.In
group_roles.objectfor a group. In this case, access is granted only to group users.
7.7.5. Checking Access Privileges of Subjects #
During the subject authentication, a session itself and session JWT tokens are created. When an access token is created, it includes user_id. When a user makes requests to perform operations, the access token is attached to the request headers.
The manager performs authorization, extracts the user’s user_id from the access token and checks for the privilege in roles. If the privilege is available, access is granted. If the privilege is unavailable, the request is rejected.
The following is required to check that a subject has the permission to perform an operation with an object:
user_idoragent_id: The user or agent ID.class: The class name for the object (resource type).object: The object ID (optional).
The client specifies the Authorization: Bearer header in the request and attaches the access token.
The server receives the request and extracts the data needed to verify access:
The
user_id(oragent_id) value is extracted from the access token.The
classvalue is defined based on the privilege.The
objectvalues:For GET requests of the
/resourcestype, the values are extracted from the URL and request parameters (ids=?).For GET requests of the
/resources/objectIDtype, the values are extracted from the URL.For PUT requests, the values are extracted from the request body.
For DELETE requests of the
/resourcestype, the values are extracted from the request body (a separate object field).
To verify that a user has a specific privilege, the handler may need a mapping of operation IDs to their corresponding privileges. The verification is performed via the repository and the user_privileges view.