Name
sn_em_tbac.EvtMgmtTagBasedComparators
Description
Function to compare values for Tag Based Alert Clustering Engine. This script is being called from alert correlation rules.
Script
var EvtMgmtTagBasedComparators = Class.create();
EvtMgmtTagBasedComparators.prototype = {
type: 'EvtMgmtTagBasedComparators',
initialize: function() {
// Is correlation case sensitive property, defaults to true.
this.correlationCaseSensitiveProperty = gs.getProperty('sa_analytics.correlation_case_sensitive', 'true');
// List of allowed algorithms
this.allowedFuzzyAlgorithms = gs.getProperty('evt_mgmt.sn_em_tbac.allowed_fuzzy_algorithms', '');
// Supported algorithm names
this.LEVENSHTEIN = 'levenshtein';
// Default fuzzy algorithm
this.DEFAULT_FUZZY_ALGORITHM = this.LEVENSHTEIN;
},
/*
* Returns true if s1 is equal to s2, taking the correlation case sensitivity property into consideration.
* Returns false if the given arguments are not strings, or if the strings aren't equal.
*/
exact: function(s1, s2) {
if (!this.areStrings(s1, s2)) {
return false;
}
// If the property is set to false then lower case the strings before comparing them.
if (!this.isCorrelationCaseSensitive()) {
s1 = s1.toLowerCase();
s2 = s2.toLowerCase();
}
return s1 == s2;
},
/*
* Fuzzy function to return true if strings are similar.
*/
fuzzy: function(similarity, s1, s2, algorithm) {
similarity = Number(similarity);
if (!this.areStrings(s1, s2) || isNaN(similarity) || similarity < 0 || similarity > 100) {
return false;
}
similarity = similarity / 100; // convert to a number between [0,1]
// Set default algorithm if the given algorithm is NOT allowed
if (this.allowedFuzzyAlgorithms && !this.allowedFuzzyAlgorithms.includes(algorithm)) {
algorithm = this.DEFAULT_FUZZY_ALGORITHM;
}
var result = 0;
// In case of fuzzy match, always transform the compared string to lower case.
s1 = s1.toLowerCase();
s2 = s2.toLowerCase();
switch (algorithm) {
case this.LEVENSHTEIN:
result = this._levenshteinAlgorithm(s1, s2);
break;
}
return result >= similarity;
},
/*
* Returns true if each of s1 and s2 are matching the given pattern, false otherwise.
*/
pattern: function(s1, s2, patternAsRegexWithoutFlags) {
if (!this.areStrings(s1, s2)) {
return false;
}
// As regex with flags: i - case insensitive, g - global (all occurrences in string).
// Add the case-insensitive flag only if the correlation case sensitivity property is set to false.
var caseInsensitiveFlag = (!this.isCorrelationCaseSensitive()) ? 'i' : '';
var flags = caseInsensitiveFlag + 'g'; // 'ig' or 'g' depends on case sensitivity property.
var regexp = new RegExp(patternAsRegexWithoutFlags, flags);
return (s1.match(regexp) != null) && (s2.match(regexp) != null);
},
/*
* Returns true if the given GR is matching the given filter condition, false otherwise.
* Takes the correlation case sensitivity property value into consideration.
*/
checkRecord: function(gr, filterCondition) {
if (!gr || !gr.isValidRecord()) {
return false;
}
var glideFilter = new GlideFilter(filterCondition, 'filterConditionWithCases');
// If the property is set to false then set the case sensitive flag to false.
if (!this.isCorrelationCaseSensitive()) {
glideFilter.setCaseSensitive(false);
}
return glideFilter.match(gr, true);
},
// Levenshtein distance algorithm for Fuzzy match comparison.
_levenshteinAlgorithm: function(a, b) {
if (a.length == 0) return b.length;
if (b.length == 0) return a.length;
var matrix = [];
// increment along the first column of each row
var i;
for (i = 0; i <= b.length; i++) {
matrix[i] = [i];
}
// increment each column in the first row
var j;
for (j = 0; j <= a.length; j++) {
matrix[0][j] = j;
}
// Fill in the rest of the matrix
for (i = 1; i <= b.length; i++) {
for (j = 1; j <= a.length; j++) {
if (b.charAt(i - 1) == a.charAt(j - 1)) {
matrix[i][j] = matrix[i - 1][j - 1];
} else {
matrix[i][j] = Math.min(matrix[i - 1][j - 1] + 1, // substitution
Math.min(matrix[i][j - 1] + 1, // insertion
matrix[i - 1][j] + 1)); // deletion
}
}
}
var levenshteinDistance = matrix[b.length][a.length];
// Addition to levenshtein distance, to get the result as decimal.
return (1 - (levenshteinDistance / Math.max(a.length, b.length)));
},
isCorrelationCaseSensitive: function() {
return this.correlationCaseSensitiveProperty == 'true';
},
// Returns true if the type of s1 and s2 is string, false otherwise.
areStrings: function(s1, s2) {
return (typeof s1 === 'string' && typeof s2 === 'string');
}
};
Sys ID
08d44353532c70107c03ddeeff7b120a