Name

global.GlobalIPExclusionUtil

Description

A Utility class that provides useful functions to query and manipulate IP Address list/IP Range or Subnet that is part of global IP Exclusion list.

Script

/**
* Utility class for Global IP Exclusion
* This class provides useful utility functions that can be used to query and
* manipulate records in ip_exclusion table.
*/
var GlobalIPExclusionUtil = Class.create();

(function() {
  GlobalIPExclusionUtil.prototype = {
      contains: contains,
      addToIPExclusionList: addToIPExclusionList,
      getDiscoverableIPs: getDiscoverableIPs,
      getExcludedIPList: getExcludedIPList,

      type: 'GlobalIPExclusionUtil'
  };

  var IP_EXCLUSION_TABLE = 'ip_exclusion';
  var IP_EXCLUDED_COLUMN = 'ip_excluded';
  var DESCRIPTION_COLUMN = 'description';
  var LOG_SOURCE = 'GlobalIPExclusionUtil';
  var nodeLogger = new sn_automation.AutomationAPI().getNodeLogger();
  var INVALID_INPUT_MSG = 'Invalid Input! Input must be a non-empty string representing an IPv4 Address list/Range/Subnet. Global IP Exclusion of IPv6 addresses is not supported';

  /**
   * Determine if IP Exclusion list contains all the specified
   *  IP Address list/Range/Subnet
   *
   * @param  {string}   Dotted-decimal notation of IP Address or IP Range or subnet
   *                      Example: 1.1.1.1 or 1.1.1.0-1.1.1.100 or 1.1.1.0/16
   * @return {boolean}  true/false
   *                      true if ip_exclusion list contains the specified IP entirely
   *                      false if atleast one of the items in specified IP is not in
   *                           ip_exclusion list
   */
  function contains(ip) {
      debugMsg('Invoking contains for IP = ' + ip);

      if (!_isValidIP(ip)) {
          errorMsg('Error in contains(' + ip + ') : ' + INVALID_INPUT_MSG);
          return false;
      }
      
      // to handle calls from workflow
      if (typeof ip == 'object')
          ip = ip.toString();

      var discoverbleIPs = getDiscoverableIPs(ip);

      if (!discoverbleIPs || discoverbleIPs.length == 0) {
          infoMsg('Global IP Exclusion List contains [' + ip + ']');
          return true;
      } else {
          infoMsg('Global IP Exclusion List does not contain ' + discoverbleIPs);
          return false;
      }
  }

  function _isValidIP(input) {
      // to handle calls from workflow
      input = input + '';

      //IPv6 addresses are not supported
      return (!_isEmpty(input) && _convertToPrimitiveType(input) && (input.indexOf(':') == -1));
  }

  function _isEmpty(inputString) {
      return (!inputString || inputString.trim().length == 0);
  }

  /**
   * Add IP Collection item(s) to Global IP Exclusion list
   *
   * @param  {string}  Dotted-decimal notation of an IP Address List/IP Range or subnet
   *    Example: 1.1.1.1 or 1.1.1.1, 2.2.2.2, 3.3.3.0 or 1.1.1.0-1.1.1.100 or 1.1.1.0/16
   * @return {boolean}
   *    true  - if atleast one new record was successfully added to ip_exclusion table
   *    false - if specified item already exists in ip exclusion list
   *            or insertion failed due to other reasons
   */
  function addToIPExclusionList(ip) {
      debugMsg('Invoking addToIPExclusionList, input = ' + ip);

      var ipCollectionSysId;
      var ipCollectionSysIdList;
      var ipExclusionSysId;

      if (!_isValidIP(ip)) {
          errorMsg('Error in addToIPExclusionList(' + ip + ') : ' + INVALID_INPUT_MSG);
          return false;
      }

      var ipNotInExclusionList = getDiscoverableIPs(ip);
      debugMsg('ipNotInExclusionList = ' + ipNotInExclusionList);

      //skip insertion if ip or ip List is already part of ip_exclusion
      if (!ipNotInExclusionList || ipNotInExclusionList.length == 0) {
          debugMsg('IP Exclusion List already contains ' + ip);
          return true;
      }

      ipCollectionSysIdList = SNC.IPCollectionUtil.findOrCreateCollection(ipNotInExclusionList.toString());

      if (!ipCollectionSysIdList || ipCollectionSysIdList.length == 0) {
          warnMsg('Insertion Failed! Unable to find or insert a record in IP Collection');
          return false;
      }

      var count = ipCollectionSysIdList.size();
      var status = false;
      for (var index = 0; index < count; index++) {
          if (_insert(ipCollectionSysIdList.get(index)))
              status = true;
      }

      if (status)
          infoMsg('Insertion successful! Added ' + ipNotInExclusionList + ' to IP Exclusion List');
      else
          warnMsg('Insertion failed! Unable to add ' + ip + ' to IP Exclusion List');

      return status;
  }

  /**
   * Insert a record in ip_exclusion for the given IPCollection reference
   *
   * @param  {string} ip_address_collection.sysId
   * @return {string} ip_exclusion.sysId of newly inserted record
   */
  function _insert(ipCollectionSysId) {
      var gr = new GlideRecord(IP_EXCLUSION_TABLE);
      gr.setValue(IP_EXCLUDED_COLUMN, ipCollectionSysId);
      gr.setValue(DESCRIPTION_COLUMN, 'Source = GlobalIPExclusionUtil API');

      return gr.insert();
  }

  /**
   * Get an IP Range for a given IP excluding all IP in Global IP Exclusion List
   *
   * @param  {string}  Dotted-decimal notation of IP Address list/IP Range/Subnet
   *         Example: 1.1.1.1 or 1.1.1.1, 3.2.1.2 or 1.1.1.0-1.1.1.100 or 1.1.1.0/16
   * @return {string}  List of IPRange , example: [1.1.1.0-1.1.1.100]
   *                   An array of distinct input IPs if ip_exclusion is empty
   *                   or null in case of invalid input
   *
   * Usage example: getDiscoverableIPs('1.1.1.1,3.2.1.2')
   *   1. if ip_exclusion is empty, returns '1.1.1.1-1.1.1.1,3.2.1.2-3.2.1.2'
   *   2. if ip_exclusion contains input, returns null
   *   3. if ip_exclusion includes 1.1.1.1 & not 3.2.1.2, returns '3.2.1.2-3.2.1.2'
   */
  function getDiscoverableIPs(ips) {
      debugMsg('Invoking getDiscoverableIPs for IP = ' + ips);

      var discoverableIPRange = [];
      var excludedIPList;
      var inputIPCollection;
      var inputIPList = [];

      if (!_isValidIP(ips)) {
          debugMsg(INVALID_INPUT_MSG);
          return null;
      }

      var uniqueInputIPs = removeDuplicates(ips);

      excludedIPList = getExcludedIPList();
      if (!excludedIPList || excludedIPList.length == 0)
          return uniqueInputIPs;

      //2. Convert input IP into an IPCollection list
      inputIPList = _convertToPrimitiveTypeList(uniqueInputIPs);

      //3.Get optimal list of IP by removing excluded IPs from the input list
      var optimalList = SncIPMetaCollection.getOptimalCollection(inputIPList, excludedIPList, true);

      if (optimalList) {
          var ipCollections = optimalList.getIPCollections();
          if (ipCollections != null && ipCollections.size() > 0)
              discoverableIPRange.push(ipCollections);
          debugMsg('Discoverable IP = ' + discoverableIPRange);
      }

      return discoverableIPRange;
  }


  /**
   * Get a list of all the IP Collection items in Global IP Exclusion list
   *
   * @return {Array<IPCollection>}
   */
  function getExcludedIPList() {
      debugMsg('Invoking getExcludedIPList');

      var excludedIPList = [];
      var excludedIPSysIdList = _getSysIdForAllExcludedIPs();

      if (!excludedIPSysIdList || excludedIPSysIdList.length == 0) {
          infoMsg('IP Exclusion list is empty!');
          return excludedIPList;
      }

      var listSize = excludedIPSysIdList.length;

      for (var index = 0; index < listSize; index++) {
          var excludedIPs = SNC.IPCollectionUtil.getPrimitiveIPCollection(excludedIPSysIdList[index]);
          if (excludedIPs != null)
              excludedIPList.push(excludedIPs);
      }

      if (excludedIPList && excludedIPList.length > 0)
          debugMsg('excludedIPList size = ' + excludedIPList.length);

      return excludedIPList;
  }

  /**
   * Get a list of sysIds for all active IP Collection references
   * in Global IP Exclusion List
   *
   * @return {Array<String>} An array of IP Collection sysIds to be excluded
   */
  function _getSysIdForAllExcludedIPs() {
      debugMsg('Invoking _getSysIdForAllExcludedIPs');

      var excludedIPCollectionSysIdsList = [];

      var gr = new GlideRecord(IP_EXCLUSION_TABLE);
      gr.addActiveQuery();
      gr.query();
      while (gr.next())
          excludedIPCollectionSysIdsList.push(gr.getValue(IP_EXCLUDED_COLUMN) + '');

      debugMsg('excludedIPCollectionSysIdsList.size = ' + excludedIPCollectionSysIdsList.length);

      return excludedIPCollectionSysIdsList;
  }

  /**
   * Convert given ip into its Primitive IPCollection type object
   *
   * @param {string}    Dotted-decimal notation of IP Address list/IP Range/Subnet
   *       Example: 1.1.1.1 or 1.1.1.1, 3.2.1.2 or 1.1.1.0-1.1.1.100 or 1.1.1.0/16
   * @return {<TYPE>}   valid types: IPList/IPRangeV4/IPNetworkV4
   */
  function _convertToPrimitiveType(ip) {
      debugMsg('Invoking _convertToPrimitiveType for ip = ' + ip);

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

      var subnet = SncIPNetworkV4.getIPNetworkInstance(ip);
      if (subnet && subnet.size() > 0)
          return subnet;

      var ipRange = SncIPRangeV4.getIPRangeV4Instance(ip);
      if (ipRange && ipRange.size() > 0)
          return ipRange;

      var ipAddressList = SncIPList.getIPListInstance(ip);
      if (ipAddressList && ipAddressList.size() > 0)
          return ipAddressList;

      return null;
  }

  /**
   * Convert given ips into a list of distinct Primitive IPCollection type objects
   *
   * @param {string}     Dotted-decimal notation of IP Address list/IP Range/Subnet
   *       Example: 1.1.1.1 or 1.1.1.1,1.1.1.0-1.1.1.100 or 1.1.1.0/16,3.2.1.0
   * @return {List<TYPE>}  List<IPCollection>
   */
  function _convertToPrimitiveTypeList(ips) {
      debugMsg('Invoking _convertToPrimitiveTypeList for ips = ' + ips);

      var totalNumberOfUniqueIPs = (ips == null) ? 0 : ips.length;
      var ipList = [];

      for (var index = 0; index < totalNumberOfUniqueIPs; index++) {
          var ipItem = _convertToPrimitiveType(ips[index]);
          if (ipItem)
              ipList.push(ipItem);
      }

      debugMsg('ipList size = ' + ipList.length);

      return ipList;
  }

  /**
   * Convert given ips into a distinct string array
   *
   * @param {string}     Dotted-decimal notation of IP Address list/IP Range/Subnet
   *                     Example: 1.1.1.1,1.1.1.1,3.2.1.0 or 10.0.0.0/23 or ['1.1.1.1', '10.11.1.10']
   * @return {Array<string>}
   */
  function removeDuplicates(ips) {
      debugMsg('Invoking removeDuplicates for ips = ' + ips);

      if (!ips)
          return []; // Handles null, undefined or 0.

      // to handle calls from workflow
      if (!(ips instanceof Array))
          ips = (ips + '').split(',');

      if (ips.length == 1)
          return ips;

      return new global.DiscoArrayUtil().unique(ips);
  }

  function debugMsg(msg) {
      nodeLogger.debug('[' + LOG_SOURCE + '] ' + msg);
  }

  function infoMsg(msg) {
      nodeLogger.info('[' + LOG_SOURCE + '] ' + msg);
      gs.log(msg, LOG_SOURCE);
  }

  function warnMsg(msg) {
      nodeLogger.warn('[' + LOG_SOURCE + '] ' + msg);
      gs.logWarning(msg, LOG_SOURCE);
  }

  function errorMsg(msg) {
      nodeLogger.error('[' + LOG_SOURCE + '] ' + msg);
      gs.logError(msg, LOG_SOURCE);
  }

})();

Sys ID

ee67fc145b12201048501e991e81c7c7

Offical Documentation

Official Docs: