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()
コード例 #2
0
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()
コード例 #3
0
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)
コード例 #4
0
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()