-
Notifications
You must be signed in to change notification settings - Fork 8.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[SecuritySolution] - Create API that calculates the risk score for an…
… Entity (#181715) ## Summary Create the API that calculates and stores the risk score for one entity. ### API ``` POST /api/risk_scores/calculation/entity { identifier_type: "host", // host || user identifier: "Host-mbl1642qhk", } ``` ### Example Response ``` { success: true, // a calculation can be successful but have no score, I didnt like the idea of sending an empty object in that case score : { // optional if a score is calculated "calculated_level": "Low", "calculated_score": 48.94973536147405, "calculated_score_norm": 31.565227875770386, "category_1_score": 18.74032747376495, "category_1_count": 50, "notes": [], "inputs": [...inputs], "category_2_score": 12.824900402005436, "category_2_count": 1, "criticality_level": "low_impact", "criticality_modifier": 2 } } ```` ### How to test it? ``` KIBANA_URL="http://localhost:5601/pablo" curl "$KIBANA_URL/api/risk_scores/calculation/entity" \ -H 'kbn-xsrf:hello' \ --user elastic:changeme \ -X 'POST' \ -H 'elastic-api-version: 1' \ -H "Content-Type: application/json" \ -d '{"identifier_type": "host", "identifier": "Test-Host.name"}' ``` ### Checklist - [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
- Loading branch information
Showing
19 changed files
with
917 additions
and
89 deletions.
There are no files selected for viewing
169 changes: 169 additions & 0 deletions
169
x-pack/plugins/security_solution/common/api/entity_analytics/risk_engine/common.gen.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,169 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0; you may not use this file except in compliance with the Elastic License | ||
* 2.0. | ||
*/ | ||
|
||
import { z } from 'zod'; | ||
|
||
/* | ||
* NOTICE: Do not edit this file manually. | ||
* This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. | ||
* | ||
* info: | ||
* title: Risk Engine Common Schema | ||
* version: 1.0.0 | ||
*/ | ||
|
||
export type AfterKeys = z.infer<typeof AfterKeys>; | ||
export const AfterKeys = z.object({ | ||
host: z.object({}).catchall(z.string()).optional(), | ||
user: z.object({}).catchall(z.string()).optional(), | ||
}); | ||
|
||
/** | ||
* The identifier of the Kibana data view to be used when generating risk scores. | ||
*/ | ||
export type DataViewId = z.infer<typeof DataViewId>; | ||
export const DataViewId = z.string(); | ||
|
||
/** | ||
* An elasticsearch DSL filter object. Used to filter the risk inputs involved, which implicitly filters the risk scores themselves. | ||
*/ | ||
export type Filter = z.infer<typeof Filter>; | ||
export const Filter = z.unknown(); | ||
|
||
/** | ||
* Specifies how many scores will be involved in a given calculation. Note that this value is per `identifier_type`, i.e. a value of 10 will calculate 10 host scores and 10 user scores, if available. To avoid missed data, keep this value consistent while paginating through scores. | ||
*/ | ||
export type PageSize = z.infer<typeof PageSize>; | ||
export const PageSize = z.number().default(1000); | ||
|
||
export type KibanaDate = z.infer<typeof KibanaDate>; | ||
export const KibanaDate = z.union([z.string(), z.string().datetime(), z.string()]); | ||
|
||
/** | ||
* Defines the time period on which risk inputs will be filtered. | ||
*/ | ||
export type DateRange = z.infer<typeof DateRange>; | ||
export const DateRange = z.object({ | ||
start: KibanaDate, | ||
end: KibanaDate, | ||
}); | ||
|
||
export type IdentifierType = z.infer<typeof IdentifierType>; | ||
export const IdentifierType = z.enum(['host', 'user']); | ||
export type IdentifierTypeEnum = typeof IdentifierType.enum; | ||
export const IdentifierTypeEnum = IdentifierType.enum; | ||
|
||
/** | ||
* A generic representation of a document contributing to a Risk Score. | ||
*/ | ||
export type RiskScoreInput = z.infer<typeof RiskScoreInput>; | ||
export const RiskScoreInput = z.object({ | ||
/** | ||
* The unique identifier (`_id`) of the original source document | ||
*/ | ||
id: z.string().optional(), | ||
/** | ||
* The unique index (`_index`) of the original source document | ||
*/ | ||
index: z.string().optional(), | ||
/** | ||
* The risk category of the risk input document. | ||
*/ | ||
category: z.string().optional(), | ||
/** | ||
* A human-readable description of the risk input document. | ||
*/ | ||
description: z.string().optional(), | ||
/** | ||
* The weighted risk score of the risk input document. | ||
*/ | ||
risk_score: z.number().min(0).max(100).optional(), | ||
/** | ||
* The @timestamp of the risk input document. | ||
*/ | ||
timestamp: z.string().optional(), | ||
}); | ||
|
||
export type RiskScore = z.infer<typeof RiskScore>; | ||
export const RiskScore = z.object({ | ||
/** | ||
* The time at which the risk score was calculated. | ||
*/ | ||
'@timestamp': z.string().datetime(), | ||
/** | ||
* The identifier field defining this risk score. Coupled with `id_value`, uniquely identifies the entity being scored. | ||
*/ | ||
id_field: z.string(), | ||
/** | ||
* The identifier value defining this risk score. Coupled with `id_field`, uniquely identifies the entity being scored. | ||
*/ | ||
id_value: z.string(), | ||
/** | ||
* Lexical description of the entity's risk. | ||
*/ | ||
calculated_level: z.string(), | ||
/** | ||
* The raw numeric value of the given entity's risk score. | ||
*/ | ||
calculated_score: z.number(), | ||
/** | ||
* The normalized numeric value of the given entity's risk score. Useful for comparing with other entities. | ||
*/ | ||
calculated_score_norm: z.number().min(0).max(100), | ||
/** | ||
* The contribution of Category 1 to the overall risk score (`calculated_score_norm`). Category 1 contains Detection Engine Alerts. | ||
*/ | ||
category_1_score: z.number(), | ||
/** | ||
* The number of risk input documents that contributed to the Category 1 score (`category_1_score`). | ||
*/ | ||
category_1_count: z.number(), | ||
/** | ||
* The contribution of Category 2 to the overall risk score (`calculated_score_norm`). Category 2 contains context from external sources. | ||
*/ | ||
category_2_score: z.number().optional(), | ||
/** | ||
* The number of risk input documents that contributed to the Category 2 score (`category_2_score`). | ||
*/ | ||
category_2_count: z.number().optional(), | ||
/** | ||
* The designated criticality level of the entity. Possible values are `low_impact`, `medium_impact`, `high_impact`, and `extreme_impact`. | ||
*/ | ||
criticality_level: z.string().optional(), | ||
/** | ||
* The numeric modifier corresponding to the criticality level of the entity, which is used as an input to the risk score calculation. | ||
*/ | ||
criticality_modifier: z.number().optional(), | ||
/** | ||
* A list of the highest-risk documents contributing to this risk score. Useful for investigative purposes. | ||
*/ | ||
inputs: z.array(RiskScoreInput), | ||
}); | ||
|
||
/** | ||
* Configuration used to tune risk scoring. Weights can be used to change the score contribution of risk inputs for hosts and users at both a global level and also for Risk Input categories (e.g. 'category_1'). | ||
*/ | ||
export type RiskScoreWeight = z.infer<typeof RiskScoreWeight>; | ||
export const RiskScoreWeight = z.object({ | ||
type: z.string(), | ||
value: z.string().optional(), | ||
host: z.number().min(0).max(1).optional(), | ||
user: z.number().min(0).max(1).optional(), | ||
}); | ||
|
||
/** | ||
* A list of weights to be applied to the scoring calculation. | ||
*/ | ||
export type RiskScoreWeights = z.infer<typeof RiskScoreWeights>; | ||
export const RiskScoreWeights = z.array(RiskScoreWeight); | ||
|
||
export type RiskEngineInitStep = z.infer<typeof RiskEngineInitStep>; | ||
export const RiskEngineInitStep = z.object({ | ||
type: z.string(), | ||
success: z.boolean(), | ||
error: z.string().optional(), | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
39 changes: 39 additions & 0 deletions
39
...security_solution/common/api/entity_analytics/risk_engine/entity_calculation_route.gen.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0; you may not use this file except in compliance with the Elastic License | ||
* 2.0. | ||
*/ | ||
|
||
import { z } from 'zod'; | ||
|
||
/* | ||
* NOTICE: Do not edit this file manually. | ||
* This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. | ||
* | ||
* info: | ||
* title: Risk Scoring API | ||
* version: 1.0.0 | ||
*/ | ||
|
||
import { IdentifierType, RiskScore } from './common.gen'; | ||
|
||
export type RiskScoresEntityCalculationRequest = z.infer<typeof RiskScoresEntityCalculationRequest>; | ||
export const RiskScoresEntityCalculationRequest = z.object({ | ||
/** | ||
* Used to identify the entity. | ||
*/ | ||
identifier: z.string(), | ||
/** | ||
* Used to define the type of entity. | ||
*/ | ||
identifier_type: IdentifierType, | ||
}); | ||
|
||
export type RiskScoresEntityCalculationResponse = z.infer< | ||
typeof RiskScoresEntityCalculationResponse | ||
>; | ||
export const RiskScoresEntityCalculationResponse = z.object({ | ||
success: z.boolean(), | ||
score: RiskScore.optional(), | ||
}); |
62 changes: 62 additions & 0 deletions
62
...ity_solution/common/api/entity_analytics/risk_engine/entity_calculation_route.schema.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
openapi: 3.0.0 | ||
|
||
info: | ||
version: 1.0.0 | ||
title: Risk Scoring API | ||
description: These APIs allow the consumer to manage Entity Risk Scores within Entity Analytics. | ||
|
||
servers: | ||
- url: 'http://{kibana_host}:{port}' | ||
variables: | ||
kibana_host: | ||
default: localhost | ||
port: | ||
default: '5601' | ||
|
||
paths: | ||
/api/risk_scores/calculation/entity: | ||
post: | ||
summary: Trigger calculation of Risk Scores for an entity | ||
description: Calculates and persists Risk Scores for an entity, returning the calculated risk score. | ||
requestBody: | ||
description: The entity type and identifier | ||
content: | ||
application/json: | ||
schema: | ||
$ref: '#/components/schemas/RiskScoresEntityCalculationRequest' | ||
required: true | ||
responses: | ||
'200': | ||
description: Successful response | ||
content: | ||
application/json: | ||
schema: | ||
$ref: '#/components/schemas/RiskScoresEntityCalculationResponse' | ||
'400': | ||
description: Invalid request | ||
|
||
components: | ||
schemas: | ||
RiskScoresEntityCalculationRequest: | ||
type: object | ||
required: | ||
- identifier | ||
- identifier_type | ||
properties: | ||
identifier: | ||
description: Used to identify the entity. | ||
type: string | ||
example: 'my.host' | ||
identifier_type: | ||
description: Used to define the type of entity. | ||
$ref: './common.schema.yaml#/components/schemas/IdentifierType' | ||
|
||
RiskScoresEntityCalculationResponse: | ||
type: object | ||
required: | ||
- success | ||
properties: | ||
success: | ||
type: boolean | ||
score: | ||
$ref: './common.schema.yaml#/components/schemas/RiskScore' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.