The Now Platform® Washington DC release is live. Watch now!

Help
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Mark Roethof
Tera Patron
Tera Patron

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!

đź‘Ť
If this post helped you in any way, I would appreciate it if you hit bookmark or mark it as helpful.

Interested in more articles, blogs, videos, and Share projects on Instance Scan I published?
Instance Scan


Kind regards,
Mark
2020-2021 ServiceNow Community MVP
2020-2021 ServiceNow Developer MVP

---

LinkedIn

Comments
Maik Skoddow
Tera Patron
Tera Patron

Hi @Mark Roethof ,

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 Roethof
Tera Patron
Tera Patron

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

Sascha Wildgru1
ServiceNow Employee
ServiceNow Employee

The CodeSanity app contains a set of Instance Scan checks aimed at improving source code and application quality. Developers should run them before shipping a new application version.

Vote to make it part of the platform OOTB!

https://community.servicenow.com/community?id=view_idea&sysparm_idea_id=23716958db25d514904fa9fb1396...

Or install it right away:

https://www.wildgrube.com/servicenow-codesanity

Version history
Last update:
‎11-01-2021 10:25 PM
Updated by: