Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Security Solution][Detections] Await promises to ensure promise rejection does not crash kibana #88564

Merged
merged 3 commits into from
Jan 19, 2021

Conversation

marshallmain
Copy link
Contributor

@marshallmain marshallmain commented Jan 17, 2021

Summary

In modern versions of node js, an unhandled promise rejection causes the process to exit. We were creating promises that could reject without .catch and Kibana would crash if the promise rejected.

To reproduce the promise rejection on master:

  1. Create 2 indices, one with @timestamp mapped and one with event.ingested mapped.
PUT /test-1
{
  "mappings": {
    "properties": {
      "@timestamp": {
        "type": "date"
      }
    }
  }
}

PUT /test-2
{
  "mappings": {
    "properties": {
      "event.ingested": {
        "type": "date"
      }
    }
  }
}
  1. Create a KQL rule that searches both indices and add event.ingested as the timestamp override. Save the rule.
  2. Edit the KQL rule and remove test-2 from the indices searched but leave test-1. Activate the rule. The rule will attempt to search test-1 using event.ingested to sort on, however, the search will return an error causing the promise to reject and Kibana will crash when the rule runs for the second time. Not sure yet why it doesn't crash on the first rule run despite the promise rejecting - possibly a race, if it can reach the point where the promise is awaited before the promise rejects then it won't be unhandled.

Checklist

Delete any items that are not applicable to this PR.

For maintainers

@marshallmain marshallmain requested review from a team as code owners January 17, 2021 06:34
@marshallmain marshallmain added v7.11.0 v8.0.0 release_note:skip Skip the PR/issue when compiling release notes Team:Detections and Resp Security Detection Response Team v7.12.0 labels Jan 17, 2021
Copy link
Contributor

@dhurley14 dhurley14 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be great if we could add some unit tests exposing the failing functionality that then pass / is handled with these changes.

In general, the code in search_after_bulk_create has become a bit unruly. This code is making it more difficult to write unit tests for and could use some TLC before we begin merging into a unified architecture with alerting. While you're in here I think this code could utilize some general cleanup. It seems to me we generally want to take the search results from the two searches, merge them, and then do a bulk create all while checking a few conditions to determine when to exit and stop searching. I think it would be great if we could streamline the code and take the outputs from some pure functions and make them inputs to the others and in a way that would make it easier to test. This would in turn help us remove the let hasSortId and let hasBackupSortId which will help us with maintainability going forward.

@marshallmain
Copy link
Contributor Author

@elasticmachine merge upstream

@marshallmain
Copy link
Contributor Author

I don't think this behavior is a good candidate for unit testing since a unit test for this case would be extremely dependent on the function implementation rather than the desired function outputs. The unit test would have to mock specific external API calls inside the function in the right order. In addition, since the bug is a race condition we'd have to be very careful when mocking the calls as to not make a flaky test.

If we want to add tooling to detect errors like this one, something like https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-floating-promises.md would probably be effective.

I agree that this code needs to be simplified, however I believe this bug fix needs to go into 7.11 as it can crash Kibana and we shouldn't be doing significant refactoring for 7.11 at this stage.

Copy link
Contributor

@dhurley14 dhurley14 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair enough. I think a small refactor from the promises being executed in series to running in parallel with Promise.all might be a good update in general. I think you might have mentioned this before?

@marshallmain
Copy link
Contributor Author

Running the queries in parallel would be an improvement, however in making that change we would also want to handle the error cases for each query independently - right now a promise rejection from either query falls through to the catch at the end. I think it would be safer to bundle that refactoring together in 7.12+.

@kibanamachine
Copy link
Contributor

💚 Build Succeeded

Metrics [docs]

✅ unchanged

History

To update your PR or re-run it, just comment with:
@elasticmachine merge upstream

@marshallmain marshallmain merged commit 90f2abd into elastic:master Jan 19, 2021
@marshallmain marshallmain deleted the search-after-reject branch January 19, 2021 21:11
marshallmain added a commit to marshallmain/kibana that referenced this pull request Jan 19, 2021
…ction does not crash kibana (elastic#88564)

* Await promises to ensure promise rejection does not crash kibana

* Fix test

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
marshallmain added a commit to marshallmain/kibana that referenced this pull request Jan 19, 2021
…ction does not crash kibana (elastic#88564)

* Await promises to ensure promise rejection does not crash kibana

* Fix test

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
marshallmain added a commit that referenced this pull request Jan 20, 2021
…ction does not crash kibana (#88564) (#88760)

* Await promises to ensure promise rejection does not crash kibana

* Fix test

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
marshallmain added a commit that referenced this pull request Jan 20, 2021
…ction does not crash kibana (#88564) (#88761)

* Await promises to ensure promise rejection does not crash kibana

* Fix test

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
release_note:skip Skip the PR/issue when compiling release notes Team:Detections and Resp Security Detection Response Team v7.11.0 v7.12.0 v8.0.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants