Beispiel #1
0
    def _create_a_schedule_function(self, event, *args, **kwargs):
        """Function: Schedule a rule to run on a schedule. This rule will be executed for a given incident, artifact, task, etc."""
        try:
            # Get the function parameters:
            scheduler_type = self.get_select_param(
                kwargs.get("scheduler_type"
                           ))  # select, values: "cron", "interval", "date"
            scheduler_type_value = kwargs.get("scheduler_type_value")  # text
            scheduler_rule_name = kwargs.get("scheduler_rule_name")  # text
            scheduler_rule_parameters = kwargs.get(
                "scheduler_rule_parameters")  # text
            scheduler_label_prefix = kwargs.get(
                "scheduler_label_prefix")  # text

            incident_id = kwargs.get("incident_id")  # number
            object_id = kwargs.get("object_id")  # number
            # row_id is presently unavailable from a pre-proessing script.
            # A future change to resilient is needed to allow this natively. Presently, supplying this information manually is needed
            row_id = kwargs.get("row_id")  # number

            if row_id:
                object_id = event.message["workflow"]["object_type"]['id']

            object_type_id = event.message["workflow"]["object_type"]['id']
            object_type_name = event.message["workflow"]["object_type"]['name']

            scheduler_label_prefix = "{}-{}".format(scheduler_label_prefix,
                                                    incident_id)

            log.info("scheduler_type: %s", scheduler_type)
            log.info("scheduler_type_value: %s", scheduler_type_value)
            log.info("scheduler_rule_name: %s", scheduler_rule_name)
            log.info("scheduler_rule_parameters: %s",
                     scheduler_rule_parameters)
            log.info("scheduler_label_prefix: %s", scheduler_label_prefix)

            log.info("incident_id: %s", incident_id)
            log.info("object_id: %s", object_id)
            log.info("row_id: %s", row_id)

            # get the rule id
            rest_client = self.rest_client()

            # make sure incident isn't closed
            resp = get_incident(rest_client, incident_id)
            if not resp.get("success", True):
                raise FunctionError(
                    "Incident {} not found".format(incident_id))

            if not resp or resp['end_date'] is not None:
                raise FunctionError("Incident is closed")

            # get the rule id
            rule_id, rule_object_type_id = get_rule_by_name(
                rest_client, scheduler_rule_name.strip(' '))
            if not rule_id:
                raise ValueError(u"Rule name not found: %s",
                                 scheduler_rule_name)

            if object_type_id != rule_object_type_id:
                raise ValueError(u"Rule does not match the action object: %s",
                                 object_type_name)

            rc = ResultPayload(SECTION_SCHEDULER, **kwargs)

            rule_params = None
            if scheduler_rule_parameters:
                rule_params = self.validate_rule_parameters(
                    scheduler_rule_parameters)

            incident_data = [
                incident_id, object_id, row_id, scheduler_label_prefix,
                scheduler_rule_name, rule_id, rule_object_type_id, rule_params,
                self.opts[SECTION_RESILIENT]
            ]

            # validate the type and type_value
            trigger = self.res_scheduler.build_trigger(scheduler_type,
                                                       scheduler_type_value)

            # a d d   j o b
            scheduler = ResilientScheduler.get_scheduler()
            scheduled_job = scheduler.add_job(triggered_job,
                                              trigger,
                                              id=scheduler_label_prefix,
                                              args=incident_data,
                                              kwargs=rule_params)

            log.debug(u"Scheduled_job: {}".format(scheduled_job))

            yield StatusMessage("Rule scheduled")

            # convert for results
            job = scheduled_job.__getstate__()
            job['next_run_time'] = self.res_scheduler.get_str_date(
                job['next_run_time'])
            job['trigger'] = None
            # clear args which contain passwords ([resilient])
            job = ResilientScheduler.clean_password(job)

            results = rc.done(True, job)

            # Produce a FunctionResult with the results
            yield FunctionResult(results)
        except Exception:
            yield FunctionError()
Beispiel #2
0
def triggered_job(incident_id, object_id, row_id, scheduler_label, rule_name,
                  rule_id, rule_object_type_id, rule_params, opts, **kwargs):
    """
    This function is called when a scheduled rule is triggered. It is run asynchronous of the create_scheduled_rule process.
    It's role is to build the api call-back to Resilient to run the rule.
    In addition to invoking a rule, a note is added to the incideent to indicate that a scheduled rule was run.
    :param incident_id:
    :param object_id: task_id, note_id, artifact_id, etc.
    :param row_id: used when object_id is a datatable_id
    :param scheduler_label:
    :param rule_name:
    :param rule_id:
    :param rule_object_type_id: internal id referring to incident, task, artifact, etc.
    :param rule_params:
    :param opts: contains [resilient] parameters needed to connect back to Resilient for API calls
    :param kwargs: catch all for additional arguments as necessary
    :return: None
    """
    log.debug(incident_id)
    log.debug(rule_id)
    log.debug(rule_object_type_id)
    log.debug(rule_params)
    log.debug(kwargs)

    # get the rest client
    rest_client = get_resilient_client(opts)
    scheduler = ResilientScheduler.get_scheduler()

    # make sure the incident is still open and not deleted
    try:
        resp = get_incident(rest_client, incident_id)
    except SimpleHTTPException:
        resp = None

    if not resp or resp['end_date'] is not None:
        log.warning(
            u"Incident %s is not found or closed. Removing scheduled rule: %s",
            incident_id, rule_name)
        scheduler.remove_job(scheduler_label)
        return

    # make sure the rule is still enabled
    try:
        get_rule_by_id(rest_client, rule_id)
    except KeyError as err:
        # remove rules which no longer exist
        log.error(u"Rule '%s' not found and schedule will be removed.",
                  rule_name)
        add_comment(
            rest_client, incident_id,
            u"Error running rule '{}': {}".format(scheduler_label, str(err)))
        scheduler.remove_job(scheduler_label)
        return

    # build url for invoking a rule
    rule_type = lookup_object_type(rest_client, rule_object_type_id)
    if rule_type == "tasks":
        url = "/{}/{}".format(rule_type, object_id)
    else:
        url = "/incidents/{}".format(incident_id)

        if rule_type != '':
            url = url + "/{}/{}".format(rule_type, object_id)

    if row_id:
        url = url + "/row_data/{}".format(row_id)

    url = url + "/action_invocations"

    # build the JSON for rule
    payload = {"action_id": rule_id, "properties": rule_params}

    log.info("Executing Rule '{}:{}' for Incident {}".format(
        scheduler_label, rule_name, incident_id))

    # run the rule
    try:
        resp = rest_client.post(url, payload)
        log.debug(resp)
    except SimpleHTTPException as err:
        # is the object removed?
        if "Not Found" in str(err):
            log.error(
                "Object not found and schedule will be removed for rule '%s'",
                rule_id)
            add_comment(
                rest_client, incident_id,
                u"Error running rule '{}': {}".format(scheduler_label,
                                                      str(err)))
            scheduler.remove_job(scheduler_label)
            return

    if rule_type:
        add_comment(
            rest_client, incident_id,
            u"Scheduled job '{}' run on {}: {}".format(rule_name, rule_type,
                                                       object_id))
    else:
        add_comment(rest_client, incident_id,
                    u"Scheduled job '{}' run on incident".format(rule_name))