class FunctionComponent(ResilientComponent): """Component that implements Resilient function 'sentinel_get_incident_comments''""" def __init__(self, opts): """constructor provides access to the configuration options""" super(FunctionComponent, self).__init__(opts) self.options = opts.get(PACKAGE_NAME, {}) self.sentinel_profiles = SentinelProfiles(opts, self.options) @handler("reload") def _reload(self, event, opts): """Configuration options have changed, save new values""" self.options = opts.get(PACKAGE_NAME, {}) self.sentinel_profiles = SentinelProfiles(opts, self.options) @function("sentinel_get_incident_comments") def _sentinel_get_incident_comments_function(self, event, *args, **kwargs): """Function: Get Comments from a Sentinel Incident""" try: validate_fields(["sentinel_profile", "sentinel_incident_id"], kwargs) yield StatusMessage("Starting 'sentinel_get_incident_comments'") rc = ResultPayload(PACKAGE_NAME, **kwargs) # Get the function parameters: incident_id = kwargs.get("incident_id") # int sentinel_incident_id = kwargs.get("sentinel_incident_id") # text sentinel_profile = kwargs.get("sentinel_profile") # text log = logging.getLogger(__name__) log.info("incident_id: %s", incident_id) log.info("sentinel_incident_id: %s", sentinel_incident_id) log.info("sentinel_profile: %s", sentinel_profile) sentinel_api = SentinelAPI(self.options['tenant_id'], self.options['client_id'], self.options['app_secret'], self.opts, self.options) resilient_api = ResilientCommon(self.rest_client()) profile_data = self.sentinel_profiles.get_profile(sentinel_profile) result, status, reason = sentinel_api.get_comments( profile_data, sentinel_incident_id) new_comments = [] if status: new_comments = resilient_api.filter_resilient_comments( incident_id, result['value']) yield StatusMessage("Finished 'sentinel_get_incident_comments'") results = rc.done(status, {"value": new_comments}, reason=reason) # Produce a FunctionResult with the results yield FunctionResult(results) except Exception: yield FunctionError()
class FunctionComponent(ResilientComponent): """Component that implements Resilient function 'sentinel_get_incident_entities''""" def __init__(self, opts): """constructor provides access to the configuration options""" super(FunctionComponent, self).__init__(opts) self.options = opts.get(PACKAGE_NAME, {}) self.sentinel_profiles = SentinelProfiles(opts, self.options) @handler("reload") def _reload(self, event, opts): """Configuration options have changed, save new values""" self.options = opts.get(PACKAGE_NAME, {}) self.sentinel_profiles = SentinelProfiles(opts, self.options) @function("sentinel_get_incident_entities") def _sentinel_get_incident_entities_function(self, event, *args, **kwargs): """Function: Get the Entities associated with a Sentinel Incident""" try: validate_fields(["sentinel_profile", "sentinel_incident_id"], kwargs) yield StatusMessage("Starting 'sentinel_get_incident_entities'") rc = ResultPayload(PACKAGE_NAME, **kwargs) # Get the function parameters: sentinel_incident_id = kwargs.get("sentinel_incident_id") # text sentinel_profile = kwargs.get("sentinel_profile") # text log = logging.getLogger(__name__) log.info("sentinel_incident_id: %s", sentinel_incident_id) log.info("sentinel_profile: %s", sentinel_profile) sentinel_api = SentinelAPI(self.options['tenant_id'], self.options['client_id'], self.options['app_secret'], self.opts, self.options) profile_data = self.sentinel_profiles.get_profile(sentinel_profile) # read all entities associated with a Sentinel incident result, status, reason = sentinel_api.get_incident_entities( profile_data, sentinel_incident_id) log.debug(result) # iterate over the alerts and get all the entities entities = {} if status: for alert in result['value']: log.debug("Alert: %s", alert['name']) entity_result, entity_status, entity_reason = \ sentinel_api.get_incident_alert_entities(alert['properties']['relatedResourceId']) # organize entities using the key of the alert_id if entity_status: entities[ alert['name']] = entity_result['value']['entities'] else: reason = entity_reason yield StatusMessage("Finished 'sentinel_get_incident_entities'") results = rc.done(status, entities, reason=reason) # Produce a FunctionResult with the results yield FunctionResult(results) except Exception: yield FunctionError()
class FunctionComponent(ResilientComponent): """This component handles initial population of a feed and ongoing modifications from the associated queue.""" def __init__(self, opts): super(FunctionComponent, self).__init__(opts) try: self.options = opts.get(PACKAGE_NAME, {}) self.sentinel_profiles = SentinelProfiles(opts, self.options) self.jinja_env = JinjaEnvironment() self.channel = ".".join(["actions", CHANNEL]) except Exception as err: LOG.error("exception: %s", err) error_trace = traceback.format_exc() LOG.error("Traceback %s", error_trace) @handler() def _sentinel_update_incident_function(self, event, *args, **kwargs): # pylint: disable=unused-argument """Ingests data of any type that can be sent to a Resilient message destination""" # dismiss none Action events if not isinstance(event, ActionMessage): return # make sure to only handle incident changes if event.message['object_type'] != INCIDENT_TYPE: return # get the incident data resilient_incident = event.message['incident'] validate_fields(["sentinel_profile", SENTINEL_INCIDENT_NUMBER], resilient_incident['properties']) # Get the function parameters: sentinel_profile = resilient_incident['properties'].get("sentinel_profile") # text sentinel_incident_id = resilient_incident['properties'].get(SENTINEL_INCIDENT_NUMBER) # text log = logging.getLogger(__name__) log.info("sentinel_profile: %s", sentinel_profile) log.info("sentinel_incident_id: %s", sentinel_incident_id) sentinel_api = SentinelAPI(self.options['tenant_id'], self.options['client_id'], self.options['app_secret'], self.opts, self.options) profile_data = self.sentinel_profiles.get_profile(sentinel_profile) # is this SOAR incident active or closed? if resilient_incident["plan_status"] == "A": template = profile_data.get("sentinel_update_incident_template") default_template = DEFAULT_SENTINEL_UPDATE_INCIDENT_TEMPLATE else: template = profile_data.get("sentinel_close_incident_template") default_template = DEFAULT_SENTINEL_CLOSE_INCIDENT_TEMPLATE incident_payload = self.jinja_env.make_payload_from_template( template, default_template, resilient_incident) result, status, reason = sentinel_api.create_update_incident( profile_data, sentinel_incident_id, incident_payload ) if status: log.info("Sentinel incident updated. incident: %s", result['properties']['incidentNumber']) else: log.error("Sentinel incident failure for incident %s: %s", sentinel_incident_id, reason)
class FunctionComponent(ResilientComponent): """Component that implements Resilient function 'sentinel_add_incident_comment''""" def __init__(self, opts): """constructor provides access to the configuration options""" super(FunctionComponent, self).__init__(opts) self.options = opts.get(PACKAGE_NAME, {}) self.sentinel_profiles = SentinelProfiles(opts, self.options) @handler("reload") def _reload(self, event, opts): """Configuration options have changed, save new values""" self.options = opts.get(PACKAGE_NAME, {}) self.sentinel_profiles = SentinelProfiles(opts, self.options) @function("sentinel_add_incident_comment") def _sentinel_add_incident_comment_function(self, event, *args, **kwargs): """Function: Create a comment for a given Sentinel incident""" try: yield StatusMessage("Starting 'sentinel_add_incident_comment'") validate_fields([ "sentinel_profile", "sentinel_incident_id", "sentinel_incident_comment" ], kwargs) rc = ResultPayload(PACKAGE_NAME, **kwargs) # Get the function parameters: sentinel_profile = kwargs.get("sentinel_profile") # text sentinel_incident_id = kwargs.get("sentinel_incident_id") # text sentinel_incident_comment = kwargs.get( "sentinel_incident_comment") # text log = logging.getLogger(__name__) log.info("sentinel_profile: %s", sentinel_profile) log.info("sentinel_incident_id: %s", sentinel_incident_id) log.info("sentinel_incident_comment: %s", sentinel_incident_comment) sentinel_api = SentinelAPI(self.options['tenant_id'], self.options['client_id'], self.options['app_secret'], self.opts, self.options) # do not resync comments originating from Sentinel if FROM_SENTINEL_COMMENT_HDR in sentinel_incident_comment or SENT_TO_SENTINEL_HDR in sentinel_incident_comment: yield StatusMessage( "Bypassing synchronization of note: {}".format( sentinel_incident_comment)) result = {} reason = None status = False else: profile_data = self.sentinel_profiles.get_profile( sentinel_profile) result, status, reason = sentinel_api.create_comment( profile_data, sentinel_incident_id, clean_html(sentinel_incident_comment)) if status: yield StatusMessage("Sentinel comment added to incident: {}"\ .format(sentinel_incident_id)) else: yield StatusMessage("Sentinel comment failure for incident {}: {}"\ .format(sentinel_incident_id, reason)) yield StatusMessage("Finished 'sentinel_add_incident_comment'") results = rc.done(status, result, reason=reason) # Produce a FunctionResult with the results yield FunctionResult(results) except Exception: yield FunctionError()