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

[SIEM] Migrate DE Routes to NP #58292

Merged
merged 99 commits into from
Mar 4, 2020
Merged

[SIEM] Migrate DE Routes to NP #58292

merged 99 commits into from
Mar 4, 2020

Conversation

rylnd
Copy link
Contributor

@rylnd rylnd commented Feb 21, 2020

Summary

#45831 #49529
Now that alerting's on NP, we're unblocked on our own migration. This migrates all remaining backend legacy code, with the exception of the config service. In a final PR, we'll use our NP-provided config object instead, and do the git mv from /legacy/plugins to /plugins.

Overview of changes

  • Conversion of DE routes to NP router
    • unblocked by alerting client
    • replaces getClients service with request handler context
    • adds validation generator to cross the bridge between our schema definitions and our Types
  • Adds siemClient to the request handler context
    • we needed a place to combine space id and our plugin configuration
    • decided against adding indexExists as that is dependent on user-specified indices and has nothing to do specifically with SIEM
  • Refactors routing tests now that we have no direct Hapi dependence
    • This was the biggest and most sprawling change necessitated by the above. Our route definitions used to be Hapi-compliant, and we leveraged this fact to create a kibana server “mock” that was really a Hapi server instance. Combined with the server’s nice inject helper, this meant we could easily test our routes without having to make an HTTP call
    • with NP, each of the above statements is nullified: we can’t pass our routes to Hapi without an adapter, our requests are not Hapi-compliant, and there is no NP server mock that would allow us to test our routes without HTTP and a full kibana server running.
    • I've built a routing test harness that allows the aforementioned scenario. It relies on kibana mocks and is tied heavily to the routing implementation, but is composed of three relatively simple pieces:
      • a router spy to record/return the registered route
      • a method (inject) to invoke the request handler and return the response spy it operated upon
      • a method (validate) to run our validation function on the provided request. similar to inject, it returns the response spy it operated on, allowing us to inspect both pass/fail status and any error messages that were generated.

Checklist

Delete any items that are not applicable to this PR.

For maintainers

@rylnd rylnd added Team:SIEM v8.0.0 release_note:skip Skip the PR/issue when compiling release notes v7.7.0 labels Feb 21, 2020
@rylnd rylnd self-assigned this Feb 21, 2020
@elasticmachine
Copy link
Contributor

Pinging @elastic/siem (Team:SIEM)

We're going to add our client to the route handler context. Currently,
it's sole purpose is to provide us with the signalsIndex to use for the
request.

This will allow us to stop passing around most uses of config and
getSpaceId, as they were used for this same purpose.
This is one of the more comprehensive routes, so I think we're good to
convert the rest.
We're gonna need this all over the place. Until our schema can generate
an NP-compatible type, we can use this helper to generate an equivalent
validator.
Copy link
Contributor

@yctercero yctercero left a comment

Choose a reason for hiding this comment

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

Pulled down and played around with it - LGTM! I replied to the comments you left regarding import_rules_routes and piggybacked on some comments already left by others.

Copy link
Contributor

@FrankHassanabad FrankHassanabad left a comment

Choose a reason for hiding this comment

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

Left comments, read through it, tested it, and everything looks very good here.

LGTM, feel free to make any changes you feel are worth it. Don't want to hold up all the goodness here.

Copy link
Contributor

@yctercero yctercero left a comment

Choose a reason for hiding this comment

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

Forgot to approve! LGTM

If we annotate that both incoming pieces of our headers are of the
correct type, then we can spread them into an object of the same type
and avoid the index signature issue.
We need to thread through the utility that provides us this same
functionality.
@dhurley14 dhurley14 requested a review from yctercero March 3, 2020 21:53
Copy link
Contributor

@yctercero yctercero left a comment

Choose a reason for hiding this comment

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

LGTM again ;)

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.

LGTM. checked out code and tested locally. Thanks for managing all the merge conflicts and updating the tests while keeping the test coverage up!

@kibanamachine
Copy link
Contributor

💚 Build Succeeded

History

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

@rylnd rylnd merged commit 875e2a5 into elastic:master Mar 4, 2020
@rylnd rylnd deleted the siem_np_alerting branch March 4, 2020 03:47
rylnd added a commit that referenced this pull request Mar 4, 2020
* Define a very basic SiemClient

We're going to add our client to the route handler context. Currently,
it's sole purpose is to provide us with the signalsIndex to use for the
request.

This will allow us to stop passing around most uses of config and
getSpaceId, as they were used for this same purpose.

* WIP: Convert first DE route to NP

This is one of the more comprehensive routes, so I think we're good to
convert the rest.

* Abstract joi/NP validator to helper

We're gonna need this all over the place. Until our schema can generate
an NP-compatible type, we can use this helper to generate an equivalent
validator.

* Second route down

* Another one

* updateRulesRoute

* Fix exports

* patchRulesRoute

* Normalize request param type names

* findRulesRoute

* addPrepackagedRulesRoute

* getPrepackagedRulesStatusRoute

* createRulesBulkRoute

* updateRulesBulkRoute

* patchRulesBulkRoute

* deleteRulesBulkRoute

* importRulesRoute

* exportRulesRoute

* findRulesStatusesRoute

* setSignalsStatusRoute

* querySignalsRoute

* Remove unused type

* createIndexRoute

* Convert readIndexRoute

Removes support for a HEAD request here, becuase it was only used by the
signal_index_exists script (which is now gone). A GET request will have
the same semantics, with a few more bytes in the response.

* deleteIndexRoute

* readTagsRoute

* readPrivilegesRoute

We're incorrectly accessing request.auth in here still, fixing that
next.

* We are always authenticated until we support optional auth

* Clean up our route initialization

* Remove our now-unused ClientsService
* Remove unused getIndex helper and references
* Remove legacy route initialization (partial application)

All our routing tests are still totally broken. Coming up!

* Reference name property in context registration

This should be replaced with a reference to the constant, but at least
this doesn't add a third way it's being referenced.

* Convert our first route tests to NP

The API for our test utils isn't final, but this at least gets some
tests passing. We'll see how it handles a more complex example.

* Create Rules tests

* Update addPrepackagedRules tests

There were a lot of incorrect tests in here due to some incorrect route
registration: we were asserting a 404 but receiving a false positive
because the route we wanted didn't exist.

* Read Privileges Route tests

* Delete Rules route tests

* Use more permissive validation in request mock

* createRulesBulkRoute tests

* deleteRulesBulkRoute tests

* More explicit result mock

It was very unclear in the tests what this mock represented.

* findRulesRoute tests

* getPrepackagedRulesRoute tests

* PatchRulesBulkRoute tests

* Convert migrated tests to newest interface

* PatchRulesRoute tests

Also fixes a potential false positive in our patch_rule_bulk_route
validation tests by providing a more realistic payload with a single key
missing.

* Rename file for consistency

* UpdateRulesBulkRoute tests

* deleteRulesBulkRoute tests

* findRulesStatusRoute tests

* updateRulesRoute tests

* setSignalStatusRoute tests

* querySignalsRoute tests

This actually caught a bug where we were not resolving our response  before returning

* Update schema tests following rename of type

* Converts Import Rules route tests to NP form

Most of these tests are failing due to our request not being parsed by
Hapi as it previously was. Once we figure out how to generate a
post-middleware request with a file stream, these should be easily
fixed.

* Remove unused import

This was the last remaining reference to hapi in our server plugin. yay!

* Remove unnecessary tests

We're already covering our error paths here.

* Hit success branch of bulk patch route test

* Add test around error path in our route

* Update our router to validate requests by default

This gives us two important behaviors:

1. Requests to inject() will be populated with default values
2. We can test request validation independent of a handler call
  * This allows more straightforward assertions as we don't have to
  disambiguate between a schema rejection and a data rejection.

* Update route validation tests with new interface

We don't need to reach into our route in the test, nor ts-ignore it.

* Update ImportRules route tests for NP testing

Gets rid of the multipart-form processing that Hapi would convert for us
into a Readable stream. Instead, we generate our own post-middleware
requst that's got a stream on it.

* Remove unnecessary router method

A bug in an initial implementation of inject() lead me to believe that
validations were removing the stream from our requests; this turned out
to be false! YAGNI

* Add an adapter for our route responses

This provides a uniform interface of { body, status, calls }, where body
and status come from the highest-status call (in the case of many). In a
case where we build multiple responses, the preference is to return the
most problematic one first. If there's an issue, one can look into the
other calls and see what's going on.

This breaks the tests and is not fully implemented, but this will allow
us to change how we build responses without affecting our tests.

* Fix remaining assertions in one test file

Helped flesh out our adapter a bit more.

* Update our response adapter to represent how NP transforms our errors

Most importantly, we return a statusCode but not a status_code.

* Update tests to interface with our Response type

This makes them robust to framework/implementation changes.

* Generate our error responses with our siemResponse wrapper

This adds the status_code key that we desire in our error responses.

Tests were updated as well, and they're currently failing because they
expect statusCode, not status_code.

* Update test assertions to look for status_code

* Remove unused import

* Return a meaningful error if an invalid request was injected

This ensures we a) mimic platform behavior so that b) we don't risk a
false positive if our invalid request were to somehow succeed.

* Return a useful error when no route has been registered

* Add back POST variant of delete_rules_bulk_route

Some browsers do not support a request body for DELETE requests.

* Allow headers to be passed to our error response

This is used by Apollo to set some cache/allow headers in the case of
specific bad requests.

* Add back our header-passing from Apollo errors

I also inverted the logic here to handle the special case first.

* Add some tests around our error response helper

* Fix types of our error wrapper

* Move router logic into separate function

This could be decomposed further but getRoute becomes more verbose, so
meh.

* Convert our mock server to a class

It makes the shared state (mocks) of these functions more explicit, and also
does away with some dumb tuple-returns I had (a consequence of trying to
make everything pure).

* Remove need for a route spy

Instead of mocking certain router methods with the same spy and then
retrieving its calls, we can simply iterate over the calls of the router
methods we care about. This is a little less logic and a little more
straightforward.

* Update test with updated copy

We're consolidating on "signals index" when referring to the data index
where signals are stored.

* Remove unneeded type assertion from our route validation factory

We implicitly cast our return value here when we provide the generic
type parameter, so there's no reason for the explicit cast.

* Use exact message assertions

* Export our SiemRequestContext type for consumers

This will move to server/index in NP.

* Make our SiemClient properties readonly

We don't want consumers mutating our state.

* Throw error if SiemClientFactory has not been properly set up

* Remove unnecessary spread

* Use reduce's type argument instead of an explicit assertion

* Remove unnecessary optional chaining

This was a holdover from when we captured calls that had no body, but is
now unnecessary.

* Remove unnecessary headers on mock requests

* Remove non-null assertion in favor of constructor assignment

* Prefer type annotations to explicit casting

If we annotate that both incoming pieces of our headers are of the
correct type, then we can spread them into an object of the same type
and avoid the index signature issue.

* Skip test failure do to handling of authentication

We need to thread through the utility that provides us this same
functionality.

* Mock our cluster calls with realistic data

* Remove TODO as this is addressed in a later PR

Co-authored-by: Josh Dover <me@joshdover.com>

Co-authored-by: Josh Dover <me@joshdover.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:SIEM v7.7.0 v8.0.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants