Name

sn_agent.AgentNowAssetValidiator

Description

Uitlity script containing the following functions validate Check that the attachments to agent asset record are valid updateAssetChoiceList update the sn_agent_asset_name table based on names of records in sn_agent_asset

Script

var AgentNowAssetValidiator = Class.create();
AgentNowAssetValidiator.prototype = {
  initialize: function() {},

  validateAsset: function(currentAssetGr) {
      // Find attachment
      var attachGr = this.getAttachmentForAsset(currentAssetGr);
      if (!attachGr.next()) {
          if (currentAssetGr.sys_overrides) {
              gs.addErrorMessage(gs.getMessage("Update of plugins from other domains are not allowed."));
          } else if (currentAssetGr.operation() == "insert") {
              gs.addErrorMessage(gs.getMessage('No attachment found on record. Please add an attachment.'));
              current.setAbortAction(true);
          }
          return false;
      }
      var validated = this.validateAssetFields(currentAssetGr, attachGr) && this.validateNameAndPopulate(currentAssetGr, attachGr);
      if (!validated) {
          if (currentAssetGr.operation() == "insert")
              current.setAbortAction(true);
          return false;
      }
  },

  validateAssetFields: function(currentAssetGr, attachGr) {
      if (currentAssetGr.operation() == "insert") {
          // Check there are no additional attachments
          if (attachGr.hasNext()) {
              gs.addErrorMessage(gs.getMessage('The record cannot have more than one attachment.'));
              return false;
          }
          if (this.isRecordExist(currentAssetGr, attachGr.file_name)) {
              gs.addErrorMessage(gs.getMessage('A record with the same name and path already exists.'));
              return false;
          }
          //we are restricted by the length of name column in sys_attchemnt which is 100 characters, when exceeding 100 characters, the name is cut and '.tar' suffix is removed
          if (attachGr.getValue('file_name').length >= 100) {
              gs.addErrorMessage(gs.getMessage('The attached file name exceeds 100 characters.'));
              return false;
          }
          // Check the file name and os version does not contain spaces or special characters	
          if (!/^[A-Za-z0-9_.-]+$/i.test(attachGr.getValue('file_name'))) {
              gs.addErrorMessage(gs.getMessage('The attached file name must only contain alphanumeric characters and: . , - , _'));
              return false;
          }
      }
      if (!/^[A-Za-z0-9_.-]+$/i.test(currentAssetGr.os_version)) {
          gs.addErrorMessage(gs.getMessage('The os version must only contain alphanumeric characters and: . , - , _'));
          return false;
      }
      return true;
  },

  validateNameAndPopulate: function(currentAssetGr, attachGr) {
      var fileName = '';
      fileName = attachGr.getValue('file_name');
      if (!fileName.endsWith(".tar.gz")) {
          gs.addErrorMessage(gs.getMessage('Attached file must be in tar.gz format.'));
          return false;
      }

      var indexOfSuffixTarGz = fileName.lastIndexOf(".tar.gz");
      if (indexOfSuffixTarGz != -1) {
          //There is always an index because it is checked that the name ends with .tar.gz
          current.name = fileName.substring(0, indexOfSuffixTarGz);
      }

      if (current.name.startsWith('.') || current.name.endsWith('.')) {
          gs.addErrorMessage(gs.getMessage('Attachment name cannot start or end with a period.'));
          return false;
      }

      return true;
  },

  // Is record with same name and path exist
  isRecordExist: function(current, name) {
      var absoluteName = name.replace('.tar.gz', '');
      var pluginGR = new GlideRecord('sn_agent_asset');
      pluginGR.addQuery('sys_id', "!=", current.getUniqueValue());
      pluginGR.addQuery('name', absoluteName);
      pluginGR.addQuery('arch', current.arch);
      pluginGR.addQuery('os', current.os);
      pluginGR.addQuery('os_version', current.os_version);
      pluginGR.addQuery('platform', current.platform);
      pluginGR.query();

      return pluginGR.hasNext();
  },

  getAttachmentForAsset: function(currentAssetGr) {

      var attachGr = new GlideRecord('sys_attachment');
      attachGr.addQuery('table_name', 'sn_agent_asset');
      attachGr.addQuery('table_sys_id', currentAssetGr.getUniqueValue());
      attachGr.query();
      return attachGr;
  },

  hasAttachment: function(sysID) {

      var attachGr = new GlideRecord('sys_attachment');
      attachGr.addQuery('table_name', 'sn_agent_asset');
      attachGr.addQuery('table_sys_id', sysID);
      attachGr.query();
      return attachGr.hasNext();
  },

  updateAssetChoiceList: function() {
      var assetNames = {};
      var assetGr = new GlideRecord('sn_agent_asset');
      assetGr.addQuery('directory', false);
      assetGr.query();
      while (assetGr.next()) {
          assetNames[assetGr.name + ''] = 1;
      }

      // Find existing choices
      var currentChoices = {};
      var choiceGr = new GlideRecord('sn_agent_asset_name');
      choiceGr.query();
      while (choiceGr.next()) {
          currentChoices[choiceGr.name + ''] = choiceGr.getUniqueValue();
      }

      // Add choices if needed
      var assetName;
      for (assetName in assetNames) {
          if (!currentChoices[assetName]) {
              // insert new choice
              choiceGr = new GlideRecord('sn_agent_asset_name');
              choiceGr.setValue('name', assetName);
              choiceGr.insert();
          }
      }

      // Remove choices if needed
      for (assetName in currentChoices) {
          if (!assetNames[assetName]) {
              // Remove a choice
              choiceGr = new GlideRecord('sn_agent_asset_name');
              var recordFound = choiceGr.get(currentChoices[assetName]);
              if (recordFound) {
                  choiceGr.deleteRecord();
              }
          }
      }
  },

  /*
   * check if asset name is being used on record other than the the current record
   */
  isAssetNameUsed: function(assetName, current) {
      var choiceGr = new GlideRecord('sn_agent_asset_name');
      choiceGr.addQuery('name', assetName);
      choiceGr.query();
      if (!choiceGr.next()) {
          //gs.info('====== asset name ' + assetName + ' not found');
          return '';
      }

      // Check if this asset name is used in check definitions
      var checkGr = new GlideRecord('sn_agent_check_def');
      checkGr.addQuery('assets', 'CONTAINS', choiceGr.getUniqueValue());
      checkGr.query();
      if (checkGr.next()) {
          // there are check definitions using this asset name. Check if there are other assets with the same name
          var assetGr = new GlideRecord('sn_agent_asset');
          assetGr.addQuery('name', assetName);
          assetGr.addQuery('sys_id', "!=", current.getUniqueValue());
          assetGr.query();
          if (!assetGr.next()) {
              gs.info('===== asset name ' + assetName + ' found in check ' + checkGr.name);
              return checkGr.name + '';
          }
      }
      //gs.info('====== asset name ' + assetName + ' not used by checks, or there are other assets with same name');
      return '';
  },


  addAssetsToCheck: function(check_def, check, payloadVersion) {
      if (!check_def || !check_def.assets)
          return;

      gs.debug('Assets : ' + check_def.assets + '');
      var assetsArray = check_def.assets.toString().split(',');
      assetNamesTemp = [];
      for (var idx in assetsArray) {
          var assetId = assetsArray[idx];
          var assetName = this.getAssetName(assetId);
          if (assetName)
              assetNamesTemp.push(assetName);
      }
      if (!payloadVersion || payloadVersion < 2)
          check['assets'] = assetNamesTemp.toString();
      else
          check['assets'] = assetNamesTemp;
  },

  /*
   * get the asset name from map between sys IDs in sn_agent_asset_name and names. If the map was not created yet, create it now
   */
  getAssetName: function(assetNameId) {
      if (!assetNameId)
          return;

      if (!this.assetNames) {
          this.assetNames = {};
          var assetNameGr = new GlideRecord('sn_agent_asset_name');
          assetNameGr.query();
          while (assetNameGr.next())
              this.assetNames[assetNameGr.getUniqueValue()] = assetNameGr.name + '';
      }
      if (this.assetNames[assetNameId]) {
          return this.assetNames[assetNameId];
      }
  },

  /*
   * check if we are allowed to delete asset. We block asset deletion if the asset name is being used by check definition and there is no other asset with the same name
   */
  shouldAllowDeleteOfAsset: function(current) {
      var choiceGr = new GlideRecord('sn_agent_asset_name');
      var assetName = current.name + '';
      choiceGr.addQuery('name', assetName);

      var checkname = this.isAssetNameUsed(assetName, current);
      if (checkname != '') {
          current.setAbortAction(true);
          gs.addErrorMessage(gs.getMessage("Plugin named {0} cannot be deleted since it is being used by check definition {1}", [assetName, checkname]));
          return;
      }
  },

  type: 'AgentNowAssetValidiator'
};

Sys ID

78752bd0b74733003e766068de11a9ab

Offical Documentation

Official Docs: