Name

sn_grc.GRCCMDBQueryIntegrationBase

Description

This script include contains functionalities to integrate with CMDB query builder for entity scoping.

Script

var GRCCMDBQueryIntegrationBase = Class.create();
GRCCMDBQueryIntegrationBase.prototype = {
  cmdbQueryUtils: new global.CMDBQueryUtils(),

  initialize: function() {
      var queryResults = null,
          queryResultsWithIO = null;
  },

  findConfigurationItems: function(hashValue, table, queryId, filters, isEncodedQuery) {
      var cmdbQueryResults = {
              ciWithoutIORelations: null,
              ciWithIORelations: null,
              result: false
          },
          finalResults = null;
      try {
          if (gs.nil(table) || gs.nil(queryId)) {
              return cmdbQueryResults;
          }

          var existingCmdbGroupApiResponse = this._getExistingQueryResults(queryId, hashValue);
          if (!gs.nil(existingCmdbGroupApiResponse)) {
              cmdbQueryResults.result = true;
              cmdbQueryResults.ciWithoutIORelations = existingCmdbGroupApiResponse.results;
              cmdbQueryResults.ciWithIORelations = this.queryResultsWithIO[hashValue] ? this.queryResultsWithIO[hashValue] : null;
          } else {
              finalResults = this._getResultsFromCMDB(table, queryId, null, filters, isEncodedQuery, false, hashValue);
              cmdbQueryResults.result = finalResults.result;
              cmdbQueryResults.ciWithoutIORelations = finalResults.ciWithoutIORelations;
              cmdbQueryResults.ciWithIORelations = finalResults.ciWithIORelations ? finalResults.ciWithIORelations : null;
          }

      } catch (ex) {
          gs.error(gs.getMessage('Exception occured from sn_grc.GRCCMDBQueryIntegrationBase.findConfigurationItems: {0}', ex.toString()));
      }

      return cmdbQueryResults;
  },

  getCMDBQueryNodes: function(queryId) {
      return this._getCMDBQueryNodes(queryId);
  },

  _getExistingQueryResults: function(queryId, entityFilterId) {
      if (gs.nil(this.queryResults) || this.queryResults.length == 0) return null;
      for (var i = 0; i < this.queryResults.length; i++) {
          if (queryId == this.queryResults[i].queryId) {
              for (var j = 0; j < this.queryResults[i].results.length; j++) {
                  if (entityFilterId == this.queryResults[i].results[j].hash) {
                      return this.queryResults[i].results[j];
                  }
              }
          }
      }
  },

  _getResultsFromCMDB: function(table, queryId, configurationItems, filters, isEncodedQuery, isIOMappingRequired, hashValue) {
      var resultsResponse = {
          result: false

      };
      var queryDetails = this._getQueryWithFilters(queryId, filters, isEncodedQuery);
      var isNewApiAvailable = !gs.nil(this.cmdbQueryUtils.getCMDBQueryExecutionDetails);

      if (!gs.nil(queryDetails.queryJson)) {
          var cmdbResponse = isNewApiAvailable ? this._invokeCMDBNewAPI(queryDetails, hashValue, table) : this._invokeCMDB(queryDetails, hashValue);
          resultsResponse.result = cmdbResponse.result;
          var resultCis = (cmdbResponse.result && !gs.nil(cmdbResponse.outputCis)) ? isNewApiAvailable ? Object.keys(cmdbResponse.outputCis) : JSON.parse(cmdbResponse.outputCis) : null;

          cmdbResponse.newGroupId ? this._associateCmdbGroupToEntityFilter(hashValue, cmdbResponse.newGroupId) : '';
          if (!gs.nil(resultCis) && resultCis.length > 0) {
              var queryIO = {
                  hash: hashValue,
                  resultTable: this._getQueryResultTable(cmdbResponse.newQueryId),
                  queryName: cmdbResponse.newQueryName,
                  results: resultCis
              };

              if (gs.nil(this.queryResults)) this.queryResults = [];

              var queryResultsAvailable = false;
              for (var i = 0; i < this.queryResults.length; i++) {
                  if (queryId == this.queryResults[i].queryId) {
                      var existingFiltersAvailable = false;
                      for (var j = 0; j < this.queryResults[i].results.length; j++) {
                          if (queryIO.hash == this.queryResults[i].results[j].hash) {
                              this.queryResults[i].results[j] = queryIO;
                              existingFiltersAvailable = true;
                              break;
                          }
                      }
                      if (!existingFiltersAvailable) {
                          this.queryResults[i].results.push(queryIO);
                      }
                      queryResultsAvailable = true;
                      break;
                  }
              }

              if (!queryResultsAvailable) {
                  var queryResult = {
                      queryId: queryId,
                      results: [queryIO]
                  };

                  this.queryResults.push(queryResult);
              }

              if (isNewApiAvailable) {
                  if (gs.nil(this.queryResultsWithIO)) this.queryResultsWithIO = {};
                  this.queryResultsWithIO[hashValue] = cmdbResponse.outputCis;
                  resultsResponse.ciWithIORelations = cmdbResponse.outputCis;
              }

              resultsResponse.ciWithoutIORelations = resultCis;
          }
      }

      return resultsResponse;
  },

  _getExistingResultTable: function(queryId, hashValue) {
      var table = null;

      if (!gs.nil(this.queryResults) && this.queryResults.length > 0) {

          for (var i = 0; i < this.queryResults.length; i++) {
              if (queryId == this.queryResults[i].queryId) {
                  for (var j = 0; j < this.queryResults[i].results.length; j++) {
                      if (hashValue == this.queryResults[i].results[j].hash) {
                          table = this.queryResults[i].results[j].resultTable;
                          break;
                      }
                  }
              }
          }
      }

      return table;
  },

  _getCMDBQueryNodes: function(queryId) {
      var nodes = [];
      var queryDetails = this._getSelectedQueryDetails(queryId);

      if (!gs.nil(queryDetails)) {
          var jsonObject = JSON.parse(queryDetails.queryJson);
          if (jsonObject.nodes.length > 0) {
              var ioTableName = 'cmdb_ci_information_object';
              for (var i = 0; i < jsonObject.nodes.length; i++) {
                  var node = {};
                  node.isStartNode = jsonObject.nodes[i].isStartNode;
                  node.nodeId = jsonObject.nodes[i].nodeId;
                  node.table = jsonObject.nodes[i].ci_type;
                  node.name = jsonObject.nodes[i].ci_type_label;
                  node.isEndNode = false;

                  if (!node.isStartNode) {
                      if (node.table == ioTableName) {
                          node.isEndNode = true;
                          for (var j = 0; j < jsonObject.edges.length; j++) {
                              if (node.nodeId == jsonObject.edges[j].from) {
                                  node.isEndNode = false;
                                  break;
                              }
                          }
                      }
                  }

                  nodes.push(node);
              }
          }
      }

      return nodes;
  },

  _getEncodedQueryForGivenCis: function(table, sysIds, ioFilters) {
      var encodedQuery = this._getEncodedQuery(ioFilters, false);
      if (gs.nil(encodedQuery)) {
          encodedQuery = {};
      }
      encodedQuery[table] = 'sys_idIN' + sysIds.join(',');

      return encodedQuery;
  },

  _invokeCMDBNewAPI: function(queryDetails, hashValue, table) {
      var queryRecordDetails = '',
          newQueryId = '';

      var entityTypeFilter = new GlideRecord('sn_grc_enrichment_query');
      if (!entityTypeFilter.get(hashValue)) return;
      var cmdbQueryGr = entityTypeFilter.final_query;
      cmdbQueryGr = cmdbQueryGr.nil() ? '' : cmdbQueryGr.getRefRecord();

      if (cmdbQueryGr && cmdbQueryGr.isValidRecord()) {
          queryRecordDetails = [cmdbQueryGr.getUniqueValue(), cmdbQueryGr.getValue('name')];
      }

      if (gs.nil(queryRecordDetails)) {
          queryRecordDetails = this._createCMDBQuery(queryDetails);
          newQueryId = queryRecordDetails[0];

          entityTypeFilter.setValue('final_query', newQueryId);
          entityTypeFilter.update();
      } else {
          newQueryId = queryRecordDetails[0];
          this._updateCMDBQuery(newQueryId, queryDetails);
      }

      if (gs.nil(queryRecordDetails) || queryRecordDetails.length < 2) return null;

      var response = this._executeQueryForResults(queryRecordDetails[1]);

      var ciIOMappings = this._getDataFromResultTable(newQueryId, response.resultTable);

      return {
          result: response.isSuccess,
          outputCis: ciIOMappings,
          newQueryId: newQueryId,
          newQueryName: queryRecordDetails[1]
      };
  },

  _invokeCMDB: function(queryDetails, hashValue) {
      var groupId = '',
          queryRecordDetails = null,
          newQueryId = '';
      var grEntityFilterToCmdbGroup = new GlideRecord("sn_grc_m2m_enrichment_query_cmdb_group");
      grEntityFilterToCmdbGroup.addQuery('entity_filter', hashValue);
      grEntityFilterToCmdbGroup.query();
      if (grEntityFilterToCmdbGroup.next()) {
          groupId = grEntityFilterToCmdbGroup.getValue('cmdb_group');
          queryRecordDetails = this._getExistingCMDBQueryDetails(groupId);
      } else {
          groupId = this._createCMDBGroup();
      }

      if (gs.nil(queryRecordDetails)) {
          queryRecordDetails = this._createCMDBQuery(queryDetails);
          newQueryId = queryRecordDetails[0];
          this._createMappingBetweenGroupAndQuery(groupId, newQueryId);
      } else {
          newQueryId = queryRecordDetails[0];
          this._updateCMDBQuery(queryRecordDetails[0], queryDetails);
      }

      if (gs.nil(queryRecordDetails) || queryRecordDetails.length < 2) return null;

      var response = this._executeCMDBGroup(groupId);

      return {
          result: response.result,
          outputCis: response.outputCis,
          newGroupId: groupId,
          newQueryId: newQueryId,
          newQueryName: queryRecordDetails[1]
      };
  },

  _updateCMDBQuery: function(queryId, latestQueryDetails) {
      var gr = new GlideRecord('qb_saved_query');
      if (gr.get(queryId)) {
          gr.setValue("query", latestQueryDetails.queryJson);
          gr.update();
      }
  },

  _getExistingCMDBQueryDetails: function(groupId) {
      var grGroupToQueryMapper = new GlideRecord('cmdb_group_contains_qb_query');
      grGroupToQueryMapper.addQuery('group', groupId);
      grGroupToQueryMapper.query();

      while (grGroupToQueryMapper.next()) {
          var grCmdbQuery = new GlideRecord('qb_saved_query');
          if (grCmdbQuery.get(grGroupToQueryMapper.getValue('qb_query'))) {
              return [grCmdbQuery.getUniqueValue(), grCmdbQuery.getValue('name')];
          }
      }

      return null;
  },

  _getQueryWithFilters: function(queryId, filters, isEncodedQuery) {
      var requiredDetailsForNewQuery = {
          queryJson: '',
          resultTableName: ''
      };
      var selectedQueryDetails = this._getSelectedQueryDetails(queryId);

      if (gs.nil(selectedQueryDetails.queryJson)) {
          return requiredDetailsForNewQuery;
      }

      requiredDetailsForNewQuery.resultTableName = selectedQueryDetails.resultTableName;

      var encodedQuery = this._getEncodedQuery(filters, isEncodedQuery);

      requiredDetailsForNewQuery.queryJson = selectedQueryDetails.queryJson;

      if (!gs.nil(encodedQuery)) {
          var nodeKeys = Object.keys(encodedQuery);
          if (nodeKeys.length > 0) {
              var jsonObject = JSON.parse(selectedQueryDetails.queryJson);
              for (var j = 0; j < jsonObject.nodes.length; j++) {
                  if (!gs.nil(encodedQuery[jsonObject.nodes[j].ci_type])) {
                      jsonObject.nodes[j].filters_attrib = encodedQuery[jsonObject.nodes[j].ci_type];
                      jsonObject.nodes[j].applied_filters = encodedQuery[jsonObject.nodes[j].ci_type];
                  }
              }
              requiredDetailsForNewQuery.queryJson = JSON.stringify(jsonObject);
          }
      }

      return requiredDetailsForNewQuery;
  },

  _createCMDBGroup: function() {
      var groupName = this._guid();
      var grCmdbGroup = new GlideRecord('cmdb_group');
      grCmdbGroup.initialize();
      grCmdbGroup.setValue('group_name', groupName);
      var groupId = grCmdbGroup.insert();

      return groupId;
  },

  _createCMDBQuery: function(queryDetails) {
      var newQueryName = 'GRC_' + this._guid();
      var gr = new GlideRecord('qb_saved_query');
      gr.initialize();
      gr.setValue('name', newQueryName);
      gr.setValue('query', queryDetails.queryJson);
      var querySysId = gr.insert();

      return [querySysId, newQueryName];
  },

  _getDataFromResultTable: function(queryId, resultTableName) {
      if (gs.nil(resultTableName) || !gs.tableExists(resultTableName)) return null;

      var queryResultTableFields = this._getCMDBQueryFieldNames(queryId);

      if (gs.nil(queryResultTableFields)) return null;

      var startNodeField = queryResultTableFields['start_node'];
      var ioFields = queryResultTableFields['information_objects'];

      var results = {};
      var currentRecIndex = 0,
          offset = 1000;

      var resultsGr = new GlideRecord(resultTableName);
      resultsGr.chooseWindow(currentRecIndex, currentRecIndex + offset, false);
      resultsGr.query();

      while (resultsGr.hasNext()) {
          while (resultsGr.next()) {
              currentRecIndex++;

              var startNodeValue = resultsGr.getValue(startNodeField);
              results[startNodeValue] = results[startNodeValue] ? results[startNodeValue] : {};

              for (var key in ioFields) {
                  if (ioFields[key] && !gs.nil(resultsGr.getValue(ioFields[key])))
                      results[startNodeValue][resultsGr.getValue(ioFields[key])] = true;
              }
          }
          resultsGr.initialize();
          resultsGr.chooseWindow(currentRecIndex, currentRecIndex + offset, false);
          resultsGr.query();
      }

      return results;
  },

  _executeQueryForResults: function(queryName) {
      var globalAPIResponse = {
          error: {},
          resultTable: '',
          isSuccess: false
      };

      var executionResultsResponse = this.cmdbQueryUtils.getCMDBQueryExecutionDetails(queryName);
      if (!gs.nil(executionResultsResponse)) {
          executionResultsResponse = JSON.parse(executionResultsResponse);
          switch (executionResultsResponse.status) {
              case 'COMPLETE':
                  globalAPIResponse.isSuccess = true;
                  globalAPIResponse.resultTable = executionResultsResponse.table_name;
                  break;
              case 'FAILED':
                  globalAPIResponse.error = executionResultsResponse.error;
                  globalAPIResponse.isSuccess = false;
                  gs.error('sn_grc.GRCCMDBQueryIntegrationBase.getAssociationsFromQueryResults: CMDB Query execution failed. Error: ' + JSON.stringify(globalAPIResponse.error));
                  break;
              case 'TIME_OUT':
              case 'MAX_LIMIT':
                  globalAPIResponse.isSuccess = false;
                  gs.error('sn_grc.GRCCMDBQueryIntegrationBase.getAssociationsFromQueryResults: CMDB Query execution failed. Error: ' + JSON.stringify(executionResultsResponse.status));
                  break;
          }
      }
      return globalAPIResponse;
  },

  _createMappingBetweenGroupAndQuery: function(groupId, newQueryId) {
      var gr = new GlideRecord('cmdb_group_contains_qb_query');
      gr.initialize();
      gr.setValue('group', groupId);
      gr.setValue('qb_query', newQueryId);
      var sysId = gr.insert();

      return sysId;
  },

  _executeCMDBGroup: function(groupId) {
      var cmdbResponse = {
          outputCis: [],
          result: false
      };

      try {
          var response = sn_cmdbgroup.CMDBGroupAPI.getAllCIFromQueryBuilder(groupId, false, false);
          if (!gs.nil(response)) {
              var responseObj = JSON.parse(response);
              cmdbResponse.result = responseObj.result;
              if (responseObj.result && !gs.nil(responseObj.idList)) {
                  cmdbResponse.outputCis = JSON.stringify(responseObj.idList);
              }
          }
      } catch (ex) {
          gs.error('Error occured from sn_grc.GRCCMDBQueryIntegrationBase._executeCMDBGroup {0}', ex.toString());
      }

      return cmdbResponse;
  },

  _associateCmdbGroupToEntityFilter: function(entityFilterId, groupId) {
      if (!gs.nil(entityFilterId) && !gs.nil(groupId)) {
          new GRCUtils().associateCmdbGroupToEntityFilter(entityFilterId, groupId);
      }
  },

  _getSelectedQueryDetails: function(queryId) {
      var requiredDetails = {
          queryJson: '',
          resultTableName: ''
      };

      var glideRecord = new GlideRecord('qb_saved_query');
      glideRecord.addQuery('sys_id', queryId);
      glideRecord.query();
      if (glideRecord.next()) {
          requiredDetails.queryJson = glideRecord.getValue('query');
          requiredDetails.resultTableName = glideRecord.getValue('result_table');
      }

      return requiredDetails;
  },

  _getEncodedQuery: function(filters, isEncodedQuery) {
      if (gs.nil(filters) || isEncodedQuery) return filters;

      var encodedQuery = 'sys_idIN' + filters;
      var encodedQueryFilters = {
          cmdb_ci_information_object: encodedQuery
      };
      return encodedQueryFilters;
  },

  _getPaginations: function(largeArray) {
      var index = 0;
      var chunk_size = 100;
      var tempArray = [];

      for (index = 0; index < largeArray.length; index += chunk_size) {
          var myChunk = largeArray.slice(index, index + chunk_size);
          tempArray.push(myChunk);
      }

      return tempArray;
  },

  _queryTable: function(table, sysIds, requiredField) {
      var requiredData = [];
      var glideRecord = new GlideRecord(table);
      glideRecord.addQuery('sys_id', 'IN', sysIds);
      glideRecord.query();
      while (glideRecord.next()) {
          requiredData.push(glideRecord.getValue(requiredField));
      }

      return requiredData;
  },

  _getQueryResultTable: function(newQueryId) {
      var name = '';
      var glideRecord = new GlideRecord('cmdb_qb_table_mapping');
      glideRecord.addQuery('query', newQueryId);
      glideRecord.setLimit(1);
      glideRecord.query();
      if (glideRecord.next()) {
          name = glideRecord.getValue('table_name');
      }

      return name;
  },

  _getCMDBQueryFieldNames: function(queryId) {
      var fields = {
          'start_node': '',
          'information_objects': {}
      };

      var savedQueryGr = new GlideRecord('qb_saved_query');
      if (!savedQueryGr.get(queryId)) return;

      var query = JSON.parse(savedQueryGr.getValue('query'));
      var queryNodes = query['nodes'];
      var queryEdges = query['edges'];

      for (var i = 0; i < queryNodes.length; i++) {
          if (queryNodes[i].isStartNode) {
              fields['start_node'] = 'u_' + queryNodes[i].name.toLowerCase().replaceAll(' ', '_');
              continue;
          }

          if (queryNodes[i].ci_type == 'cmdb_ci_information_object')
              fields['information_objects'][queryNodes[i].nodeId] = 'u_' + queryNodes[i].name.toLowerCase().replaceAll(' ', '_');
      }

      for (var i = 0; i < queryEdges.length; i++) {
          if (fields['information_objects'][queryEdges[i].from])
              delete fields['information_objects'][queryEdges[i].from];
      }

      return fields;
  },

  _guid: function(len) {
      var buf = [],
          chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',
          charlen = chars.length,
          length = len || 32;

      for (var i = 0; i < length; i++) {
          buf[i] = chars.charAt(Math.floor(Math.random() * charlen));
      }

      return buf.join('');
  },

  type: 'GRCCMDBQueryIntegrationBase'
};

Sys ID

13b3a4be53c364105468ddeeff7b1263

Offical Documentation

Official Docs: