Name

sn_cmp.AWSEventHandler

Description

No description available

Script

var AWSEventHandler = Class.create();
AWSEventHandler.prototype = Object.extendsObject(CloudEventHandler, {

  processEvent: function(headersStr, bodyStr, queryParamsStr, eventId) {
      var response = {};
  	response.sys_domain = this.getErrorEventsDefaultDomain();
      var json = new global.JSON();
      var body = json.decode(bodyStr);

      // Format  arn:partition:service:region:account-id:resource
      // Example arn:aws:sns:us-west-1:974065848211:TEST_ITOM2
      var topicArr = body.TopicArn.split(":");
      var message = json.decode(body.Message);
      var configItem = message.configurationItem;

      var ldc;
      var serviceAccountId;
      if (topicArr && topicArr.length >= 5) {
          ldc = topicArr[3];
          serviceAccountId = topicArr[4];

          if (!gs.nil(configItem) && !gs.nil(configItem.awsAccountId)) {
              /** Priority would be given to the message(event payload) rather than the ARN.
               * Field usecase can be having one common account to push the SNS topics from various other accounts
               * or having nested service accounts
               **/
              serviceAccountId = configItem.awsAccountId;
          }
      } else {
          response.state = 'skipped';
          response.error_message = gs.getMessage('Invalid TopicArn provided');
          return response;
      }

      if (body.Subject)
          response.subject = body.Subject;

      var serviceAccountGR = this._verifyServiceAccount(serviceAccountId);
  	if (!gs.nil(serviceAccountGR))
  		response.sys_domain = serviceAccountGR.sys_domain;

      if (!this._verifyLDC(serviceAccountId, ldc)) {
          response.state = 'skipped';
          response.error_message = gs.getMessage('LDC {1} is not set up in Service Account {0}', [serviceAccountId, ldc]);
          return response;
      }

      var type = body.Type;
      if (type == 'SubscriptionConfirmation') { //auto subscribe
          var request = new sn_ws.RESTMessageV2();
          request.setEndpoint(body.SubscribeURL);
          request.setHttpMethod('GET');
          request.execute();

          response.state = 'processed';
          response.event_name = 'SubscriptionConfirmation';
          response.event_time = this.getEventTime(body.Timestamp);
      } else if (type == 'Notification') {
          var eventName = message.messageType;
          var notificationTime = message.notificationCreationTime;

          response.event_name = eventName;
          response.event_time = this.getEventTime(notificationTime);

          if (eventName == 'ConfigurationItemChangeNotification') {
              var resourceType = message.configurationItem.resourceType;
              var preferResponseMapping = gs.getProperty('sn_cmp.cloud_event.use_response_mapping_aws');
  			var invocationPatternId = '';
  			var ciClassType = '';
              if (preferResponseMapping == 'true') {
                  if (this._doesResponseMappingExist(resourceType)){
                      this._processEventWithResponseMapping(serviceAccountId, ldc, message, resourceType, serviceAccountGR, response);
                  } else {
                      invocationPatternId = this._getPatternId(resourceType);
                      ciClassType = this._getClassTypeId(resourceType);
                      if (invocationPatternId) {
                          return this._processEventWithPattern(serviceAccountId, ldc, message, resourceType, invocationPatternId, response, ciClassType, eventId);
                      }
                  }
              } else {
                  invocationPatternId = this._getPatternId(resourceType);
                  ciClassType = this._getClassTypeId(resourceType);
                  if (invocationPatternId) {
                      return this._processEventWithPattern(serviceAccountId, ldc, message, resourceType, invocationPatternId, response, ciClassType, eventId);
                  } else {
                      this._processEventWithResponseMapping(serviceAccountId, ldc, message, resourceType, serviceAccountGR, response);
                  }
              }
          }


          var service = message.Service;
          if (service == "AWS Auto Scaling") {
              //logic to get instance detail.
              var ownerInstanceId;
              var scalingGroupName = message.AutoScalingGroupName;
              var gr = new GlideRecord('cmdb_ci_sa_server_array');
              gr.addQuery('object_id', scalingGroupName);
              gr.query();
              if (gr.next()) {
                  ownerInstanceId = gr.getUniqueValue() + '';
              }
              var nodeId = message.EC2InstanceId;
              this.refreshNode(serviceAccountId, ldc, nodeId, ownerInstanceId);

          }

          response.state = 'processed';
      } else { //unsupported event type, skip it for now
          response.state = 'skipped';
          response.error_message = gs.getMessage('Unsupported event type: {0}', [type]);
      }
      //this._debug('response:' + global.JSUtil.describeObject(response));
      return response;
  },
  
  _doesResponseMappingExist: function(resourceType) {
  	var ciClass = '';
  	var typeGr = new GlideRecord('sn_capi_resource_type');
  	typeGr.addQuery('name', resourceType);
  	typeGr.query();
  	if (typeGr.next())
  		ciClass = typeGr.getValue('ci_class');

  	var rmGr = new GlideRecord('sn_cmp_response_mapping');
  	rmGr.addQuery('datasource.name', 'Cloud Event');
  	rmGr.addQuery('ci_class', ciClass);
  	rmGr.query();
  	return rmGr.hasNext();
  },
  
  _processEventWithResponseMapping: function(serviceAccountId, ldc, message, resourceType, serviceAccountGR, response) {
  	var responseProcessor = new sn_cmp.ResponseProcessor(serviceAccountId,
                      ldc,
                      'Cloud Event');

  	var cloudModelObject = responseProcessor.processResponseArray([].concat(message.configurationItem),
  		resourceType,
  		null);

  	//this._debug('cloudModelObject:' + global.JSUtil.describeObject(cloudModelObject));
  	var processedPayload = new sn_cmp_api.CloudModelProcessorScript().updateCIs(new global.JSON().encode(cloudModelObject), serviceAccountGR.sys_domain);
  	this._debug('processedPayload:' + processedPayload);
  	response.resource_id = message.configurationItem.resourceId;
  	this._updateResponse(response, resourceType, processedPayload);
  },
  
  _processEventWithPattern: function(serviceAccountId, ldc, message, resourceType, invocationPatternId, response, ciClassType, eventId) {
  	//Initialize the response
  	response.state = 'processing';
  	response.discovery_status = null;
  	response.error_message = "";
  	var msgInputObjectId = message.configurationItem.resourceName;
  	if (gs.nil(msgInputObjectId))
  		msgInputObjectId = message.configurationItem.resourceId;

  	//Prepare the mandatory parameters to pass to the pattern context
  	var configObj = {
  		changeType: message.configurationItemDiff.changeType,
  		classType: ciClassType,
  		accountId: serviceAccountId,
  		ldc: ldc,
  		inputObjectId: msgInputObjectId,
  		cloudId: message.configurationItem.ARN,
  		patternId: invocationPatternId,
  		eventId: eventId,
  		eventType: "AWS"
  	};

  	var cloudPatternInvocation = new sn_cmp.CloudPatternInvocation();
  	var result = cloudPatternInvocation.eventBasedDiscovery(configObj, response);
      var processedPayload = {};
  	if (result) {
  		//For sucess invocation the state will be update in HorizontalDiscoveryResultHandler.finalizeCloudChangeEvent()
  		//Will be determine if the pattern is success or not
  		var ciSysId = this._getCiId(ciClassType, message.configurationItem.resourceId);
  		processedPayload = "{\"" + ciClassType + "\":\"" + ciSysId + "\"}";
  	} else {
  		response.state = (response.state) ? response.state : 'error';
  		response.error_message = (response.error_message) ? response.error_message : gs.getMessage('Cannot invoke pattern discovery for: {0}', [JSON.stringify(configObj, null, 2)]);
  	}
  	response.resource_id = message.configurationItem.resourceId;
  	this._updateResponse(response, resourceType, processedPayload);
  	return response;
  },

  refreshNode: function(serviceAccountId, ldc, instanceId, ownerInstanceId) {

      var order = {
          'ownerInstanceId': ownerInstanceId + '',
          'resource': "Virtual Server Array",
          'entityType': 'Resource',
          'operationName': 'Virtual Server Array Interface.DescribeNode',
          orderFormData: {
              'CloudServiceAccountId': serviceAccountId + '',
              'ObjectID': instanceId + '',
              'Location': ldc + '',
              'ownerInstanceId': ownerInstanceId + ''
          }
      };

      var orderScript = new sn_cmp_api.OrderServiceScript();
      orderScript.submitOrder(new global.JSON().encode(order));
  },

  getEventTime: function(eventTime) {
      var re = /^(\d\d\d\d-\d\d-\d\d)T(\d\d:\d\d:\d\d)\.\d\d\dZ$/g;
      var arr = re.exec(eventTime);
      if (arr && arr.length == 3)
          return new GlideDateTime(arr[1] + ' ' + arr[2]);
      return '';
  },

  type: 'AWSEventHandler'
});

Sys ID

7705061dd754320097eb6ccf6e61038a

Offical Documentation

Official Docs: