mirror of
https://github.com/elastic/kibana.git
synced 2025-04-18 23:21:39 -04:00
[OAS] Support examples (and more) (#212495)
## Summary Close https://github.com/elastic/kibana/issues/188926 Adds the ability to merge in an arbitrary OAS operation object (search [spec](https://swagger.io/specification/) for "operation object") in code generated OAS. This enables us to write examples next to the code: <img width="306" alt="Screenshot 2025-02-26 at 11 24 00" src="https://github.com/user-attachments/assets/5df92ae9-c8c5-4797-8b7c-764e937e84e9" /> ```ts // Inside the router declaration router.post( { path: `${BASE_ALERTING_API_PATH}/rule/{id?}`, security: DEFAULT_ALERTING_ROUTE_SECURITY, options: { access: 'public', summary: `Create a rule`, tags: ['oas-tag:alerting'], // NEW 👇🏻: this file can contain operation-level OAS and will merge/override anything that we auto generate oasOperationObject: () => path.join(__dirname, 'create_rule.examples.yaml'), // ☝🏻 can also be a TS-checked OpenAPIV3.OperationObject ``` Tested with create rule example overlay ([gist](https://gist.github.com/jloleysens/dc643522a3f58dc2aed3dcef966b42df)) and bump <img width="1236" alt="Screenshot 2025-02-26 at 11 45 57" src="https://github.com/user-attachments/assets/c21b466a-ddab-49ce-b4ba-a04fd0e6c1b7" /> ## Docs Added developer guide docs to https://docs.elastic.dev/kibana-dev-docs/genereating-oas-for-http-apis#2-route-definitions <details> <summary>images</summary> <img width="799" alt="Screenshot 2025-03-13 at 13 02 31" src="https://github.com/user-attachments/assets/e89b2c5a-1984-4672-a40b-b492581e690f" /> <img width="819" alt="Screenshot 2025-03-13 at 13 02 39" src="https://github.com/user-attachments/assets/1375a25a-4d91-46b4-8ce5-42c763657d96" /> </details> ### TO DO - [x] Document the feature in TS - [x] Document feature in dev docs - [x] Add tests --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
f2af002a5e
commit
5e90e557cf
49 changed files with 4146 additions and 1652 deletions
|
@ -92,7 +92,7 @@ import { fooResource } from '../../schemas/v1';
|
|||
// Note: this response schema is instantiated lazily to avoid creating schemas that are not needed in most cases!
|
||||
const fooResourceResponse = () => {
|
||||
return schema.object({
|
||||
id: schema.string({
|
||||
id: schema.string({
|
||||
maxLength: 20,
|
||||
meta: { description: 'Add a description.' }
|
||||
}),
|
||||
|
@ -129,7 +129,7 @@ function registerFooRoute(router: IRouter, docLinks: DoclinksStart) {
|
|||
version: '2023-10-31',
|
||||
validate: {
|
||||
request: {
|
||||
body: ,
|
||||
body: fooResource,
|
||||
},
|
||||
response: {
|
||||
200: {
|
||||
|
@ -155,6 +155,124 @@ function registerFooRoute(router: IRouter, docLinks: DoclinksStart) {
|
|||
}
|
||||
```
|
||||
|
||||
##### Adding examples
|
||||
|
||||
Beyond the schema of requests and responses, it is **very useful** to provide
|
||||
concrete requests and responses as examples. Examples go beyond defaults and
|
||||
provide a more intuitive understanding for end users in learning the behaviour
|
||||
of your API. See the [bump.sh documentation](https://docs.bump.sh/guides/openapi/specification/v3.1/data-models/examples/)
|
||||
for more information on how examples will be shown to end users.
|
||||
|
||||
To add examples to the endpoint we created above you could do the following:
|
||||
|
||||
```typescript
|
||||
// ...
|
||||
.addVersion({
|
||||
version: '2023-10-31',
|
||||
options: {
|
||||
// Be sure and lazily instantiate this value. It's only used at dev time!
|
||||
oasOperationObject: () => ({
|
||||
requestBody: {
|
||||
content: {
|
||||
'application/json': {
|
||||
examples: {
|
||||
fooExample1: {
|
||||
summary: 'An example foo request',
|
||||
value: {
|
||||
name: 'Cool foo!',
|
||||
} as FooResource,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
responses: {
|
||||
200: {
|
||||
content: {
|
||||
'application/json': {
|
||||
examples: {
|
||||
/* Put your 200 response examples here */
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
},
|
||||
validate: {
|
||||
request: {
|
||||
body: fooResource,
|
||||
},
|
||||
response: {
|
||||
200: {
|
||||
body: fooResourceResponse,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
// ...
|
||||
```
|
||||
The strength of this approach is your examples are captured in code and type
|
||||
checked at dev time. So any shape errors should be caught as you author.
|
||||
|
||||
<details>
|
||||
|
||||
<summary>I have prexisting YAML based examples I'd like to use!</summary>
|
||||
|
||||
If you pre-existing examples created in YAML that you would like
|
||||
to use the following approach:
|
||||
|
||||
```typescript
|
||||
import path from 'node:path';
|
||||
|
||||
const oasOperationObject: () => path.join(__dirname, 'foo.examples.yaml'),
|
||||
|
||||
// ...
|
||||
.addVersion({
|
||||
version: '2023-10-31',
|
||||
options: {
|
||||
oasOperationObject,
|
||||
},
|
||||
validate: {
|
||||
request: {
|
||||
body: fooResource,
|
||||
},
|
||||
response: {
|
||||
200: {
|
||||
body: fooResourceResponse,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
// ...
|
||||
```
|
||||
|
||||
Where the contents of `foo.examples.yaml` are:
|
||||
|
||||
```yaml
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
examples: # Make sure to use the examples array, example (singular) has been deprecated
|
||||
fooExample:
|
||||
summary: Foo example
|
||||
description: >
|
||||
An example request of creating foo.
|
||||
value:
|
||||
name: 'Cool foo!'
|
||||
fooExampleRef:
|
||||
# You can use JSONSchema $refs to organize this file further
|
||||
$ref: "./examples/foo_example_i_factored_out_of_this_file.yaml"
|
||||
responses:
|
||||
200:
|
||||
content:
|
||||
application/json:
|
||||
examples:
|
||||
# Apply a similar pattern to writing examples here
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
#### 3. Generating OAS
|
||||
|
||||
See <a href="#how-do-i-see-my-http-apis-oas">this section</a> about viewing your HTTP APIs OAS.
|
||||
|
|
|
@ -1777,6 +1777,206 @@
|
|||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"examples": {
|
||||
"createEsQueryEsqlRuleRequest": {
|
||||
"description": "Create an Elasticsearch query rule that uses Elasticsearch Query Language (ES|QL) to define its query and a server log connector to send notifications.\n",
|
||||
"summary": "Elasticsearch query rule (ES|QL)",
|
||||
"value": {
|
||||
"actions": [
|
||||
{
|
||||
"frequency": {
|
||||
"notify_when": "onActiveAlert",
|
||||
"summary": false
|
||||
},
|
||||
"group": "query matched",
|
||||
"id": "d0db1fe0-78d6-11ee-9177-f7d404c8c945",
|
||||
"params": {
|
||||
"level": "info",
|
||||
"message": "Elasticsearch query rule '{{rule.name}}' is active:\n- Value: {{context.value}} - Conditions Met: {{context.conditions}} over {{rule.params.timeWindowSize}}{{rule.params.timeWindowUnit}} - Timestamp: {{context.date}} - Link: {{context.link}}"
|
||||
}
|
||||
}
|
||||
],
|
||||
"consumer": "stackAlerts",
|
||||
"name": "my Elasticsearch query ESQL rule",
|
||||
"params": {
|
||||
"esqlQuery": {
|
||||
"esql": "FROM kibana_sample_data_logs | KEEP bytes, clientip, host, geo.dest | where geo.dest != \"GB\" | STATS sumbytes = sum(bytes) by clientip, host | WHERE sumbytes > 5000 | SORT sumbytes desc | LIMIT 10"
|
||||
},
|
||||
"searchType": "esqlQuery",
|
||||
"size": 0,
|
||||
"threshold": [
|
||||
0
|
||||
],
|
||||
"thresholdComparator": ">",
|
||||
"timeField": "@timestamp",
|
||||
"timeWindowSize": 1,
|
||||
"timeWindowUnit": "d"
|
||||
},
|
||||
"rule_type_id": ".es-query",
|
||||
"schedule": {
|
||||
"interval": "1d"
|
||||
}
|
||||
}
|
||||
},
|
||||
"createEsQueryKqlRuleRequest": {
|
||||
"description": "Create an Elasticsearch query rule that uses Kibana query language (KQL).",
|
||||
"summary": "Elasticsearch query rule (KQL)",
|
||||
"value": {
|
||||
"consumer": "alerts",
|
||||
"name": "my Elasticsearch query KQL rule",
|
||||
"params": {
|
||||
"aggType": "count",
|
||||
"excludeHitsFromPreviousRun": true,
|
||||
"groupBy": "all",
|
||||
"searchConfiguration": {
|
||||
"index": "90943e30-9a47-11e8-b64d-95841ca0b247",
|
||||
"query": {
|
||||
"language": "kuery",
|
||||
"query": "\"\"geo.src : \"US\" \"\""
|
||||
}
|
||||
},
|
||||
"searchType": "searchSource",
|
||||
"size": 100,
|
||||
"threshold": [
|
||||
1000
|
||||
],
|
||||
"thresholdComparator": ">",
|
||||
"timeWindowSize": 5,
|
||||
"timeWindowUnit": "m"
|
||||
},
|
||||
"rule_type_id": ".es-query",
|
||||
"schedule": {
|
||||
"interval": "1m"
|
||||
}
|
||||
}
|
||||
},
|
||||
"createEsQueryRuleRequest": {
|
||||
"description": "Create an Elasticsearch query rule that uses Elasticsearch query domain specific language (DSL) to define its query and a server log connector to send notifications.\n",
|
||||
"summary": "Elasticsearch query rule (DSL)",
|
||||
"value": {
|
||||
"actions": [
|
||||
{
|
||||
"frequency": {
|
||||
"notify_when": "onThrottleInterval",
|
||||
"summary": true,
|
||||
"throttle": "1d"
|
||||
},
|
||||
"group": "query matched",
|
||||
"id": "fdbece50-406c-11ee-850e-c71febc4ca7f",
|
||||
"params": {
|
||||
"level": "info",
|
||||
"message": "The system has detected {{alerts.new.count}} new, {{alerts.ongoing.count}} ongoing, and {{alerts.recovered.count}} recovered alerts."
|
||||
}
|
||||
},
|
||||
{
|
||||
"frequency": {
|
||||
"notify_when": "onActionGroupChange",
|
||||
"summary": false
|
||||
},
|
||||
"group": "recovered",
|
||||
"id": "fdbece50-406c-11ee-850e-c71febc4ca7f",
|
||||
"params": {
|
||||
"level": "info",
|
||||
"message": "Recovered"
|
||||
}
|
||||
}
|
||||
],
|
||||
"consumer": "alerts",
|
||||
"name": "my Elasticsearch query rule",
|
||||
"params": {
|
||||
"esQuery": "\"\"\"{\"query\":{\"match_all\" : {}}}\"\"\"",
|
||||
"index": [
|
||||
"kibana_sample_data_logs"
|
||||
],
|
||||
"size": 100,
|
||||
"threshold": [
|
||||
100
|
||||
],
|
||||
"thresholdComparator": ">",
|
||||
"timeField": "@timestamp",
|
||||
"timeWindowSize": 1,
|
||||
"timeWindowUnit": "d"
|
||||
},
|
||||
"rule_type_id": ".es-query",
|
||||
"schedule": {
|
||||
"interval": "1d"
|
||||
}
|
||||
}
|
||||
},
|
||||
"createIndexThresholdRuleRequest": {
|
||||
"description": "Create an index threshold rule that uses a server log connector to send notifications when the threshold is met.\n",
|
||||
"summary": "Index threshold rule",
|
||||
"value": {
|
||||
"actions": [
|
||||
{
|
||||
"frequency": {
|
||||
"notify_when": "onActionGroupChange",
|
||||
"summary": false
|
||||
},
|
||||
"group": "threshold met",
|
||||
"id": "48de3460-f401-11ed-9f8e-399c75a2deeb",
|
||||
"params": {
|
||||
"level": "info",
|
||||
"message": "Rule '{{rule.name}}' is active for group '{{context.group}}':\n\n- Value: {{context.value}}\n- Conditions Met: {{context.conditions}} over {{rule.params.timeWindowSize}}{{rule.params.timeWindowUnit}}\n- Timestamp: {{context.date}}"
|
||||
}
|
||||
}
|
||||
],
|
||||
"alert_delay": {
|
||||
"active": 3
|
||||
},
|
||||
"consumer": "alerts",
|
||||
"name": "my rule",
|
||||
"params": {
|
||||
"aggField": "sheet.version",
|
||||
"aggType": "avg",
|
||||
"groupBy": "top",
|
||||
"index": [
|
||||
".test-index"
|
||||
],
|
||||
"termField": "name.keyword",
|
||||
"termSize": 6,
|
||||
"threshold": [
|
||||
1000
|
||||
],
|
||||
"thresholdComparator": ">",
|
||||
"timeField": "@timestamp",
|
||||
"timeWindowSize": 5,
|
||||
"timeWindowUnit": "m"
|
||||
},
|
||||
"rule_type_id": ".index-threshold",
|
||||
"schedule": {
|
||||
"interval": "1m"
|
||||
},
|
||||
"tags": [
|
||||
"cpu"
|
||||
]
|
||||
}
|
||||
},
|
||||
"createTrackingContainmentRuleRequest": {
|
||||
"description": "Create a tracking containment rule that checks when an entity is contained or no longer contained within a boundary.\n",
|
||||
"summary": "Tracking containment rule",
|
||||
"value": {
|
||||
"consumer": "alerts",
|
||||
"name": "my tracking rule",
|
||||
"params": {
|
||||
"boundaryGeoField": "location",
|
||||
"boundaryIndexId": "0cd90abf-abe7-44c7-909a-f621bbbcfefc",
|
||||
"boundaryIndexTitle": "boundary*",
|
||||
"boundaryNameField": "name",
|
||||
"boundaryType": "entireIndex",
|
||||
"dateField\"": "@timestamp",
|
||||
"entity": "agent.keyword",
|
||||
"geoField": "geo.coordinates",
|
||||
"index": "kibana_sample_data_logs",
|
||||
"indexId": "90943e30-9a47-11e8-b64d-95841ca0b247"
|
||||
},
|
||||
"rule_type_id": ".geo-containment",
|
||||
"schedule": {
|
||||
"interval": "1h"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"schema": {
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
|
@ -2073,6 +2273,339 @@
|
|||
"200": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"examples": {
|
||||
"createEsQueryEsqlRuleResponse": {
|
||||
"description": "The response for successfully creating an Elasticsearch query rule that uses Elasticsearch Query Language (ES|QL).",
|
||||
"summary": "Elasticsearch query rule (ES|QL)",
|
||||
"value": {
|
||||
"actions": [
|
||||
{
|
||||
"connector_type_id": ".server-log",
|
||||
"frequency": {
|
||||
"notify_when": "onActiveAlert",
|
||||
"summary": false,
|
||||
"throttle": null
|
||||
},
|
||||
"group": "query matched",
|
||||
"id": "d0db1fe0-78d6-11ee-9177-f7d404c8c945",
|
||||
"params": {
|
||||
"level": "info",
|
||||
"message": "Elasticsearch query rule '{{rule.name}}' is active:\n- Value: {{context.value}} - Conditions Met: {{context.conditions}} over {{rule.params.timeWindowSize}}{{rule.params.timeWindowUnit}} - Timestamp: {{context.date}} - Link: {{context.link}}"
|
||||
},
|
||||
"uuid": "bfe370a3-531b-4855-bbe6-ad739f578844"
|
||||
}
|
||||
],
|
||||
"api_key_created_by_user": false,
|
||||
"api_key_owner": "elastic",
|
||||
"consumer": "stackAlerts",
|
||||
"created_at": "2023-11-01T19:00:10.453Z",
|
||||
"created_by": "elastic",
|
||||
"enabled": true,
|
||||
"execution_status": {
|
||||
"last_execution_date": "2023-11-01T19:00:10.453Z",
|
||||
"status": "pending"
|
||||
},
|
||||
"id": "e0d62360-78e8-11ee-9177-f7d404c8c945",
|
||||
"mute_all": false,
|
||||
"muted_alert_ids": [],
|
||||
"name": "my Elasticsearch query ESQL rule",
|
||||
"notify_when": null,
|
||||
"params": {
|
||||
"aggType": "count",
|
||||
"esqlQuery": {
|
||||
"esql": "FROM kibana_sample_data_logs | keep bytes, clientip, host, geo.dest | WHERE geo.dest != \"GB\" | stats sumbytes = sum(bytes) by clientip, host | WHERE sumbytes > 5000 | sort sumbytes desc | limit 10"
|
||||
},
|
||||
"excludeHitsFromPreviousRun\"": "true,",
|
||||
"groupBy": "all",
|
||||
"searchType": "esqlQuery",
|
||||
"size": 0,
|
||||
"threshold": [
|
||||
0
|
||||
],
|
||||
"thresholdComparator": ">",
|
||||
"timeField": "@timestamp",
|
||||
"timeWindowSize": 1,
|
||||
"timeWindowUnit": "d"
|
||||
},
|
||||
"revision": 0,
|
||||
"rule_type_id": ".es-query",
|
||||
"running": false,
|
||||
"schedule": {
|
||||
"interval": "1d"
|
||||
},
|
||||
"scheduled_task_id": "e0d62360-78e8-11ee-9177-f7d404c8c945",
|
||||
"tags": [],
|
||||
"throttle": null,
|
||||
"updated_at": "2023-11-01T19:00:10.453Z",
|
||||
"updated_by": "elastic\","
|
||||
}
|
||||
},
|
||||
"createEsQueryKqlRuleResponse": {
|
||||
"description": "The response for successfully creating an Elasticsearch query rule that uses Kibana query language (KQL).",
|
||||
"summary": "Elasticsearch query rule (KQL)",
|
||||
"value": {
|
||||
"actions": [],
|
||||
"api_key_created_by_user": false,
|
||||
"api_key_owner": "elastic",
|
||||
"consumer": "alerts",
|
||||
"created_at": "2023-07-14T20:24:50.729Z",
|
||||
"created_by": "elastic",
|
||||
"enabled": true,
|
||||
"execution_status": {
|
||||
"last_execution_date": "2023-07-14T20:24:50.729Z",
|
||||
"status": "pending"
|
||||
},
|
||||
"id": "7bd506d0-2284-11ee-8fad-6101956ced88",
|
||||
"mute_all": false,
|
||||
"muted_alert_ids": [],
|
||||
"name": "my Elasticsearch query KQL rule\"",
|
||||
"notify_when": null,
|
||||
"params": {
|
||||
"aggType": "count",
|
||||
"excludeHitsFromPreviousRun": true,
|
||||
"groupBy": "all",
|
||||
"searchConfiguration": {
|
||||
"index": "90943e30-9a47-11e8-b64d-95841ca0b247",
|
||||
"query": {
|
||||
"language": "kuery",
|
||||
"query": "\"\"geo.src : \"US\" \"\""
|
||||
}
|
||||
},
|
||||
"searchType": "searchSource",
|
||||
"size": 100,
|
||||
"threshold": [
|
||||
1000
|
||||
],
|
||||
"thresholdComparator": ">",
|
||||
"timeWindowSize": 5,
|
||||
"timeWindowUnit": "m"
|
||||
},
|
||||
"revision": 0,
|
||||
"rule_type_id": ".es-query",
|
||||
"running": false,
|
||||
"schedule": {
|
||||
"interval": "1m"
|
||||
},
|
||||
"scheduled_task_id": "7bd506d0-2284-11ee-8fad-6101956ced88",
|
||||
"tags": [],
|
||||
"throttle": null,
|
||||
"updated_at": "2023-07-14T20:24:50.729Z",
|
||||
"updated_by": "elastic"
|
||||
}
|
||||
},
|
||||
"createEsQueryRuleResponse": {
|
||||
"description": "The response for successfully creating an Elasticsearch query rule that uses Elasticsearch query domain specific language (DSL).",
|
||||
"summary": "Elasticsearch query rule (DSL)",
|
||||
"value": {
|
||||
"actions": [
|
||||
{
|
||||
"connector_type_id": ".server-log",
|
||||
"frequency": {
|
||||
"notify_when": "onThrottleInterval",
|
||||
"summary": true,
|
||||
"throttle": "1d"
|
||||
},
|
||||
"group": "query matched",
|
||||
"id": "fdbece50-406c-11ee-850e-c71febc4ca7f",
|
||||
"params": {
|
||||
"level": "info",
|
||||
"message": "The system has detected {{alerts.new.count}} new, {{alerts.ongoing.count}} ongoing, and {{alerts.recovered.count}} recovered alerts."
|
||||
},
|
||||
"uuid": "53f3c2a3-e5d0-4cfa-af3b-6f0881385e78"
|
||||
},
|
||||
{
|
||||
"connector_type_id": ".server-log",
|
||||
"frequency": {
|
||||
"notify_when": "onActionGroupChange",
|
||||
"summary": false,
|
||||
"throttle": null
|
||||
},
|
||||
"group": "recovered",
|
||||
"id": "fdbece50-406c-11ee-850e-c71febc4ca7f",
|
||||
"params": {
|
||||
"level": "info",
|
||||
"message": "Recovered"
|
||||
},
|
||||
"uuid": "2324e45b-c0df-45c7-9d70-4993e30be758"
|
||||
}
|
||||
],
|
||||
"api_key_created_by_user": false,
|
||||
"api_key_owner": "elastic",
|
||||
"consumer": "alerts",
|
||||
"created_at": "2023-08-22T00:03:38.263Z",
|
||||
"created_by": "elastic",
|
||||
"enabled": true,
|
||||
"execution_status": {
|
||||
"last_execution_date": "2023-08-22T00:03:38.263Z",
|
||||
"status": "pending"
|
||||
},
|
||||
"id": "58148c70-407f-11ee-850e-c71febc4ca7f",
|
||||
"mute_all": false,
|
||||
"muted_alert_ids": [],
|
||||
"name": "my Elasticsearch query rule",
|
||||
"notify_when": null,
|
||||
"params": {
|
||||
"aggType": "count",
|
||||
"esQuery": "\"\"\"{\"query\":{\"match_all\" : {}}}\"\"\"",
|
||||
"excludeHitsFromPreviousRun": true,
|
||||
"groupBy": "all",
|
||||
"index": [
|
||||
"kibana_sample_data_logs"
|
||||
],
|
||||
"searchType": "esQuery",
|
||||
"size": 100,
|
||||
"threshold": [
|
||||
100
|
||||
],
|
||||
"thresholdComparator": ">",
|
||||
"timeField": "@timestamp",
|
||||
"timeWindowSize": 1,
|
||||
"timeWindowUnit": "d"
|
||||
},
|
||||
"revision": 0,
|
||||
"rule_type_id": ".es-query",
|
||||
"running": false,
|
||||
"schedule": {
|
||||
"interval": "1d"
|
||||
},
|
||||
"scheduled_task_id": "58148c70-407f-11ee-850e-c71febc4ca7f",
|
||||
"tags": [],
|
||||
"throttle": null,
|
||||
"updated_at": "2023-08-22T00:03:38.263Z",
|
||||
"updated_by": "elastic"
|
||||
}
|
||||
},
|
||||
"createIndexThresholdRuleResponse": {
|
||||
"description": "The response for successfully creating an index threshold rule.",
|
||||
"summary": "Index threshold rule",
|
||||
"value": {
|
||||
"actions": [
|
||||
{
|
||||
"connector_type_id": ".server-log",
|
||||
"frequency": {
|
||||
"notify_when": "onActionGroupChange",
|
||||
"summary": false,
|
||||
"throttle": null
|
||||
},
|
||||
"group": "threshold met",
|
||||
"id": "dceeb5d0-6b41-11eb-802b-85b0c1bc8ba2",
|
||||
"params": {
|
||||
"level": "info",
|
||||
"message": "Rule {{rule.name}} is active for group {{context.group} :\n\n- Value: {{context.value}}\n- Conditions Met: {{context.conditions}} over {{rule.params.timeWindowSize}}{{rule.params.timeWindowUnit}}\n- Timestamp: {{context.date}}"
|
||||
},
|
||||
"uuid": "07aef2a0-9eed-4ef9-94ec-39ba58eb609d"
|
||||
}
|
||||
],
|
||||
"alert_delay": {
|
||||
"active": 3
|
||||
},
|
||||
"api_key_created_by_user": false,
|
||||
"api_key_owner": "elastic",
|
||||
"consumer": "alerts",
|
||||
"created_at": "2022-06-08T17:20:31.632Z",
|
||||
"created_by": "elastic",
|
||||
"enabled": true,
|
||||
"execution_status": {
|
||||
"last_execution_date": "2022-06-08T17:20:31.632Z",
|
||||
"status": "pending"
|
||||
},
|
||||
"id": "41893910-6bca-11eb-9e0d-85d233e3ee35",
|
||||
"mute_all": false,
|
||||
"muted_alert_ids": [],
|
||||
"name": "my rule",
|
||||
"notify_when": null,
|
||||
"params": {
|
||||
"aggField": "sheet.version",
|
||||
"aggType": "avg",
|
||||
"groupBy": "top",
|
||||
"index": [
|
||||
".test-index"
|
||||
],
|
||||
"termField": "name.keyword",
|
||||
"termSize": 6,
|
||||
"threshold": [
|
||||
1000
|
||||
],
|
||||
"thresholdComparator": ">",
|
||||
"timeField": "@timestamp",
|
||||
"timeWindowSize": 5,
|
||||
"timeWindowUnit": "m"
|
||||
},
|
||||
"revision": 0,
|
||||
"rule_type_id": ".index-threshold",
|
||||
"running": false,
|
||||
"schedule": {
|
||||
"interval": "1m"
|
||||
},
|
||||
"scheduled_task_id": "425b0800-6bca-11eb-9e0d-85d233e3ee35",
|
||||
"tags": [
|
||||
"cpu"
|
||||
],
|
||||
"throttle": null,
|
||||
"updated_at": "2022-06-08T17:20:31.632Z",
|
||||
"updated_by": "elastic"
|
||||
}
|
||||
},
|
||||
"createTrackingContainmentRuleResponse": {
|
||||
"description": "The response for successfully creating a tracking containment rule.",
|
||||
"summary": "Tracking containment rule",
|
||||
"value": {
|
||||
"actions": [],
|
||||
"api_key_created_by_user": false,
|
||||
"api_key_owner": "elastic",
|
||||
"consumer": "alerts",
|
||||
"created_at": "2024-02-14T19:52:55.920Z",
|
||||
"created_by": "elastic",
|
||||
"enabled": true,
|
||||
"execution_status": {
|
||||
"last_duration": 74,
|
||||
"last_execution_date": "2024-02-15T03:25:38.125Z",
|
||||
"status": "ok"
|
||||
},
|
||||
"id": "b6883f9d-5f70-4758-a66e-369d7c26012f",
|
||||
"last_run": {
|
||||
"alerts_count": {
|
||||
"active": 0,
|
||||
"ignored": 0,
|
||||
"new": 0,
|
||||
"recovered": 0
|
||||
},
|
||||
"outcome": "succeeded",
|
||||
"outcome_msg": null,
|
||||
"outcome_order": 0,
|
||||
"warning": null
|
||||
},
|
||||
"mute_all": false,
|
||||
"muted_alert_ids": [],
|
||||
"name": "my tracking rule",
|
||||
"next_run": "2024-02-15T03:26:38.033Z",
|
||||
"notify_when": null,
|
||||
"params": {
|
||||
"boundaryGeoField": "location",
|
||||
"boundaryIndexId": "0cd90abf-abe7-44c7-909a-f621bbbcfefc",
|
||||
"boundaryIndexTitle": "boundary*",
|
||||
"boundaryNameField": "name",
|
||||
"boundaryType": "entireIndex",
|
||||
"dateField": "@timestamp",
|
||||
"entity": "agent.keyword",
|
||||
"geoField": "geo.coordinates",
|
||||
"index": "kibana_sample_data_logs",
|
||||
"indexId": "90943e30-9a47-11e8-b64d-95841ca0b247"
|
||||
},
|
||||
"revision": 1,
|
||||
"rule_type_id": ".geo-containment",
|
||||
"running": false,
|
||||
"schedule": {
|
||||
"interval": "1h"
|
||||
},
|
||||
"scheduled_task_id": "b6883f9d-5f70-4758-a66e-369d7c26012f",
|
||||
"tags": [],
|
||||
"throttle": null,
|
||||
"updated_at": "2024-02-15T03:24:32.574Z",
|
||||
"updated_by": "elastic"
|
||||
}
|
||||
}
|
||||
},
|
||||
"schema": {
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
|
@ -2970,6 +3503,50 @@
|
|||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"examples": {
|
||||
"updateRuleRequest": {
|
||||
"description": "Update an index threshold rule that uses a server log connector to send notifications when the threshold is met.",
|
||||
"summary": "Index threshold rule",
|
||||
"value": {
|
||||
"actions": [
|
||||
{
|
||||
"frequency": {
|
||||
"notify_when": "onActionGroupChange",
|
||||
"summary": false
|
||||
},
|
||||
"group": "threshold met",
|
||||
"id": "96b668d0-a1b6-11ed-afdf-d39a49596974",
|
||||
"params": {
|
||||
"level": "info",
|
||||
"message": "Rule {{rule.name}} is active for group {{context.group}}:\n\n- Value: {{context.value}}\n- Conditions Met: {{context.conditions}} over {{rule.params.timeWindowSize}}{{rule.params.timeWindowUnit}}\n- Timestamp: {{context.date}}"
|
||||
}
|
||||
}
|
||||
],
|
||||
"name": "new name",
|
||||
"params": {
|
||||
"aggField": "sheet.version",
|
||||
"aggType": "avg",
|
||||
"groupBy": "top",
|
||||
"index": [
|
||||
".updated-index"
|
||||
],
|
||||
"termField": "name.keyword",
|
||||
"termSize": 6,
|
||||
"threshold": [
|
||||
1000
|
||||
],
|
||||
"thresholdComparator": ">",
|
||||
"timeField": "@timestamp",
|
||||
"timeWindowSize": 5,
|
||||
"timeWindowUnit": "m"
|
||||
},
|
||||
"schedule": {
|
||||
"interval": "1m"
|
||||
},
|
||||
"tags": []
|
||||
}
|
||||
}
|
||||
},
|
||||
"schema": {
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
|
@ -3249,6 +3826,86 @@
|
|||
"200": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"examples": {
|
||||
"updateRuleResponse": {
|
||||
"description": "The response for successfully updating an index threshold rule.",
|
||||
"summary": "Index threshold rule",
|
||||
"value": {
|
||||
"actions": [
|
||||
{
|
||||
"connector_type_id": ".server-log",
|
||||
"frequency": {
|
||||
"notify_when": "onActionGroupChange",
|
||||
"summary": false,
|
||||
"throttle": null
|
||||
},
|
||||
"group": "threshold met",
|
||||
"id": "96b668d0-a1b6-11ed-afdf-d39a49596974",
|
||||
"params": {
|
||||
"level": "info",
|
||||
"message": "Rule {{rule.name}} is active for group {{context.group}}:\n\n- Value: {{context.value}}\n- Conditions Met: {{context.conditions}} over {{rule.params.timeWindowSize}}{{rule.params.timeWindowUnit}}\n- Timestamp: {{context.date}"
|
||||
},
|
||||
"uuid": "07aef2a0-9eed-4ef9-94ec-39ba58eb609d"
|
||||
}
|
||||
],
|
||||
"api_key_created_by_user": false,
|
||||
"api_key_owner": "elastic",
|
||||
"consumer": "alerts",
|
||||
"created_at": "2024-03-26T23:13:20.985Z",
|
||||
"created_by": "elastic",
|
||||
"enabled": true,
|
||||
"execution_status": {
|
||||
"last_duration": 52,
|
||||
"last_execution_date": "2024-03-26T23:22:51.390Z",
|
||||
"status": "ok"
|
||||
},
|
||||
"id": "ac4e6b90-6be7-11eb-ba0d-9b1c1f912d74",
|
||||
"last_run": {
|
||||
"alerts_count": {
|
||||
"active": 0,
|
||||
"ignored": 0,
|
||||
"new": 0,
|
||||
"recovered": 0
|
||||
},
|
||||
"outcome": "succeeded",
|
||||
"outcome_msg": null,
|
||||
"warning": null
|
||||
},
|
||||
"mute_all": false,
|
||||
"muted_alert_ids": [],
|
||||
"name": "new name",
|
||||
"next_run": "2024-03-26T23:23:51.316Z",
|
||||
"params": {
|
||||
"aggField": "sheet.version",
|
||||
"aggType": "avg",
|
||||
"groupBy": "top",
|
||||
"index": [
|
||||
".updated-index"
|
||||
],
|
||||
"termField": "name.keyword",
|
||||
"termSize": 6,
|
||||
"threshold": [
|
||||
1000
|
||||
],
|
||||
"thresholdComparator": ">",
|
||||
"timeField": "@timestamp",
|
||||
"timeWindowSize": 5,
|
||||
"timeWindowUnit": "m"
|
||||
},
|
||||
"revision": 1,
|
||||
"rule_type_id": ".index-threshold",
|
||||
"running": false,
|
||||
"schedule": {
|
||||
"interval": "1m"
|
||||
},
|
||||
"scheduled_task_id": "4c5eda00-e74f-11ec-b72f-5b18752ff9ea",
|
||||
"tags": [],
|
||||
"throttle": null,
|
||||
"updated_at": "2024-03-26T23:22:59.949Z",
|
||||
"updated_by": "elastic"
|
||||
}
|
||||
}
|
||||
},
|
||||
"schema": {
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
|
@ -4861,6 +5518,257 @@
|
|||
"200": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"examples": {
|
||||
"findConditionalActionRulesResponse": {
|
||||
"description": "A response that contains information about an index threshold rule.",
|
||||
"summary": "Index threshold rule",
|
||||
"value": {
|
||||
"data": [
|
||||
{
|
||||
"actions": [
|
||||
{
|
||||
"frequency": {
|
||||
"notify_when": "onActionGroupChange",
|
||||
"summary": false,
|
||||
"throttle": null
|
||||
},
|
||||
"group": "threshold met",
|
||||
"id": "9dca3e00-74f5-11ed-9801-35303b735aef",
|
||||
"params": {
|
||||
"connector_type_id": ".server-log",
|
||||
"level": "info",
|
||||
"message": "Rule {{rule.name}} is active for group {{context.group}}:\n\n- Value: {{context.value}}\n- Conditions Met: {{context.conditions}} over {{rule.params.timeWindowSize}}{{rule.params.timeWindowUnit}}\n- Timestamp: {{context.date}}"
|
||||
},
|
||||
"uuid": "1c7a1280-f28c-4e06-96b2-e4e5f05d1d61"
|
||||
}
|
||||
],
|
||||
"api_key_created_by_user": false,
|
||||
"api_key_owner": "elastic",
|
||||
"consumer": "alerts",
|
||||
"created_at": "2022-12-05T23:40:33.132Z",
|
||||
"created_by": "elastic",
|
||||
"enabled": true,
|
||||
"execution_status": {
|
||||
"last_duration": 48,
|
||||
"last_execution_date": "2022-12-06T01:44:23.983Z",
|
||||
"status": "ok"
|
||||
},
|
||||
"id": "3583a470-74f6-11ed-9801-35303b735aef",
|
||||
"last_run": {
|
||||
"alerts_count": {
|
||||
"active": 0,
|
||||
"ignored": 0,
|
||||
"new": 0,
|
||||
"recovered": 0
|
||||
},
|
||||
"outcome": "succeeded",
|
||||
"outcome_msg": null,
|
||||
"warning": null
|
||||
},
|
||||
"mute_all": false,
|
||||
"muted_alert_ids": [],
|
||||
"name": "my alert",
|
||||
"next_run": "2022-12-06T01:45:23.912Z",
|
||||
"params": {
|
||||
"aggField": "sheet.version",
|
||||
"aggType": "avg",
|
||||
"groupBy": "top",
|
||||
"index": [
|
||||
"test-index"
|
||||
],
|
||||
"termField": "name.keyword",
|
||||
"termSize": 6,
|
||||
"threshold": [
|
||||
1000
|
||||
],
|
||||
"thresholdComparator": ">",
|
||||
"timeField": "@timestamp",
|
||||
"timeWindowSize": 5,
|
||||
"timeWindowUnit": "m"
|
||||
},
|
||||
"revision": 1,
|
||||
"rule_type_id": ".index-threshold",
|
||||
"schedule": {
|
||||
"interval": "1m"
|
||||
},
|
||||
"scheduled_task_id": "3583a470-74f6-11ed-9801-35303b735aef",
|
||||
"tags": [
|
||||
"cpu"
|
||||
],
|
||||
"throttle": null,
|
||||
"updated_at": "2022-12-05T23:40:33.132Z",
|
||||
"updated_by": "elastic"
|
||||
}
|
||||
],
|
||||
"page": 1,
|
||||
"per_page": 10,
|
||||
"total": 1
|
||||
}
|
||||
},
|
||||
"findRulesResponse": {
|
||||
"description": "A response that contains information about a security rule that has conditional actions.",
|
||||
"summary": "Security rule",
|
||||
"value": {
|
||||
"data": [
|
||||
{
|
||||
"actions": [
|
||||
{
|
||||
"alerts_filter": {
|
||||
"query": {
|
||||
"filters": [
|
||||
{
|
||||
"$state": {
|
||||
"store": "appState"
|
||||
},
|
||||
"meta": {
|
||||
"alias": null,
|
||||
"disabled": false,
|
||||
"field": "client.geo.region_iso_code",
|
||||
"index": "c4bdca79-e69e-4d80-82a1-e5192c621bea",
|
||||
"key": "client.geo.region_iso_code",
|
||||
"negate": false,
|
||||
"params": {
|
||||
"query": "CA-QC",
|
||||
"type": "phrase"
|
||||
}
|
||||
},
|
||||
"query": {
|
||||
"match_phrase": {
|
||||
"client.geo.region_iso_code": "CA-QC"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"kql": ""
|
||||
},
|
||||
"timeframe": {
|
||||
"days": [
|
||||
7
|
||||
],
|
||||
"hours": {
|
||||
"end": "17:00",
|
||||
"start": "08:00"
|
||||
},
|
||||
"timezone": "UTC"
|
||||
}
|
||||
},
|
||||
"connector_type_id": ".index",
|
||||
"frequency": {
|
||||
"notify_when": "onActiveAlert",
|
||||
"summary": true,
|
||||
"throttle": null
|
||||
},
|
||||
"group": "default",
|
||||
"id": "49eae970-f401-11ed-9f8e-399c75a2deeb",
|
||||
"params": {
|
||||
"documents": [
|
||||
{
|
||||
"alert_id": {
|
||||
"[object Object]": null
|
||||
},
|
||||
"context_message": {
|
||||
"[object Object]": null
|
||||
},
|
||||
"rule_id": {
|
||||
"[object Object]": null
|
||||
},
|
||||
"rule_name": {
|
||||
"[object Object]": null
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"uuid": "1c7a1280-f28c-4e06-96b2-e4e5f05d1d61"
|
||||
}
|
||||
],
|
||||
"api_key_created_by_user": false,
|
||||
"api_key_owner": "elastic",
|
||||
"consumer": "siem",
|
||||
"created_at": "2023-05-16T15:50:28.358Z",
|
||||
"created_by": "elastic",
|
||||
"enabled": true,
|
||||
"execution_status": {
|
||||
"last_duration": 166,
|
||||
"last_execution_date": "2023-05-16T20:26:49.590Z",
|
||||
"status": "ok"
|
||||
},
|
||||
"id": "6107a8f0-f401-11ed-9f8e-399c75a2deeb",
|
||||
"last_run": {
|
||||
"alerts_count": {
|
||||
"active": 0,
|
||||
"ignored": 0,
|
||||
"new": 0,
|
||||
"recovered": 0
|
||||
},
|
||||
"outcome": "succeeded",
|
||||
"outcome_msg": [
|
||||
"Rule execution completed successfully"
|
||||
],
|
||||
"outcome_order": 0,
|
||||
"warning": null
|
||||
},
|
||||
"mute_all": false,
|
||||
"muted_alert_ids": [],
|
||||
"name": "security_rule",
|
||||
"next_run": "2023-05-16T20:27:49.507Z",
|
||||
"notify_when": null,
|
||||
"params": {
|
||||
"author": [],
|
||||
"description": "A security threshold rule.",
|
||||
"exceptionsList": [],
|
||||
"falsePositives": [],
|
||||
"filters": [],
|
||||
"from": "now-3660s",
|
||||
"immutable": false,
|
||||
"index": [
|
||||
"kibana_sample_data_logs"
|
||||
],
|
||||
"language": "kuery",
|
||||
"license": "",
|
||||
"maxSignals": 100,
|
||||
"meta": {
|
||||
"from": "1h",
|
||||
"kibana_siem_app_url": "https://localhost:5601/app/security"
|
||||
},
|
||||
"outputIndex": "",
|
||||
"query": "*",
|
||||
"references": [],
|
||||
"riskScore": 21,
|
||||
"riskScoreMapping": [],
|
||||
"ruleId": "an_internal_rule_id",
|
||||
"severity": "low",
|
||||
"severityMapping": [],
|
||||
"threat": [],
|
||||
"threshold": {
|
||||
"cardinality": [],
|
||||
"field": [
|
||||
"bytes"
|
||||
],
|
||||
"value": 1
|
||||
},
|
||||
"to": "now",
|
||||
"type": "threshold",
|
||||
"version": 1
|
||||
},
|
||||
"revision": 1,
|
||||
"rule_type_id": "siem.thresholdRule",
|
||||
"running": false,
|
||||
"schedule": {
|
||||
"interval": "1m"
|
||||
},
|
||||
"scheduled_task_id": "6107a8f0-f401-11ed-9f8e-399c75a2deeb",
|
||||
"tags": [],
|
||||
"throttle": null,
|
||||
"updated_at": "2023-05-16T20:25:42.559Z",
|
||||
"updated_by": "elastic"
|
||||
}
|
||||
],
|
||||
"page": 1,
|
||||
"per_page": 10,
|
||||
"total": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
"schema": {
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
|
|
|
@ -1777,6 +1777,206 @@
|
|||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"examples": {
|
||||
"createEsQueryEsqlRuleRequest": {
|
||||
"description": "Create an Elasticsearch query rule that uses Elasticsearch Query Language (ES|QL) to define its query and a server log connector to send notifications.\n",
|
||||
"summary": "Elasticsearch query rule (ES|QL)",
|
||||
"value": {
|
||||
"actions": [
|
||||
{
|
||||
"frequency": {
|
||||
"notify_when": "onActiveAlert",
|
||||
"summary": false
|
||||
},
|
||||
"group": "query matched",
|
||||
"id": "d0db1fe0-78d6-11ee-9177-f7d404c8c945",
|
||||
"params": {
|
||||
"level": "info",
|
||||
"message": "Elasticsearch query rule '{{rule.name}}' is active:\n- Value: {{context.value}} - Conditions Met: {{context.conditions}} over {{rule.params.timeWindowSize}}{{rule.params.timeWindowUnit}} - Timestamp: {{context.date}} - Link: {{context.link}}"
|
||||
}
|
||||
}
|
||||
],
|
||||
"consumer": "stackAlerts",
|
||||
"name": "my Elasticsearch query ESQL rule",
|
||||
"params": {
|
||||
"esqlQuery": {
|
||||
"esql": "FROM kibana_sample_data_logs | KEEP bytes, clientip, host, geo.dest | where geo.dest != \"GB\" | STATS sumbytes = sum(bytes) by clientip, host | WHERE sumbytes > 5000 | SORT sumbytes desc | LIMIT 10"
|
||||
},
|
||||
"searchType": "esqlQuery",
|
||||
"size": 0,
|
||||
"threshold": [
|
||||
0
|
||||
],
|
||||
"thresholdComparator": ">",
|
||||
"timeField": "@timestamp",
|
||||
"timeWindowSize": 1,
|
||||
"timeWindowUnit": "d"
|
||||
},
|
||||
"rule_type_id": ".es-query",
|
||||
"schedule": {
|
||||
"interval": "1d"
|
||||
}
|
||||
}
|
||||
},
|
||||
"createEsQueryKqlRuleRequest": {
|
||||
"description": "Create an Elasticsearch query rule that uses Kibana query language (KQL).",
|
||||
"summary": "Elasticsearch query rule (KQL)",
|
||||
"value": {
|
||||
"consumer": "alerts",
|
||||
"name": "my Elasticsearch query KQL rule",
|
||||
"params": {
|
||||
"aggType": "count",
|
||||
"excludeHitsFromPreviousRun": true,
|
||||
"groupBy": "all",
|
||||
"searchConfiguration": {
|
||||
"index": "90943e30-9a47-11e8-b64d-95841ca0b247",
|
||||
"query": {
|
||||
"language": "kuery",
|
||||
"query": "\"\"geo.src : \"US\" \"\""
|
||||
}
|
||||
},
|
||||
"searchType": "searchSource",
|
||||
"size": 100,
|
||||
"threshold": [
|
||||
1000
|
||||
],
|
||||
"thresholdComparator": ">",
|
||||
"timeWindowSize": 5,
|
||||
"timeWindowUnit": "m"
|
||||
},
|
||||
"rule_type_id": ".es-query",
|
||||
"schedule": {
|
||||
"interval": "1m"
|
||||
}
|
||||
}
|
||||
},
|
||||
"createEsQueryRuleRequest": {
|
||||
"description": "Create an Elasticsearch query rule that uses Elasticsearch query domain specific language (DSL) to define its query and a server log connector to send notifications.\n",
|
||||
"summary": "Elasticsearch query rule (DSL)",
|
||||
"value": {
|
||||
"actions": [
|
||||
{
|
||||
"frequency": {
|
||||
"notify_when": "onThrottleInterval",
|
||||
"summary": true,
|
||||
"throttle": "1d"
|
||||
},
|
||||
"group": "query matched",
|
||||
"id": "fdbece50-406c-11ee-850e-c71febc4ca7f",
|
||||
"params": {
|
||||
"level": "info",
|
||||
"message": "The system has detected {{alerts.new.count}} new, {{alerts.ongoing.count}} ongoing, and {{alerts.recovered.count}} recovered alerts."
|
||||
}
|
||||
},
|
||||
{
|
||||
"frequency": {
|
||||
"notify_when": "onActionGroupChange",
|
||||
"summary": false
|
||||
},
|
||||
"group": "recovered",
|
||||
"id": "fdbece50-406c-11ee-850e-c71febc4ca7f",
|
||||
"params": {
|
||||
"level": "info",
|
||||
"message": "Recovered"
|
||||
}
|
||||
}
|
||||
],
|
||||
"consumer": "alerts",
|
||||
"name": "my Elasticsearch query rule",
|
||||
"params": {
|
||||
"esQuery": "\"\"\"{\"query\":{\"match_all\" : {}}}\"\"\"",
|
||||
"index": [
|
||||
"kibana_sample_data_logs"
|
||||
],
|
||||
"size": 100,
|
||||
"threshold": [
|
||||
100
|
||||
],
|
||||
"thresholdComparator": ">",
|
||||
"timeField": "@timestamp",
|
||||
"timeWindowSize": 1,
|
||||
"timeWindowUnit": "d"
|
||||
},
|
||||
"rule_type_id": ".es-query",
|
||||
"schedule": {
|
||||
"interval": "1d"
|
||||
}
|
||||
}
|
||||
},
|
||||
"createIndexThresholdRuleRequest": {
|
||||
"description": "Create an index threshold rule that uses a server log connector to send notifications when the threshold is met.\n",
|
||||
"summary": "Index threshold rule",
|
||||
"value": {
|
||||
"actions": [
|
||||
{
|
||||
"frequency": {
|
||||
"notify_when": "onActionGroupChange",
|
||||
"summary": false
|
||||
},
|
||||
"group": "threshold met",
|
||||
"id": "48de3460-f401-11ed-9f8e-399c75a2deeb",
|
||||
"params": {
|
||||
"level": "info",
|
||||
"message": "Rule '{{rule.name}}' is active for group '{{context.group}}':\n\n- Value: {{context.value}}\n- Conditions Met: {{context.conditions}} over {{rule.params.timeWindowSize}}{{rule.params.timeWindowUnit}}\n- Timestamp: {{context.date}}"
|
||||
}
|
||||
}
|
||||
],
|
||||
"alert_delay": {
|
||||
"active": 3
|
||||
},
|
||||
"consumer": "alerts",
|
||||
"name": "my rule",
|
||||
"params": {
|
||||
"aggField": "sheet.version",
|
||||
"aggType": "avg",
|
||||
"groupBy": "top",
|
||||
"index": [
|
||||
".test-index"
|
||||
],
|
||||
"termField": "name.keyword",
|
||||
"termSize": 6,
|
||||
"threshold": [
|
||||
1000
|
||||
],
|
||||
"thresholdComparator": ">",
|
||||
"timeField": "@timestamp",
|
||||
"timeWindowSize": 5,
|
||||
"timeWindowUnit": "m"
|
||||
},
|
||||
"rule_type_id": ".index-threshold",
|
||||
"schedule": {
|
||||
"interval": "1m"
|
||||
},
|
||||
"tags": [
|
||||
"cpu"
|
||||
]
|
||||
}
|
||||
},
|
||||
"createTrackingContainmentRuleRequest": {
|
||||
"description": "Create a tracking containment rule that checks when an entity is contained or no longer contained within a boundary.\n",
|
||||
"summary": "Tracking containment rule",
|
||||
"value": {
|
||||
"consumer": "alerts",
|
||||
"name": "my tracking rule",
|
||||
"params": {
|
||||
"boundaryGeoField": "location",
|
||||
"boundaryIndexId": "0cd90abf-abe7-44c7-909a-f621bbbcfefc",
|
||||
"boundaryIndexTitle": "boundary*",
|
||||
"boundaryNameField": "name",
|
||||
"boundaryType": "entireIndex",
|
||||
"dateField\"": "@timestamp",
|
||||
"entity": "agent.keyword",
|
||||
"geoField": "geo.coordinates",
|
||||
"index": "kibana_sample_data_logs",
|
||||
"indexId": "90943e30-9a47-11e8-b64d-95841ca0b247"
|
||||
},
|
||||
"rule_type_id": ".geo-containment",
|
||||
"schedule": {
|
||||
"interval": "1h"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"schema": {
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
|
@ -2073,6 +2273,339 @@
|
|||
"200": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"examples": {
|
||||
"createEsQueryEsqlRuleResponse": {
|
||||
"description": "The response for successfully creating an Elasticsearch query rule that uses Elasticsearch Query Language (ES|QL).",
|
||||
"summary": "Elasticsearch query rule (ES|QL)",
|
||||
"value": {
|
||||
"actions": [
|
||||
{
|
||||
"connector_type_id": ".server-log",
|
||||
"frequency": {
|
||||
"notify_when": "onActiveAlert",
|
||||
"summary": false,
|
||||
"throttle": null
|
||||
},
|
||||
"group": "query matched",
|
||||
"id": "d0db1fe0-78d6-11ee-9177-f7d404c8c945",
|
||||
"params": {
|
||||
"level": "info",
|
||||
"message": "Elasticsearch query rule '{{rule.name}}' is active:\n- Value: {{context.value}} - Conditions Met: {{context.conditions}} over {{rule.params.timeWindowSize}}{{rule.params.timeWindowUnit}} - Timestamp: {{context.date}} - Link: {{context.link}}"
|
||||
},
|
||||
"uuid": "bfe370a3-531b-4855-bbe6-ad739f578844"
|
||||
}
|
||||
],
|
||||
"api_key_created_by_user": false,
|
||||
"api_key_owner": "elastic",
|
||||
"consumer": "stackAlerts",
|
||||
"created_at": "2023-11-01T19:00:10.453Z",
|
||||
"created_by": "elastic",
|
||||
"enabled": true,
|
||||
"execution_status": {
|
||||
"last_execution_date": "2023-11-01T19:00:10.453Z",
|
||||
"status": "pending"
|
||||
},
|
||||
"id": "e0d62360-78e8-11ee-9177-f7d404c8c945",
|
||||
"mute_all": false,
|
||||
"muted_alert_ids": [],
|
||||
"name": "my Elasticsearch query ESQL rule",
|
||||
"notify_when": null,
|
||||
"params": {
|
||||
"aggType": "count",
|
||||
"esqlQuery": {
|
||||
"esql": "FROM kibana_sample_data_logs | keep bytes, clientip, host, geo.dest | WHERE geo.dest != \"GB\" | stats sumbytes = sum(bytes) by clientip, host | WHERE sumbytes > 5000 | sort sumbytes desc | limit 10"
|
||||
},
|
||||
"excludeHitsFromPreviousRun\"": "true,",
|
||||
"groupBy": "all",
|
||||
"searchType": "esqlQuery",
|
||||
"size": 0,
|
||||
"threshold": [
|
||||
0
|
||||
],
|
||||
"thresholdComparator": ">",
|
||||
"timeField": "@timestamp",
|
||||
"timeWindowSize": 1,
|
||||
"timeWindowUnit": "d"
|
||||
},
|
||||
"revision": 0,
|
||||
"rule_type_id": ".es-query",
|
||||
"running": false,
|
||||
"schedule": {
|
||||
"interval": "1d"
|
||||
},
|
||||
"scheduled_task_id": "e0d62360-78e8-11ee-9177-f7d404c8c945",
|
||||
"tags": [],
|
||||
"throttle": null,
|
||||
"updated_at": "2023-11-01T19:00:10.453Z",
|
||||
"updated_by": "elastic\","
|
||||
}
|
||||
},
|
||||
"createEsQueryKqlRuleResponse": {
|
||||
"description": "The response for successfully creating an Elasticsearch query rule that uses Kibana query language (KQL).",
|
||||
"summary": "Elasticsearch query rule (KQL)",
|
||||
"value": {
|
||||
"actions": [],
|
||||
"api_key_created_by_user": false,
|
||||
"api_key_owner": "elastic",
|
||||
"consumer": "alerts",
|
||||
"created_at": "2023-07-14T20:24:50.729Z",
|
||||
"created_by": "elastic",
|
||||
"enabled": true,
|
||||
"execution_status": {
|
||||
"last_execution_date": "2023-07-14T20:24:50.729Z",
|
||||
"status": "pending"
|
||||
},
|
||||
"id": "7bd506d0-2284-11ee-8fad-6101956ced88",
|
||||
"mute_all": false,
|
||||
"muted_alert_ids": [],
|
||||
"name": "my Elasticsearch query KQL rule\"",
|
||||
"notify_when": null,
|
||||
"params": {
|
||||
"aggType": "count",
|
||||
"excludeHitsFromPreviousRun": true,
|
||||
"groupBy": "all",
|
||||
"searchConfiguration": {
|
||||
"index": "90943e30-9a47-11e8-b64d-95841ca0b247",
|
||||
"query": {
|
||||
"language": "kuery",
|
||||
"query": "\"\"geo.src : \"US\" \"\""
|
||||
}
|
||||
},
|
||||
"searchType": "searchSource",
|
||||
"size": 100,
|
||||
"threshold": [
|
||||
1000
|
||||
],
|
||||
"thresholdComparator": ">",
|
||||
"timeWindowSize": 5,
|
||||
"timeWindowUnit": "m"
|
||||
},
|
||||
"revision": 0,
|
||||
"rule_type_id": ".es-query",
|
||||
"running": false,
|
||||
"schedule": {
|
||||
"interval": "1m"
|
||||
},
|
||||
"scheduled_task_id": "7bd506d0-2284-11ee-8fad-6101956ced88",
|
||||
"tags": [],
|
||||
"throttle": null,
|
||||
"updated_at": "2023-07-14T20:24:50.729Z",
|
||||
"updated_by": "elastic"
|
||||
}
|
||||
},
|
||||
"createEsQueryRuleResponse": {
|
||||
"description": "The response for successfully creating an Elasticsearch query rule that uses Elasticsearch query domain specific language (DSL).",
|
||||
"summary": "Elasticsearch query rule (DSL)",
|
||||
"value": {
|
||||
"actions": [
|
||||
{
|
||||
"connector_type_id": ".server-log",
|
||||
"frequency": {
|
||||
"notify_when": "onThrottleInterval",
|
||||
"summary": true,
|
||||
"throttle": "1d"
|
||||
},
|
||||
"group": "query matched",
|
||||
"id": "fdbece50-406c-11ee-850e-c71febc4ca7f",
|
||||
"params": {
|
||||
"level": "info",
|
||||
"message": "The system has detected {{alerts.new.count}} new, {{alerts.ongoing.count}} ongoing, and {{alerts.recovered.count}} recovered alerts."
|
||||
},
|
||||
"uuid": "53f3c2a3-e5d0-4cfa-af3b-6f0881385e78"
|
||||
},
|
||||
{
|
||||
"connector_type_id": ".server-log",
|
||||
"frequency": {
|
||||
"notify_when": "onActionGroupChange",
|
||||
"summary": false,
|
||||
"throttle": null
|
||||
},
|
||||
"group": "recovered",
|
||||
"id": "fdbece50-406c-11ee-850e-c71febc4ca7f",
|
||||
"params": {
|
||||
"level": "info",
|
||||
"message": "Recovered"
|
||||
},
|
||||
"uuid": "2324e45b-c0df-45c7-9d70-4993e30be758"
|
||||
}
|
||||
],
|
||||
"api_key_created_by_user": false,
|
||||
"api_key_owner": "elastic",
|
||||
"consumer": "alerts",
|
||||
"created_at": "2023-08-22T00:03:38.263Z",
|
||||
"created_by": "elastic",
|
||||
"enabled": true,
|
||||
"execution_status": {
|
||||
"last_execution_date": "2023-08-22T00:03:38.263Z",
|
||||
"status": "pending"
|
||||
},
|
||||
"id": "58148c70-407f-11ee-850e-c71febc4ca7f",
|
||||
"mute_all": false,
|
||||
"muted_alert_ids": [],
|
||||
"name": "my Elasticsearch query rule",
|
||||
"notify_when": null,
|
||||
"params": {
|
||||
"aggType": "count",
|
||||
"esQuery": "\"\"\"{\"query\":{\"match_all\" : {}}}\"\"\"",
|
||||
"excludeHitsFromPreviousRun": true,
|
||||
"groupBy": "all",
|
||||
"index": [
|
||||
"kibana_sample_data_logs"
|
||||
],
|
||||
"searchType": "esQuery",
|
||||
"size": 100,
|
||||
"threshold": [
|
||||
100
|
||||
],
|
||||
"thresholdComparator": ">",
|
||||
"timeField": "@timestamp",
|
||||
"timeWindowSize": 1,
|
||||
"timeWindowUnit": "d"
|
||||
},
|
||||
"revision": 0,
|
||||
"rule_type_id": ".es-query",
|
||||
"running": false,
|
||||
"schedule": {
|
||||
"interval": "1d"
|
||||
},
|
||||
"scheduled_task_id": "58148c70-407f-11ee-850e-c71febc4ca7f",
|
||||
"tags": [],
|
||||
"throttle": null,
|
||||
"updated_at": "2023-08-22T00:03:38.263Z",
|
||||
"updated_by": "elastic"
|
||||
}
|
||||
},
|
||||
"createIndexThresholdRuleResponse": {
|
||||
"description": "The response for successfully creating an index threshold rule.",
|
||||
"summary": "Index threshold rule",
|
||||
"value": {
|
||||
"actions": [
|
||||
{
|
||||
"connector_type_id": ".server-log",
|
||||
"frequency": {
|
||||
"notify_when": "onActionGroupChange",
|
||||
"summary": false,
|
||||
"throttle": null
|
||||
},
|
||||
"group": "threshold met",
|
||||
"id": "dceeb5d0-6b41-11eb-802b-85b0c1bc8ba2",
|
||||
"params": {
|
||||
"level": "info",
|
||||
"message": "Rule {{rule.name}} is active for group {{context.group} :\n\n- Value: {{context.value}}\n- Conditions Met: {{context.conditions}} over {{rule.params.timeWindowSize}}{{rule.params.timeWindowUnit}}\n- Timestamp: {{context.date}}"
|
||||
},
|
||||
"uuid": "07aef2a0-9eed-4ef9-94ec-39ba58eb609d"
|
||||
}
|
||||
],
|
||||
"alert_delay": {
|
||||
"active": 3
|
||||
},
|
||||
"api_key_created_by_user": false,
|
||||
"api_key_owner": "elastic",
|
||||
"consumer": "alerts",
|
||||
"created_at": "2022-06-08T17:20:31.632Z",
|
||||
"created_by": "elastic",
|
||||
"enabled": true,
|
||||
"execution_status": {
|
||||
"last_execution_date": "2022-06-08T17:20:31.632Z",
|
||||
"status": "pending"
|
||||
},
|
||||
"id": "41893910-6bca-11eb-9e0d-85d233e3ee35",
|
||||
"mute_all": false,
|
||||
"muted_alert_ids": [],
|
||||
"name": "my rule",
|
||||
"notify_when": null,
|
||||
"params": {
|
||||
"aggField": "sheet.version",
|
||||
"aggType": "avg",
|
||||
"groupBy": "top",
|
||||
"index": [
|
||||
".test-index"
|
||||
],
|
||||
"termField": "name.keyword",
|
||||
"termSize": 6,
|
||||
"threshold": [
|
||||
1000
|
||||
],
|
||||
"thresholdComparator": ">",
|
||||
"timeField": "@timestamp",
|
||||
"timeWindowSize": 5,
|
||||
"timeWindowUnit": "m"
|
||||
},
|
||||
"revision": 0,
|
||||
"rule_type_id": ".index-threshold",
|
||||
"running": false,
|
||||
"schedule": {
|
||||
"interval": "1m"
|
||||
},
|
||||
"scheduled_task_id": "425b0800-6bca-11eb-9e0d-85d233e3ee35",
|
||||
"tags": [
|
||||
"cpu"
|
||||
],
|
||||
"throttle": null,
|
||||
"updated_at": "2022-06-08T17:20:31.632Z",
|
||||
"updated_by": "elastic"
|
||||
}
|
||||
},
|
||||
"createTrackingContainmentRuleResponse": {
|
||||
"description": "The response for successfully creating a tracking containment rule.",
|
||||
"summary": "Tracking containment rule",
|
||||
"value": {
|
||||
"actions": [],
|
||||
"api_key_created_by_user": false,
|
||||
"api_key_owner": "elastic",
|
||||
"consumer": "alerts",
|
||||
"created_at": "2024-02-14T19:52:55.920Z",
|
||||
"created_by": "elastic",
|
||||
"enabled": true,
|
||||
"execution_status": {
|
||||
"last_duration": 74,
|
||||
"last_execution_date": "2024-02-15T03:25:38.125Z",
|
||||
"status": "ok"
|
||||
},
|
||||
"id": "b6883f9d-5f70-4758-a66e-369d7c26012f",
|
||||
"last_run": {
|
||||
"alerts_count": {
|
||||
"active": 0,
|
||||
"ignored": 0,
|
||||
"new": 0,
|
||||
"recovered": 0
|
||||
},
|
||||
"outcome": "succeeded",
|
||||
"outcome_msg": null,
|
||||
"outcome_order": 0,
|
||||
"warning": null
|
||||
},
|
||||
"mute_all": false,
|
||||
"muted_alert_ids": [],
|
||||
"name": "my tracking rule",
|
||||
"next_run": "2024-02-15T03:26:38.033Z",
|
||||
"notify_when": null,
|
||||
"params": {
|
||||
"boundaryGeoField": "location",
|
||||
"boundaryIndexId": "0cd90abf-abe7-44c7-909a-f621bbbcfefc",
|
||||
"boundaryIndexTitle": "boundary*",
|
||||
"boundaryNameField": "name",
|
||||
"boundaryType": "entireIndex",
|
||||
"dateField": "@timestamp",
|
||||
"entity": "agent.keyword",
|
||||
"geoField": "geo.coordinates",
|
||||
"index": "kibana_sample_data_logs",
|
||||
"indexId": "90943e30-9a47-11e8-b64d-95841ca0b247"
|
||||
},
|
||||
"revision": 1,
|
||||
"rule_type_id": ".geo-containment",
|
||||
"running": false,
|
||||
"schedule": {
|
||||
"interval": "1h"
|
||||
},
|
||||
"scheduled_task_id": "b6883f9d-5f70-4758-a66e-369d7c26012f",
|
||||
"tags": [],
|
||||
"throttle": null,
|
||||
"updated_at": "2024-02-15T03:24:32.574Z",
|
||||
"updated_by": "elastic"
|
||||
}
|
||||
}
|
||||
},
|
||||
"schema": {
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
|
@ -2970,6 +3503,50 @@
|
|||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"examples": {
|
||||
"updateRuleRequest": {
|
||||
"description": "Update an index threshold rule that uses a server log connector to send notifications when the threshold is met.",
|
||||
"summary": "Index threshold rule",
|
||||
"value": {
|
||||
"actions": [
|
||||
{
|
||||
"frequency": {
|
||||
"notify_when": "onActionGroupChange",
|
||||
"summary": false
|
||||
},
|
||||
"group": "threshold met",
|
||||
"id": "96b668d0-a1b6-11ed-afdf-d39a49596974",
|
||||
"params": {
|
||||
"level": "info",
|
||||
"message": "Rule {{rule.name}} is active for group {{context.group}}:\n\n- Value: {{context.value}}\n- Conditions Met: {{context.conditions}} over {{rule.params.timeWindowSize}}{{rule.params.timeWindowUnit}}\n- Timestamp: {{context.date}}"
|
||||
}
|
||||
}
|
||||
],
|
||||
"name": "new name",
|
||||
"params": {
|
||||
"aggField": "sheet.version",
|
||||
"aggType": "avg",
|
||||
"groupBy": "top",
|
||||
"index": [
|
||||
".updated-index"
|
||||
],
|
||||
"termField": "name.keyword",
|
||||
"termSize": 6,
|
||||
"threshold": [
|
||||
1000
|
||||
],
|
||||
"thresholdComparator": ">",
|
||||
"timeField": "@timestamp",
|
||||
"timeWindowSize": 5,
|
||||
"timeWindowUnit": "m"
|
||||
},
|
||||
"schedule": {
|
||||
"interval": "1m"
|
||||
},
|
||||
"tags": []
|
||||
}
|
||||
}
|
||||
},
|
||||
"schema": {
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
|
@ -3249,6 +3826,86 @@
|
|||
"200": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"examples": {
|
||||
"updateRuleResponse": {
|
||||
"description": "The response for successfully updating an index threshold rule.",
|
||||
"summary": "Index threshold rule",
|
||||
"value": {
|
||||
"actions": [
|
||||
{
|
||||
"connector_type_id": ".server-log",
|
||||
"frequency": {
|
||||
"notify_when": "onActionGroupChange",
|
||||
"summary": false,
|
||||
"throttle": null
|
||||
},
|
||||
"group": "threshold met",
|
||||
"id": "96b668d0-a1b6-11ed-afdf-d39a49596974",
|
||||
"params": {
|
||||
"level": "info",
|
||||
"message": "Rule {{rule.name}} is active for group {{context.group}}:\n\n- Value: {{context.value}}\n- Conditions Met: {{context.conditions}} over {{rule.params.timeWindowSize}}{{rule.params.timeWindowUnit}}\n- Timestamp: {{context.date}"
|
||||
},
|
||||
"uuid": "07aef2a0-9eed-4ef9-94ec-39ba58eb609d"
|
||||
}
|
||||
],
|
||||
"api_key_created_by_user": false,
|
||||
"api_key_owner": "elastic",
|
||||
"consumer": "alerts",
|
||||
"created_at": "2024-03-26T23:13:20.985Z",
|
||||
"created_by": "elastic",
|
||||
"enabled": true,
|
||||
"execution_status": {
|
||||
"last_duration": 52,
|
||||
"last_execution_date": "2024-03-26T23:22:51.390Z",
|
||||
"status": "ok"
|
||||
},
|
||||
"id": "ac4e6b90-6be7-11eb-ba0d-9b1c1f912d74",
|
||||
"last_run": {
|
||||
"alerts_count": {
|
||||
"active": 0,
|
||||
"ignored": 0,
|
||||
"new": 0,
|
||||
"recovered": 0
|
||||
},
|
||||
"outcome": "succeeded",
|
||||
"outcome_msg": null,
|
||||
"warning": null
|
||||
},
|
||||
"mute_all": false,
|
||||
"muted_alert_ids": [],
|
||||
"name": "new name",
|
||||
"next_run": "2024-03-26T23:23:51.316Z",
|
||||
"params": {
|
||||
"aggField": "sheet.version",
|
||||
"aggType": "avg",
|
||||
"groupBy": "top",
|
||||
"index": [
|
||||
".updated-index"
|
||||
],
|
||||
"termField": "name.keyword",
|
||||
"termSize": 6,
|
||||
"threshold": [
|
||||
1000
|
||||
],
|
||||
"thresholdComparator": ">",
|
||||
"timeField": "@timestamp",
|
||||
"timeWindowSize": 5,
|
||||
"timeWindowUnit": "m"
|
||||
},
|
||||
"revision": 1,
|
||||
"rule_type_id": ".index-threshold",
|
||||
"running": false,
|
||||
"schedule": {
|
||||
"interval": "1m"
|
||||
},
|
||||
"scheduled_task_id": "4c5eda00-e74f-11ec-b72f-5b18752ff9ea",
|
||||
"tags": [],
|
||||
"throttle": null,
|
||||
"updated_at": "2024-03-26T23:22:59.949Z",
|
||||
"updated_by": "elastic"
|
||||
}
|
||||
}
|
||||
},
|
||||
"schema": {
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
|
@ -4861,6 +5518,257 @@
|
|||
"200": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"examples": {
|
||||
"findConditionalActionRulesResponse": {
|
||||
"description": "A response that contains information about an index threshold rule.",
|
||||
"summary": "Index threshold rule",
|
||||
"value": {
|
||||
"data": [
|
||||
{
|
||||
"actions": [
|
||||
{
|
||||
"frequency": {
|
||||
"notify_when": "onActionGroupChange",
|
||||
"summary": false,
|
||||
"throttle": null
|
||||
},
|
||||
"group": "threshold met",
|
||||
"id": "9dca3e00-74f5-11ed-9801-35303b735aef",
|
||||
"params": {
|
||||
"connector_type_id": ".server-log",
|
||||
"level": "info",
|
||||
"message": "Rule {{rule.name}} is active for group {{context.group}}:\n\n- Value: {{context.value}}\n- Conditions Met: {{context.conditions}} over {{rule.params.timeWindowSize}}{{rule.params.timeWindowUnit}}\n- Timestamp: {{context.date}}"
|
||||
},
|
||||
"uuid": "1c7a1280-f28c-4e06-96b2-e4e5f05d1d61"
|
||||
}
|
||||
],
|
||||
"api_key_created_by_user": false,
|
||||
"api_key_owner": "elastic",
|
||||
"consumer": "alerts",
|
||||
"created_at": "2022-12-05T23:40:33.132Z",
|
||||
"created_by": "elastic",
|
||||
"enabled": true,
|
||||
"execution_status": {
|
||||
"last_duration": 48,
|
||||
"last_execution_date": "2022-12-06T01:44:23.983Z",
|
||||
"status": "ok"
|
||||
},
|
||||
"id": "3583a470-74f6-11ed-9801-35303b735aef",
|
||||
"last_run": {
|
||||
"alerts_count": {
|
||||
"active": 0,
|
||||
"ignored": 0,
|
||||
"new": 0,
|
||||
"recovered": 0
|
||||
},
|
||||
"outcome": "succeeded",
|
||||
"outcome_msg": null,
|
||||
"warning": null
|
||||
},
|
||||
"mute_all": false,
|
||||
"muted_alert_ids": [],
|
||||
"name": "my alert",
|
||||
"next_run": "2022-12-06T01:45:23.912Z",
|
||||
"params": {
|
||||
"aggField": "sheet.version",
|
||||
"aggType": "avg",
|
||||
"groupBy": "top",
|
||||
"index": [
|
||||
"test-index"
|
||||
],
|
||||
"termField": "name.keyword",
|
||||
"termSize": 6,
|
||||
"threshold": [
|
||||
1000
|
||||
],
|
||||
"thresholdComparator": ">",
|
||||
"timeField": "@timestamp",
|
||||
"timeWindowSize": 5,
|
||||
"timeWindowUnit": "m"
|
||||
},
|
||||
"revision": 1,
|
||||
"rule_type_id": ".index-threshold",
|
||||
"schedule": {
|
||||
"interval": "1m"
|
||||
},
|
||||
"scheduled_task_id": "3583a470-74f6-11ed-9801-35303b735aef",
|
||||
"tags": [
|
||||
"cpu"
|
||||
],
|
||||
"throttle": null,
|
||||
"updated_at": "2022-12-05T23:40:33.132Z",
|
||||
"updated_by": "elastic"
|
||||
}
|
||||
],
|
||||
"page": 1,
|
||||
"per_page": 10,
|
||||
"total": 1
|
||||
}
|
||||
},
|
||||
"findRulesResponse": {
|
||||
"description": "A response that contains information about a security rule that has conditional actions.",
|
||||
"summary": "Security rule",
|
||||
"value": {
|
||||
"data": [
|
||||
{
|
||||
"actions": [
|
||||
{
|
||||
"alerts_filter": {
|
||||
"query": {
|
||||
"filters": [
|
||||
{
|
||||
"$state": {
|
||||
"store": "appState"
|
||||
},
|
||||
"meta": {
|
||||
"alias": null,
|
||||
"disabled": false,
|
||||
"field": "client.geo.region_iso_code",
|
||||
"index": "c4bdca79-e69e-4d80-82a1-e5192c621bea",
|
||||
"key": "client.geo.region_iso_code",
|
||||
"negate": false,
|
||||
"params": {
|
||||
"query": "CA-QC",
|
||||
"type": "phrase"
|
||||
}
|
||||
},
|
||||
"query": {
|
||||
"match_phrase": {
|
||||
"client.geo.region_iso_code": "CA-QC"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"kql": ""
|
||||
},
|
||||
"timeframe": {
|
||||
"days": [
|
||||
7
|
||||
],
|
||||
"hours": {
|
||||
"end": "17:00",
|
||||
"start": "08:00"
|
||||
},
|
||||
"timezone": "UTC"
|
||||
}
|
||||
},
|
||||
"connector_type_id": ".index",
|
||||
"frequency": {
|
||||
"notify_when": "onActiveAlert",
|
||||
"summary": true,
|
||||
"throttle": null
|
||||
},
|
||||
"group": "default",
|
||||
"id": "49eae970-f401-11ed-9f8e-399c75a2deeb",
|
||||
"params": {
|
||||
"documents": [
|
||||
{
|
||||
"alert_id": {
|
||||
"[object Object]": null
|
||||
},
|
||||
"context_message": {
|
||||
"[object Object]": null
|
||||
},
|
||||
"rule_id": {
|
||||
"[object Object]": null
|
||||
},
|
||||
"rule_name": {
|
||||
"[object Object]": null
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"uuid": "1c7a1280-f28c-4e06-96b2-e4e5f05d1d61"
|
||||
}
|
||||
],
|
||||
"api_key_created_by_user": false,
|
||||
"api_key_owner": "elastic",
|
||||
"consumer": "siem",
|
||||
"created_at": "2023-05-16T15:50:28.358Z",
|
||||
"created_by": "elastic",
|
||||
"enabled": true,
|
||||
"execution_status": {
|
||||
"last_duration": 166,
|
||||
"last_execution_date": "2023-05-16T20:26:49.590Z",
|
||||
"status": "ok"
|
||||
},
|
||||
"id": "6107a8f0-f401-11ed-9f8e-399c75a2deeb",
|
||||
"last_run": {
|
||||
"alerts_count": {
|
||||
"active": 0,
|
||||
"ignored": 0,
|
||||
"new": 0,
|
||||
"recovered": 0
|
||||
},
|
||||
"outcome": "succeeded",
|
||||
"outcome_msg": [
|
||||
"Rule execution completed successfully"
|
||||
],
|
||||
"outcome_order": 0,
|
||||
"warning": null
|
||||
},
|
||||
"mute_all": false,
|
||||
"muted_alert_ids": [],
|
||||
"name": "security_rule",
|
||||
"next_run": "2023-05-16T20:27:49.507Z",
|
||||
"notify_when": null,
|
||||
"params": {
|
||||
"author": [],
|
||||
"description": "A security threshold rule.",
|
||||
"exceptionsList": [],
|
||||
"falsePositives": [],
|
||||
"filters": [],
|
||||
"from": "now-3660s",
|
||||
"immutable": false,
|
||||
"index": [
|
||||
"kibana_sample_data_logs"
|
||||
],
|
||||
"language": "kuery",
|
||||
"license": "",
|
||||
"maxSignals": 100,
|
||||
"meta": {
|
||||
"from": "1h",
|
||||
"kibana_siem_app_url": "https://localhost:5601/app/security"
|
||||
},
|
||||
"outputIndex": "",
|
||||
"query": "*",
|
||||
"references": [],
|
||||
"riskScore": 21,
|
||||
"riskScoreMapping": [],
|
||||
"ruleId": "an_internal_rule_id",
|
||||
"severity": "low",
|
||||
"severityMapping": [],
|
||||
"threat": [],
|
||||
"threshold": {
|
||||
"cardinality": [],
|
||||
"field": [
|
||||
"bytes"
|
||||
],
|
||||
"value": 1
|
||||
},
|
||||
"to": "now",
|
||||
"type": "threshold",
|
||||
"version": 1
|
||||
},
|
||||
"revision": 1,
|
||||
"rule_type_id": "siem.thresholdRule",
|
||||
"running": false,
|
||||
"schedule": {
|
||||
"interval": "1m"
|
||||
},
|
||||
"scheduled_task_id": "6107a8f0-f401-11ed-9f8e-399c75a2deeb",
|
||||
"tags": [],
|
||||
"throttle": null,
|
||||
"updated_at": "2023-05-16T20:25:42.559Z",
|
||||
"updated_by": "elastic"
|
||||
}
|
||||
],
|
||||
"page": 1,
|
||||
"per_page": 10,
|
||||
"total": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
"schema": {
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -4,67 +4,6 @@ info:
|
|||
title: Overlays for the alerting rule examples and parameters
|
||||
version: 0.0.1
|
||||
actions:
|
||||
# Add some alerting API examples
|
||||
- target: "$.paths['/api/alerting/rule/{id}']['post']"
|
||||
description: "Add examples to create rule API"
|
||||
update:
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
examples:
|
||||
createEsQueryEsqlRuleRequest:
|
||||
$ref: "../examples/create_es_query_esql_rule_request.yaml"
|
||||
createEsQueryRuleRequest:
|
||||
$ref: "../examples/create_es_query_rule_request.yaml"
|
||||
createEsQueryKqlRuleRequest:
|
||||
$ref: "../examples/create_es_query_kql_rule_request.yaml"
|
||||
createIndexThresholdRuleRequest:
|
||||
$ref: "../examples/create_index_threshold_rule_request.yaml"
|
||||
createTrackingContainmentRuleRequest:
|
||||
$ref: "../examples/create_tracking_containment_rule_request.yaml"
|
||||
responses:
|
||||
200:
|
||||
content:
|
||||
application/json:
|
||||
examples:
|
||||
createEsQueryEsqlRuleResponse:
|
||||
$ref: "../examples/create_es_query_esql_rule_response.yaml"
|
||||
createEsQueryRuleResponse:
|
||||
$ref: "../examples/create_es_query_rule_response.yaml"
|
||||
createEsQueryKqlRuleResponse:
|
||||
$ref: "../examples/create_es_query_kql_rule_response.yaml"
|
||||
createIndexThresholdRuleResponse:
|
||||
$ref: "../examples/create_index_threshold_rule_response.yaml"
|
||||
createTrackingContainmentRuleResponse:
|
||||
$ref: "../examples/create_tracking_containment_rule_response.yaml"
|
||||
- target: "$.paths['/api/alerting/rule/{id}']['put']"
|
||||
description: "Add examples to update rule API"
|
||||
update:
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
examples:
|
||||
updateRuleRequest:
|
||||
$ref: '../examples/update_rule_request.yaml'
|
||||
responses:
|
||||
200:
|
||||
content:
|
||||
application/json:
|
||||
examples:
|
||||
updateRuleResponse:
|
||||
$ref: '../examples/update_rule_response.yaml'
|
||||
- target: "$.paths['/api/alerting/rules/_find']['get']"
|
||||
description: "Add examples to find rules API"
|
||||
update:
|
||||
responses:
|
||||
200:
|
||||
content:
|
||||
application/json:
|
||||
examples:
|
||||
findRulesResponse:
|
||||
$ref: '../examples/find_rules_response.yaml'
|
||||
findConditionalActionRulesResponse:
|
||||
$ref: '../examples/find_rules_response_conditional_action.yaml'
|
||||
# Fix some optional path parameters
|
||||
- target: "$.paths['/api/alerting/rule/{id}']['post'].parameters[?(@.name=='id')]"
|
||||
description: Remove optional indicator from path parameter
|
||||
|
|
|
@ -103,6 +103,7 @@
|
|||
"globby/fast-glob": "^3.3.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@apidevtools/json-schema-ref-parser": "^11.9.1",
|
||||
"@appland/sql-parser": "^1.5.1",
|
||||
"@aws-crypto/sha256-js": "^5.2.0",
|
||||
"@aws-crypto/util": "^5.2.0",
|
||||
|
|
|
@ -611,6 +611,7 @@
|
|||
"fp-ts",
|
||||
"getos",
|
||||
"joi-to-json",
|
||||
"@apidevtools/json-schema-ref-parser",
|
||||
"json5",
|
||||
"load-json-file",
|
||||
"mock-fs",
|
||||
|
|
|
@ -304,7 +304,7 @@ export class HttpService
|
|||
mergeMap(async () => {
|
||||
try {
|
||||
// Potentially quite expensive
|
||||
const result = generateOpenApiDocument(
|
||||
const result = await generateOpenApiDocument(
|
||||
this.httpServer.getRouters({ pluginId: query.pluginId }),
|
||||
{
|
||||
baseUrl,
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
* License v3.0 only", or the "Server Side Public License, v 1".
|
||||
*/
|
||||
|
||||
import type { OpenAPIV3 } from 'openapi-types';
|
||||
import type { DeepPartial } from '@kbn/utility-types';
|
||||
import type { RouteValidator } from './route_validator';
|
||||
|
||||
/**
|
||||
|
@ -387,6 +389,37 @@ export interface RouteConfigOptions<Method extends RouteMethod> {
|
|||
*/
|
||||
deprecated?: RouteDeprecationInfo;
|
||||
|
||||
/**
|
||||
* Filepath to a YAML file or a partial {@link OpenAPIV3.OperationObject} to
|
||||
* be merged with the code generated for this endpoint.
|
||||
*
|
||||
* @note Always instantiate the objects lazily to avoid unnecessarily loading
|
||||
* objects into memory.
|
||||
*
|
||||
* @example
|
||||
* As a path to a OAS file
|
||||
* () => path.join(__dirname, 'my_examples.yaml')
|
||||
*
|
||||
* @example
|
||||
* As an object
|
||||
* () => ({
|
||||
* requestBody: {
|
||||
* content: {
|
||||
* 200: {
|
||||
* examples: {
|
||||
* fooExample: {
|
||||
* value: { coolType: true } as { coolType: true },
|
||||
* },
|
||||
* },
|
||||
* },
|
||||
* },
|
||||
* },
|
||||
* })
|
||||
*/
|
||||
oasOperationObject?: () =>
|
||||
| string
|
||||
| DeepPartial<Pick<OpenAPIV3.OperationObject, 'requestBody' | 'responses'>>;
|
||||
|
||||
/**
|
||||
* Whether this route should be treated as "invisible" and excluded from router
|
||||
* OAS introspection.
|
||||
|
|
|
@ -34,9 +34,17 @@ export type VersionedRouteConfig<Method extends RouteMethod> = Omit<
|
|||
RouteConfig<unknown, unknown, unknown, Method>,
|
||||
'validate' | 'options'
|
||||
> & {
|
||||
options?: Omit<
|
||||
options?: Pick<
|
||||
RouteConfigOptions<Method>,
|
||||
'access' | 'description' | 'summary' | 'deprecated' | 'discontinued'
|
||||
| 'authRequired'
|
||||
| 'xsrfRequired'
|
||||
| 'tags'
|
||||
| 'body'
|
||||
| 'timeout'
|
||||
| 'excludeFromOAS'
|
||||
| 'excludeFromRateLimiter'
|
||||
| 'httpResource'
|
||||
| 'availability'
|
||||
>;
|
||||
/** See {@link RouteConfigOptions<RouteMethod>['access']} */
|
||||
access: Exclude<RouteConfigOptions<Method>['access'], undefined>;
|
||||
|
@ -342,6 +350,11 @@ export interface AddVersionOpts<P, Q, B> {
|
|||
|
||||
options?: {
|
||||
deprecated?: RouteDeprecationInfo;
|
||||
/**
|
||||
* @public
|
||||
* {@inheritdoc RouteConfigOptions['oasOperationObject']}
|
||||
*/
|
||||
oasOperationObject?: RouteConfigOptions<RouteMethod>['oasOperationObject'];
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
*/
|
||||
|
||||
import { schema, Type } from '@kbn/config-schema';
|
||||
import { get } from 'lodash';
|
||||
import { generateOpenApiDocument } from './generate_oas';
|
||||
import { createTestRouters, createRouter, createVersionedRouter } from './generate_oas.test.util';
|
||||
import {
|
||||
|
@ -23,7 +24,7 @@ interface RecursiveType {
|
|||
|
||||
describe('generateOpenApiDocument', () => {
|
||||
describe('@kbn/config-schema', () => {
|
||||
it('generates the expected OpenAPI document for the shared schema', () => {
|
||||
it('generates the expected OpenAPI document for the shared schema', async () => {
|
||||
const [routers, versionedRouters] = createTestRouters({
|
||||
routers: {
|
||||
testRouter: {
|
||||
|
@ -34,7 +35,7 @@ describe('generateOpenApiDocument', () => {
|
|||
bodySchema: createSharedConfigSchema(),
|
||||
});
|
||||
expect(
|
||||
generateOpenApiDocument(
|
||||
await generateOpenApiDocument(
|
||||
{
|
||||
routers,
|
||||
versionedRouters,
|
||||
|
@ -48,7 +49,7 @@ describe('generateOpenApiDocument', () => {
|
|||
).toEqual(sharedOas);
|
||||
});
|
||||
|
||||
it('generates the expected OpenAPI document', () => {
|
||||
it('generates the expected OpenAPI document', async () => {
|
||||
const [routers, versionedRouters] = createTestRouters({
|
||||
routers: {
|
||||
testRouter: {
|
||||
|
@ -80,7 +81,7 @@ describe('generateOpenApiDocument', () => {
|
|||
},
|
||||
});
|
||||
expect(
|
||||
generateOpenApiDocument(
|
||||
await generateOpenApiDocument(
|
||||
{
|
||||
routers,
|
||||
versionedRouters,
|
||||
|
@ -94,7 +95,7 @@ describe('generateOpenApiDocument', () => {
|
|||
).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('generates references in the expected format', () => {
|
||||
it('generates references in the expected format', async () => {
|
||||
const sharedIdSchema = schema.string({ minLength: 1, meta: { description: 'test' } });
|
||||
const sharedNameSchema = schema.string({ minLength: 1 });
|
||||
const otherSchema = schema.object(
|
||||
|
@ -102,7 +103,7 @@ describe('generateOpenApiDocument', () => {
|
|||
{ meta: { id: 'foo' } }
|
||||
);
|
||||
expect(
|
||||
generateOpenApiDocument(
|
||||
await generateOpenApiDocument(
|
||||
{
|
||||
routers: [
|
||||
createRouter({
|
||||
|
@ -139,7 +140,7 @@ describe('generateOpenApiDocument', () => {
|
|||
).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('handles recursive schemas', () => {
|
||||
it('handles recursive schemas', async () => {
|
||||
const id = 'recursive';
|
||||
const recursiveSchema: Type<RecursiveType> = schema.object(
|
||||
{
|
||||
|
@ -149,7 +150,7 @@ describe('generateOpenApiDocument', () => {
|
|||
{ meta: { id } }
|
||||
);
|
||||
expect(
|
||||
generateOpenApiDocument(
|
||||
await generateOpenApiDocument(
|
||||
{
|
||||
routers: [
|
||||
createRouter({
|
||||
|
@ -187,7 +188,7 @@ describe('generateOpenApiDocument', () => {
|
|||
});
|
||||
|
||||
describe('Zod', () => {
|
||||
it('generates the expected OpenAPI document for the shared schema', () => {
|
||||
it('generates the expected OpenAPI document for the shared schema', async () => {
|
||||
const [routers, versionedRouters] = createTestRouters({
|
||||
routers: { testRouter: { routes: [{ method: 'get' }, { method: 'post' }] } },
|
||||
versionedRouters: { testVersionedRouter: { routes: [{}] } },
|
||||
|
@ -195,7 +196,7 @@ describe('generateOpenApiDocument', () => {
|
|||
});
|
||||
|
||||
expect(
|
||||
generateOpenApiDocument(
|
||||
await generateOpenApiDocument(
|
||||
{
|
||||
routers,
|
||||
versionedRouters,
|
||||
|
@ -211,9 +212,9 @@ describe('generateOpenApiDocument', () => {
|
|||
});
|
||||
|
||||
describe('unknown schema/validation', () => {
|
||||
it('produces the expected output', () => {
|
||||
it('produces the expected output', async () => {
|
||||
expect(
|
||||
generateOpenApiDocument(
|
||||
await generateOpenApiDocument(
|
||||
{
|
||||
routers: [
|
||||
createRouter({
|
||||
|
@ -275,7 +276,7 @@ describe('generateOpenApiDocument', () => {
|
|||
});
|
||||
|
||||
describe('tags', () => {
|
||||
it('handles tags as expected', () => {
|
||||
it('handles tags as expected', async () => {
|
||||
const [routers, versionedRouters] = createTestRouters({
|
||||
routers: {
|
||||
testRouter1: {
|
||||
|
@ -314,7 +315,7 @@ describe('generateOpenApiDocument', () => {
|
|||
},
|
||||
},
|
||||
});
|
||||
const result = generateOpenApiDocument(
|
||||
const result = await generateOpenApiDocument(
|
||||
{
|
||||
routers,
|
||||
versionedRouters,
|
||||
|
@ -337,7 +338,7 @@ describe('generateOpenApiDocument', () => {
|
|||
});
|
||||
|
||||
describe('availability', () => {
|
||||
it('creates the expected availability entries', () => {
|
||||
it('creates the expected availability entries', async () => {
|
||||
const [routers, versionedRouters] = createTestRouters({
|
||||
routers: {
|
||||
testRouter1: {
|
||||
|
@ -391,7 +392,7 @@ describe('generateOpenApiDocument', () => {
|
|||
},
|
||||
},
|
||||
});
|
||||
const result = generateOpenApiDocument(
|
||||
const result = await generateOpenApiDocument(
|
||||
{
|
||||
routers,
|
||||
versionedRouters,
|
||||
|
@ -434,4 +435,84 @@ describe('generateOpenApiDocument', () => {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('merges operation objects', async () => {
|
||||
const oasOperationObject = () => ({
|
||||
requestBody: {
|
||||
content: {
|
||||
'application/json': {
|
||||
examples: {
|
||||
fooExample: {
|
||||
value: 999,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
const [routers, versionedRouters] = createTestRouters({
|
||||
routers: {
|
||||
testRouter: {
|
||||
routes: [
|
||||
{
|
||||
method: 'get',
|
||||
options: {
|
||||
access: 'public',
|
||||
oasOperationObject,
|
||||
},
|
||||
},
|
||||
{ method: 'post' },
|
||||
],
|
||||
},
|
||||
},
|
||||
versionedRouters: {
|
||||
testVersionedRouter: {
|
||||
routes: [
|
||||
{
|
||||
options: {
|
||||
access: 'public',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
bodySchema: createSharedConfigSchema(),
|
||||
});
|
||||
|
||||
versionedRouters[0].getRoutes()[0].handlers[0].options!.options!.oasOperationObject =
|
||||
oasOperationObject;
|
||||
|
||||
const oas = await generateOpenApiDocument(
|
||||
{ routers, versionedRouters },
|
||||
{
|
||||
title: 'test',
|
||||
baseUrl: 'https://test.oas',
|
||||
version: '99.99.99',
|
||||
}
|
||||
);
|
||||
|
||||
expect(
|
||||
get(oas, [
|
||||
'paths',
|
||||
'/foo/{id}/{path}',
|
||||
'get',
|
||||
'requestBody',
|
||||
'content',
|
||||
'application/json',
|
||||
'examples',
|
||||
])
|
||||
).toEqual({
|
||||
fooExample: {
|
||||
value: 999,
|
||||
},
|
||||
});
|
||||
|
||||
expect(
|
||||
get(oas, ['paths', '/bar', 'get', 'requestBody', 'content', 'application/json', 'examples'])
|
||||
).toEqual({
|
||||
fooExample: {
|
||||
value: 999,
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -39,10 +39,10 @@ export interface GenerateOpenApiDocumentOptions {
|
|||
filters?: GenerateOpenApiDocumentOptionsFilters;
|
||||
}
|
||||
|
||||
export const generateOpenApiDocument = (
|
||||
export const generateOpenApiDocument = async (
|
||||
appRouters: { routers: Router[]; versionedRouters: CoreVersionedRouter[] },
|
||||
opts: GenerateOpenApiDocumentOptions
|
||||
): OpenAPIV3.Document => {
|
||||
): Promise<OpenAPIV3.Document> => {
|
||||
let { filters = { access: 'public' } } = opts;
|
||||
if (filters.access === 'public' && !filters.version) {
|
||||
filters = { ...filters, version: SERVERLESS_VERSION_2023_10_31 };
|
||||
|
@ -51,11 +51,11 @@ export const generateOpenApiDocument = (
|
|||
const paths: OpenAPIV3.PathsObject = {};
|
||||
const getOpId = createOpIdGenerator();
|
||||
for (const router of appRouters.routers) {
|
||||
const result = processRouter(router, converter, getOpId, filters);
|
||||
const result = await processRouter(router, converter, getOpId, filters);
|
||||
Object.assign(paths, result.paths);
|
||||
}
|
||||
for (const router of appRouters.versionedRouters) {
|
||||
const result = processVersionedRouter(router, converter, getOpId, filters);
|
||||
const result = await processVersionedRouter(router, converter, getOpId, filters);
|
||||
Object.assign(paths, result.paths);
|
||||
}
|
||||
const tags = buildGlobalTags(paths, opts.tags);
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* 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", the "GNU Affero General Public License v3.0 only", and the "Server Side
|
||||
* Public License v 1"; you may not use this file except in compliance with, at
|
||||
* your election, the "Elastic License 2.0", the "GNU Affero General Public
|
||||
* License v3.0 only", or the "Server Side Public License, v 1".
|
||||
*/
|
||||
|
||||
import type { OpenAPIV3 } from 'openapi-types';
|
||||
import type { DeepPartial } from '@kbn/utility-types';
|
||||
import { dereference } from '@apidevtools/json-schema-ref-parser';
|
||||
import deepMerge from 'deepmerge';
|
||||
import type { CustomOperationObject } from './type';
|
||||
|
||||
export async function mergeOperation(
|
||||
pathToSpecOrSpec: string | DeepPartial<OpenAPIV3.OperationObject>,
|
||||
operation: CustomOperationObject
|
||||
) {
|
||||
if (typeof pathToSpecOrSpec === 'string') {
|
||||
Object.assign(operation, deepMerge(operation, await dereference(pathToSpecOrSpec)));
|
||||
} else {
|
||||
Object.assign(operation, deepMerge(operation, pathToSpecOrSpec));
|
||||
}
|
||||
}
|
|
@ -148,23 +148,23 @@ describe('processRouter', () => {
|
|||
],
|
||||
} as unknown as Router;
|
||||
|
||||
it('only provides routes for version 2023-10-31', () => {
|
||||
const result1 = processRouter(testRouter, new OasConverter(), createOpIdGenerator(), {
|
||||
it('only provides routes for version 2023-10-31', async () => {
|
||||
const result1 = await processRouter(testRouter, new OasConverter(), createOpIdGenerator(), {
|
||||
version: '2023-10-31',
|
||||
access: 'public',
|
||||
});
|
||||
|
||||
expect(Object.keys(result1.paths!)).toHaveLength(5);
|
||||
|
||||
const result2 = processRouter(testRouter, new OasConverter(), createOpIdGenerator(), {
|
||||
const result2 = await processRouter(testRouter, new OasConverter(), createOpIdGenerator(), {
|
||||
version: '2024-10-31',
|
||||
access: 'public',
|
||||
});
|
||||
expect(Object.keys(result2.paths!)).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('updates description with privileges required', () => {
|
||||
const result = processRouter(testRouter, new OasConverter(), createOpIdGenerator(), {
|
||||
it('updates description with privileges required', async () => {
|
||||
const result = await processRouter(testRouter, new OasConverter(), createOpIdGenerator(), {
|
||||
version: '2023-10-31',
|
||||
access: 'public',
|
||||
});
|
||||
|
|
|
@ -28,8 +28,9 @@ import {
|
|||
import type { GenerateOpenApiDocumentOptionsFilters } from './generate_oas';
|
||||
import type { CustomOperationObject, InternalRouterRoute } from './type';
|
||||
import { extractAuthzDescription } from './extract_authz_description';
|
||||
import { mergeOperation } from './merge_operation';
|
||||
|
||||
export const processRouter = (
|
||||
export const processRouter = async (
|
||||
appRouter: Router,
|
||||
converter: OasConverter,
|
||||
getOpId: GetOpId,
|
||||
|
@ -99,6 +100,10 @@ export const processRouter = (
|
|||
|
||||
setXState(route.options.availability, operation);
|
||||
|
||||
if (route.options.oasOperationObject) {
|
||||
await mergeOperation(route.options.oasOperationObject(), operation);
|
||||
}
|
||||
|
||||
const path: OpenAPIV3.PathItemObject = {
|
||||
[route.method]: operation,
|
||||
};
|
||||
|
|
|
@ -121,8 +121,8 @@ describe('extractVersionedResponses', () => {
|
|||
});
|
||||
|
||||
describe('processVersionedRouter', () => {
|
||||
it('correctly extracts the version based on the version filter', () => {
|
||||
const baseCase = processVersionedRouter(
|
||||
it('correctly extracts the version based on the version filter', async () => {
|
||||
const baseCase = await processVersionedRouter(
|
||||
{ getRoutes: () => [createTestRoute()] } as unknown as CoreVersionedRouter,
|
||||
new OasConverter(),
|
||||
createOpIdGenerator(),
|
||||
|
@ -133,7 +133,7 @@ describe('processVersionedRouter', () => {
|
|||
'application/test+json',
|
||||
]);
|
||||
|
||||
const filteredCase = processVersionedRouter(
|
||||
const filteredCase = await processVersionedRouter(
|
||||
{ getRoutes: () => [createTestRoute()] } as unknown as CoreVersionedRouter,
|
||||
new OasConverter(),
|
||||
createOpIdGenerator(),
|
||||
|
@ -144,8 +144,8 @@ describe('processVersionedRouter', () => {
|
|||
]);
|
||||
});
|
||||
|
||||
it('correctly updates the authz description for routes that require privileges', () => {
|
||||
const results = processVersionedRouter(
|
||||
it('correctly updates the authz description for routes that require privileges', async () => {
|
||||
const results = await processVersionedRouter(
|
||||
{ getRoutes: () => [createTestRoute()] } as unknown as CoreVersionedRouter,
|
||||
new OasConverter(),
|
||||
createOpIdGenerator(),
|
||||
|
|
|
@ -31,8 +31,9 @@ import {
|
|||
GetOpId,
|
||||
} from './util';
|
||||
import { isReferenceObject } from './oas_converter/common';
|
||||
import { mergeOperation } from './merge_operation';
|
||||
|
||||
export const processVersionedRouter = (
|
||||
export const processVersionedRouter = async (
|
||||
appRouter: CoreVersionedRouter,
|
||||
converter: OasConverter,
|
||||
getOpId: GetOpId,
|
||||
|
@ -130,6 +131,10 @@ export const processVersionedRouter = (
|
|||
|
||||
setXState(route.options.options?.availability, operation);
|
||||
|
||||
if (handler.options.options?.oasOperationObject) {
|
||||
await mergeOperation(handler.options.options.oasOperationObject(), operation);
|
||||
}
|
||||
|
||||
const path: OpenAPIV3.PathItemObject = {
|
||||
[route.method]: operation,
|
||||
};
|
||||
|
|
|
@ -19,5 +19,6 @@
|
|||
"@kbn/config-schema",
|
||||
"@kbn/zod",
|
||||
"@kbn/zod-helpers",
|
||||
"@kbn/utility-types",
|
||||
]
|
||||
}
|
||||
|
|
|
@ -203,7 +203,6 @@ export function registerRoutes<TDependencies extends Record<string, any>>({
|
|||
access,
|
||||
summary: options.summary,
|
||||
description: options.description,
|
||||
// @ts-expect-error we are essentially calling multiple methods at the same type so TS gets confused
|
||||
options: omit(options, 'access', 'description', 'summary', 'deprecated', 'discontinued'),
|
||||
security,
|
||||
}).addVersion(
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
summary: Elasticsearch query rule (ES|QL)
|
||||
description: >
|
||||
Create an Elasticsearch query rule that uses Elasticsearch Query Language (ES|QL) to define its query and a server log connector to send notifications.
|
||||
value:
|
||||
name: my Elasticsearch query ESQL rule
|
||||
params:
|
||||
searchType: esqlQuery
|
||||
esqlQuery:
|
||||
esql: 'FROM kibana_sample_data_logs | KEEP bytes, clientip, host, geo.dest | where geo.dest != "GB" | STATS sumbytes = sum(bytes) by clientip, host | WHERE sumbytes > 5000 | SORT sumbytes desc | LIMIT 10'
|
||||
timeField: "@timestamp"
|
||||
timeWindowSize: 1
|
||||
timeWindowUnit: d
|
||||
size: 0
|
||||
thresholdComparator: ">"
|
||||
threshold:
|
||||
- 0
|
||||
consumer: stackAlerts
|
||||
rule_type_id: .es-query
|
||||
schedule:
|
||||
interval: 1d
|
||||
actions:
|
||||
- group: query matched
|
||||
id: d0db1fe0-78d6-11ee-9177-f7d404c8c945
|
||||
params:
|
||||
level: info
|
||||
message: "Elasticsearch query rule '{{rule.name}}' is active:
|
||||
|
||||
- Value: {{context.value}}
|
||||
- Conditions Met: {{context.conditions}} over {{rule.params.timeWindowSize}}{{rule.params.timeWindowUnit}}
|
||||
- Timestamp: {{context.date}}
|
||||
- Link: {{context.link}}"
|
||||
frequency:
|
||||
summary: false
|
||||
notify_when: onActiveAlert
|
|
@ -0,0 +1,58 @@
|
|||
summary: Elasticsearch query rule (ES|QL)
|
||||
description: The response for successfully creating an Elasticsearch query rule that uses Elasticsearch Query Language (ES|QL).
|
||||
value:
|
||||
id: e0d62360-78e8-11ee-9177-f7d404c8c945
|
||||
enabled: true
|
||||
name: my Elasticsearch query ESQL rule
|
||||
tags: []
|
||||
rule_type_id: .es-query
|
||||
consumer: stackAlerts
|
||||
schedule:
|
||||
interval: 1d
|
||||
actions:
|
||||
- group: query matched
|
||||
id: d0db1fe0-78d6-11ee-9177-f7d404c8c945
|
||||
params:
|
||||
level: info
|
||||
message: "Elasticsearch query rule '{{rule.name}}' is active:
|
||||
|
||||
- Value: {{context.value}}
|
||||
- Conditions Met: {{context.conditions}} over {{rule.params.timeWindowSize}}{{rule.params.timeWindowUnit}}
|
||||
- Timestamp: {{context.date}}
|
||||
- Link: {{context.link}}"
|
||||
connector_type_id: .server-log
|
||||
frequency:
|
||||
summary: false
|
||||
notify_when: onActiveAlert
|
||||
throttle: null
|
||||
uuid: bfe370a3-531b-4855-bbe6-ad739f578844
|
||||
params:
|
||||
searchType: esqlQuery
|
||||
esqlQuery:
|
||||
esql: 'FROM kibana_sample_data_logs | keep bytes, clientip, host, geo.dest | WHERE geo.dest != "GB" | stats sumbytes = sum(bytes) by clientip, host | WHERE sumbytes > 5000 | sort sumbytes desc | limit 10'
|
||||
timeField: "@timestamp"
|
||||
timeWindowSize: 1
|
||||
timeWindowUnit: d
|
||||
size: 0
|
||||
thresholdComparator: ">"
|
||||
threshold:
|
||||
- 0
|
||||
excludeHitsFromPreviousRun": true,
|
||||
aggType: count
|
||||
groupBy: all
|
||||
scheduled_task_id: e0d62360-78e8-11ee-9177-f7d404c8c945
|
||||
created_by: elastic
|
||||
updated_by: elastic",
|
||||
created_at: '2023-11-01T19:00:10.453Z'
|
||||
updated_at: '2023-11-01T19:00:10.453Z'
|
||||
api_key_owner: elastic
|
||||
api_key_created_by_user: false
|
||||
throttle: null
|
||||
mute_all: false
|
||||
notify_when: null
|
||||
muted_alert_ids: []
|
||||
execution_status:
|
||||
status: pending
|
||||
last_execution_date: '2023-11-01T19:00:10.453Z'
|
||||
revision: 0
|
||||
running: false
|
|
@ -0,0 +1,24 @@
|
|||
summary: Elasticsearch query rule (KQL)
|
||||
description: Create an Elasticsearch query rule that uses Kibana query language (KQL).
|
||||
value:
|
||||
consumer: alerts
|
||||
name: my Elasticsearch query KQL rule
|
||||
params:
|
||||
aggType: count
|
||||
excludeHitsFromPreviousRun: true
|
||||
groupBy: all
|
||||
searchConfiguration:
|
||||
query:
|
||||
query: '""geo.src : "US" ""'
|
||||
language: kuery
|
||||
index: 90943e30-9a47-11e8-b64d-95841ca0b247
|
||||
searchType: searchSource
|
||||
size: 100
|
||||
threshold:
|
||||
- 1000
|
||||
thresholdComparator: ">"
|
||||
timeWindowSize: 5
|
||||
timeWindowUnit: m
|
||||
rule_type_id: .es-query
|
||||
schedule:
|
||||
interval: 1m
|
|
@ -0,0 +1,44 @@
|
|||
summary: Elasticsearch query rule (KQL)
|
||||
description: The response for successfully creating an Elasticsearch query rule that uses Kibana query language (KQL).
|
||||
value:
|
||||
id: 7bd506d0-2284-11ee-8fad-6101956ced88
|
||||
enabled: true
|
||||
name: my Elasticsearch query KQL rule"
|
||||
tags: []
|
||||
rule_type_id: .es-query
|
||||
consumer: alerts
|
||||
schedule:
|
||||
interval: 1m
|
||||
actions: []
|
||||
params:
|
||||
searchConfiguration:
|
||||
query:
|
||||
query: '""geo.src : "US" ""'
|
||||
language: kuery
|
||||
index: 90943e30-9a47-11e8-b64d-95841ca0b247
|
||||
searchType: searchSource
|
||||
timeWindowSize: 5
|
||||
timeWindowUnit: m
|
||||
threshold:
|
||||
- 1000
|
||||
thresholdComparator: ">"
|
||||
size: 100
|
||||
aggType: count
|
||||
groupBy: all
|
||||
excludeHitsFromPreviousRun: true
|
||||
created_by: elastic
|
||||
updated_by: elastic
|
||||
created_at: '2023-07-14T20:24:50.729Z'
|
||||
updated_at: '2023-07-14T20:24:50.729Z'
|
||||
api_key_owner: elastic
|
||||
api_key_created_by_user: false
|
||||
throttle: null
|
||||
notify_when: null
|
||||
mute_all: false
|
||||
muted_alert_ids: []
|
||||
scheduled_task_id: 7bd506d0-2284-11ee-8fad-6101956ced88
|
||||
execution_status:
|
||||
status: pending
|
||||
last_execution_date: '2023-07-14T20:24:50.729Z'
|
||||
revision: 0
|
||||
running: false
|
|
@ -0,0 +1,38 @@
|
|||
summary: Elasticsearch query rule (DSL)
|
||||
description: >
|
||||
Create an Elasticsearch query rule that uses Elasticsearch query domain specific language (DSL) to define its query and a server log connector to send notifications.
|
||||
value:
|
||||
actions:
|
||||
- group: query matched
|
||||
params:
|
||||
level: info
|
||||
message: "The system has detected {{alerts.new.count}} new, {{alerts.ongoing.count}} ongoing, and {{alerts.recovered.count}} recovered alerts."
|
||||
id: fdbece50-406c-11ee-850e-c71febc4ca7f
|
||||
frequency:
|
||||
throttle: "1d"
|
||||
summary: true
|
||||
notify_when: onThrottleInterval
|
||||
- group: recovered
|
||||
params:
|
||||
level: info
|
||||
message: Recovered
|
||||
id: fdbece50-406c-11ee-850e-c71febc4ca7f
|
||||
frequency:
|
||||
summary: false
|
||||
notify_when: onActionGroupChange
|
||||
consumer: alerts
|
||||
name: my Elasticsearch query rule
|
||||
params:
|
||||
esQuery: '"""{"query":{"match_all" : {}}}"""'
|
||||
index:
|
||||
- kibana_sample_data_logs
|
||||
size: 100
|
||||
threshold:
|
||||
- 100
|
||||
thresholdComparator: ">"
|
||||
timeField: "@timestamp"
|
||||
timeWindowSize: 1
|
||||
timeWindowUnit: d
|
||||
rule_type_id: .es-query
|
||||
schedule:
|
||||
interval: 1d
|
|
@ -0,0 +1,65 @@
|
|||
summary: Elasticsearch query rule (DSL)
|
||||
description: The response for successfully creating an Elasticsearch query rule that uses Elasticsearch query domain specific language (DSL).
|
||||
value:
|
||||
id: 58148c70-407f-11ee-850e-c71febc4ca7f
|
||||
enabled: true
|
||||
name: my Elasticsearch query rule
|
||||
tags: []
|
||||
rule_type_id: .es-query
|
||||
consumer: alerts
|
||||
schedule:
|
||||
interval: 1d
|
||||
actions:
|
||||
- group: query matched
|
||||
id: fdbece50-406c-11ee-850e-c71febc4ca7f
|
||||
params:
|
||||
level: info
|
||||
message: "The system has detected {{alerts.new.count}} new, {{alerts.ongoing.count}} ongoing, and {{alerts.recovered.count}} recovered alerts."
|
||||
connector_type_id: .server-log
|
||||
frequency:
|
||||
summary: true
|
||||
notify_when: onThrottleInterval
|
||||
throttle: "1d"
|
||||
uuid: 53f3c2a3-e5d0-4cfa-af3b-6f0881385e78
|
||||
- group: recovered
|
||||
id: fdbece50-406c-11ee-850e-c71febc4ca7f
|
||||
params:
|
||||
level: info
|
||||
message: Recovered
|
||||
connector_type_id: .server-log
|
||||
frequency:
|
||||
summary: false
|
||||
notify_when: onActionGroupChange
|
||||
throttle: null
|
||||
uuid: 2324e45b-c0df-45c7-9d70-4993e30be758
|
||||
params:
|
||||
thresholdComparator: ">"
|
||||
timeWindowSize: 1
|
||||
timeWindowUnit: d
|
||||
threshold:
|
||||
- 100
|
||||
size: 100
|
||||
timeField: "@timestamp"
|
||||
index:
|
||||
- kibana_sample_data_logs
|
||||
esQuery: '"""{"query":{"match_all" : {}}}"""'
|
||||
excludeHitsFromPreviousRun: true
|
||||
aggType: count
|
||||
groupBy: all
|
||||
searchType: esQuery
|
||||
scheduled_task_id: 58148c70-407f-11ee-850e-c71febc4ca7f
|
||||
created_by: elastic
|
||||
updated_by: elastic
|
||||
created_at: '2023-08-22T00:03:38.263Z'
|
||||
updated_at: '2023-08-22T00:03:38.263Z'
|
||||
api_key_owner: elastic
|
||||
api_key_created_by_user: false
|
||||
throttle: null
|
||||
mute_all: false
|
||||
notify_when: null
|
||||
muted_alert_ids: []
|
||||
execution_status:
|
||||
status: pending
|
||||
last_execution_date: '2023-08-22T00:03:38.263Z'
|
||||
revision: 0
|
||||
running: false
|
|
@ -0,0 +1,29 @@
|
|||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
examples:
|
||||
createEsQueryEsqlRuleRequest:
|
||||
$ref: "./es_query/create_es_query_esql_rule_request.yaml"
|
||||
createEsQueryRuleRequest:
|
||||
$ref: "./es_query/create_es_query_rule_request.yaml"
|
||||
createEsQueryKqlRuleRequest:
|
||||
$ref: "./es_query/create_es_query_kql_rule_request.yaml"
|
||||
createIndexThresholdRuleRequest:
|
||||
$ref: "./index_threshold/create_index_threshold_rule_request.yaml"
|
||||
createTrackingContainmentRuleRequest:
|
||||
$ref: "./geo_containment/create_tracking_containment_rule_request.yaml"
|
||||
responses:
|
||||
200:
|
||||
content:
|
||||
application/json:
|
||||
examples:
|
||||
createEsQueryEsqlRuleResponse:
|
||||
$ref: "./es_query/create_es_query_esql_rule_response.yaml"
|
||||
createEsQueryRuleResponse:
|
||||
$ref: "./es_query/create_es_query_rule_response.yaml"
|
||||
createEsQueryKqlRuleResponse:
|
||||
$ref: "./es_query/create_es_query_kql_rule_response.yaml"
|
||||
createIndexThresholdRuleResponse:
|
||||
$ref: "./index_threshold/create_index_threshold_rule_response.yaml"
|
||||
createTrackingContainmentRuleResponse:
|
||||
$ref: "./geo_containment/create_tracking_containment_rule_response.yaml"
|
|
@ -0,0 +1,20 @@
|
|||
summary: Tracking containment rule
|
||||
description: >
|
||||
Create a tracking containment rule that checks when an entity is contained or no longer contained within a boundary.
|
||||
value:
|
||||
consumer: alerts
|
||||
name: my tracking rule
|
||||
params:
|
||||
index: kibana_sample_data_logs
|
||||
dateField": '@timestamp'
|
||||
geoField: geo.coordinates
|
||||
entity: agent.keyword
|
||||
boundaryType: entireIndex
|
||||
boundaryIndexTitle: boundary*
|
||||
boundaryGeoField: location
|
||||
boundaryNameField: name
|
||||
indexId: 90943e30-9a47-11e8-b64d-95841ca0b247
|
||||
boundaryIndexId: 0cd90abf-abe7-44c7-909a-f621bbbcfefc
|
||||
rule_type_id: .geo-containment
|
||||
schedule:
|
||||
interval: 1h
|
|
@ -0,0 +1,51 @@
|
|||
summary: Tracking containment rule
|
||||
description: The response for successfully creating a tracking containment rule.
|
||||
value:
|
||||
id: b6883f9d-5f70-4758-a66e-369d7c26012f
|
||||
name: my tracking rule
|
||||
tags: []
|
||||
enabled: true
|
||||
consumer: alerts
|
||||
throttle: null
|
||||
revision: 1
|
||||
running: false
|
||||
schedule:
|
||||
interval: 1h
|
||||
params:
|
||||
index: kibana_sample_data_logs
|
||||
dateField: '@timestamp'
|
||||
geoField: geo.coordinates
|
||||
entity: agent.keyword
|
||||
boundaryType: entireIndex
|
||||
boundaryIndexTitle: boundary*
|
||||
boundaryGeoField: location
|
||||
boundaryNameField: name
|
||||
indexId: 90943e30-9a47-11e8-b64d-95841ca0b247
|
||||
boundaryIndexId: 0cd90abf-abe7-44c7-909a-f621bbbcfefc
|
||||
rule_type_id: .geo-containment
|
||||
created_by: elastic
|
||||
updated_by: elastic
|
||||
created_at: '2024-02-14T19:52:55.920Z'
|
||||
updated_at: '2024-02-15T03:24:32.574Z'
|
||||
api_key_owner: elastic
|
||||
notify_when: null
|
||||
mute_all: false
|
||||
muted_alert_ids: []
|
||||
scheduled_task_id: b6883f9d-5f70-4758-a66e-369d7c26012f
|
||||
execution_status:
|
||||
status: ok
|
||||
last_execution_date: '2024-02-15T03:25:38.125Z'
|
||||
last_duration: 74
|
||||
actions: []
|
||||
last_run:
|
||||
alerts_count:
|
||||
active: 0
|
||||
new: 0
|
||||
recovered: 0
|
||||
ignored: 0
|
||||
outcome_msg: null
|
||||
outcome_order: 0
|
||||
outcome: succeeded
|
||||
warning: null
|
||||
next_run: '2024-02-15T03:26:38.033Z'
|
||||
api_key_created_by_user: false
|
|
@ -12,6 +12,7 @@ export { ruleParamsSchema, ruleParamsSchemaWithDefaultValue } from './latest';
|
|||
export {
|
||||
ruleParamsSchema as ruleParamsSchemaV1,
|
||||
ruleParamsSchemaWithDefaultValue as ruleParamsSchemaWithDefaultValueV1,
|
||||
createRuleParamsExamples as createRuleParamsExamplesV1,
|
||||
} from './v1';
|
||||
|
||||
export type { RuleParams } from './latest';
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
summary: Index threshold rule
|
||||
description: >
|
||||
Create an index threshold rule that uses a server log connector to send notifications when the threshold is met.
|
||||
value:
|
||||
actions:
|
||||
- id: 48de3460-f401-11ed-9f8e-399c75a2deeb
|
||||
frequency:
|
||||
notify_when: onActionGroupChange
|
||||
summary: false
|
||||
group: threshold met
|
||||
params:
|
||||
level: info
|
||||
message: "Rule '{{rule.name}}' is active for group '{{context.group}}':\n\n- Value: {{context.value}}\n- Conditions Met: {{context.conditions}} over {{rule.params.timeWindowSize}}{{rule.params.timeWindowUnit}}\n- Timestamp: {{context.date}}"
|
||||
alert_delay:
|
||||
active: 3
|
||||
consumer: alerts
|
||||
name: my rule
|
||||
params:
|
||||
aggType: avg
|
||||
termSize: 6
|
||||
thresholdComparator: ">"
|
||||
timeWindowSize: 5
|
||||
timeWindowUnit: m
|
||||
groupBy: top
|
||||
threshold:
|
||||
- 1000
|
||||
index:
|
||||
- .test-index
|
||||
timeField: "@timestamp"
|
||||
aggField: sheet.version
|
||||
termField: name.keyword
|
||||
rule_type_id: .index-threshold
|
||||
schedule:
|
||||
interval: 1m
|
||||
tags:
|
||||
- cpu
|
|
@ -0,0 +1,56 @@
|
|||
summary: Index threshold rule
|
||||
description: The response for successfully creating an index threshold rule.
|
||||
value:
|
||||
actions:
|
||||
- group: threshold met
|
||||
id: dceeb5d0-6b41-11eb-802b-85b0c1bc8ba2
|
||||
uuid: 07aef2a0-9eed-4ef9-94ec-39ba58eb609d
|
||||
connector_type_id: .server-log
|
||||
frequency:
|
||||
notify_when: onActionGroupChange
|
||||
summary: false
|
||||
throttle: null
|
||||
params:
|
||||
level: info
|
||||
message: "Rule {{rule.name}} is active for group {{context.group} :\n\n- Value: {{context.value}}\n- Conditions Met: {{context.conditions}} over {{rule.params.timeWindowSize}}{{rule.params.timeWindowUnit}}\n- Timestamp: {{context.date}}"
|
||||
alert_delay:
|
||||
active: 3
|
||||
api_key_created_by_user: false
|
||||
api_key_owner: elastic
|
||||
consumer: alerts
|
||||
created_at: '2022-06-08T17:20:31.632Z'
|
||||
created_by: elastic
|
||||
enabled: true
|
||||
execution_status:
|
||||
last_execution_date: '2022-06-08T17:20:31.632Z'
|
||||
status: pending
|
||||
id: 41893910-6bca-11eb-9e0d-85d233e3ee35
|
||||
muted_alert_ids: []
|
||||
mute_all: false
|
||||
name: my rule
|
||||
notify_when: null
|
||||
params:
|
||||
aggType: avg
|
||||
termSize: 6
|
||||
thresholdComparator: ">"
|
||||
timeWindowSize: 5
|
||||
timeWindowUnit: m
|
||||
groupBy: top
|
||||
threshold:
|
||||
- 1000
|
||||
index:
|
||||
- ".test-index"
|
||||
timeField: "@timestamp"
|
||||
aggField: sheet.version
|
||||
termField: name.keyword
|
||||
revision: 0
|
||||
rule_type_id: .index-threshold
|
||||
running: false
|
||||
schedule:
|
||||
interval: 1m
|
||||
scheduled_task_id: 425b0800-6bca-11eb-9e0d-85d233e3ee35
|
||||
tags:
|
||||
- cpu
|
||||
throttle: null
|
||||
updated_at: '2022-06-08T17:20:31.632Z'
|
||||
updated_by: elastic
|
|
@ -6,7 +6,7 @@
|
|||
* your election, the "Elastic License 2.0", the "GNU Affero General Public
|
||||
* License v3.0 only", or the "Server Side Public License, v 1".
|
||||
*/
|
||||
|
||||
import path from 'node:path';
|
||||
import type { TypeOf } from '@kbn/config-schema';
|
||||
import { schema } from '@kbn/config-schema';
|
||||
|
||||
|
@ -23,5 +23,8 @@ export const ruleParamsSchemaWithDefaultValue = schema.recordOf(
|
|||
}
|
||||
);
|
||||
|
||||
export const createRuleParamsExamples = () =>
|
||||
path.join(__dirname, 'examples_create_rule_params.yaml');
|
||||
|
||||
export type RuleParams = TypeOf<typeof ruleParamsSchema>;
|
||||
export type RuleParamsWithDefaultValue = TypeOf<typeof ruleParamsSchemaWithDefaultValue>;
|
||||
|
|
|
@ -27,6 +27,7 @@ export {
|
|||
actionSchema as actionSchemaV1,
|
||||
createParamsSchema as createParamsSchemaV1,
|
||||
createBodySchema as createBodySchemaV1,
|
||||
createRuleParamsExamplesV1,
|
||||
} from './schemas/v1';
|
||||
|
||||
export type {
|
||||
|
|
|
@ -6,7 +6,10 @@
|
|||
*/
|
||||
|
||||
import { schema } from '@kbn/config-schema';
|
||||
import { ruleParamsSchemaWithDefaultValueV1 } from '@kbn/response-ops-rule-params';
|
||||
import {
|
||||
ruleParamsSchemaWithDefaultValueV1,
|
||||
createRuleParamsExamplesV1,
|
||||
} from '@kbn/response-ops-rule-params';
|
||||
import { validateDurationV1, validateHoursV1, validateTimezoneV1 } from '../../../validation';
|
||||
import { notifyWhenSchemaV1, alertDelaySchemaV1 } from '../../../response';
|
||||
import { alertsFilterQuerySchemaV1 } from '../../../../alerts_filter_query';
|
||||
|
@ -188,6 +191,8 @@ export const createBodySchema = schema.object({
|
|||
flapping: schema.maybe(schema.nullable(flappingSchemaV1)),
|
||||
});
|
||||
|
||||
export { createRuleParamsExamplesV1 };
|
||||
|
||||
export const createParamsSchema = schema.object({
|
||||
id: schema.maybe(
|
||||
schema.string({
|
||||
|
|
|
@ -11,6 +11,7 @@ export type { FindRulesRequestQuery, FindRulesResponse } from './types/latest';
|
|||
export {
|
||||
findRulesRequestQuerySchema as findRulesRequestQuerySchemaV1,
|
||||
findRulesInternalRequestBodySchema as findRulesInternalRequestBodySchemaV1,
|
||||
findRuleParamsExamples as findRuleParamsExamplesV1,
|
||||
} from './schemas/v1';
|
||||
|
||||
export type {
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
responses:
|
||||
200:
|
||||
content:
|
||||
application/json:
|
||||
examples:
|
||||
findRulesResponse:
|
||||
$ref: './examples_find_rule_response_conditional_action.yaml'
|
||||
findConditionalActionRulesResponse:
|
||||
$ref: './examples_find_rules_response.yaml'
|
|
@ -4,9 +4,11 @@
|
|||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import path from 'node:path';
|
||||
import { schema } from '@kbn/config-schema';
|
||||
|
||||
export const findRuleParamsExamples = () => path.join(__dirname, 'examples_find_rules.yaml');
|
||||
|
||||
export const findRulesRequestQuerySchema = schema.object({
|
||||
per_page: schema.number({
|
||||
defaultValue: 10,
|
||||
|
|
|
@ -26,6 +26,7 @@ export {
|
|||
actionAlertsFilterSchema as actionAlertsFilterSchemaV1,
|
||||
actionSchema as actionSchemaV1,
|
||||
updateBodySchema as updateBodySchemaV1,
|
||||
updateRuleParamsExamples as updateRuleParamsExamplesV1,
|
||||
updateParamsSchema as updateParamsSchemaV1,
|
||||
} from './schemas/v1';
|
||||
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
examples:
|
||||
updateRuleRequest:
|
||||
$ref: './examples_update_rule.request.yaml'
|
||||
responses:
|
||||
200:
|
||||
content:
|
||||
application/json:
|
||||
examples:
|
||||
updateRuleResponse:
|
||||
$ref: './examples_update_rule.response.yaml'
|
|
@ -5,6 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import path from 'node:path';
|
||||
import { schema } from '@kbn/config-schema';
|
||||
import { ruleParamsSchemaWithDefaultValueV1 } from '@kbn/response-ops-rule-params';
|
||||
import { validateDurationV1, validateHoursV1, validateTimezoneV1 } from '../../../validation';
|
||||
|
@ -12,6 +13,8 @@ import { notifyWhenSchemaV1, alertDelaySchemaV1 } from '../../../response';
|
|||
import { alertsFilterQuerySchemaV1 } from '../../../../alerts_filter_query';
|
||||
import { flappingSchemaV1 } from '../../../common';
|
||||
|
||||
export const updateRuleParamsExamples = () => path.join(__dirname, 'examples_update_rule.yaml');
|
||||
|
||||
export const actionFrequencySchema = schema.object({
|
||||
summary: schema.boolean({
|
||||
meta: { description: 'Indicates whether the action is a summary.' },
|
||||
|
@ -121,6 +124,8 @@ export const actionSchema = schema.object(
|
|||
}
|
||||
);
|
||||
|
||||
export const findRuleParamsExamples = () => path.join(__dirname, 'examples_update_rule.yaml');
|
||||
|
||||
export const updateBodySchema = schema.object({
|
||||
name: schema.string({
|
||||
meta: {
|
||||
|
|
|
@ -14,6 +14,7 @@ import type {
|
|||
import {
|
||||
createBodySchemaV1,
|
||||
createParamsSchemaV1,
|
||||
createRuleParamsExamplesV1,
|
||||
} from '../../../../../common/routes/rule/apis/create';
|
||||
import type { RuleParamsV1 } from '../../../../../common/routes/rule/response';
|
||||
import { ruleResponseSchemaV1 } from '../../../../../common/routes/rule/response';
|
||||
|
@ -39,6 +40,7 @@ export const createRuleRoute = ({ router, licenseState, usageCounter }: RouteOpt
|
|||
access: 'public',
|
||||
summary: `Create a rule`,
|
||||
tags: ['oas-tag:alerting'],
|
||||
oasOperationObject: createRuleParamsExamplesV1,
|
||||
},
|
||||
validate: {
|
||||
request: {
|
||||
|
|
|
@ -11,7 +11,10 @@ import type {
|
|||
FindRulesRequestQueryV1,
|
||||
FindRulesResponseV1,
|
||||
} from '../../../../../common/routes/rule/apis/find';
|
||||
import { findRulesRequestQuerySchemaV1 } from '../../../../../common/routes/rule/apis/find';
|
||||
import {
|
||||
findRulesRequestQuerySchemaV1,
|
||||
findRuleParamsExamplesV1,
|
||||
} from '../../../../../common/routes/rule/apis/find';
|
||||
import type { RuleParamsV1 } from '../../../../../common/routes/rule/response';
|
||||
import { ruleResponseSchemaV1 } from '../../../../../common/routes/rule/response';
|
||||
import type { ILicenseState } from '../../../../lib';
|
||||
|
@ -35,6 +38,7 @@ export const findRulesRoute = (
|
|||
access: 'public',
|
||||
summary: 'Get information about rules',
|
||||
tags: ['oas-tag:alerting'],
|
||||
oasOperationObject: findRuleParamsExamplesV1,
|
||||
},
|
||||
validate: {
|
||||
request: {
|
||||
|
|
|
@ -14,6 +14,7 @@ import type {
|
|||
import {
|
||||
updateBodySchemaV1,
|
||||
updateParamsSchemaV1,
|
||||
updateRuleParamsExamplesV1,
|
||||
} from '../../../../../common/routes/rule/apis/update';
|
||||
import type { RuleParamsV1 } from '../../../../../common/routes/rule/response';
|
||||
import { ruleResponseSchemaV1 } from '../../../../../common/routes/rule/response';
|
||||
|
@ -40,6 +41,7 @@ export const updateRuleRoute = (
|
|||
access: 'public',
|
||||
summary: `Update a rule`,
|
||||
tags: ['oas-tag:alerting'],
|
||||
oasOperationObject: updateRuleParamsExamplesV1,
|
||||
},
|
||||
validate: {
|
||||
request: {
|
||||
|
|
11
yarn.lock
11
yarn.lock
|
@ -71,7 +71,7 @@
|
|||
"@jridgewell/gen-mapping" "^0.1.0"
|
||||
"@jridgewell/trace-mapping" "^0.3.9"
|
||||
|
||||
"@apidevtools/json-schema-ref-parser@11.7.2", "@apidevtools/json-schema-ref-parser@^11.5.5":
|
||||
"@apidevtools/json-schema-ref-parser@11.7.2":
|
||||
version "11.7.2"
|
||||
resolved "https://registry.yarnpkg.com/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-11.7.2.tgz#cdf3e0aded21492364a70e193b45b7cf4177f031"
|
||||
integrity sha512-4gY54eEGEstClvEkGnwVkTkrx0sqwemEFG5OSRRn3tD91XH0+Q8XIkYIfo7IwEWPpJZwILb9GUXeShtplRc/eA==
|
||||
|
@ -80,6 +80,15 @@
|
|||
"@types/json-schema" "^7.0.15"
|
||||
js-yaml "^4.1.0"
|
||||
|
||||
"@apidevtools/json-schema-ref-parser@^11.5.5", "@apidevtools/json-schema-ref-parser@^11.9.1":
|
||||
version "11.9.1"
|
||||
resolved "https://registry.yarnpkg.com/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-11.9.1.tgz#51d297224f6ee1dab40dfb2dfe298812b8e0ef9c"
|
||||
integrity sha512-OvyhwtYaWSTfo8NfibmFlgl+pIMaBOmN0OwZ3CPaGscEK3B8FCVDuQ7zgxY8seU/1kfSvNWnyB0DtKJyNLxX7g==
|
||||
dependencies:
|
||||
"@jsdevtools/ono" "^7.1.3"
|
||||
"@types/json-schema" "^7.0.15"
|
||||
js-yaml "^4.1.0"
|
||||
|
||||
"@apidevtools/json-schema-ref-parser@^9.0.6":
|
||||
version "9.0.9"
|
||||
resolved "https://registry.yarnpkg.com/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.0.9.tgz#d720f9256e3609621280584f2b47ae165359268b"
|
||||
|
|
Loading…
Add table
Reference in a new issue