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] Support arrays in event fields for Severity/Risk overrides #83723

Merged
merged 6 commits into from
Dec 1, 2020

Conversation

banderror
Copy link
Contributor

@banderror banderror commented Nov 18, 2020

Addresses: #82384

Summary

This PR changes the behavior of severity and risk score overrides in two ways:

  • adds support for arrays in the mapped event fields (so a rule can be triggered by an event where e.g. event.custom_severity has a value like [45, 70, 90])
  • makes the logic of overrides more flexible, resilient to the incoming values (filters out junk, extracts meaningful values, does its best to find a value that would fit the mapping)

TODO:

  • Risc score mapping: support arrays
  • Risc score mapping: support arbitrary floats within the range [0;100] according to ECS
  • Severity: support arrays
  • Severity mapping: support numbers and strings in arbitrary (non-ECS) fields
  • Add unit tests
  • Add FTR integration tests for BE API

Useful info

You might find useful some background info on severity and risk score overrides, as well as fields from ECS corresponding to them.

Testing

Frank clearly described how to reproduce the bug in the parent issue: #82384
This instruction can be used to do manual QA and make sure the bug is fixed.

Also, I added a few FTR integration tests for the overrides:

  • x-pack/test/detection_engine_api_integration/security_and_spaces/tests/generating_signals.ts
  • x-pack/test/functional/es_archives/signals/severity_risk_overrides

You can run them with:

node scripts/functional_tests --config x-pack/test/detection_engine_api_integration/security_and_spaces/config.ts --include x-pack/test/detection_engine_api_integration/security_and_spaces/tests/generating_signals.ts

Tests implementation is based on #83764.

Checklist

Delete any items that are not applicable to this PR.

For maintainers

@banderror banderror force-pushed the severity-risk-overrides-arrays branch 4 times, most recently from 568f46c to 75ad0ca Compare November 19, 2020 18:50
@peluja1012 peluja1012 added Team:SIEM Team:Detections and Resp Security Detection Response Team labels Nov 20, 2020
@banderror banderror force-pushed the severity-risk-overrides-arrays branch 3 times, most recently from 7c96731 to 80503d9 Compare November 22, 2020 15:15
@banderror banderror self-assigned this Nov 22, 2020
@banderror banderror force-pushed the severity-risk-overrides-arrays branch from 80503d9 to 56f0f7f Compare November 23, 2020 12:38
@spong spong requested a review from a team November 23, 2020 17:57
Copy link
Contributor

@rylnd rylnd left a comment

Choose a reason for hiding this comment

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

Did a cursory code review; most of my comments are nits, FYI.

The additional logic looks good to me, but I'm not going to explicitly approve because I haven't touched/am not familiar with this code. I'm happy to do another pass here when this is out of draft, though!

expected: BuildRiskScoreFromMappingReturn;
}

function testIt({ fieldValue, scoreDefault, scoreMapping, expected }: TestCase) {
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: we tend to prefer arrow functions

Copy link
Contributor

Choose a reason for hiding this comment

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

nit: I would personally do away with the testIt function as I find it makes the tests a bit too convoluted, but that's totally subjective.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

On functions, arrows vs fn expressions vs fn declarations. Normally, unless there's a different coding standard/guideline, to vertically structure the code I prefer using the "newspaper metaphor" coined by Uncle Bob in his Clean Code book.

Newspaper Metaphor. The source file should be organized like a newspaper article, with the highest level summary at the top, and more and more details further down. Functions called from the top function come directly below it, and so on down to the lowest level and most detailed functions at the bottom. This is a good way to organize the source code, even though IDE:s make the location of functions less important, since it is so easy to navigate in and out of them.

It's a top-down approach, from general things to details, and it's possible with function declarations. With arrows and fn expressions it's possible to use the opposite bottow-up approach, where you first have details, helper functions etc, and at the bottom of the file there's let's say the main function.

Normally I use arrows in all other cases: inline calls, closures to an outer this, just a bunch of small independent functions in a file (e.g. selectors), etc.

Of course I wouldn't go against our guidelines, whether they are documented or not, and against the typical style of the codebase. For the sake of consistency.

Hopefully I managed to explain my motivation. Let me know what you think. Although the styleguide uses fn declarations, it's a general one. If this style looks too foreign for the security_solution plugin's codebase, I'll change it to the one based on arrows.

Copy link
Contributor Author

@banderror banderror Nov 24, 2020

Choose a reason for hiding this comment

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

On the testIt helper. Yea, it definitely has pros and cons. It reduces duplication and makes the test suite shorter, but abstracts away some details. One can perceive it as either good or bad thing in terms of readability and easiness to understand the tests. I personally find that as soon as you got what testIt does, it's easier and faster to read all the tests. On the other hand, it can be just a bit harder to start reading the tests once you opened the file.

If you don't have tests written in such a way and/or don't like it (yes, even subjectively), I'll refactor. But maybe there are people who are ok with that?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Any opinions, clarifications, comments or just votes are super-welcome. This helps me a lot with learning the codebase faster.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

"Newspaper metaphor" with fn declarations?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

testIt helper?

return doc;
};

export const sampleDocRiskScore = (riskScore?: unknown): SignalSourceHit => ({
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: we're starting to add a lot of indirection to these tests, and I question the utility of such a method over something like:

const testEventWithDescriptiveName = {
  ...buildSpecificEventType(),
  [fieldName]: overriddenValue,
};

For context: my perception has been that we typically prefer repetitive, inline test logic as opposed to shared helpers, with the exceptions of (normalized) data generation and ad hoc test helpers within the test file.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Discussed with @rylnd. We talked about creating test data factories and all that patterns in general, agreed on a few ideas, but no action required for this PR.

}

function getMaxOf(array: number[]) {
// NOTE: It's safer to use reduce rather than Math.max(...array). The latter won't handle large input.
Copy link
Contributor

Choose a reason for hiding this comment

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

Huh, TIL!

@banderror banderror force-pushed the severity-risk-overrides-arrays branch from bbb3f75 to 22b227f Compare November 25, 2020 16:00
@banderror banderror changed the title [Security Solution] Severity/Risk override does not work with arrays [Security Solution][Detections] Support arrays in event fields for Severity/Risk overrides Nov 25, 2020
@banderror banderror added Team: SecuritySolution Security Solutions Team working on SIEM, Endpoint, Timeline, Resolver, etc. release_note:fix v8.0.0 v7.11.0 labels Nov 25, 2020
@banderror banderror marked this pull request as ready for review November 25, 2020 16:08
@banderror banderror requested review from a team as code owners November 25, 2020 16:08
@elasticmachine
Copy link
Contributor

Pinging @elastic/siem (Team:SIEM)

@banderror banderror added the Feature:Detection Rules Anything related to Security Solution's Detection Rules label Nov 25, 2020
@banderror banderror force-pushed the severity-risk-overrides-arrays branch from 22b227f to 713134b Compare November 26, 2020 19:12
@banderror banderror requested a review from a team November 26, 2020 19:31
@kibanamachine
Copy link
Contributor

💚 Build Succeeded

Metrics [docs]

✅ unchanged

History

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

Copy link
Contributor

@peluja1012 peluja1012 left a comment

Choose a reason for hiding this comment

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

LGTM. Tested functionality with various severity and risk score combinations, including array values, and the generated signals respected the mappings and yielded expected results. Thanks for the fix and for the added FTR test coverage as well!

@banderror
Copy link
Contributor Author

Just for the record, here's the data I used to test the fix manually:

###### Testing mapping as described in the GitHub issue (slightly extended)

PUT delme-test-overrides
{
  "mappings": {
    "dynamic": "strict",
    "properties": {
      "@timestamp": {
        "type": "date"
      },
      "severity_override": {
        "type": "keyword"
      },
      "risk_override": {
        "type": "integer"
      }
    }
  }
}

PUT delme-test-overrides/_doc/1
{
 "@timestamp": "2020-11-24T13:00:01.000Z",
 "severity_override" : "sev_90",
 "risk_override": 3.14
}

PUT delme-test-overrides/_doc/2
{
 "@timestamp": "2020-11-24T13:00:02.000Z",
 "severity_override": ["sev_90", "sev_max"],
 "risk_override": [3.14]
}

PUT delme-test-overrides/_doc/3
{
 "@timestamp": "2020-11-24T13:00:03.000Z",
 "severity_override": ["sev_max", "sev_90"],
 "risk_override": "3.14"
}

PUT delme-test-overrides/_doc/4
{
 "@timestamp": "2020-11-24T13:00:04.000Z",
 "severity_override": "sev_max",
 "risk_override": [1.23, "3.14"]
}

PUT delme-test-overrides/_doc/5
{
 "@timestamp": "2020-11-24T13:00:05.000Z",
 "severity_override": 99
}


###### Testing mapping to integer non-ECS severity field

PUT delme-test-overrides-sev-int
{
  "mappings": {
    "dynamic": "strict",
    "properties": {
      "@timestamp": {
        "type": "date"
      },
      "severity_override": {
        "type": "long"
      }
    }
  }
}

PUT delme-test-overrides-sev-int/_doc/1
{
 "@timestamp": "2020-11-29T13:00:01.000Z",
 "severity_override": 60
}

PUT delme-test-overrides-sev-int/_doc/2
{
 "@timestamp": "2020-11-29T13:00:02.000Z",
 "severity_override": 70
}

PUT delme-test-overrides-sev-int/_doc/3
{
 "@timestamp": "2020-11-29T13:00:03.000Z",
 "severity_override": 80
}

PUT delme-test-overrides-sev-int/_doc/4
{
 "@timestamp": "2020-11-29T13:00:04.000Z",
 "severity_override": 90
}


###### Testing mapping to integer event.severity field from ECS

PUT delme-test-overrides-sev-ecs
{
  "mappings": {
    "dynamic": "strict",
    "properties": {
      "@timestamp": {
        "type": "date"
      },
      "event": {
        "properties": {
          "severity": {
            "type": "long"
          }
        }
      }
    }
  }
}

PUT delme-test-overrides-sev-ecs/_doc/1
{
 "@timestamp": "2020-11-30T13:00:01.000Z",
 "event": {
   "severity": 60
 }
}

PUT delme-test-overrides-sev-ecs/_doc/2
{
 "@timestamp": "2020-11-30T13:00:02.000Z",
 "event": {
   "severity": 70
 }
}

PUT delme-test-overrides-sev-ecs/_doc/3
{
 "@timestamp": "2020-11-30T13:00:03.000Z",
 "event": {
   "severity": 80
 }
}

PUT delme-test-overrides-sev-ecs/_doc/4
{
 "@timestamp": "2020-11-30T13:00:04.000Z",
 "event": {
   "severity": 90
 }
}


###### Testing mapping support in EQL rules

PUT delme-test-overrides-sev-eql
{
  "mappings": {
    "dynamic": "strict",
    "properties": {
      "@timestamp": {
        "type": "date"
      },
      "event": {
        "properties": {
          "category": {
            "type": "keyword"
          }
        }
      },
      "params": {
        "properties": {
          "severity_override": {
            "type": "keyword"
          }
        }
      }
    }
  }
}

PUT delme-test-overrides-sev-eql/_doc/1
{
 "@timestamp": "2020-12-01T08:00:01.000Z",
 "event": {
   "category": "authentication"
 },
 "params": {
   "severity_override": "sev_90"
 }
}

PUT delme-test-overrides-sev-eql/_doc/2
{
 "@timestamp": "2020-12-01T08:00:02.000Z",
 "event": {
   "category": "authentication"
 },
 "params": {
   "severity_override": "sev_max"
 }
}


#############################

GET _cat/shards/delme-test-overrides*?v&s=shard,prirep

GET delme-test-overrides/_search
GET delme-test-overrides-sev-int/_search
GET delme-test-overrides-sev-ecs/_search
GET delme-test-overrides-sev-eql/_search

DELETE delme-test-overrides*

@banderror banderror merged commit 80e88ce into elastic:master Dec 1, 2020
banderror added a commit to banderror/kibana that referenced this pull request Dec 1, 2020
…verity/Risk overrides (elastic#83723)

This PR changes the behavior of severity and risk score overrides in two ways:

- adds support for arrays in the mapped event fields (so a rule can be triggered by an event where e.g. `event.custom_severity` has a value like `[45, 70, 90]`)
- makes the logic of overrides more flexible, resilient to the incoming values (filters out junk, extracts meaningful values, does its best to find a value that would fit the mapping)
@banderror banderror deleted the severity-risk-overrides-arrays branch December 1, 2020 14:06
banderror added a commit that referenced this pull request Dec 1, 2020
…verity/Risk overrides (#83723) (#84643)

This PR changes the behavior of severity and risk score overrides in two ways:

- adds support for arrays in the mapped event fields (so a rule can be triggered by an event where e.g. `event.custom_severity` has a value like `[45, 70, 90]`)
- makes the logic of overrides more flexible, resilient to the incoming values (filters out junk, extracts meaningful values, does its best to find a value that would fit the mapping)
gmmorris added a commit to gmmorris/kibana that referenced this pull request Dec 1, 2020
* master: (63 commits)
  Revert the Revert of "[Alerting] renames Resolved action group to Recovered (elastic#84123)"  (elastic#84662)
  declare kbn/monaco dependency on kbn/i18n explicitly (elastic#84660)
  Remove unscripted fields from sample data index-pattern saved objects (elastic#84659)
  [ML] Fix unnecessary trigger of wildcard field type search for ML plugin routes. (elastic#84605)
  Update create.asciidoc (elastic#84046)
  [Security Solution][Detections] Fix labels and issue with mandatory fields (elastic#84525)
  Fix flaky test suite (elastic#84602)
  [Security Solution] [Detections] Create a 'partial failure' status for rules (elastic#84293)
  Revert "[Alerting] renames Resolved action group to Recovered (elastic#84123)"
  Update code-comments describing babel plugins (elastic#84622)
  [Security Solution] [Cases] Cypress for case connector selector options (elastic#80745)
  [Discover] Unskip doc table tests (elastic#84564)
  [Lens] (Accessibility) Improve landmarks in Lens (elastic#84511)
  [Lens] (Accessibility) Focus mistakenly stops on righthand form (elastic#84519)
  Return early when parallel install process detected (elastic#84190)
  [Security Solution][Detections] Support arrays in event fields for Severity/Risk overrides (elastic#83723)
  [Security Solution][Detections] Fix grammatical error in validation message for threshold field in "Create new rule" -> "Define rule" (elastic#84490)
  [Fleet] Update agent details page  (elastic#84434)
  adding documentation of use of NODE_EXTRA_CA_CERTS env var (elastic#84578)
  [Search] Integrate "Send to background" UI with session service (elastic#83073)
  ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature:Detection Rules Anything related to Security Solution's Detection Rules release_note:fix Team:Detections and Resp Security Detection Response Team Team: SecuritySolution Security Solutions Team working on SIEM, Endpoint, Timeline, Resolver, etc. Team:SIEM v7.11.0 v8.0.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants