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] Incorporates EQL options in EQL query validation on both Rule Creation and Timeline #178468

Merged
merged 25 commits into from
Mar 19, 2024

Conversation

rylnd
Copy link
Contributor

@rylnd rylnd commented Mar 12, 2024

Summary

This PR updates the Detection Rule Creation and Timeline forms to account for the new(er) EQL options fields (timestamp_field, event_category_field, and tiebreaker_field) when validating the EQL query. While the rule query and timeline query (respectively) would correctly persist and use these options, they were unused during EQL validation, meaning that in certain situations it was impossible to produce a "valid" (from the perspective of the form) EQL query if your data necessitated one of those options (see #158326 for more details).

Changes

The above was accomplished by:

  1. Adding a hidden form field to the UI for eqlOptions
    • A lack of a field component meant that formData never held any value for this field
    • This meant that the form-based validations (i.e. eqlValidator) would not have access to eqlOptions
  2. Updating the onOptionsChange hook to additionally inform the form of changes to eqlOptions
    • This allows the form to have updated values for eqlOptions with minimal changes
    • Not ideal from a data-flow perspective, since the field changes are updating two copies of eqlOptions. However, we're only using the "form copy" for the validation call, and everything else works as it did before.

Additional changes

Update: I've reverted the described changes to the default timeline values below, and moved that to a separate issue.

In the course of performing the above tasks for timeline, I found the behavior there to be slightly different: we were specifying default values for these fields, which was redundant in some cases (timestamp_field, event_category_field), and invalid in the case of tiebreaker_field. You can see here how the tiebreaker_field must be changed to make the query valid:

Screen.Recording.2024-03-11.at.10.12.28.PM.mov

I opted to remove these default values, as well as the defaulting behavior from the search strategy call (see 10a47fd). While these values may be persisted in existing saved timelines, this makes the EQL workflow much cleaner for new users, and those users with persisted EQL options can now modify and validate those options on the fly.

Steps to Review

For @elastic/kibana-visualizations and/or @elastic/kibana-data-discovery : I've added a few tests to the EQL search strategy that document existing behavior RE EQL option fields. Nothing about the search strategy itself was changed. If you think the tests aren't useful, I'm happy to delete them.

  1. Create an index without a @timestamp field, and insert some data:

    Dev Tools
    PUT timestamp/
    {
      "mappings": {
        "dynamic": "strict",
        "properties": {
          "timestamp": {
            "type": "date",
            "format": "epoch_second"
          },
          "locale": {
            "type": "keyword"
          },
          "created_at": {
            "type": "date",
            "format": "epoch_second"
          },
          "event": {
            "properties": {
              "category": {
                "ignore_above": 1024,
                "type": "keyword"
              }
            }
          }
        }
      }
    }
    
    PUT timestamp/_doc/4
    {
      "timestamp": 1710211630,
      "locale": "es",
      "created_at": 1710211630,
      "event.category": "configuration"
    }
    
  2. Create a new EQL detection rule, and choose timestamp as the index pattern

  3. Type any where true as the query, and observe a validation error (Found 1 problem line -1:-1: Unknown column [@timestamp])

  4. Open EQL Settings popover, and select timestamp from the Timestamp field dropdown

  5. Observe that the query has been revalidated, and found valid.

New Behavior:

Screen.Recording.2024-03-11.at.10.06.19.PM.mov

Related Issues

Checklist

Delete any items that are not applicable to this PR.

For maintainers

rylnd added 10 commits February 23, 2024 12:32
The conclusion is that we currently need _both_ of these fields for the
EQL rule to operate if the data doesn't have a @timestamp at all.
However, the UI does not allow you to set both of these fields.
…rameters

This is a sanity check to allowing our EQL validation functionality to
leverage these same options.
This will break our calls, which is what we want (they need to pass
options now).
Previously, the eqlOptions field was referenced in the schema of the
Define Step form, but as there was no component controlling the field,
it was unknown to the form data, and consequently unavailable to the
queryBar validator (which is ultimately our goal here).

By adding a component for the eqlOptions field (albeit hidden), and
updating our onOptionsChange callback to additionally set that field
data, the rule form now has eqlOptions available during validation of
the EQL query.
This is one case where the form lib makes that super easy 👍.
This was mostly a sanity check, but good to document this API IMO.
By adding the field to the form itself (as a hidden field), and
modifying the onOptionsChange callback to additionally update the form
value, we now have that field value available to us when validating the
EQL query itself.

This is all near-identical to the changes just made to
the Define Step rule creation form.
* The default value of `''` for `tiebreaker_field` is invalid and must be
  changed by the user
* The redux store selector was using default values that both didn't make sense and
  were never used
* Removes defaulting behavior for options in the timeline EQL search
  strategy, since sending `timestamp_field: undefined` is equivalent to
  not specifying any value (and thus falls back to the equivalent EQL
  default)
@rylnd rylnd added the Team:Detection Engine Security Solution Detection Engine Area label Mar 12, 2024
@rylnd rylnd self-assigned this Mar 12, 2024
@rylnd rylnd added Feature:Timeline Security Solution Timeline feature Feature:Event Correlation (EQL) Rule Security Solution Event Correlation (EQL) rule type Feature:Rule Creation Security Solution Detection Rule Creation workflow labels Mar 12, 2024
@rylnd
Copy link
Contributor Author

rylnd commented Mar 12, 2024

/ci

rylnd added 3 commits March 12, 2024 13:50
While the data I wrote was "non-ECS," that's not a necessary feature of
the bug here. It simply needs to _not_ have a @timestamp field.

This also updates the corresponding FTR tests to not be exclusive
(whoops).
While the '@' in the file/folder seems to work, I'm a little dubious of
the portability. Using normal characters here just to be safe.
This is retrieving the general rule index pattern input (of which there
is no other reference); I think the naming was due to it originally
being introduced while testing the IM rule type.
@rylnd
Copy link
Contributor Author

rylnd commented Mar 12, 2024

/ci

This automates the process that I've been using to test this: given data
without an `@timestamp` (the default time field for EQL), you'll see
errors when we attempt to validate the EQL query UNTIL you choose
another timestamp field via the EQL options.
@rylnd
Copy link
Contributor Author

rylnd commented Mar 12, 2024

/ci

@rylnd rylnd marked this pull request as ready for review March 13, 2024 00:12
@rylnd rylnd requested review from a team as code owners March 13, 2024 00:12
An empty string is the default value for the EQL option
`tiebreaker_field` in the timeline EQL form. However, if this is passed
directly to ES an error will be thrown, as this is never a valid value
for that option.

A similar guard exists in the timeline EQL search strategy; we're adding
one to our validation call as well now that it has to deal with those
values.
These additional parameters do not need to be specified in order to
produce a valid query, but I am requiring that the key be specified for
sanity's sake.
@rylnd
Copy link
Contributor Author

rylnd commented Mar 13, 2024

@kqualters-elastic I split off the defaulting conversation into https://github.com/elastic/security-team/issues/8892. On this PR, I've reverted the defaulting changes, and added the necessary guard to prevent the behavior in the above video.

@@ -814,17 +827,16 @@ const StepDefineRuleComponent: FC<StepDefineRuleProps> = ({
<>
<StepContentWrapper addPadding={!isUpdateView}>
<Form form={form} data-test-subj="stepDefineRule">
<StyledVisibleContainer isVisible={false}>
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is wholly unrelated to this PR, but react was throwing dev warnings on this page and I couldn't help but fix it. See 3a9d040 for more details.

@@ -174,4 +183,34 @@ describe('EQL rules', { tags: ['@ess', '@serverless'] }, () => {
});
});
});

describe('with source data requiring EQL overrides', () => {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is the one true 🔴 -> 🟢 test in this PR; the rest are just documenting existing behavior.

@kqualters-elastic
Copy link
Contributor

kqualters-elastic commented Mar 13, 2024

@rylnd cool, I ran everything locally before that commit and all lgtm 👍 I think an easy solution (and could probably revert to how you had it) would be to just add the default field to either the form field description label or the input placeholder, and not have any defaults in the app state at all. Solves 2 and lets it work how you initially had it I think.

Copy link
Member

@lukasolson lukasolson left a comment

Choose a reason for hiding this comment

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

DataDiscovery code changes LGTM!

rylnd added 3 commits March 14, 2024 12:16
In elastic#178724, we added the ability to retrieve archives from another
location (namely, where our FTR archives live). This allows me to delete
the duplicated archive specific for the cypress usage, and share the FTR
archive between both. Nice!
}: Params): Promise<{ valid: boolean; errors: string[] }> => {
const { rawResponse: response } = await firstValueFrom(
data.search.search<EqlSearchStrategyRequest, EqlSearchStrategyResponse>(
{
params: {
index: dataViewTitle,
body: { query, runtime_mappings: runtimeMappings, size: 0 },
// @ts-expect-error top-level keys are unexpected in {@link EqlSearchRequest}
Copy link
Contributor

Choose a reason for hiding this comment

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

why this error happens here?
I don't see any top level await introduced here

Copy link
Contributor Author

Choose a reason for hiding this comment

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

These @ts-expect-errors were due to an incompatibility between the actual EQL endpoint, and the types in the search strategy. I managed to extend the type to make this all work without the need for the @ts-expect-error: 6767182.

I'm not sure what you were referring to with the await comment, though.

cy.task('esArchiverUnload', { archiveName: 'no_at_timestamp_field', type: 'ftr' });
});

it('includes EQL options in query validation', () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

can you please run flaky test runner to ensure this test is not flaky?

https://ci-stats.kibana.dev/trigger_flaky_test_runner/1

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Of course.

Do you see anything in the test itself that looks suspect?

Copy link
Contributor

Choose a reason for hiding this comment

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

nothing suspicious, but when adding new test we usually run them in flaky test runner to ensure they are not flaky, as an effort to reduce overall Cypress tests flakiness.
Since even perfectly written code does not guarantee tests won't be flaky unfortunately


expect(_log.errors).to.be.empty();
expect(_log.warnings).to.eql([
'This rule reached the maximum alert limit for the rule execution. Some alerts were not created.',
Copy link
Contributor

Choose a reason for hiding this comment

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

test title suggests no alerts were generated, but they were
specifying only timestamp_field results in a warning, and no alerts are generated

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oops! Good catch. f3e55d5

logs: [_log],
} = await previewRule({ supertest, rule });

expect(_log.errors).to.be.empty();
Copy link
Contributor

Choose a reason for hiding this comment

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

test title suggests no alerts were generated and error encountered
no error in test and alert were generated
specifying only timestamp_override results in an error, and no alerts are generated

Copy link
Contributor Author

Choose a reason for hiding this comment

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

expect(previewAlerts.length).to.be.greaterThan(0);
});

it('specifying both timestamp_override and timestamp_field behaves as expected', async () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

can we add more details what is expected in this case.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good catch, thank you! f3e55d5

rylnd added 3 commits March 18, 2024 17:07
The actual ES client/EQL endpoint allows for specifying options at both
the top level _and_ within the request's `body` parameter. However, we
had only typed the latter in our original implementation.

This aligns the types with the actual (demonstrable, as evidenced by all
the @ts-expect-errors) behavior of the server, using a
union type cribbed from responseops (see elastic#171348).

Consequently, all these `@ts-expect-error`s can now be removed.
A few of these were updated in the course of development without the
title being updated. This clarifies the behavior in the case of data
with `@timestamp`, as well as replacing the vague "behaves as expected"
descriptions with more helpful ones.
@rylnd rylnd requested a review from vitaliidm March 18, 2024 22:41
@rylnd
Copy link
Contributor Author

rylnd commented Mar 18, 2024

@vitaliidm thanks for the diligence in your review! I fixed the type error, as well as the test descriptions, and the flaky runner is running now. Ready for another review!

@kibana-ci
Copy link
Collaborator

💚 Build Succeeded

Metrics [docs]

Async chunks

Total size of all lazy-loaded chunks that will be downloaded as the user navigates the app

id before after diff
securitySolution 15.5MB 15.5MB +1.3KB

History

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

cc @rylnd

Copy link
Contributor

@vitaliidm vitaliidm left a comment

Choose a reason for hiding this comment

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

Detection Engine area LGTM
@rylnd thank you for fixing it, adding extensive test coverage and addressing my review comments

@rylnd rylnd added the backport:prev-minor Backport to (8.x) the previous minor version (i.e. one version back from main) label Mar 19, 2024
@rylnd rylnd merged commit 5be91c9 into elastic:main Mar 19, 2024
38 checks passed
@rylnd rylnd deleted the rylnd/bugfix/eql_rule_timestamp_override branch March 19, 2024 17:52
kibanamachine pushed a commit to kibanamachine/kibana that referenced this pull request Mar 19, 2024
…on both Rule Creation and Timeline (elastic#178468)

## Summary

This PR updates the Detection Rule Creation and Timeline forms to
account for the new(er) EQL options fields (`timestamp_field`,
`event_category_field`, and `tiebreaker_field`) when validating the EQL
query. While the rule query and timeline query (respectively) would
correctly persist and use these options, they were unused during EQL
validation, meaning that in certain situations it was impossible to
produce a "valid" (from the perspective of the form) EQL query if your
data necessitated one of those options (see
elastic#158326 for more details).

### Changes
The above was accomplished by:

1. Adding a hidden form field to the UI for `eqlOptions`
* A lack of a field component meant that `formData` never held any value
for this field
* This meant that the form-based validations (i.e. `eqlValidator`) would
not have access to `eqlOptions`
2. Updating the `onOptionsChange` hook to additionally inform the form
of changes to `eqlOptions`
* This allows the form to have updated values for `eqlOptions` with
minimal changes
* Not ideal from a data-flow perspective, since the field changes are
updating two copies of `eqlOptions`. However, we're only using the "form
copy" for the validation call, and everything else works as it did
before.

### Additional changes
__Update__: I've reverted the described changes to the default timeline
values below, and moved that to a [separate
issue](elastic/security-team#8892).

In the course of performing the above tasks for timeline, I found the
behavior there to be slightly different: we were specifying default
values for these fields, which was redundant in some cases
(`timestamp_field`, `event_category_field`), and invalid in the case of
`tiebreaker_field`. You can see here how the `tiebreaker_field` must be
changed to make the query valid:

https://github.com/elastic/kibana/assets/657252/556bc998-c147-4825-8bde-5d8d03873e75

~~I opted to remove these default values, as well as the defaulting
behavior from the search strategy call (see
10a47fd). While these values may be
persisted in existing saved timelines, this makes the EQL workflow much
cleaner for new users, and those users with persisted EQL options can
now modify and validate those options on the fly.~~

#### Steps to Review

For @elastic/kibana-visualizations and/or @elastic/kibana-data-discovery
: I've added a few tests to the EQL search strategy that document
existing behavior RE EQL option fields. Nothing about the search
strategy itself was changed. If you think the tests aren't useful, I'm
happy to delete them.

1. Create an index without a `@timestamp` field, and insert some data:
    <details>
    <summary>Dev Tools</summary>

       PUT timestamp/
       {
         "mappings": {
           "dynamic": "strict",
           "properties": {
             "timestamp": {
               "type": "date",
               "format": "epoch_second"
             },
             "locale": {
               "type": "keyword"
             },
             "created_at": {
               "type": "date",
               "format": "epoch_second"
             },
             "event": {
               "properties": {
                 "category": {
                   "ignore_above": 1024,
                   "type": "keyword"
                 }
               }
             }
           }
         }
       }

       PUT timestamp/_doc/4
       {
         "timestamp": 1710211630,
         "locale": "es",
         "created_at": 1710211630,
         "event.category": "configuration"
       }
    </details>
2. Create a new EQL detection rule, and choose `timestamp` as the index
pattern
3. Type `any where true` as the query, and observe a validation error
(`Found 1 problem line -1:-1: Unknown column [@timestamp]`)
4. Open EQL Settings popover, and select `timestamp` from the `Timestamp
field` dropdown
5. Observe that the query has been revalidated, and found valid.

### New Behavior:

https://github.com/elastic/kibana/assets/657252/22a63363-d597-4dfd-8f9a-647f4084ec0e

### Related Issues
* Addresses elastic#158326

### Checklist

Delete any items that are not applicable to this PR.

- [ ]
[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)
was added for features that require explanation or tutorials
- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios
- [x] [Flaky Test
Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was
used on any tests changed

### For maintainers

- [x] This was checked for breaking API changes and was [labeled
appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)

(cherry picked from commit 5be91c9)
@kibanamachine
Copy link
Contributor

💚 All backports created successfully

Status Branch Result
8.13

Note: Successful backport PRs will be merged automatically after passing CI.

Questions ?

Please refer to the Backport tool documentation

kibanamachine added a commit that referenced this pull request Mar 19, 2024
…dation on both Rule Creation and Timeline (#178468) (#178994)

# Backport

This will backport the following commits from `main` to `8.13`:
- [[Security Solution] Incorporates EQL options in EQL query validation
on both Rule Creation and Timeline
(#178468)](#178468)

<!--- Backport version: 9.4.3 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sqren/backport)

<!--BACKPORT [{"author":{"name":"Ryland
Herrick","email":"[email protected]"},"sourceCommit":{"committedDate":"2024-03-19T17:52:35Z","message":"[Security
Solution] Incorporates EQL options in EQL query validation on both Rule
Creation and Timeline (#178468)\n\n## Summary\r\n\r\nThis PR updates the
Detection Rule Creation and Timeline forms to\r\naccount for the new(er)
EQL options fields (`timestamp_field`,\r\n`event_category_field`, and
`tiebreaker_field`) when validating the EQL\r\nquery. While the rule
query and timeline query (respectively) would\r\ncorrectly persist and
use these options, they were unused during EQL\r\nvalidation, meaning
that in certain situations it was impossible to\r\nproduce a \"valid\"
(from the perspective of the form) EQL query if your\r\ndata
necessitated one of those options
(see\r\nhttps://github.com//issues/158326 for more
details).\r\n\r\n### Changes\r\nThe above was accomplished by:\r\n\r\n1.
Adding a hidden form field to the UI for `eqlOptions`\r\n* A lack of a
field component meant that `formData` never held any value\r\nfor this
field\r\n* This meant that the form-based validations (i.e.
`eqlValidator`) would\r\nnot have access to `eqlOptions`\r\n2. Updating
the `onOptionsChange` hook to additionally inform the form\r\nof changes
to `eqlOptions`\r\n* This allows the form to have updated values for
`eqlOptions` with\r\nminimal changes\r\n* Not ideal from a data-flow
perspective, since the field changes are\r\nupdating two copies of
`eqlOptions`. However, we're only using the \"form\r\ncopy\" for the
validation call, and everything else works as it did\r\nbefore.\r\n\r\n
\r\n### Additional changes\r\n__Update__: I've reverted the described
changes to the default timeline\r\nvalues below, and moved that to a
[separate\r\nissue](https://github.com/elastic/security-team/issues/8892).\r\n\r\nIn
the course of performing the above tasks for timeline, I found
the\r\nbehavior there to be slightly different: we were specifying
default\r\nvalues for these fields, which was redundant in some
cases\r\n(`timestamp_field`, `event_category_field`), and invalid in the
case of\r\n`tiebreaker_field`. You can see here how the
`tiebreaker_field` must be\r\nchanged to make the query
valid:\r\n\r\n\r\nhttps://github.com/elastic/kibana/assets/657252/556bc998-c147-4825-8bde-5d8d03873e75\r\n\r\n\r\n~~I
opted to remove these default values, as well as the
defaulting\r\nbehavior from the search strategy call
(see\r\n10a47fdaba5860a44638aada78c0cf8c37b2c580). While these values
may be\r\npersisted in existing saved timelines, this makes the EQL
workflow much\r\ncleaner for new users, and those users with persisted
EQL options can\r\nnow modify and validate those options on the
fly.~~\r\n\r\n#### Steps to Review\r\n\r\nFor
@elastic/kibana-visualizations and/or
@elastic/kibana-data-discovery\r\n: I've added a few tests to the EQL
search strategy that document\r\nexisting behavior RE EQL option fields.
Nothing about the search\r\nstrategy itself was changed. If you think
the tests aren't useful, I'm\r\nhappy to delete them.\r\n\r\n1. Create
an index without a `@timestamp` field, and insert some data:\r\n
<details>\r\n <summary>Dev Tools</summary>\r\n\r\n PUT timestamp/\r\n
{\r\n \"mappings\": {\r\n \"dynamic\": \"strict\",\r\n \"properties\":
{\r\n \"timestamp\": {\r\n \"type\": \"date\",\r\n \"format\":
\"epoch_second\"\r\n },\r\n \"locale\": {\r\n \"type\": \"keyword\"\r\n
},\r\n \"created_at\": {\r\n \"type\": \"date\",\r\n \"format\":
\"epoch_second\"\r\n },\r\n \"event\": {\r\n \"properties\": {\r\n
\"category\": {\r\n \"ignore_above\": 1024,\r\n \"type\":
\"keyword\"\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n PUT
timestamp/_doc/4\r\n {\r\n \"timestamp\": 1710211630,\r\n \"locale\":
\"es\",\r\n \"created_at\": 1710211630,\r\n \"event.category\":
\"configuration\"\r\n }\r\n </details>\r\n2. Create a new EQL detection
rule, and choose `timestamp` as the index\r\npattern\r\n3. Type `any
where true` as the query, and observe a validation error\r\n(`Found 1
problem line -1:-1: Unknown column [@timestamp]`)\r\n4. Open EQL
Settings popover, and select `timestamp` from the `Timestamp\r\nfield`
dropdown\r\n5. Observe that the query has been revalidated, and found
valid.\r\n\r\n\r\n### New
Behavior:\r\n\r\n\r\nhttps://github.com/elastic/kibana/assets/657252/22a63363-d597-4dfd-8f9a-647f4084ec0e\r\n\r\n\r\n\r\n###
Related Issues\r\n* Addresses
https://github.com/elastic/kibana/issues/158326\r\n\r\n###
Checklist\r\n\r\nDelete any items that are not applicable to this
PR.\r\n\r\n- [
]\r\n[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)\r\nwas
added for features that require explanation or tutorials\r\n- [x] [Unit
or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common scenarios\r\n- [x] [Flaky
Test\r\nRunner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1)
was\r\nused on any tests changed\r\n\r\n### For maintainers\r\n\r\n- [x]
This was checked for breaking API changes and was
[labeled\r\nappropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)","sha":"5be91c94b1c7e6b1aebd5fe75c86e2bc17c90ad0","branchLabelMapping":{"^v8.14.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:fix","Feature:Timeline","Feature:Event
Correlation (EQL) Rule","Feature:Rule
Creation","backport:prev-minor","Team:Detection
Engine","v8.14.0"],"title":"[Security Solution] Incorporates EQL options
in EQL query validation on both Rule Creation and
Timeline","number":178468,"url":"https://github.com/elastic/kibana/pull/178468","mergeCommit":{"message":"[Security
Solution] Incorporates EQL options in EQL query validation on both Rule
Creation and Timeline (#178468)\n\n## Summary\r\n\r\nThis PR updates the
Detection Rule Creation and Timeline forms to\r\naccount for the new(er)
EQL options fields (`timestamp_field`,\r\n`event_category_field`, and
`tiebreaker_field`) when validating the EQL\r\nquery. While the rule
query and timeline query (respectively) would\r\ncorrectly persist and
use these options, they were unused during EQL\r\nvalidation, meaning
that in certain situations it was impossible to\r\nproduce a \"valid\"
(from the perspective of the form) EQL query if your\r\ndata
necessitated one of those options
(see\r\nhttps://github.com//issues/158326 for more
details).\r\n\r\n### Changes\r\nThe above was accomplished by:\r\n\r\n1.
Adding a hidden form field to the UI for `eqlOptions`\r\n* A lack of a
field component meant that `formData` never held any value\r\nfor this
field\r\n* This meant that the form-based validations (i.e.
`eqlValidator`) would\r\nnot have access to `eqlOptions`\r\n2. Updating
the `onOptionsChange` hook to additionally inform the form\r\nof changes
to `eqlOptions`\r\n* This allows the form to have updated values for
`eqlOptions` with\r\nminimal changes\r\n* Not ideal from a data-flow
perspective, since the field changes are\r\nupdating two copies of
`eqlOptions`. However, we're only using the \"form\r\ncopy\" for the
validation call, and everything else works as it did\r\nbefore.\r\n\r\n
\r\n### Additional changes\r\n__Update__: I've reverted the described
changes to the default timeline\r\nvalues below, and moved that to a
[separate\r\nissue](https://github.com/elastic/security-team/issues/8892).\r\n\r\nIn
the course of performing the above tasks for timeline, I found
the\r\nbehavior there to be slightly different: we were specifying
default\r\nvalues for these fields, which was redundant in some
cases\r\n(`timestamp_field`, `event_category_field`), and invalid in the
case of\r\n`tiebreaker_field`. You can see here how the
`tiebreaker_field` must be\r\nchanged to make the query
valid:\r\n\r\n\r\nhttps://github.com/elastic/kibana/assets/657252/556bc998-c147-4825-8bde-5d8d03873e75\r\n\r\n\r\n~~I
opted to remove these default values, as well as the
defaulting\r\nbehavior from the search strategy call
(see\r\n10a47fdaba5860a44638aada78c0cf8c37b2c580). While these values
may be\r\npersisted in existing saved timelines, this makes the EQL
workflow much\r\ncleaner for new users, and those users with persisted
EQL options can\r\nnow modify and validate those options on the
fly.~~\r\n\r\n#### Steps to Review\r\n\r\nFor
@elastic/kibana-visualizations and/or
@elastic/kibana-data-discovery\r\n: I've added a few tests to the EQL
search strategy that document\r\nexisting behavior RE EQL option fields.
Nothing about the search\r\nstrategy itself was changed. If you think
the tests aren't useful, I'm\r\nhappy to delete them.\r\n\r\n1. Create
an index without a `@timestamp` field, and insert some data:\r\n
<details>\r\n <summary>Dev Tools</summary>\r\n\r\n PUT timestamp/\r\n
{\r\n \"mappings\": {\r\n \"dynamic\": \"strict\",\r\n \"properties\":
{\r\n \"timestamp\": {\r\n \"type\": \"date\",\r\n \"format\":
\"epoch_second\"\r\n },\r\n \"locale\": {\r\n \"type\": \"keyword\"\r\n
},\r\n \"created_at\": {\r\n \"type\": \"date\",\r\n \"format\":
\"epoch_second\"\r\n },\r\n \"event\": {\r\n \"properties\": {\r\n
\"category\": {\r\n \"ignore_above\": 1024,\r\n \"type\":
\"keyword\"\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n PUT
timestamp/_doc/4\r\n {\r\n \"timestamp\": 1710211630,\r\n \"locale\":
\"es\",\r\n \"created_at\": 1710211630,\r\n \"event.category\":
\"configuration\"\r\n }\r\n </details>\r\n2. Create a new EQL detection
rule, and choose `timestamp` as the index\r\npattern\r\n3. Type `any
where true` as the query, and observe a validation error\r\n(`Found 1
problem line -1:-1: Unknown column [@timestamp]`)\r\n4. Open EQL
Settings popover, and select `timestamp` from the `Timestamp\r\nfield`
dropdown\r\n5. Observe that the query has been revalidated, and found
valid.\r\n\r\n\r\n### New
Behavior:\r\n\r\n\r\nhttps://github.com/elastic/kibana/assets/657252/22a63363-d597-4dfd-8f9a-647f4084ec0e\r\n\r\n\r\n\r\n###
Related Issues\r\n* Addresses
https://github.com/elastic/kibana/issues/158326\r\n\r\n###
Checklist\r\n\r\nDelete any items that are not applicable to this
PR.\r\n\r\n- [
]\r\n[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)\r\nwas
added for features that require explanation or tutorials\r\n- [x] [Unit
or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common scenarios\r\n- [x] [Flaky
Test\r\nRunner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1)
was\r\nused on any tests changed\r\n\r\n### For maintainers\r\n\r\n- [x]
This was checked for breaking API changes and was
[labeled\r\nappropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)","sha":"5be91c94b1c7e6b1aebd5fe75c86e2bc17c90ad0"}},"sourceBranch":"main","suggestedTargetBranches":[],"targetPullRequestStates":[{"branch":"main","label":"v8.14.0","branchLabelMappingKey":"^v8.14.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/178468","number":178468,"mergeCommit":{"message":"[Security
Solution] Incorporates EQL options in EQL query validation on both Rule
Creation and Timeline (#178468)\n\n## Summary\r\n\r\nThis PR updates the
Detection Rule Creation and Timeline forms to\r\naccount for the new(er)
EQL options fields (`timestamp_field`,\r\n`event_category_field`, and
`tiebreaker_field`) when validating the EQL\r\nquery. While the rule
query and timeline query (respectively) would\r\ncorrectly persist and
use these options, they were unused during EQL\r\nvalidation, meaning
that in certain situations it was impossible to\r\nproduce a \"valid\"
(from the perspective of the form) EQL query if your\r\ndata
necessitated one of those options
(see\r\nhttps://github.com//issues/158326 for more
details).\r\n\r\n### Changes\r\nThe above was accomplished by:\r\n\r\n1.
Adding a hidden form field to the UI for `eqlOptions`\r\n* A lack of a
field component meant that `formData` never held any value\r\nfor this
field\r\n* This meant that the form-based validations (i.e.
`eqlValidator`) would\r\nnot have access to `eqlOptions`\r\n2. Updating
the `onOptionsChange` hook to additionally inform the form\r\nof changes
to `eqlOptions`\r\n* This allows the form to have updated values for
`eqlOptions` with\r\nminimal changes\r\n* Not ideal from a data-flow
perspective, since the field changes are\r\nupdating two copies of
`eqlOptions`. However, we're only using the \"form\r\ncopy\" for the
validation call, and everything else works as it did\r\nbefore.\r\n\r\n
\r\n### Additional changes\r\n__Update__: I've reverted the described
changes to the default timeline\r\nvalues below, and moved that to a
[separate\r\nissue](https://github.com/elastic/security-team/issues/8892).\r\n\r\nIn
the course of performing the above tasks for timeline, I found
the\r\nbehavior there to be slightly different: we were specifying
default\r\nvalues for these fields, which was redundant in some
cases\r\n(`timestamp_field`, `event_category_field`), and invalid in the
case of\r\n`tiebreaker_field`. You can see here how the
`tiebreaker_field` must be\r\nchanged to make the query
valid:\r\n\r\n\r\nhttps://github.com/elastic/kibana/assets/657252/556bc998-c147-4825-8bde-5d8d03873e75\r\n\r\n\r\n~~I
opted to remove these default values, as well as the
defaulting\r\nbehavior from the search strategy call
(see\r\n10a47fdaba5860a44638aada78c0cf8c37b2c580). While these values
may be\r\npersisted in existing saved timelines, this makes the EQL
workflow much\r\ncleaner for new users, and those users with persisted
EQL options can\r\nnow modify and validate those options on the
fly.~~\r\n\r\n#### Steps to Review\r\n\r\nFor
@elastic/kibana-visualizations and/or
@elastic/kibana-data-discovery\r\n: I've added a few tests to the EQL
search strategy that document\r\nexisting behavior RE EQL option fields.
Nothing about the search\r\nstrategy itself was changed. If you think
the tests aren't useful, I'm\r\nhappy to delete them.\r\n\r\n1. Create
an index without a `@timestamp` field, and insert some data:\r\n
<details>\r\n <summary>Dev Tools</summary>\r\n\r\n PUT timestamp/\r\n
{\r\n \"mappings\": {\r\n \"dynamic\": \"strict\",\r\n \"properties\":
{\r\n \"timestamp\": {\r\n \"type\": \"date\",\r\n \"format\":
\"epoch_second\"\r\n },\r\n \"locale\": {\r\n \"type\": \"keyword\"\r\n
},\r\n \"created_at\": {\r\n \"type\": \"date\",\r\n \"format\":
\"epoch_second\"\r\n },\r\n \"event\": {\r\n \"properties\": {\r\n
\"category\": {\r\n \"ignore_above\": 1024,\r\n \"type\":
\"keyword\"\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n PUT
timestamp/_doc/4\r\n {\r\n \"timestamp\": 1710211630,\r\n \"locale\":
\"es\",\r\n \"created_at\": 1710211630,\r\n \"event.category\":
\"configuration\"\r\n }\r\n </details>\r\n2. Create a new EQL detection
rule, and choose `timestamp` as the index\r\npattern\r\n3. Type `any
where true` as the query, and observe a validation error\r\n(`Found 1
problem line -1:-1: Unknown column [@timestamp]`)\r\n4. Open EQL
Settings popover, and select `timestamp` from the `Timestamp\r\nfield`
dropdown\r\n5. Observe that the query has been revalidated, and found
valid.\r\n\r\n\r\n### New
Behavior:\r\n\r\n\r\nhttps://github.com/elastic/kibana/assets/657252/22a63363-d597-4dfd-8f9a-647f4084ec0e\r\n\r\n\r\n\r\n###
Related Issues\r\n* Addresses
https://github.com/elastic/kibana/issues/158326\r\n\r\n###
Checklist\r\n\r\nDelete any items that are not applicable to this
PR.\r\n\r\n- [
]\r\n[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)\r\nwas
added for features that require explanation or tutorials\r\n- [x] [Unit
or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common scenarios\r\n- [x] [Flaky
Test\r\nRunner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1)
was\r\nused on any tests changed\r\n\r\n### For maintainers\r\n\r\n- [x]
This was checked for breaking API changes and was
[labeled\r\nappropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)","sha":"5be91c94b1c7e6b1aebd5fe75c86e2bc17c90ad0"}}]}]
BACKPORT-->

---------

Co-authored-by: Ryland Herrick <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backport:prev-minor Backport to (8.x) the previous minor version (i.e. one version back from main) Feature:Event Correlation (EQL) Rule Security Solution Event Correlation (EQL) rule type Feature:Rule Creation Security Solution Detection Rule Creation workflow Feature:Timeline Security Solution Timeline feature release_note:fix Team:Detection Engine Security Solution Detection Engine Area v8.13.0 v8.14.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants