IBM QRadar SOAR

IBM QRadar SOAR

Join this online user group to communicate across Security product users and IBM experts by sharing advice and best practices with peers and staying up to date regarding product enhancements.

 View Only

Handle "Patch Failure" properly

  • 1.  Handle "Patch Failure" properly

    Posted Thu December 09, 2021 03:51 AM
    Hi all

    I am working on a way to handle the {'success': False, 'title': 'Patch Failure'} errors, precisely the conflict ones.

    The full message I have is:
    2021-12-07 12:59:58,598 DEBUG [_handle_patch_response] {'success': False, 'title': 'Patch Failure', 'message': 'One or more edits to an object (Type=Incident, ID 117,440) could not be applied due to a conflicting edit by another user. The following fields were in conflict:  description, spam', 'hints': ['patch_conflict_detected'], 'error_code': 'generic', 'field_failures': [{'field': 'description', 'your_original_value': "a string", 'actual_current_value': "another string same as original value"}, {'field': 'spam', 'your_original_value': None, 'actual_current_value': 33346}]}
    2021-12-07 12:59:58,598 INFO [_handle_patch_response] Patch conflict detected - invoking callback
    ​


    Starting from this patch method I use in my code...

    uri_current = '/incidents/{}?handle_format=names'.format(incident_id)
    current_incident = resilient_client.get(uri_current)
    
    patch_current = resilient.Patch(current_incident)
    
    patch_text = "Patching Property Field [{}] with new Value [{}] for Incident ID [{}]"
    
    # remove eventual duplicates
    patch_list = [dict(t) for t in {tuple(d.items()) for d in patch_list}]
    
    # group by incident_id in ascending order
    patch_list.sort(key=lambda x: x["incident_id"])
    
    for pl_c in patch_list:
        if pl_c["incident_id"] == incident_id:
            patch_current.add_value(pl_c["property_field"], pl_c["new_property_value"])
            logging.info(
                patch_text.format(pl_c["property_field"], pl_c["new_property_value"], pl_c["incident_id"]))
            print(
                patch_text.format(pl_c["property_field"], pl_c["new_property_value"], pl_c["incident_id"]))
    
    patch_response_current = resilient_client.patch(uri_current, patch_current, overwrite_conflict=True)
    patch_response_current = patch_response_current.json()
    logging.info(patch_response_current)
    print(str(patch_response_current) + " for Incident [{}]".format(current_incident["id"]))


    ... I ended with trying the patch_with_callback method, but with no success. Implemented as below, in continuation of above:

    if patch_response_current["success"] is False:
        logging.error("Failed Patch for Current Incident [{}]".format(current_incident["id"]))
        print("Failed Patch for Current Incident [{}]".format(current_incident["id"]))
        for k, v in patch_response_current.items():
            if k == "field_failures":
                for field in v:
                    field_name = field["field"]
    
                    for element in patch_list:
                        if element["incident_id"] == current_incident["id"]:
                            for e in patch_list:
                                if e["property_field"] == field_name:
                                    field_value = e["new_property_value"]
                                    break
                            break
    
                    def patch_conflict_handler_current(response, patch_status, patch):
                        current_value = patch_status.get_actual_current_value(field_name)
                        patch.exchange_conflicting_value(patch_status,
                                                         field_name,
                                                         field_value)
    
                    callback_result = resilient_client.patch_with_callback(uri_current, patch_current,
                                                                           callback=patch_conflict_handler_current)
    
                    print("Callback Result for Current Incident [{}]: {}".format(current_incident["id"],
                                                                                 callback_result))
                    logging.warning(
                        "Callback Result for Current Incident [{}]: {}".format(current_incident["id"],
                                                                               callback_result))


    What I am doing wrong ?
    Why, in my logs, I never see any of the messages in IF block (logging.error and logging.warning) in case of patch_reponse["status"] is False like the code never reach that condition ?
    What does it mean the overwrite_conflict=True in patch() method ? Does it work properly ? If yes, why I see conflict errors and why I have to use patch_with_callback method ?
    What does Patch conflict detected - invoking callback in logs mean ? If this message shows up, the patch is applied anyway ?

    Thanks



    ------------------------------
    Lucian Sipos
    ------------------------------