- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
03-23-2021 08:18 PM
Hi There,
Just wanting some clarity around how vulnerability assignment rules are applied when a new VI is created. We currently have a few hundred vulnerability assignment rules configured because each technology type have different requirements for remediation ownership. For example, on our Windows AU servers, some vulnerabilities will be the responsibility of the technical service team to remediate and other the Business Application Support Group who are using that server. Then I have a catch all rule which should pick anything not assigned by one of the previously defined rules and assign to a group who will perform analysis on why the VI was not assigned to either a technical service or business server. In most cases those VIs that should end up there would be where an assignment rule doesn't match OR a previous assignment rule could not find a related Business Application against a CI (these are scripted assignment rules using the CMDB service mapping to identify which Business Application is using the host.
Now I've noticed something recently where my catch all assignment rule is not picking up a VI.
For example, I have a VI related to Microsoft Excel on a windows servers. Now I have an assignment rule (execution order 50) which says if the server is a windows server and the plugin name contains 'Microsoft Excel', then use this scripted rule to locate the related Business Application and assign to the related Support Group.
Now if the script was unable to detect a related Business Application, the support group field on the VI is not populated, so is blank. I would then expect the next assignment rule (execution order 75) to pick up this VI and process it. This assignment rule basically says, if its a windows servers assign to this support group.
But from what I can see in the system is if the first rule matches but wasn't able to derive a support group, the system is leaving the VI unassigned. Can someone clarify what the logic should be?
Solved! Go to Solution.
- Labels:
-
Vulnerability Response
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
03-24-2021 05:50 AM
Beat me to it Chris!
Hi Nicole, hope all is well.
Chris is absolutely correct - a scripted rule should check whether it has successfully retrieved a group, and try another way or return the default group if it has not.
This is probably not how most people would assume Assignment rules work, and your assumptions are perfectly reasonable. So I'd like to also share how they are executed so you and your colleagues can interrogate the logic yourselves.
Assignment rules are run by a Business Rule on the Vulnerable Item table named "Run assignment rules". This business rule invokes the Script Include "AssignmentUtils", and calls the method "getAssignmentGroup" in that Script include.
While it does check to see if any object has been returned, this just ensures there hasn't been an error when evaluating the script. Here's the script itself, from Vulnerability Response version 13.0.3:
getAssignmentGroup: function(vulItem) {
var assignment_info = {};
assignment_info['assignment_group'] = "";
assignment_info['assignment_rule'] = "";
var assignmentGroup = "";
// Iterate assignment rules
var assignmentRules = this._getAssignmentRules();
if ((!assignmentRules) || (!assignmentRules.list) || (!assignmentRules.rules))
return assignment_info;
for (var i = 0; i < assignmentRules.list.length; i++) {
var gr = assignmentRules.rules[assignmentRules.list[i]];
// This check ensures,
// (1) The assignment rules for Infrastructure Vulnerability are applied
// only for Vulnerable Item (sn_vul_vulnerable_item) records
// (2) The assignment rules for Application Vulnerability are applied
// only on Application flaw (sn_vul_app_vulnerable_item) records
if (gr.table != vulItem.sys_class_name)
continue;
// If the condition is empty, this is a default condition, always matches
if ((!gr.condition) || (this.util.checkRecord(vulItem, gr.condition))) {
// Simple group
if (gr.type == "1")
assignmentGroup = gr.assignment_group;
// Assignment group field
else if (gr.type == "2") {
var arr = gr.assignment_group_fields.split('.');
var recordPosition = vulItem;
for (var x = 0; x < arr.length; x++) {
var columnName = arr[x];
recordPosition = recordPosition[columnName]; // dot walking into assignment group
if (recordPosition == null)
break;
}
assignmentGroup = recordPosition;
// Script
} else if (gr.type == "3") {
var evaluator = new GlideScopedEvaluator();
evaluator.putVariable("current", vulItem);
evaluator.evaluateScript(assignmentRules.rules[assignmentRules.list[i]], "script", null);
assignmentGroup = vulItem.assignment_group;
}
// return the assignment information
assignment_info = {};
assignment_info['assignment_group'] = assignmentGroup;
assignment_info['assignment_rule'] = gr.sys_id;
return assignment_info;
}
}
return assignment_info;
},

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
03-24-2021 05:17 AM
Hi,
When Assignment Rules are running, the first Rule that matches stops the processing of the Rules. No other rules are considered. In other words, the first Condition that is true runs that Rule. When a rule runs, it must return an Assignment Group.
When you design rules in general, you must always ensure that when the Rules conditions are met, the Rule will always return an Assignment Group.
In a basic rule, you need to add a condition to test the Assignment Group and ensure that it is not empty. i.e., If the Support Group is not Empty.
In a scripted rule, you need to test to see if the Assignment Group you are after is not empty. If it is empty, you need to handle that. You can handle that by having a "default" assignment group that will be used in the event of an empty Assignment Group field. Of course, you could do a couple of other Assignment Group looks up first in the script, but you always need a fallback/default group if no Assignment Group is found.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
03-24-2021 05:50 AM
Beat me to it Chris!
Hi Nicole, hope all is well.
Chris is absolutely correct - a scripted rule should check whether it has successfully retrieved a group, and try another way or return the default group if it has not.
This is probably not how most people would assume Assignment rules work, and your assumptions are perfectly reasonable. So I'd like to also share how they are executed so you and your colleagues can interrogate the logic yourselves.
Assignment rules are run by a Business Rule on the Vulnerable Item table named "Run assignment rules". This business rule invokes the Script Include "AssignmentUtils", and calls the method "getAssignmentGroup" in that Script include.
While it does check to see if any object has been returned, this just ensures there hasn't been an error when evaluating the script. Here's the script itself, from Vulnerability Response version 13.0.3:
getAssignmentGroup: function(vulItem) {
var assignment_info = {};
assignment_info['assignment_group'] = "";
assignment_info['assignment_rule'] = "";
var assignmentGroup = "";
// Iterate assignment rules
var assignmentRules = this._getAssignmentRules();
if ((!assignmentRules) || (!assignmentRules.list) || (!assignmentRules.rules))
return assignment_info;
for (var i = 0; i < assignmentRules.list.length; i++) {
var gr = assignmentRules.rules[assignmentRules.list[i]];
// This check ensures,
// (1) The assignment rules for Infrastructure Vulnerability are applied
// only for Vulnerable Item (sn_vul_vulnerable_item) records
// (2) The assignment rules for Application Vulnerability are applied
// only on Application flaw (sn_vul_app_vulnerable_item) records
if (gr.table != vulItem.sys_class_name)
continue;
// If the condition is empty, this is a default condition, always matches
if ((!gr.condition) || (this.util.checkRecord(vulItem, gr.condition))) {
// Simple group
if (gr.type == "1")
assignmentGroup = gr.assignment_group;
// Assignment group field
else if (gr.type == "2") {
var arr = gr.assignment_group_fields.split('.');
var recordPosition = vulItem;
for (var x = 0; x < arr.length; x++) {
var columnName = arr[x];
recordPosition = recordPosition[columnName]; // dot walking into assignment group
if (recordPosition == null)
break;
}
assignmentGroup = recordPosition;
// Script
} else if (gr.type == "3") {
var evaluator = new GlideScopedEvaluator();
evaluator.putVariable("current", vulItem);
evaluator.evaluateScript(assignmentRules.rules[assignmentRules.list[i]], "script", null);
assignmentGroup = vulItem.assignment_group;
}
// return the assignment information
assignment_info = {};
assignment_info['assignment_group'] = assignmentGroup;
assignment_info['assignment_rule'] = gr.sys_id;
return assignment_info;
}
}
return assignment_info;
},
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
03-24-2021 03:35 PM
Thanks Chris, Julian - really appreciate the quick response! Now I can finally stop banging my head against the wall about why VIs are left unassigned. Ok will have a chat to our internal SNOW developers about adding the extra line of code to nominate an assignment group if the script returns nothing.
Is there any chance SNOW would consider an enhancement to the getAssignmentGroup function to traverse through the assignment rules until it either a. returns an Assignment Group or b. gets to the last assignment rule in the execution order?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
03-24-2021 03:54 PM
Hey Chris, Julian,
Or maybe we could modify the OOB script ourselves? Paul from our team has suggested we could change this part of the script from:
assignment_info = {};
assignment_info['assignment_group'] = assignmentGroup;
assignment_info['assignment_rule'] = gr.sys_id;
return assignment_info;
assignment_info = {};
assignment_info['assignment_group'] = assignmentGroup;
assignment_info['assignment_rule'] = gr.sys_id;
return assignment_info;