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.
Privileges are not assigned to subjects directly but are acquired by subjects through roles.
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\_create
RESOURCE\_view
RESOURCE\_edit
RESOURCE\_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).
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.
Objects can be either resources or their representations in the repository, such as servers, agents, instances, users, and user groups.
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.
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.
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.
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, the
user value 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).
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.
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.
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.
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.
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.
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.user
role:
user_roles.role
privilege:
privilege.name
object:
user_roles.objects or
role_privileges.object
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.
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.
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.
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.
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.object for a role. In
this case, object access is granted to all role members.
In user_roles.object for a user. In this
case, access is granted only to a single user.
In group_roles.object for a group. In
this case, access is granted only to group users.
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_id or agent_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 (or
agent_id) value is extracted from the
access token.
The class value is defined based on the
privilege.
The object values:
For GET requests of the /resources
type, the values are extracted from the URL and request
parameters (ids=?).
For GET requests of the
/resources/objectID type, the values
are extracted from the URL.
For PUT requests, the values are extracted from the request body.
For DELETE requests of the /resources
type, 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.