OTOBO Znuny ACLs
Access Control Lists (ACLs) in OTOBO are the foundation of robust permission management. In this sub-topic, you will learn:
- Concepts and Business Value: Why ACLs are essential.
- Architecture Overview: How the ACL subsystem is structured internally.
- Match vs. Action: The basic structure of an ACL.
- System Configurations: Important SysConfig settings related to ACLs.
1. Concepts & Business Value
ACLs define which actions agents and customers are allowed to perform in the ticket system—automated and context-sensitive.
- Security: Protect sensitive functions (e.g., closing a ticket) from unauthorized use.
- Usability: Dynamically hide irrelevant buttons or menus to avoid overwhelming the user.
- Automation: Control ticket flows (prioritization, escalation, assignment) directly via ACL rules without additional code.
- Maintainability: Export, import, and version ACLs centrally—ideal for multi-instance environments.
1.1 Role- and Criteria-Based ACLs
- Role-based: Assignment based on agent roles or groups (e.g., Admin vs. Support Agent).
- Criteria-based: Control via ticket attributes (Queue, Status, Priority, DynamicFields, CustomerID).
Combining both approaches allows for precise rules, e.g., "Only senior agents can move tickets with a priority > 3 to the development queue."
2. Architecture Overview
The OTOBO ACL subsystem is distributed across several core components:
Component | Task |
---|---|
Kernel::System::ACL::DB::ACL | Perl backend: Persists and loads ACLs from the database |
Kernel::System::YAML | Serializes config_match & config_change as YAML text |
Kernel::System::Cache | Caches ACL queries with a TTL (SysConfig: ACL::CacheTTL ) |
acl_sync Table | Logs which ACLs are new or have been changed (sync_state) to trigger deployments |
ZZZACL.pm | Generated Perl file that provides all validated ACLs in the ticket modules upon deployment |
# Example: YAML serialization before DB insert
my $YAML = $Kernel::OM->Get('Kernel::System::YAML');
my $ConfigMatchYAML = $YAML->Dump(Data => $Param{ConfigMatch});
my $ConfigChangeYAML = $YAML->Dump(Data => $Param{ConfigChange});
$DBObject->Do(
SQL => 'INSERT INTO acl (..., config_match, config_change, ...) VALUES (?, ?, ?, ...)',
Bind => [\$ConfigMatchYAML, \$ConfigChangeYAML, ...],
);
Note: The superuser (UserID 1) automatically ignores all ACLs to avoid getting locked out.
3. Basic Structure of an ACL: Match vs. Action
Section | Task |
---|---|
Match | Defines conditions: checks ticket attributes (Properties) or database values (PropertiesDatabase). |
Action | Specifies which UI elements (buttons, fields) are shown/hidden (Possible, PossibleAdd, PossibleNot) or which actions are executed (status/queue changes). |
Example Match Options:
Queue
,Status
,Priority
DynamicField_<Name>
,CustomerUser
,Owner
Frontend::Module
(AgentTicketZoom, CustomerTicketCreate)
Example Action Options:
Possible
: Whitelist, e.g., allowing only specific queues or statuses.PossibleAdd
: Add additional values to a limited selection.PossibleNot
: Remove specific buttons (e.g., AgentTicketClose) from the UI.
4. Important SysConfig Settings
The core elements mentioned above are configured via SysConfig:
Key | Description | Example Value |
---|---|---|
ACL::CacheTTL | Cache lifetime in seconds (backend) | 3600 |
ACLKeysLevel1MatchTicket | Allowed first level for Match (Properties, PropertiesDatabase) | Properties, PropertiesDatabase |
ACLKeysLevel1ChangeTicket | Allowed first level for Change (Possible, PossibleAdd, PossibleNot) | Possible, PossibleAdd, PossibleNot |
ACLKeysLevel2::PropertiesTicket | Allowed Match keys (Queue, State, DynamicField, etc.) | Queue, State, CustomerUser, ... |
ACLKeysLevel2::PossibleTicket | Allowed Change keys (Form, FormStd, Action, Process, Ticket) | Form, FormStd, Action, ... |
ACLKeysLevel3::Actions###DefaultTicket | List of all possible actions in the UI (AgentTicketClose, AgentTicketEmail, ...) | (see list) |
Tip: Adjust
ACLKeysLevel*
to populate the ACL UI with only relevant entries.
Evaluation, Stop-on-Match & Performance
The evaluation of Access Control Lists (ACLs) determines which rules are applied when a ticket is loaded or an action is performed in the ticket system. An efficient configuration of these processes, along with targeted performance optimizations, is crucial to ensure a smooth and scalable agent interface.
Evaluation Cycle
Each time an agent opens a ticket or performs an action (e.g., a button click), OTOBO processes the list of all active ACLs, sorted by their sort key (name or ID). The following flow shows the check and execution process:
- Match (ConfigMatch): Criteria such as Queue, Status, Priority, or DynamicFields are checked here.
- Change (ConfigChange): Defines which UI elements are removed or added (Possible, PossibleAdd, PossibleNot) or which automatic actions occur (queue/status changes).
- StopAfterMatch: If set to 1, processing stops after the first matching ACL.
Note: A correctly set
StopAfterMatch
prevents subsequent ACLs from triggering unintended changes.
Stop-on-Match Strategies
Option | Effect |
---|---|
StopAfterMatch=1 | Once an ACL matches, no others are checked—ideal for exclusive rules. |
StopAfterMatch=0 | All ACLs are checked—necessary when multiple ACLs need to intervene independently. |
Tip: Numeric prefixes (e.g., 100-
, 200-
) in the ACL name control the natural sorting and thus the priority of critically important rules.
Performance Optimization
A large set of ACLs can increase the loading times of ticket forms. These measures help to improve performance:
- Adjust CacheTTL: In SysConfig under
ACL::CacheTTL
(e.g., 3600 s), you define how long loaded ACL definitions remain in the cache. - Activate Preselection Cache: The
TicketACL::ACLPreselection
module pre-fills selected options in advance, saving repeated checks. - Rule Reduction: Remove outdated or duplicate ACLs and bundle similar rules.
- Optimize Sequence: Place frequently matching ACLs at the beginning of the list.
- Indexed Fields: Use database indexes for DynamicFields and other frequently queried properties.
<Setting ID="ACL::CacheTTL">
<Group>Core::Ticket::ACL</Group>
<Value>3600</Value>
<Description>Cache lifetime for DB ACL backends in seconds.</Description>
</Setting>
Maintenance & Best Practices
Practice | Benefit |
---|---|
YAML Export | Version ACLs in Git to track changes. |
Documentation | Create a change log with timestamps, author, and the purpose of the ACL. |
Rule Review | Regular team reviews prevent overlaps. |
Test Environment | Validate new ACLs with controlled test tickets. |
Log Debugging | Enable debug logs (TicketACL::Debug::Enabled ) for detailed insights. |
Configuring Debugging
<Setting ID="TicketACL::Debug::Enabled">
<Group>Core::Ticket::ACL</Group>
<Value>1</Value>
<Description>Enable ACL debugging</Description>
</Setting>
<Setting ID="TicketACL::Debug::Filter###00-DefaultTicket.xml">
<Group>Core::Ticket::ACL</Group>
<Value><OTOBO_TICKET_TicketID></Value>
<Description>Filter for debug output by Ticket ID.</Description>
</Setting>
With these targeted strategies, you can ensure that your ACL infrastructure in OTOBO remains both high-performing and maintainable—even in large, distributed environments.
Practical Examples, Governance & Reference
In this final part of the article, we will show how ACLs are used in practice in OTOBO through concrete scenarios. We will then cover proven governance methods and provide further references.
Practical Examples
1. Automatic Prioritization to the "Alarm" Queue
Goal: Immediately move tickets with priority 5 (very high) to the Alarm queue and notify the processor.
- Name: "100-Auto-Alarm"
StopAfterMatch: 1
ValidID: 1
ConfigMatch:
Properties:
Priority:
ID: [ 5 ]
ConfigChange:
PossibleNot:
Form:
- ticketCreateQuickClose
PossibleAdd:
Form:
- ticketCreateNotifyOwner
Action:
Queue: "Alarm"
ACL basic data and match settings
ACL Change: Queue change and button add
2. Escalation Protection for "Very High" Priority Tickets
Goal: Prevent tickets with a database priority of 5 from being closed.
- Name: "101-No-Close-High"
StopAfterMatch: 1
ValidID: 1
ConfigMatch:
PropertiesDatabase:
Priority:
Name: [ "5" ]
ConfigChange:
PossibleNot:
Action:
- AgentTicketClose
ACL Change: Hide Close button
3. UI Restriction per Queue
Goal: In the Support queue, the status option resolved should not be available.
- Name: "102-Hide-Resolved-Support"
ValidID: 1
ConfigMatch:
Properties:
Queue:
Name: [ "Support" ]
ConfigChange:
PossibleNot:
FormStd:
- State::resolved
ACL Change: Remove status option
4. Customer Process Restriction
Goal: Customers are not allowed to move their own tickets to other queues.
- Name: "103-Cust-No-Reassign"
ValidID: 1
ConfigMatch:
Properties:
Frontend:
Action:
- CustomerTicketZoomReply
ConfigChange:
PossibleNot:
Action:
- AgentTicketMove
ACL Change: Hide Move button for customers
5. Time-Based Escalation After 48 Hours
Goal: Tickets that have been open for more than 48 hours are automatically assigned to Senior Agents.
- Name: "104-Escalate-48h"
ValidID: 1
ConfigMatch:
Properties:
Ticket:
CreateTimeOlderThan: 48h
ConfigChange:
Action:
Owner: "Senior-Agenten"
Note: This scenario may require an extension for time-based match criteria.
Governance & Documentation
Measure | Description |
---|---|
Naming Convention | Numeric prefixes (e.g., 100- , 200- ) for sorting and clarity. |
Changelog | Log Name , Comment , ChangeTime , and ChangeBy for each ACL change. |
Review Process | Conduct regular reviews to avoid overlaps and conflicts. |
Versioning | Export ACLs as YAML and version them in Git or a documentation tool. |
Testing | Validate ACLs in a test environment with specific test tickets. |
Further References
- ACL Reference (YAML):
Kernel/Config/Files/ZZZACL.pm
(generated) - SysConfig ACL Keys: Level 1–3 terms for fine-tuning (
Core::Ticket::ACL
) - DynamicField Documentation: Connecting dynamic fields in ACLs
With these practical examples and governance recommendations, you now have the tools to operate ACLs in OTOBO securely, efficiently, and transparently.