1.6. Security #
1.6.1. Manager and Agent #
The manager is a standard application software and does not require privileged access to operating system features. The manager service can operate fully when running under a non-privileged operating system user.
To work with the repository, the manager needs a separate database where service information is stored. Also, the DBMS user with the following rights is required:
The right to
LOGINto the instance.The repository database rights:
the ownership of the database
the right to connect to the database
no restrictions on access rights within the database (to perform migrations in the data schema)
The agent is a standard application software that requires the following for full operation:
access to operating system features
access to the managed DBMS instance
To implement most features, the agent only requires the access level of a non-privileged operating system user. There is a small number of features that require privileged access. To maintain this functionality, additional system configuration and granting of the necessary rights are required. Without the configuration and privileges, the agent cannot perform operations, which adversely affects PPEM functionality. It is recommended to complete all necessary configurations before running the agent.
Access to the managed DBMS instance can be divided into the following parts:
Access to files and directories of the DBMS instance, which is provided using operating system access levels. The user on whose behalf the agent is running must have access to the main data directory.
Note
By default, the main data directory is initialized by the
postgresowner with0600rights, so most DBMS installations restrict access to this configuration. Therefore, the optimal operational approach is to run the agent under thepostgressystem user.Access to the SQL interface of the DBMS instance, for which the agent requires the DBMS user with the following rights:
the right to
LOGINto the instancethe right to connect to all instance databases
the membership of the
pg_monitorandpg_signal_backendroles
1.6.2. Networking #
Networking between the manager and agent can be initiated by either side:
The manager can send control instructions to agents, and agents return the execution results in response.
Agents can send to the manager requests to register themselves and DBMS instances as well as to update the state of instances. The manager, in turn, sends a response to the agents’ requests.
The manager and agent use the HTTPS protocol for communication. By default, the manager uses the tcp/8080 port, and the agent uses the tcp/8081 port. This traffic direction must be taken into account when configuring network access rules. The address and port are specified in the ppem-manager.yml manager and ppem-agent.yml agent configuration files.
For secure data transfer, TLS configuration is recommended.
1.6.3. User-to-Manager Authentication #
To work with the manager, user authentication and authorization are required. Authentication can be performed using:
Built-in PPEM tools — user and group data is stored in the repository and managed by the PPEM administrator.
An external LDAP directory (OpenLDAP or Active Directory). If you use the external directory, the manager must be configured to work with this directory. All user and group data is stored in an external directory and managed by a dedicated LDAP directory administrator.
1.6.4. Manager-to-User Authentication #
The manager and agent API is secured by authorization. To execute API requests, the manager and agent perform mutual authentication and issue access tokens for subsequent authorization. The tokens have a limited lifetime — the manager and agents autonomously track token expiration and renew them when necessary.
1.6.5. Authentication and Authorization Operation Scheme #
There are three interaction types that require authentication and authorization during the manager’s operation:
All interactions are carried out via the HTTP or HTTPS protocol depending on the PPEM parameters.
1.6.5.1. User → Manager #
In this interaction type, users work in the web application.
1.6.5.1.1. User → Manager: Authentication #
The user sends a POST /v1/sessions API request to the manager’s endpoint to obtain access and refresh tokens for subsequent operations. The API request contains user credentials.
In the basic scenario, credentials are checked against the repository. When using LDAP authentication, credentials are first checked against the directory service, then if they are not found, they are checked against the repository.
1.6.5.1.2. User → Manager: Authorization #
Upon successful authentication, subsequent HTTP/HTTPS requests from users to the manager include the Authorization header, where the Bearer keyword is followed by a space and the access token text. For example:
headers: Content-Type: application/json Authorization: "Bearer eyJhbG..."
The granted access is determined using the role-based access control (RBAC) model in accordance with the roles assigned to the user:
You can assign roles to PPEM users directly or through PPEM groups they are members of.
You can assign roles to LDAP users only through PPEM groups they are members of.
To add an LDAP user to a PPEM group, the administrator must map the distinguished name (DN) of the user’s LDAP group to the PPEM group name. The user is then automatically added to the PPEM group when logging in to the web application.
The user group composition is periodically checked against the LDAP server and updated if necessary.
For more information about mapping LDAP groups to PPEM groups, refer to Integration with OpenLDAP and Active Directory.
1.6.5.2. Manager → Agent #
In this interaction type, the manager sends API requests to agents to perform various operations.
1.6.5.2.1. Manager → Agent: Authentication #
The manager sends a POST /v1/sessions API request to the agent’s endpoint to obtain access and refresh tokens for subsequent operations. The API request is made via the URL for connecting the agent to the manager from the repository and contains two parameters:
name: The agent name from the repository.api_key: The API key for connecting the agent to the manager from the repository.
1.6.5.2.2. Manager → Agent: Authorization #
Upon successful authentication, subsequent HTTP/HTTPS requests from the manager to agents include the Authorization header, where the Bearer keyword is followed by a space and the access token text. For example:
headers: Content-Type: application/json Authorization: "Bearer eyJhbG..."
The agent verifies the authenticity of the manager’s access token. To do this, the agent generates a token based on the known values of the name and api_key parameters. If the generated and received tokens match, the authentication is successful. If the authenticity is confirmed and the requested endpoint is found, further work is allowed.
1.6.5.3. Agent → Manager #
In this interaction type, agents send reports on the API command execution and updates about serviced instance objects to the manager.
1.6.5.3.1. Agent → Manager: Authentication #
The agent sends a POST /v1/sessions API request to the manager’s endpoint to obtain access and refresh tokens for subsequent operations. The API request is made via the URL for connecting the agent to the manager, which is specified in the ppem-agent.yml agent configuration file using the agent.manager.url parameter. The API request contains two parameters:
name: The agent name, which is specified in theppem-agent.ymlagent configuration file using theagent.nameparameter.api_key: The API key for connecting the agent to the manager, which is specified in theppem-agent.ymlagent configuration file using theagent.manager.api_keyparameter.
1.6.5.3.2. Agent → Manager: Authorization #
Upon successful authentication, subsequent HTTP/HTTPS requests from the agent to the manager include the Authorization header, where the Bearer keyword is followed by a space and the access token text. For example:
headers: Content-Type: application/json Authorization: "Bearer eyJhbG..."
The manager verifies the authenticity of the agent’s access token. To do this, the manager generates a token based on the known values of the name and api_key parameters. If the generated and received tokens match, the authentication is successful. If the authenticity is confirmed and the requested endpoint is found, further work is allowed.
The granted access is determined by the rules specified in the PPEM code for how the agent should access manager resources.
1.6.5.4. Lifetime of Access and Refresh Tokens #
The lifetime of access and refresh tokens is limited. It can be specified in the ppem-manager.yml manager or ppem-agent.yml agent configuration file using the jwt.lifetime.access and jwt.lifetime.refresh parameters.
When the access token expires, the manager or agent starts responding to the token owner with the “401 Unauthorized” error and the “ERR_AUTH_TOKEN_EXPIRED” code, for example:
{
"error":{
"code":"ERR_AUTH_TOKEN_EXPIRED",
"title":"token is expired"
}
}
To get a new access token, the token owner must send a PUT /v1/sessions API request to the endpoint with the refresh token that was received along with the expired access token. This results in new access and refresh tokens that can be used for further work.
If the refresh token has also expired, the token owner must re-authenticate.
1.6.6. Role-Based Access Control (RBAC) Model #
1.6.6.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.
1.6.6.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).
1.6.6.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.
1.6.6.2.2. Objects #
Objects can be either resources or their representations in the repository, such as servers, agents, instances, users, and user groups.
1.6.6.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.
1.6.6.3. Implementation #
Access privleges 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.
1.6.6.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.
1.6.6.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).
1.6.6.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.
1.6.6.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.
1.6.6.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.
1.6.6.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
1.6.6.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.
1.6.6.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.
1.6.6.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.
1.6.6.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.
1.6.6.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.