IBM Security QRadar SOAR

 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
    ------------------------------