In an audit, nobody asks "who has access to the ERP." They ask "who can DELETE an entry in the ERP" - and the access spreadsheet rarely knows the answer. Access Matrix brings that decision matrix inside GLPI: external systems, their modules, and four CRUD flags (Create, Read, Update, Delete) resolved by role, group, and user. This guide covers the resolution model, a straight-to-the-database SQL diagnostic, the cross-environment migration format, and the pitfalls that only surface in production.
The real problem: the spreadsheet nobody trusts
While maintaining client environments, the request that exposes how fragile spreadsheet-based control is comes up again and again. An audit arrives (ISO 27001, SOX, or an access report for privacy compliance) and the ask is granular: "list every role that can create and delete records in the finance system." A "has access / no access" spreadsheet cannot answer that. It does not separate read from write, has no history of who changed what, and is already stale because the last offboarding was never reflected. Access Matrix targets exactly that gap: it models access at CRUD granularity and keeps everything inside GLPI, next to the rest of the service desk operation.
What the module models: systems, modules, and four flags
The structure is deliberately simple. You register the external systems (ERP, CRM, BI, third-party portals) and, within each one, the relevant modules (for example "Accounts Payable", "Billing", "Reports"). For each combination of role and module you tick four checkboxes: Create, Read, Update, Delete. A permission can be defined at the whole-system level or per specific module. In the database this becomes the columns can_create, can_read, can_update, can_delete (tinyint 0/1), with the module set to NULL when the rule applies to the entire system.
An honest and important clarification: Access Matrix is not a proxy that blocks login to the ERP. It does not intercept the external system. It is the authoritative decision matrix - the source of truth that documents, resolves, and displays who should hold each permission, so the team provisioning access (or the auditor reviewing it) works from trustworthy data inside GLPI rather than from a loose spreadsheet.
Four-layer resolution (OR: the most permissive wins)
A user's effective permission does not come from a single place. The module combines four sources with OR logic - for each CRUD flag, if any layer grants it, the user has it. In practice, each flag's result is a max() across the layers:
- The user's role - the field that defines the role is configurable (GLPI Category, Title, or default Group) via the
role_sourcesetting. - Permission groups linked to the role - reusable CRUD sets assigned to the role.
- Permission groups linked directly to the user - one-off exceptions without touching the role.
- Individual permissions assigned directly to the account.
| # | Layer | Origin on the user record | Purpose |
|---|---|---|---|
| 1 | Role | Category / Title / default Group (config role_source) | Baseline access by function |
| 2 | Role permission group | Role → group link | Reusable package across roles |
| 3 | User permission group | User → group link | Exception without changing the role |
| 4 | Individual permission | Directly on the account | One-off fine-tuning |
On the query tab, the module shows any user's effective permission with badges indicating which layer each access came from (Role, Group, or Individual) - which makes resolution auditable rather than a black box.
Straight-to-the-database diagnostic (SQL)
In an audit, the most frequent question is "who can write (create, update, or delete) in each system." You can answer it with a SELECT straight against the per-role permission table. The example below assumes the default source (usercategories_id, the user Category) and lists only those with a write flag:
-- Roles (user Category) with WRITE power over each external system
-- Default role source = usercategories_id
SELECT s.name AS system_name,
COALESCE(m.name, '(whole system)') AS module_name,
c.name AS role,
p.can_create, p.can_update, p.can_delete
FROM glpi_plugin_nextool_accessmatrix_perm_categories p
JOIN glpi_plugin_nextool_accessmatrix_systems s
ON s.id = p.plugin_nextool_accessmatrix_systems_id
LEFT JOIN glpi_plugin_nextool_accessmatrix_modules m
ON m.id = p.plugin_nextool_accessmatrix_modules_id
JOIN glpi_usercategories c
ON c.id = p.usercategories_id
WHERE p.can_create = 1 OR p.can_update = 1 OR p.can_delete = 1
ORDER BY s.name, role;
This SELECT is read-only and covers the role layer (the baseline). The final effective permission - adding permission groups and individual tweaks via the 4-layer OR - is resolved by the module in PHP; use the query tab for the consolidated per-user value. The SQL is for quick audit sweeps and for checking the baseline before digging deeper.
Cross-environment migration: CSV Import/Export
Configuring the matrix in staging and promoting it to production without redoing everything by hand is done via CSV Import/Export. The export produces a single file with systems, modules, and permissions, in this format:
type,system_name,module_name,comment,is_active,role_source,role_id,can_create,can_read,can_update,can_delete
system,ERP Protheus,,Financial management,1,,0,0,0,0,0
module,ERP Protheus,Accounts Payable,,1,,0,0,0,0,0
permission,ERP Protheus,Accounts Payable,,0,usercategories_id,5,1,1,1,0
permission,ERP Protheus,,,0,groups_id,12,0,1,0,0
The type column distinguishes system, module, and permission rows; on permission rows, role_source says which layer that rule comes from. Before applying, the module shows a preview of the changes and writes an automatic backup (JSON snapshot) of the prior state, so you can roll back if something turns out different from expected.
Ticket integration
A dedicated tab appears on every ticket form, already pre-selecting the requester and displaying their effective permissions. In practice, when a ticket like "grant so-and-so access to module X of the ERP" comes in, the technician sees at once what that user already has in each system - without leaving the ticket, without opening another screen, without depending on that spreadsheet.
Field pitfalls (the common mistake is...)
Three details only surface once the matrix is in use, and they come from hands-on operation:
- OR never revokes. The common mistake is trying to "remove" access by unticking the flags at the user's individual layer while a permission group still grants that CRUD. Because resolution is OR (the most permissive wins), the permission still stands. There is no "deny" that overrides a "grant" from another layer: to truly remove it, take it out of the layer that grants it.
- A user with no role filled in does not inherit the role matrix. If you configured the source as Category but the user's account has the Category blank, layer 1 simply does not apply - only the user's groups and individual permissions count. The module warns about this on the query tab, but the day-to-day symptom is "I configured the role and the user still has no access." Check the role field on the user record before suspecting the module.
- Switching the role source does not erase what you configured. If you migrate
role_sourcefrom Category to Title, the permissions saved under Category do not vanish - they lie dormant in the database and stop being displayed while that mode is not theirs. Switching back to the old source brings everything back. It is safe to experiment, but know that "everything disappeared" after switching the source is almost always this, not data loss.
Modeling the matrix once is the easy part; keeping it consistent with offboardings, role changes, and recurring audits is maintenance work. That is what NexTool does: explore Access Matrix or talk to NexTool's GLPI maintenance to structure external-system access control with governance and an audit trail.
Este conteudo foi produzido com auxilio de inteligencia artificial e revisado pela equipe Nextool Solutions.