Servicenow and Crowdstrike integration error

LearnerSN7
Tera Contributor

While integration between Crowdstrike and servicenow we are recieving below error while running load all records from the devices data source. Please help if anyone has also faced the same issue during the integration.

 

TypeError: Cannot read property "length" from undefined (sys_script_include.96d149bc1b837010968c0e16dc4bcbd0.script; line 335)

Thanks
2 REPLIES 2

Bhuvan
Kilo Patron

@LearnerSN7 

 

It means you are getting empty payload where data was expected that results in error

 

https://www.servicenow.com/community/servicenow-ai-platform-forum/getting-error-quot-cannot-read-pro...

 

There is a reported issue in Crowdstrike integration that is resolved by following below thread

 

https://www.servicenow.com/community/cmdb-forum/sg-crowdstrike-data-source-is-not-pulling-data-after...

 

If this helped to answer your query, please mark it helpful & accept the solution. 

 

Thanks,

Bhuvan

var ActionHelper = Class.create();
ActionHelper.prototype = {
initialize: function (import_set_table, utils) {
this.import_set_table = import_set_table;
this.util = utils;
this.DeploymentImportController = new DeploymentImportController();
this.ServiceImportController = new ServiceImportController();
this.minWaitTimeInMs = 20000;
this.maxWaitTimeInMs = 100000;
this.MAX_RETRY_COUNT = 3;
gs.include('Constants');
},
loadData: function (connection_alias) {
var config = this.util.getConfiguration(connection_alias);
var firstRun = true;
for (var item in config) {
var connectionAliasGr = this.getAuth(connection_alias);
if (config[item].get_host_details == 1) {
var hostFilter = this.util.buildFilter(config[item].host_details_filter, config[item].timestamp, "host")[0];
gs.info('Beginning falcon device Sync. Filter: {0}', hostFilter);
var deviceData = this.loadDeviceIds(connectionAliasGr, hostFilter);
}
for (var i = 0; i < deviceData.length; i++) {
var idList = deviceData[i];
var dataToLoad = this.loadDeviceData(connectionAliasGr, idList);
dataToLoad = this.util.keepKeys(dataToLoad, SUPPORTED_HOST_FIELDS);
if (config[item].get_asset_details == 1) {
var assetFilters = this.util.buildFilter(config[item].asset_details_filter, config[item].timestamp, "asset", dataToLoad);
var assetData = [];
for (var assetFilter in assetFilters) {
gs.info('Beginning Falcon managed asset Sync. Filter: {0}', assetFilters[assetFilter]);
assetData = [...assetData, ...this.loadDiscoverData(connectionAliasGr, "/discover/queries/hosts/v1", "/discover/entities/hosts/v1", assetFilters[assetFilter], 'asset')];
}
var assetFlatten = JSON.stringify(assetData[0]);
if (typeof (assetFlatten) != "undefined" && firstRun) {
this.util.flattenObjectWithPrefix(JSON.parse(assetFlatten), "asset.", this.import_set_table, ["groups", "field_metadata", "local_ip_addresses", "mac_addresses", "triage"]);
}
}
if (config[item].get_iot_details == 1) {
var iotFilters = this.util.buildFilter(config[item].iot_data_filter, config[item].timestamp, "iot", dataToLoad);
var iotData = [];
for (var filter in iotFilters) {
gs.info('Beginning Falcon IoT Sync. Filter: {0}', iotFilters[filter]);
iotData = [...iotData, ...this.loadDiscoverData(connectionAliasGr, "/discover/queries/iot-hosts/v1", "/discover/entities/iot-hosts/v1", iotFilters[filter], 'IOT')];
}
var iotFlatten = JSON.stringify(iotData[0]);
if (typeof (iotFlatten) != "undefined" && firstRun) {
this.util.flattenObjectWithPrefix(JSON.parse(iotFlatten), "iot.", this.import_set_table, ["groups", "field_metadata", "triage", "ou"]);
}
}
if (dataToLoad) {
if ((typeof assetData != "undefined") & (typeof iotData != "undefined")) {
//merge Asset&IoT Data
//merge with Device Details
var assetMerge = this.util.mergeLists(this.util.mapAssets(assetData), this.util.mapIOT(iotData), "asset.id", "iot.id");
dataToLoad = this.util.mergeLists(dataToLoad, assetMerge, "device_id", "asset.aid");
} else if (typeof assetData != "undefined") {
//merge Asset & Device
dataToLoad = this.util.mergeLists(dataToLoad, this.util.mapAssets(assetData), "device_id", "asset.aid");
} else if (typeof iotData != "undefined") {
//merge IoT & Device
dataToLoad = this.util.mergeLists(dataToLoad, this.util.mapAssets(iotData), "device_id", "iot.aid");
}
this.util.mapComputer(this.import_set_table, dataToLoad);
}
firstRun = false;
}
this.util.setLastRunTime(config[item].sys_id);
}
},
loadSofwareData: function (connection_alias) {
var config = this.util.getConfiguration(connection_alias);
for (var item in config) {
var connectionAliasGr = this.getAuth(connection_alias);
if (config[item].get_application_details == 1) {
var appFilter = this.util.buildFilter(config[item].application_details_filter, config[item].application_timestamp, "application");
gs.info('Beginning Falcon app Sync. Filter: {0}', appFilter);
this.loadDiscoverData(connectionAliasGr, "/discover/queries/applications/v1", "/discover/entities/applications/v1", appFilter[0], 'application');
this.util.setLastRunTime(config[item].sys_id, "application");
}
}
},
loadASPMDeployments: function (connection_alias) {
var config = this.util.getConfiguration(connection_alias);
var maxRow = this.import_set_table.getMaximumRows();
for (var item in config) {
var connectionAliasGr = this.getAuth(connection_alias);
if (config[item].get_deployment_details == 1) {
//var appFilter = this.util.buildFilter(config[item].application_details_filter, config[item].application_timestamp, "application");
//gs.info('Beginning Falcon app Sync. Filter: {0}', appFilter);
this.DeploymentImportController.beginImport(import_set_table, connectionAliasGr, config[item].description, maxRow);
//this.util.setLastRunTime(config[item].sys_id, "deployment");
}
}
},
loadASPMServices: function (connection_alias) {
var config = this.util.getConfiguration(connection_alias);
var maxRow = this.import_set_table.getMaximumRows();
for (var item in config) {
var connectionAliasGr = this.getAuth(connection_alias);
if (config[item].get_deployment_details == 1) {
//var appFilter = this.util.buildFilter(config[item].application_details_filter, config[item].application_timestamp, "application");
//gs.info('Beginning Falcon app Sync. Filter: {0}', appFilter);
this.ServiceImportController.beginImport(import_set_table, connectionAliasGr, config[item].description, maxRow);
//this.util.setLastRunTime(config[item].sys_id, "deployment");
}
}
},
loadASPMServicesExtra: function (connection_alias) {
var config = this.util.getConfiguration(connection_alias);
var maxRow = this.import_set_table.getMaximumRows();
for (var item in config) {
var connectionAliasGr = this.getAuth(connection_alias);
if (config[item].get_deployment_details == 1) {
//var appFilter = this.util.buildFilter(config[item].application_details_filter, config[item].application_timestamp, "application");
//gs.info('Beginning Falcon app Sync. Filter: {0}', appFilter);
this.ServiceImportController.beginExtrasImport(import_set_table, connectionAliasGr, config[item].description, maxRow);
//this.util.setLastRunTime(config[item].sys_id, "deployment");
}
}
},
loadUnmanagedData: function(connection_alias) {
var config = this.util.getConfiguration(connection_alias);
var connectionAliasGr = this.getAuth(connection_alias);
var mergedData = [];

// Process each configuration item
for (var item in config) {
var unmanaged_asset_data = [];
var unmanaged_iot_data = [];

// Load Unmanaged Asset Data if enabled
if (config[item].get_unmanaged_asset_details == 1) {
var assetFilters = this.util.buildFilter(
config[item].unmanaged_asset_details_filter,
config[item].unmanaged_timestamp,
"unmanaged"
);

for (var filter in assetFilters) {
gs.info('Beginning Unmanaged Asset Sync. Filter: {0}', assetFilters[filter]);
unmanaged_asset_data = [...unmanaged_asset_data,
...this.loadDiscoverDataInChunks(
connectionAliasGr,
"/discover/queries/hosts/v1",
"/discover/entities/hosts/v1",
assetFilters[filter],
'unmanaged',
1000,
function(chunk) {
// Optional: Process chunks as they come in
gs.debug('Processing chunk of unmanaged assets: ' + chunk.length);
}
)
];
}
var assetFlatten = JSON.stringify(unmanaged_asset_data[0]);
this.util.flattenObjectWithPrefix(JSON.parse(assetFlatten), "asset.", this.import_set_table, ["groups", "field_metadata"]);
}

// Load Unmanaged IOT Data if enabled
if (config[item].get_unmanaged_iot_hosts == 1) {
var iotFilters = this.util.buildFilter(
config[item].unmanaged_iot_details_filter,
config[item].unmanaged_timestamp,
"unmanaged"
);

for (var filter in iotFilters) {
gs.info('Beginning Unmanaged IoT Sync. Filter: {0}', iotFilters[filter]);
unmanaged_iot_data = [...unmanaged_iot_data,
...this.loadDiscoverDataInChunks(
connectionAliasGr,
"/discover/queries/iot-hosts/v1",
"/discover/entities/iot-hosts/v1",
iotFilters[filter],
'IOT',
1000,
function(chunk) {
// Optional: Process chunks as they come in
gs.debug('Processing chunk of unmanaged IoT devices: ' + chunk.length);
}
)
];
}
var iotFlatten = JSON.stringify(unmanaged_iot_data[0]);
this.util.flattenObjectWithPrefix(JSON.parse(iotFlatten), "iot.", this.import_set_table, ["groups", "field_metadata"]);
}

// Merge data if both sources are present
if (unmanaged_asset_data.length > 0 && unmanaged_iot_data.length > 0) {
gs.info('Merging Unmanaged Asset and IoT data');
mergedData = this.util.mergeLists(
this.util.mapAssets(unmanaged_asset_data),
this.util.mapIOT(unmanaged_iot_data),
'asset.id',
'iot.id'
);
} else if (unmanaged_asset_data.length > 0) {
mergedData = unmanaged_asset_data;
} else if (unmanaged_iot_data.length > 0) {
mergedData = unmanaged_iot_data;
}

// Process merged data
if (mergedData.length > 0) {
// Insert or update records in import set table
this.processUnmanagedData(mergedData);
}

// Update last run time
this.util.setLastRunTime(config[item].sys_id, "unmanaged");
}

return mergedData;
},
processUnmanagedData: function(data) {
if (!data || !data.length) {
gs.warn('No unmanaged data to process');
return;
}

var batchSize = 1000;
var processedCount = 0;

try {
// Process data in batches
for (var i = 0; i < data.length; i += batchSize) {
var batch = data.slice(i, Math.min(i + batchSize, data.length));
 
// Call utility method to map and process the batch
this.util.mapUnmanaged(this.import_set_table, batch);
 
processedCount += batch.length;
gs.info('Processed ' + processedCount + ' of ' + data.length + ' records');
}

gs.info('Successfully processed ' + processedCount + ' unmanaged device records');

} catch (ex) {
gs.error('Error processing unmanaged data: ' + ex);
throw ex;
}
},
loadDiscoverDataInChunks: function (connectionAliasGr, idsPath, detailPath, filter, type, chunkSize, chunkProcessor) {
gs.debug("Filter Is: " + filter);
var records = [];
var sort = (type == "application") ? "last_updated_timestamp.asc" : "last_seen_timestamp.asc";
var totalProcessed = 0;
var batchSize = 10000;

while (true) {
var response = this.getDiscoverIds(connectionAliasGr, filter, sort, idsPath);
gs.info("Collected " + response.length + " Discover IDs to update.");

var ids = response.map(function (item) {
return item.application_id;
});

var chunked_ids = this.util.chunkArray(ids, 100);
for (var i = 0; i < chunked_ids.length; i++) {
var formatIdList = this.util.formatIdList(chunked_ids[i]);
var data = this.getDiscoverDetails(connectionAliasGr, formatIdList, detailPath);

if (type == 'application') {
var newTime = this.util.mapSoftware(this.import_set_table, data);
} else {
// Process other types in chunks
var processedData;
switch (type) {
case 'unmanaged':
processedData = this.util.keepKeys(data, SUPPORTED_UNMANAGED_FIELDS);
break;
case 'asset':
processedData = this.util.keepKeys(data, SUPPORTED_ASSET_FIELDS);
break;
case 'IOT':
processedData = this.util.keepKeys(data, SUPPORTED_IOT_FIELDS);
break;
}

if (processedData) {
var dataChunks = this.util.chunkArray(processedData, chunkSize);
dataChunks.forEach(function (chunk) {
if (chunkProcessor) {
chunkProcessor(chunk);
}
records = records.concat(chunk);
});
}
}
}

totalProcessed += response.length;

if (response.length < batchSize) {
break;
}

// Update filter for next iteration
if (type == 'application') {
filter = this.util.replaceTimestamp(filter, newTime);
} else {
var lastItem = records[records.length - 1];
var newTimestamp = lastItem.last_seen_timestamp;
filter = this.util.replaceTimestamp(filter, newTimestamp);
}

gs.debug("Processed " + totalProcessed + " records. Updating timestamp for next batch: " + filter);
}
gs.info("Total records processed: " + totalProcessed);
return records;
},
loadDeviceIds: function (connectionAliasGr, filter) {
var retryCount = 0;
var isSuccess = true;
do {
try {
var response = this.invokeAction('x_crowd_cmdb.crowdstrike_falcon_device_details', {
"connectionalias": connectionAliasGr,
"filter": filter
});
}
catch (e) {
if (retryCount++ < this.MAX_RETRY_COUNT) {
isSuccess = false;
gs.info("getIDs call failed due to bad return status in one or more calls. Retrying, retryCount:" + retryCount);
this.sleepInScopedApplication(retryCount - 1);
} else {
gs.error("Retry limit reached. Unable to gather IDs");
isSuccess = true;
}
}
} while (!isSuccess);
gs.info("Collected " + response.length + " Device IDs to update.");
var ids = [];
for (var i = 0; i < response.length; i++) {
ids.push(response[i].aid);
}
return this.util.chunkArray(ids, 1000);
},
loadDeviceData: function (connectionAliasGr, chunked_ids) {
var formatIdList = {};
var records = [];
formatIdList.ids = chunked_ids;
retryCount = 0;
var isSuccess = true;
do {
try {
var data = this.invokeAction('x_crowd_cmdb.sgcrowdstrike_details', {
"connectionalias": connectionAliasGr,
"ids": JSON.stringify(formatIdList)
});
for (var item in data) {
var str = JSON.stringify(data[item]);
var result = JSON.parse(str);
records.push(JSON.parse(result.device));
}
} catch (e) {
if (retryCount++ < this.MAX_RETRY_COUNT) {
isSuccess = false;
gs.info("Batch failed due to bad return status in one or more calls. Retrying, retryCount:" + retryCount);
this.sleepInScopedApplication(retryCount - 1);
} else {
gs.error("Retry limit reached. Unable to process IDs: " + JSON.stringify(formatIdList.ids));
isSuccess = true;
}
}
} while (!isSuccess);

return records;
},
loadDiscoverData: function(connectionAliasGr, idsPath, detailPath, filter, type) {
return this.loadDiscoverDataInChunks(connectionAliasGr, idsPath, detailPath, filter, type, 1000, null);
},
getDiscoverIds: function (connectionAliasGr, filter, sort, idsPath) {
var retryCount = 0;
while (retryCount <= this.MAX_RETRY_COUNT) {
try {
return this.invokeAction('x_crowd_cmdb.sgcrowdstrike_getapplicationids', {
"connectionalias": connectionAliasGr,
"filter": filter,
"sort": sort,
"path": idsPath
});
} catch (e) {
if (retryCount++ < this.MAX_RETRY_COUNT) {
gs.info("getIDs call failed. Retrying, retryCount:" + retryCount);
this.sleepInScopedApplication(retryCount - 1);
} else {
gs.error("Retry limit reached. Unable to gather IDs");
throw e;
}
}
}
},
getDiscoverDetails: function (connectionAliasGr, formatIdList, detailPath) {
var retryCount = 0;
while (retryCount <= this.MAX_RETRY_COUNT) {
try {
return this.invokeAction('x_crowd_cmdb.sgcrowdstrike_getapplicationdetails', {
"connectionalias": connectionAliasGr,
"ids": formatIdList,
"path": detailPath
});
} catch (e) {
if (retryCount++ < this.MAX_RETRY_COUNT) {
gs.info("Batch failed. Retrying, retryCount:" + retryCount);
this.sleepInScopedApplication(retryCount - 1);
} else {
gs.error("Retry limit reached. Unable to process IDs: " + JSON.stringify(formatIdList.ids));
throw e;
}
}
}
},
getAuth: function (sys_id) {
var glideRecordInput = new GlideRecord('sys_alias');
if (glideRecordInput.get(sys_id)) {
return glideRecordInput;
}
},
invokeAction: function (name, args) {
var stream;
var maxRows = 0;
try {
maxRows = import_set_table.getMaximumRows();
} catch (err) { }

if (!maxRows)
maxRows = 0;

var data = [];
try {
stream = sn_fd.FlowAPI.executeDataStreamAction(name, args);
if (gs.nil(stream)) {
gs.error(gs.getMessage("No response from action {0}", [name]));
return;
}
// Process each item in the data stream
while (stream.hasNext()) {
// Get a single item from the data stream.
var item = stream.next();

// Use the item.
data.push(item);

//only get the max rows for the import set
if (stream.getItemIndex() >= maxRows && maxRows > 0) {
gs.info("Max Rows Reached: " + maxRows);
break;
}
}

return data;

} catch (err) {
var message = err.toString();
gs.error("SG CrowdStrike Error: " + message);
if (message == 'Null stream found') {
return;
} else {
throw message;
}

}

},

sleepInScopedApplication: function (retryCount) {
var waitTime = Math.min(this.maxWaitTimeInMs, Math.pow(2, retryCount) * this.minWaitTimeInMs);
this._waitInMs(waitTime);
gs.info("Waiting for " + waitTime + " ms at retry count " + (retryCount + 1));
},

_waitInMs: function (time) {
var startTime = new GlideDateTime().getNumericValue();
var currentTime;
do {
currentTime = new GlideDateTime().getNumericValue();
} while (currentTime - startTime < time);
},

type: 'ActionHelper'
};
 
This has something to do above script.
Thanks