elastic / kibana

Your window into the Elastic Stack
https://www.elastic.co/products/kibana
Other
19.81k stars 8.2k forks source link

[Security Solution][Exceptions] Adding exception from alert does not work on first try after page refresh #176646

Open marshallmain opened 8 months ago

marshallmain commented 8 months ago

Steps to Reproduce (work on 8.10.4 and main)

  1. Generate an alert
  2. Go to the alerts table and hard refresh the page
  3. In the Actions column, click on More actions and select Add rule exception
  4. You should see the exceptions flyout open, display the form, very briefly hide the form, then display the form again.
  5. Fill in the exception name and click Add rule exception
  6. The flyout closes, but the exception will not be created

It seems that what's happening is when you click Add rule exception in the context menu, it's loading the rule through the rules API but not waiting for the rule response before opening the flyout. When the flyout opens, it initializes the reducer state with the rules prop - which is null until the API response comes back. When the API response does come back, the form is briefly hidden as the component re-renders due to the prop change, but we don't set the rule in the reducer state. When you click Add rule exception at the end to submit the form, since it doesn't have the rule in the reducer state the flyout logic does not make the request to create the exception or close alerts based on the exception.

One simple fix is to change the alert context menu so it doesn't render the exceptions flyout until the rule is available, returning

  return (
    memoRule && (
      <AddExceptionFlyout
        rules={memoRule}
        isEndpointItem={exceptionListType === ExceptionListTypeEnum.ENDPOINT}
        alertData={enrichedAlert}
        isAlertDataLoading={isLoading || isRuleLoading}
        alertStatus={alertStatus}
        isBulkAction={false}
        showAlertCloseOptions
        onCancel={onCancel}
        onConfirm={onConfirm}
      />
    )
  );

instead. More broadly though it appears that the data model in the flyout could use some simplification as it's one component trying to satisfy a few different use cases and it has logic specific to each use case inside the shared component.

Why does it work after the first try

The rule is fetched with useQuery and a staleTime of 0 so the UI will fetch the rule again every time the flyout is opened. However, even though the data is treated as stale immediately once it's fetched, the rule data is still cached. Subsequent requests through useQuery for the same rule ID will immediately return the stale cached data while waiting on the API response, and once the API response comes back the hook will update the result with the new data.

Since the flyout doesn't update the rule in the reducer state after component initialization, the component is essentially just using the API response from the last time the flyout was opened.

elasticmachine commented 8 months ago

Pinging @elastic/security-solution (Team: SecuritySolution)

elasticmachine commented 8 months ago

Pinging @elastic/security-detection-engine (Team:Detection Engine)