From bdfbf4d143bb40e9b30a95e165a9fed7ed659855 Mon Sep 17 00:00:00 2001 From: Lucifer <108731648+shivamvish160@users.noreply.github.com> Date: Sat, 18 Oct 2025 19:39:56 +0530 Subject: [PATCH 1/2] Create README.md --- .../Role Usage Analyzer/README.md | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 Server-Side Components/Script Includes/Role Usage Analyzer/README.md diff --git a/Server-Side Components/Script Includes/Role Usage Analyzer/README.md b/Server-Side Components/Script Includes/Role Usage Analyzer/README.md new file mode 100644 index 0000000000..8d15ec67a9 --- /dev/null +++ b/Server-Side Components/Script Includes/Role Usage Analyzer/README.md @@ -0,0 +1,24 @@ +# Role Usage Analyzer (Audit-Based) for ServiceNow + +## Overview + +This script analyzes role assignments and identifies roles that may be unused by checking user activity in the `sys_audit` table. It focuses on recent activity (last 90 days) to determine whether users assigned to a role have interacted with the system. + +## Features +- Uses `sys_audit` for accurate activity tracking +- Filters audit records from the **last 90 days** to reduce data volume +- Flags roles assigned to users who show **no audit activity** +- Logs potentially unused roles with user count + +## Usage + +1. Navigate to **System Definition > Script Includes** or **Scheduled Script Executions**. +2. Create a new Script Include or Scheduled Job named `Role_Usage_Analyzer_Audit`. +3. Paste the contents of `Role_Usage_Analyzer_Audit.js` into the script field. +4. Run manually or schedule it to run periodically (e.g., monthly). + +## Notes + +- The script uses `gs.daysAgo(90)` to limit the audit data to recent activity. +- You can adjust the time window by changing the `gs.daysAgo()` value. +- Consider extending the script to generate reports or notify role owners for cleanup. From 23e7cc7deee48ad90aa6c7abef4e658fcd68156e Mon Sep 17 00:00:00 2001 From: Lucifer <108731648+shivamvish160@users.noreply.github.com> Date: Sat, 18 Oct 2025 19:40:50 +0530 Subject: [PATCH 2/2] Create code.js --- .../Role Usage Analyzer/code.js | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 Server-Side Components/Script Includes/Role Usage Analyzer/code.js diff --git a/Server-Side Components/Script Includes/Role Usage Analyzer/code.js b/Server-Side Components/Script Includes/Role Usage Analyzer/code.js new file mode 100644 index 0000000000..5d677002cd --- /dev/null +++ b/Server-Side Components/Script Includes/Role Usage Analyzer/code.js @@ -0,0 +1,46 @@ + + // Role Usage Analyzer using sys_audit + // Description: Identifies roles assigned to users that show no audit activity. + + var roleUsageMap = {}; + var grUserRole = new GlideRecord('sys_user_has_role'); + grUserRole.query(); + + while (grUserRole.next()) { + var userId = grUserRole.user.toString(); + var roleId = grUserRole.role.toString(); + + if (!roleUsageMap[roleId]) { + roleUsageMap[roleId] = { + users: [], + used: false + }; + } + + roleUsageMap[roleId].users.push(userId); + } + + // Use sys_audit to check user activity in last 90 days + var grAudit = new GlideRecord('sys_audit'); + var ninetyDaysAgo = gs.daysAgo(90); + grAudit.addEncodedQuery('userISNOTEMPTY^sys_created_on>=javascript:gs.daysAgo(90)'); + grAudit.query(); + + while (grAudit.next()) { + var userId = grAudit.user.toString(); + for (var roleId in roleUsageMap) { + if (roleUsageMap[roleId].users.indexOf(userId) !== -1) { + roleUsageMap[roleId].used = true; + } + } + } + + for (var roleId in roleUsageMap) { + if (!roleUsageMap[roleId].used) { + var grRole = new GlideRecord('sys_user_role'); + if (grRole.get(roleId)) { + gs.info('[Role Usage Analyzer] Possibly Unused Role: ' + grRole.name + ' | Assigned Users: ' + roleUsageMap[roleId].users.length); + } + } + + }