Troubleshoot ACL Access Issues: A Comprehensive Guide




Troubleshooting ACL Access Issues: A Deep Dive




Troubleshooting ACL Access Issues: A Comprehensive Guide for ServiceNow Professionals

In the world of IT Service Management (ITSM) platforms like ServiceNow, robust security and controlled access to data are paramount. Access Control Lists (ACLs) are the backbone of this security model, dictating who can see, create, modify, and delete records. However, as with any complex system, users and administrators can encounter frustrating access issues. This article delves deep into troubleshooting common ACL access problems, providing practical insights, real-world examples, and best practices to help you navigate these challenges effectively.

We’ll cover everything from fundamental role and group management to advanced scripting techniques and the interplay between ACLs and other ServiceNow features like UI Policies and Data Policies. Whether you’re a seasoned ServiceNow administrator or new to the platform, this guide aims to equip you with the knowledge and confidence to tackle ACL-related hurdles.

Understanding the Fundamentals: Roles and Groups

Before we dive into troubleshooting, it’s crucial to have a solid grasp of how ServiceNow manages permissions. At its core, access is granted through roles, which are then assigned to users or groups. Understanding this relationship is key to diagnosing most access problems.

Can We Add Permissions to Users and Groups? Which is the Best Practice?

Absolutely. ServiceNow provides a flexible mechanism for assigning permissions. You can assign roles directly to individual users, or, more commonly and recommended, assign roles to groups. When a user is a member of a group, they inherit all the roles assigned to that group.

Best Practice: Assign Permissions via Groups. This is the golden rule for a reason. Imagine an employee leaving the organization. If their permissions were assigned directly to their user account, you’d have to manually revoke each role. However, if their permissions were granted through group memberships, simply removing them from the relevant groups automatically revokes all associated roles. This streamlines user lifecycle management, reduces the risk of lingering access, and significantly simplifies administration. It’s a proactive approach to security and an efficient way to manage access rights.

How to Add Permissions to User/Group Accounts Using Script

While manual assignment is straightforward, scripting offers powerful automation capabilities for managing roles, especially during bulk operations or integrations. ServiceNow’s scripting engine, primarily through GlideRecord, makes this process quite accessible.

Adding a Role to a User via Script:

When you assign a role to a user, ServiceNow creates a record in the sys_user_has_role table. This table acts as a bridge, linking users to the roles they possess. Here’s a script to add a role to a specific user:


    // Replace 'sys_id_of_the_user' and 'sys_id_of_the_role' with actual sys_ids
    var userSysId = '62826bf03710200044e0bfc8bcbe5df1'; // Example User sys_id
    var roleSysId = '2831a114c611228501d4ea6c309d626d'; // Example Role sys_id

    var userRole = new GlideRecord('sys_user_has_role');
    userRole.setValue('user', userSysId);
    userRole.setValue('role', roleSysId);
    userRole.insert();
    gs.info('Role added to user.');
    

Adding a Role to a Group via Script:

Similarly, assigning a role to a group creates a record in the sys_group_has_role table. This grants all members of that group the specified role.


    // Replace 'sys_id_of_the_group' and 'sys_id_of_the_role' with actual sys_ids
    var groupSysId = '477a05d153013010b846ddeeff7b1225'; // Example Group sys_id
    var roleSysId = '2831a114c611228501d4ea6c309d626d'; // Example Role sys_id

    var grpRole = new GlideRecord('sys_group_has_role');
    grpRole.setValue('group', groupSysId);
    grpRole.setValue('role', roleSysId);
    grpRole.insert();
    gs.info('Role added to group.');
    

How to Add and Remove Group Members Using Script

Managing group memberships is a frequent administrative task. Scripting can automate the addition and removal of users from groups, which is particularly useful for onboarding/offboarding processes or synchronizing with external directories.

Adding a Group Member:

The sys_user_grmember table stores the associations between users and groups. To add a user to a group, you create a new record in this table.


    // Replace 'sys_id_of_the_user' and 'sys_id_of_the_group' with actual sys_ids
    var userSysId = '62826bf03710200044e0bfc8bcbe5df1'; // Example User sys_id
    var groupSysId = '477a05d153013010b846ddeeff7b1225'; // Example Group sys_id

    var grMem = new GlideRecord('sys_user_grmember');
    grMem.setValue('user', userSysId);
    grMem.setValue('group', groupSysId);
    grMem.insert();
    gs.info('User added to group.');
    

Removing a Group Member:

To remove a user from a group, you need to find the corresponding record in sys_user_grmember and then delete it.


    // Replace 'sys_id_of_the_user' and 'sys_id_of_the_group' with actual sys_ids
    var userSysId = '62826bf03710200044e0bfc8bcbe5df1'; // Example User sys_id
    var groupSysId = '477a05d153013010b846ddeeff7b1225'; // Example Group sys_id

    var grMem = new GlideRecord('sys_user_grmember');
    grMem.addQuery('user', userSysId);
    grMem.addQuery('group', groupSysId);
    grMem.query();

    if (grMem.next()) {
        grMem.deleteRecord();
        gs.info('User removed from group.');
    } else {
        gs.info('User not found in the specified group.');
    }
    

Troubleshooting ACL Access: Common Scenarios

When users report that they cannot access specific records or perform certain actions, ACLs are often the first place to investigate. Here are some common scenarios and how to approach them.

Which Role is Required to Work on Access Control?

To effectively manage and troubleshoot ACLs, you need a privileged role. The security_admin role is essential. This role grants you the ability to create, modify, and view all ACL rules on the platform, allowing you to diagnose and correct access issues without being restricted by other ACLs.

Incident Tasks Preventing Incident Closure

A common requirement is to prevent an incident from being closed if there are open tasks associated with it. This is a perfect example of using a Business Rule to enforce workflow logic. This logic directly impacts the user’s ability to close an incident and can be considered a form of access control on the ‘close’ action.

Scenario: An employee tries to close an incident, but there are still open incident tasks. The system should prevent the closure and inform the user.

Solution (Before Business Rule on Incident):


    // This script would typically be in a 'before' Business Rule on the incident table,
    // specifically when the 'state' field is being updated to a 'Closed' value.

    // Assuming '3' is the sys_id or value representing the 'Closed' state for incident tasks.
    // It's best practice to use the state's name for clarity, e.g., 'state.getDisplayValue() == "Closed"'
    // or by looking up the sys_id of the 'Closed' state.

    var incidentTaskTable = 'incident_task';
    var incidentTaskGr = new GlideRecord(incidentTaskTable);
    incidentTaskGr.addQuery('incident', current.sys_id); // Link to the current incident
    // Filter for tasks that are NOT in a 'Closed' or equivalent state.
    // You'll need to determine the correct state value for 'Closed' in your instance.
    // For demonstration, let's assume '3' is the value for 'Closed'.
    incidentTaskGr.addQuery('state', '!=', 3);
    incidentTaskGr.query();

    if (incidentTaskGr.hasNext()) {
        gs.addErrorMessage('Cannot close the incident because there are open tasks associated with it.');
        current.setAbortAction(true); // Prevents the incident from being updated (closed)
    }
    

Troubleshooting Note: If this rule isn’t working, verify the `state` value used in the query. Check the `incident_task` table’s state dictionary entry to confirm the correct value for ‘Closed’. Also, ensure the Business Rule is active and running on the correct table and event (e.g., ‘before update’).

Problem Closure Automating Incident Closure

In complex ITSM processes, closing a problem record might trigger the closure of associated incidents. This ensures that once the root cause is resolved and the problem is documented, all related recurring incidents are also marked as resolved.

Scenario: When a problem is closed, all related open incidents should also be automatically closed.

Solution (After Business Rule on Problem):


    // This script would typically be in an 'after' Business Rule on the problem table,
    // triggered when the 'state' field is updated to a 'Closed' value.

    // Assuming '7' is the sys_id or value representing the 'Closed' state for problems and incidents.
    // Again, using display values or sys_ids from your instance is best practice.
    var closedStateValue = 7; // Example value for 'Closed' state

    if (current.state == closedStateValue) {
        var incidentTable = 'incident';
        var incidentGr = new GlideRecord(incidentTable);
        // Find incidents linked to this problem and that are not already closed.
        incidentGr.addQuery('problem_id', current.sys_id);
        incidentGr.addQuery('state', '!=', closedStateValue);
        incidentGr.query();

        while (incidentGr.next()) {
            incidentGr.state = closedStateValue; // Set the state to Closed
            incidentGr.update(); // Update the incident record
        }
        gs.info('Associated incidents closed for problem: ' + current.number);
    }
    

Troubleshooting Note: Ensure the `problem_id` field correctly links incidents to problems in your instance. Verify the `state` value used for closure. If incidents aren’t closing, check the Business Rule’s conditions and the `incident` table’s state field.

The Relationship Between Incident, Problem, and Change Management

Understanding how these core ITSM processes interact is vital for managing access and workflows. ACLs and related logic often depend on these relationships.

Scenario: A user experiences an issue (Incident). The same issue recurs frequently, leading to the creation of a Problem record to investigate the root cause. If the support team determines that a fix requires modification to the underlying system, they might initiate a Change Request.

This flow highlights how issues are escalated and managed: Incident (immediate impact) -> Problem (root cause analysis) -> Change Request (resolution implementation).

Access Considerations:

  • Users reporting incidents may not need access to problem analysis details or change request proposals.
  • Problem managers and change managers require specific roles to manage their respective processes.
  • ACLs ensure that only authorized personnel can view or modify sensitive problem analysis or change planning details.

Advanced Access Control Concepts

Beyond basic role assignments, ServiceNow offers sophisticated mechanisms to refine access control, ensuring granular permissions that align with business needs.

When a Table is Created, How Many Access Controls (ACLs) Get Created?

By default, when you create a new table in ServiceNow and the “Create application menus and module” checkbox is selected (which is usually the case), the platform automatically generates four Access Control Lists (ACLs) for that table. These default ACLs provide basic security:

  • read ACL: Allows users with roles assigned to the table’s application to read records.
  • write ACL: Allows users with specific roles (often defined by default, like ‘itil’) to write to records.
  • create ACL: Controls who can create new records.
  • delete ACL: Controls who can delete records.

If you uncheck the checkbox that triggers the automatic creation of these ACLs during table creation, you will need to manually define your security rules.

What are Reference Qualifiers, and Their Types? Explain Each in Detail.

Reference qualifiers are powerful tools used to filter the records displayed in a reference field or a list collector. They ensure that users can only select relevant records, improving data integrity and user experience.

There are three main types of Reference Qualifiers:

1. Simple Reference Qualifier

Description: This is the most straightforward type, allowing you to define a static query using field-value pairs. It’s ideal for filtering based on straightforward conditions.

Example: Displaying only active users in a reference field that points to the User table. You would set the qualifier to active=true.

How to Use: In the Dictionary entry for the reference field, navigate to the “Reference Qualifiers” section and enter your query in the “Reference Qualifier” field. For example: state=1^assigned_to=javascript:gs.getUserID() (This would show incidents assigned to the current user).

2. Dynamic Reference Qualifier

Description: Dynamic qualifiers use a pre-defined “Dynamic Filter Option” to create a filter that can adapt based on the context of the record or user. This offers more flexibility than simple qualifiers but is less complex than advanced scripting.

Example: Displaying only incidents assigned to the same assignment group as the current user. You would create a Dynamic Filter Option that captures this logic.

How to Use:

  1. Navigate to System Definition > Dynamic Filter Options.
  2. Create a new Dynamic Filter Option, defining the conditions (e.g., “Current user’s assignment group”).
  3. In the reference field’s Dictionary entry, select the “Reference Qualifier” type as “Dynamic” and choose your created Dynamic Filter Option from the dropdown.

3. Advanced Reference Qualifier (JavaScript Reference Qualifier)

Description: This is the most powerful and flexible type, allowing you to use custom JavaScript code to dynamically filter referenced records. It can incorporate complex logic, multiple conditions, and leverage the current user’s context or other form fields.

Example: Filtering the Incident table to show only incidents assigned to the current user’s assignment group AND have a priority less than 3.

How to Use: In the reference field’s Dictionary entry, set the “Reference Qualifier” type to “Advanced” and enter your JavaScript code in the “Reference Qualifier” field. The code must return a query string.


    // Example: Displaying incidents assigned to the current user's group with priority less than 3
    javascript: 'assignment_group=' + gs.getUser().getMyGroups().toString() + '^priority<3';
    // Or for a more specific assignment group linked to another field on the form:
    javascript: 'assignment_group=' + current.assignment_group.toString() + '^priority<3';
    

Difference in Simple, Dynamic, and Advanced:

  • Simple vs. Dynamic: Simple is static and hardcoded; Dynamic uses pre-configured filter options that can be somewhat context-aware.
  • Dynamic vs. Advanced: Dynamic relies on defined filter options; Advanced allows for custom JavaScript, offering maximum flexibility and complexity.
  • Simple vs. Advanced: Simple is for basic field=value queries; Advanced is for complex, script-driven filtering.

What is a Dependent Value?

Dependent Values in ServiceNow are used to create cascaded dropdown menus. This means the choices available in one field (the dependent field) are filtered based on the selection made in another field (the parent field). This is a common UI element for improving data entry accuracy and guiding users.

How to Configure Dependent Values:

  1. Identify Parent and Dependent Fields: For instance, ‘Category’ could be the parent field, and ‘Subcategory’ the dependent field in the Incident table.
  2. Configure the Parent Field: Ensure the parent field has a defined list of choices (e.g., Hardware, Software, Network for Category).
  3. Configure the Dependent Field:
    • Navigate to the Dictionary entry for the dependent field (e.g., Subcategory).
    • In the “Dependent Field” attribute, enter the name of the parent field (e.g., dependent_field=category).
    • Define the choices for the dependent field, linking them to the parent field’s values. For example, for ‘Subcategory’:
      • If Category = Hardware: Laptop, Desktop, Printer
      • If Category = Software: Operating System, Application, Database
      • If Category = Network: Router, Switch, Firewall

Example: When a user selects “Software” from the Category dropdown, the Subcategory dropdown will automatically update to show only options like “Operating System,” “Application,” and “Database,” hiding irrelevant choices.

What are Attributes? Name Some Attributes You Have Used.

Attributes are special instructions added to a field’s definition in the Dictionary. They modify or enhance the default behavior of a field on forms and lists. They are a declarative way to customize field behavior without writing extensive scripts.

Some commonly used attributes include:

  • no_email: Prevents email notifications from being sent for updates to this field.
  • no_attachment: Disables attachments for records in this table.
  • no_add_me: Hides the “Add Me” button on watchlist fields.
  • tree_picker: Enables a tree-like selection interface for reference fields, useful for hierarchical data.
  • readonly: Makes a field read-only.
  • mandatory: Makes a field mandatory.
  • ref_ac_columns: Specifies which columns to display in the reference field’s lookup.
  • ref_ac_columns_search: Enables searching across specified columns in the reference lookup.

How to Enable/Disable Attachments on the Form Using Attributes

You can control attachment functionality at the table level using attributes. To disable attachments for all records in a specific table, you add the no_attachment attribute to the table’s definition in its Dictionary entry.

How to Use:

  1. Navigate to System Definition > Tables.
  2. Find and open the Dictionary entry for the table you want to modify.
  3. In the “Attributes” field, add no_attachment.

This single attribute effectively removes the attachment icon and functionality from all forms and views for that table.

What are Dictionary Overrides? What Properties Can Be Overridden?

Dictionary Overrides are used when you need a field in a child table to have different properties than the same field in its parent table. Instead of duplicating fields, you can use a dictionary override to modify specific attributes for the child table.

Example: The ‘Priority’ field might have a default value of ‘4’ in a base table. However, in the ‘Incident’ table (which might extend that base table), you might want the default priority to be ‘3’. A dictionary override allows you to achieve this without altering the parent table’s definition.

Properties You Can Override:

You can override almost any attribute defined in the parent table’s Dictionary entry, including:

  • Default Value: As seen in the example above.
  • Max Length: Setting a different character limit.
  • Mandatory: Making a field mandatory in the child table even if it’s optional in the parent.
  • Read Only: Making a field read-only.
  • Display Value: Changing whether the field is displayed.
  • Reference Specification: Modifying the reference table, reference qualifer, etc.
  • Choice Lists: Changing the available choices.
  • Help Text: Modifying the help text associated with the field.

Dictionary overrides are crucial for creating specialized tables that inherit from common base tables while adapting specific field behaviors to their unique use cases.

Client-Side vs. Server-Side Logic: UI Policies and Data Policies

When troubleshooting access and form behavior, it’s important to distinguish between client-side and server-side logic. UI Policies and Data Policies play key roles here.

What are UI Policies?

UI Policies are a client-side scripting mechanism used to dynamically change the behavior of form elements. They run in the user’s browser and are ideal for immediate feedback and interactive form adjustments. They are a powerful alternative to client scripts for many common tasks.

Common Uses:

  • Making a field mandatory, read-only, or visible/hidden.
  • Setting a field’s value.
  • Showing or hiding related lists.
  • Triggering actions based on form conditions.

What is Reverse if False in UI Policies?

The “Reverse if false” checkbox in a UI Policy Action is a crucial setting. If selected, it means that the actions defined in that UI Policy will be applied when the UI Policy’s condition evaluates to true, AND these actions will be **undone** (reversed) when the condition evaluates to false.

Example:

  • UI Policy Condition: State is "In Progress"
  • UI Policy Action: Make the ‘Assignment Group’ field mandatory.
  • With “Reverse if false” checked:
    • When the state is “In Progress”, the Assignment Group becomes mandatory.
    • When the state is NOT “In Progress” (e.g., “New”, “Closed”), the Assignment Group reverts to its default mandatory/optional state (i.e., it becomes optional again if it was made mandatory).
  • Without “Reverse if false” checked:
    • When the state is “In Progress”, the Assignment Group becomes mandatory.
    • Even if the state changes to something else, the Assignment Group *remains* mandatory because the action was applied and not reversed.

This setting is essential for creating dynamic form behaviors where changes should only be active under specific conditions and revert when those conditions are no longer met.

What is the Onload Checkbox in UI Policy?

The “On Load” checkbox determines when the UI Policy’s conditions and actions are evaluated.

  • If “On Load” is checked: The UI Policy runs immediately when the form is initially loaded. All conditions and actions are applied as soon as the form appears. This is common for setting initial field visibility, mandatory status, or default values.
  • If “On Load” is NOT checked: The UI Policy does not run when the form is loaded. Instead, it will only be triggered when a user interacts with the form in a way that causes the UI Policy’s conditions to be re-evaluated. This often happens when a field value changes that is part of the UI Policy’s condition.

Choosing whether to check “On Load” depends on whether you want the UI Policy’s effects to be present from the moment the form is opened or only to react to user input.

What is the Inherit Checkbox?

The “Inherit” checkbox in a UI Policy applies to parent-child table relationships. If checked, the UI Policy defined on a parent table will also be automatically applied to its child tables (tables that extend the parent).

Example: If you create a UI Policy on the “Task” table (a common parent table) and check “Inherit,” that UI Policy will also apply to tables like “Incident,” “Change Request,” and “Problem,” which typically extend the “Task” table. This saves you from having to replicate the same UI Policy logic across multiple related tables.

Can You Write Script in UI Policy?

Yes, you absolutely can write scripts within UI Policies. This is done through UI Policy Actions. When you create a UI Policy Action, there is an option to enable “Run scripts.”

How to Use:

  1. Create your UI Policy and define its conditions.
  2. In the “UI Policy Actions” related list, create a new action.
  3. On the UI Policy Action form, check the “Run scripts” checkbox.
  4. Two script fields will appear:
    • OnApply: This script runs when the UI Policy’s conditions are met and the actions are applied.
    • OnReverse: This script runs when the UI Policy’s conditions are no longer met and the actions are reversed (if “Reverse if false” is checked).

This allows for more complex logic that cannot be achieved through the standard UI Policy action fields (like making a field read-only or setting a value). For instance, you might use a script to dynamically set a field’s value based on a calculation involving multiple other fields.

What are Data Policies?

Data Policies are similar to UI Policies but operate at the server-side. They enforce data consistency and integrity for fields across all data sources, regardless of how the record is accessed (e.g., through a form, an API, or an import). Data Policies run on the server, meaning they are not dependent on the browser’s JavaScript engine.

Common Uses:

  • Making a field mandatory, read-only, or visible/hidden.
  • Setting a field’s value.
  • These actions apply universally, ensuring data governance is maintained across the entire platform.

Key Difference: UI Policies vs. Data Policies

  • UI Policies: Client-side, form-specific behavior, instant user feedback.
  • Data Policies: Server-side, data-level enforcement, applies universally (forms, APIs, integrations).

It’s often recommended to use Data Policies for mandatory fields or read-only enforcement for critical data, as they provide a more robust layer of data governance. UI Policies are then used to enhance the user experience on forms.

Troubleshooting ACL Access: A Practical Approach

When faced with an ACL access issue, follow a systematic approach:

  1. Understand the User’s Experience: What specific action are they trying to perform? What error message are they receiving? What record are they trying to access/modify?
  2. Identify the Target Record and Operation: Determine the table and the specific operation (read, write, create, delete) that is being denied.
  3. Check User’s Roles and Group Memberships: Verify the roles assigned directly to the user and the roles inherited through their group memberships. Use the “System Security > Users” module to check this.
  4. Examine Relevant ACLs:
    • Navigate to System Security > Access Control (ACL).
    • Filter ACLs based on the target table, operation, and potentially the user’s roles.
    • Look for ACLs that might be explicitly denying access or if the necessary “allow” ACLs are missing or misconfigured.
    • Pay attention to “Application,” “Operation,” and “Name” fields. For example, to check write access on the Incident table for the ‘itil’ role, you’d look for a “write” ACL on the “incident” table.
  5. Utilize the “Test” Button in ACLs: Each ACL record has a “Test” button. This is invaluable. You can select a user, an operation, and a record to see exactly which ACLs would pass or fail for that scenario.
  6. Check Business Rules and UI Policies: Sometimes, apparent access issues are caused by Business Rules or UI Policies that are preventing an action based on workflow logic (as seen with incident tasks).
  7. Review Data Policies: Ensure no Data Policies are unexpectedly making fields read-only or mandatory in a way that hinders the user’s intended action.
  8. Consider Order of Execution: In some complex scenarios, the order in which ACLs, Business Rules, and UI Policies execute can matter. Understand the execution order for “before,” “after,” and “display” Business Rules and how UI Policies interact with them.
  9. Check for “None” Role Issues: ACLs without any roles defined can sometimes cause unexpected behavior. If an ACL has no roles, it applies to everyone, which might not be the intended outcome.
  10. Log the Issue: If you’re still stuck, thoroughly document your findings, including user details, affected record, and the troubleshooting steps taken. This is crucial for escalation or if you need to involve senior administrators.

Conclusion

Mastering ACLs and understanding the related ServiceNow features like roles, groups, UI Policies, and Data Policies is fundamental for any ServiceNow professional. By adopting a systematic troubleshooting approach, leveraging the platform’s built-in tools, and adhering to best practices like assigning permissions via groups, you can effectively manage access control, ensure data security, and empower your users to work efficiently within the ServiceNow environment. Remember, clear and concise documentation of your access control configurations is key to long-term maintainability and successful troubleshooting.


Scroll to Top