
- Post History
- Subscribe to RSS Feed
- Mark as New
- Mark as Read
- Bookmark
- Subscribe
- Printer Friendly Page
- Report Inappropriate Content
11-01-2021 10:25 PM - edited 08-14-2024 12:57 PM
Articles, Blogs, Videos, Podcasts, Share projects - Experiences from the field
Hi there,
When talking about Instance Scan, mostly mentioned for setting up Scan Checks is about performing checks on code, certain settings on Business Rules / Client Scripts / Script Includes, etcetera. Though why limit ourselves to only best practices on the coding front? Instance Scan has a really powerful scan engine, with which you can interrogate your instance on way more.
Data
In this article I'll share some examples of Scan Checks which you could use for a "Data" suite. Data checks which you could perform regularly on a Production instance. For example weekly, to support the activities of a System Administrator. Obviously these checks can bring data issues to the surface which need to be corrected, though the question could also be why are those data issues occurring? Maybe there's some scripting issue or integration issue going on, or a System Administrator who incorrectly performed some manual actions, etcetera.
Data examples
Table Check: Active approval for inactive task
Category
Manageability
Description
Approvals for inactive tasks indicate a process error or a technical error. Tasks should not proceed when approvals are still open or only canceled. If canceled, active approvals should be too.
Table
sysapproval_approver
Condition
sysapproval.active=false^stateINnot requested,requested
Table Check: Active Notifications with inactive recipient Users
Category
Manageability
Description
Validate that all notifications are configured with active users if there are any defined under the "Users" field.
Documentation
https://docs.servicenow.com/csh?topicname=t_CreateANotification.html&version=latest
Table
sysevent_email_action
Condition
active=true^recipient_usersISNOTEMPTY
Script
(function (engine) {
// Define variables
var regex = /[0-9a-f]{32}/g;
var recipients = engine.current.recipient_users.split(',');
var l = recipients.length;
for(var i = 0; i < l; i++) {
if(recipients[i].match(regex)) {
var getUser = new GlideRecord('sys_user');
getUser.addQuery('sys_id', recipients[i]);
getUser.addQuery('active', false);
getUser.setLimit(1);
getUser._query();
// Create scan finding
if(getUser.hasNext()) {
engine.finding.increment();
return;
}
}
}
})(engine);
Table Check: Active Users with inactive Manager
Category
Manageability
Description
Validate that all users are configured with an active user if there is any defined under the "Managers" field.
Documentation
https://docs.servicenow.com/csh?topicname=c_UserAdministration.html&version=latest
Table
sys_user
Condition
active=true^manager.active=false
Table Check: Active Workflow Context with Inactive Parent
Category
Manageability
Description
Workflows are generally run during the lifecycle of a record. When the record reaches a closed state, the Workflow should be finished. Still running Workflows might indicate an issue in your environment, for example the Workflow itself, related scripting, etc..
Table
wf_context
Condition
active=true
Script
(function (engine) {
// Query record
var getRecord = new GlideRecord(engine.current.getValue('table'));
getRecord.addQuery('sys_id', engine.current.getValue('id'));
getRecord.addQuery('active', false);
getRecord.setLimit(1);
getRecord._query();
// Create scan finding
if(getRecord._next()) {
engine.finding.increment();
}
})(engine);
Table Check: Orphan Incident Tasks
Category
Manageability
Description
Incident Tasks that are not associated with an Incident will most likely never be seen and modified. Every Incident Task should have a parent Incident as they always should be a part of an Incident.
Table
incident_task
Condition
active=true^incidentISEMPTY
GitHub example-instancescan-checks
The example Linter Checks mentioned in this article can also be found on the "example-instancescan-checks" GitHub repository. Also other Scan Checks can be found there which have been contributed by several people.
---
And that's it actually. Hope you like it. If any questions or remarks, let me know!
C |
If this content helped you, I would appreciate it if you hit bookmark or mark it as helpful.
Interested in more Articles, Blogs, Videos, Podcasts, Share projects I shared/participated in? |
Kind regards,
Mark Roethof
ServiceNow Technical Platform Architect @ Quint Technology
2x ServiceNow Developer MVP
2x ServiceNow Community MVP
---
- 2,693 Views
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hi
to my opinion, your scan check "Active Workflow Context with Inactive Parent" has an error.
You assume that a Workflow Context only references a record that has an "active" field, which is not true. For this reason, it must first be checked whether the corresponding table has this field before a query for "active=true" can be executed.
I also added another check, because I saw that there are active Workflow Contexts, which do not reference a Record and are therefore orphaned.
(function (engine) {
if (engine.current.getValue('id') == null || engine.current.getValue('table') == null) {
engine.finding.increment();
}
else {
//Check wether the related record has an "active" field of type boolean
var grActiveCheck = new GlideRecord(engine.current.getValue('table'));
grActiveCheck.initialize();
var intSize = grActiveCheck.getElements().size();
var arrFields = grActiveCheck.getElements();
var hasActiveField = false;
for (var i = 0; i < intSize && !hasActiveField; i++) {
var glideElement = arrFields.get(i);
var strFieldName = glideElement.getName().toString();
var strFieldType = glideElement.getED().getInternalType().toString();
hasActiveField = strFieldName == 'active' && strFieldType == 'boolean';
}
if (hasActiveField) {
grActiveCheck.addQuery('name', engine.current.getValue('table'));
grActiveCheck.addQuery('element', 'active');
grActiveCheck.query();
if (grActiveCheck.next()) {
// Query record
var grRelatedRecord = new GlideRecord(engine.current.getValue('table'));
grRelatedRecord.addQuery('sys_id', engine.current.getValue('id'));
grRelatedRecord.addQuery('active', false);
grRelatedRecord.setLimit(1);
grRelatedRecord._query();
// Create scan finding
if (grRelatedRecord._next()) {
engine.finding.increment();
}
}
}
}
})(engine);
Kind regards
Maik

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hi Maik,
Will look into your remark about the active part. Tnx.
On purpose I did not check for workflow context without a (valid) parent. I've got a different check for that. A different check because such a situation should not exist in production instances and should be investigated by a System Administrator.
Kind regards,
Mark