mirror of
https://github.com/elastic/kibana.git
synced 2025-06-27 18:51:07 -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!
|
// Note: this response schema is instantiated lazily to avoid creating schemas that are not needed in most cases!
|
||||||
const fooResourceResponse = () => {
|
const fooResourceResponse = () => {
|
||||||
return schema.object({
|
return schema.object({
|
||||||
id: schema.string({
|
id: schema.string({
|
||||||
maxLength: 20,
|
maxLength: 20,
|
||||||
meta: { description: 'Add a description.' }
|
meta: { description: 'Add a description.' }
|
||||||
}),
|
}),
|
||||||
|
@ -129,7 +129,7 @@ function registerFooRoute(router: IRouter, docLinks: DoclinksStart) {
|
||||||
version: '2023-10-31',
|
version: '2023-10-31',
|
||||||
validate: {
|
validate: {
|
||||||
request: {
|
request: {
|
||||||
body: ,
|
body: fooResource,
|
||||||
},
|
},
|
||||||
response: {
|
response: {
|
||||||
200: {
|
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
|
#### 3. Generating OAS
|
||||||
|
|
||||||
See <a href="#how-do-i-see-my-http-apis-oas">this section</a> about viewing your HTTP APIs 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": {
|
"requestBody": {
|
||||||
"content": {
|
"content": {
|
||||||
"application/json": {
|
"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": {
|
"schema": {
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"properties": {
|
"properties": {
|
||||||
|
@ -2073,6 +2273,339 @@
|
||||||
"200": {
|
"200": {
|
||||||
"content": {
|
"content": {
|
||||||
"application/json": {
|
"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": {
|
"schema": {
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"properties": {
|
"properties": {
|
||||||
|
@ -2970,6 +3503,50 @@
|
||||||
"requestBody": {
|
"requestBody": {
|
||||||
"content": {
|
"content": {
|
||||||
"application/json": {
|
"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": {
|
"schema": {
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"properties": {
|
"properties": {
|
||||||
|
@ -3249,6 +3826,86 @@
|
||||||
"200": {
|
"200": {
|
||||||
"content": {
|
"content": {
|
||||||
"application/json": {
|
"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": {
|
"schema": {
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"properties": {
|
"properties": {
|
||||||
|
@ -4861,6 +5518,257 @@
|
||||||
"200": {
|
"200": {
|
||||||
"content": {
|
"content": {
|
||||||
"application/json": {
|
"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": {
|
"schema": {
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|
|
@ -1777,6 +1777,206 @@
|
||||||
"requestBody": {
|
"requestBody": {
|
||||||
"content": {
|
"content": {
|
||||||
"application/json": {
|
"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": {
|
"schema": {
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"properties": {
|
"properties": {
|
||||||
|
@ -2073,6 +2273,339 @@
|
||||||
"200": {
|
"200": {
|
||||||
"content": {
|
"content": {
|
||||||
"application/json": {
|
"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": {
|
"schema": {
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"properties": {
|
"properties": {
|
||||||
|
@ -2970,6 +3503,50 @@
|
||||||
"requestBody": {
|
"requestBody": {
|
||||||
"content": {
|
"content": {
|
||||||
"application/json": {
|
"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": {
|
"schema": {
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"properties": {
|
"properties": {
|
||||||
|
@ -3249,6 +3826,86 @@
|
||||||
"200": {
|
"200": {
|
||||||
"content": {
|
"content": {
|
||||||
"application/json": {
|
"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": {
|
"schema": {
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"properties": {
|
"properties": {
|
||||||
|
@ -4861,6 +5518,257 @@
|
||||||
"200": {
|
"200": {
|
||||||
"content": {
|
"content": {
|
||||||
"application/json": {
|
"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": {
|
"schema": {
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"properties": {
|
"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
|
title: Overlays for the alerting rule examples and parameters
|
||||||
version: 0.0.1
|
version: 0.0.1
|
||||||
actions:
|
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
|
# Fix some optional path parameters
|
||||||
- target: "$.paths['/api/alerting/rule/{id}']['post'].parameters[?(@.name=='id')]"
|
- target: "$.paths['/api/alerting/rule/{id}']['post'].parameters[?(@.name=='id')]"
|
||||||
description: Remove optional indicator from path parameter
|
description: Remove optional indicator from path parameter
|
||||||
|
|
|
@ -103,6 +103,7 @@
|
||||||
"globby/fast-glob": "^3.3.2"
|
"globby/fast-glob": "^3.3.2"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@apidevtools/json-schema-ref-parser": "^11.9.1",
|
||||||
"@appland/sql-parser": "^1.5.1",
|
"@appland/sql-parser": "^1.5.1",
|
||||||
"@aws-crypto/sha256-js": "^5.2.0",
|
"@aws-crypto/sha256-js": "^5.2.0",
|
||||||
"@aws-crypto/util": "^5.2.0",
|
"@aws-crypto/util": "^5.2.0",
|
||||||
|
|
|
@ -611,6 +611,7 @@
|
||||||
"fp-ts",
|
"fp-ts",
|
||||||
"getos",
|
"getos",
|
||||||
"joi-to-json",
|
"joi-to-json",
|
||||||
|
"@apidevtools/json-schema-ref-parser",
|
||||||
"json5",
|
"json5",
|
||||||
"load-json-file",
|
"load-json-file",
|
||||||
"mock-fs",
|
"mock-fs",
|
||||||
|
|
|
@ -304,7 +304,7 @@ export class HttpService
|
||||||
mergeMap(async () => {
|
mergeMap(async () => {
|
||||||
try {
|
try {
|
||||||
// Potentially quite expensive
|
// Potentially quite expensive
|
||||||
const result = generateOpenApiDocument(
|
const result = await generateOpenApiDocument(
|
||||||
this.httpServer.getRouters({ pluginId: query.pluginId }),
|
this.httpServer.getRouters({ pluginId: query.pluginId }),
|
||||||
{
|
{
|
||||||
baseUrl,
|
baseUrl,
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
* License v3.0 only", or the "Server Side Public License, v 1".
|
* 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';
|
import type { RouteValidator } from './route_validator';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -387,6 +389,37 @@ export interface RouteConfigOptions<Method extends RouteMethod> {
|
||||||
*/
|
*/
|
||||||
deprecated?: RouteDeprecationInfo;
|
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
|
* Whether this route should be treated as "invisible" and excluded from router
|
||||||
* OAS introspection.
|
* OAS introspection.
|
||||||
|
|
|
@ -34,9 +34,17 @@ export type VersionedRouteConfig<Method extends RouteMethod> = Omit<
|
||||||
RouteConfig<unknown, unknown, unknown, Method>,
|
RouteConfig<unknown, unknown, unknown, Method>,
|
||||||
'validate' | 'options'
|
'validate' | 'options'
|
||||||
> & {
|
> & {
|
||||||
options?: Omit<
|
options?: Pick<
|
||||||
RouteConfigOptions<Method>,
|
RouteConfigOptions<Method>,
|
||||||
'access' | 'description' | 'summary' | 'deprecated' | 'discontinued'
|
| 'authRequired'
|
||||||
|
| 'xsrfRequired'
|
||||||
|
| 'tags'
|
||||||
|
| 'body'
|
||||||
|
| 'timeout'
|
||||||
|
| 'excludeFromOAS'
|
||||||
|
| 'excludeFromRateLimiter'
|
||||||
|
| 'httpResource'
|
||||||
|
| 'availability'
|
||||||
>;
|
>;
|
||||||
/** See {@link RouteConfigOptions<RouteMethod>['access']} */
|
/** See {@link RouteConfigOptions<RouteMethod>['access']} */
|
||||||
access: Exclude<RouteConfigOptions<Method>['access'], undefined>;
|
access: Exclude<RouteConfigOptions<Method>['access'], undefined>;
|
||||||
|
@ -342,6 +350,11 @@ export interface AddVersionOpts<P, Q, B> {
|
||||||
|
|
||||||
options?: {
|
options?: {
|
||||||
deprecated?: RouteDeprecationInfo;
|
deprecated?: RouteDeprecationInfo;
|
||||||
|
/**
|
||||||
|
* @public
|
||||||
|
* {@inheritdoc RouteConfigOptions['oasOperationObject']}
|
||||||
|
*/
|
||||||
|
oasOperationObject?: RouteConfigOptions<RouteMethod>['oasOperationObject'];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { schema, Type } from '@kbn/config-schema';
|
import { schema, Type } from '@kbn/config-schema';
|
||||||
|
import { get } from 'lodash';
|
||||||
import { generateOpenApiDocument } from './generate_oas';
|
import { generateOpenApiDocument } from './generate_oas';
|
||||||
import { createTestRouters, createRouter, createVersionedRouter } from './generate_oas.test.util';
|
import { createTestRouters, createRouter, createVersionedRouter } from './generate_oas.test.util';
|
||||||
import {
|
import {
|
||||||
|
@ -23,7 +24,7 @@ interface RecursiveType {
|
||||||
|
|
||||||
describe('generateOpenApiDocument', () => {
|
describe('generateOpenApiDocument', () => {
|
||||||
describe('@kbn/config-schema', () => {
|
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({
|
const [routers, versionedRouters] = createTestRouters({
|
||||||
routers: {
|
routers: {
|
||||||
testRouter: {
|
testRouter: {
|
||||||
|
@ -34,7 +35,7 @@ describe('generateOpenApiDocument', () => {
|
||||||
bodySchema: createSharedConfigSchema(),
|
bodySchema: createSharedConfigSchema(),
|
||||||
});
|
});
|
||||||
expect(
|
expect(
|
||||||
generateOpenApiDocument(
|
await generateOpenApiDocument(
|
||||||
{
|
{
|
||||||
routers,
|
routers,
|
||||||
versionedRouters,
|
versionedRouters,
|
||||||
|
@ -48,7 +49,7 @@ describe('generateOpenApiDocument', () => {
|
||||||
).toEqual(sharedOas);
|
).toEqual(sharedOas);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('generates the expected OpenAPI document', () => {
|
it('generates the expected OpenAPI document', async () => {
|
||||||
const [routers, versionedRouters] = createTestRouters({
|
const [routers, versionedRouters] = createTestRouters({
|
||||||
routers: {
|
routers: {
|
||||||
testRouter: {
|
testRouter: {
|
||||||
|
@ -80,7 +81,7 @@ describe('generateOpenApiDocument', () => {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
expect(
|
expect(
|
||||||
generateOpenApiDocument(
|
await generateOpenApiDocument(
|
||||||
{
|
{
|
||||||
routers,
|
routers,
|
||||||
versionedRouters,
|
versionedRouters,
|
||||||
|
@ -94,7 +95,7 @@ describe('generateOpenApiDocument', () => {
|
||||||
).toMatchSnapshot();
|
).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 sharedIdSchema = schema.string({ minLength: 1, meta: { description: 'test' } });
|
||||||
const sharedNameSchema = schema.string({ minLength: 1 });
|
const sharedNameSchema = schema.string({ minLength: 1 });
|
||||||
const otherSchema = schema.object(
|
const otherSchema = schema.object(
|
||||||
|
@ -102,7 +103,7 @@ describe('generateOpenApiDocument', () => {
|
||||||
{ meta: { id: 'foo' } }
|
{ meta: { id: 'foo' } }
|
||||||
);
|
);
|
||||||
expect(
|
expect(
|
||||||
generateOpenApiDocument(
|
await generateOpenApiDocument(
|
||||||
{
|
{
|
||||||
routers: [
|
routers: [
|
||||||
createRouter({
|
createRouter({
|
||||||
|
@ -139,7 +140,7 @@ describe('generateOpenApiDocument', () => {
|
||||||
).toMatchSnapshot();
|
).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('handles recursive schemas', () => {
|
it('handles recursive schemas', async () => {
|
||||||
const id = 'recursive';
|
const id = 'recursive';
|
||||||
const recursiveSchema: Type<RecursiveType> = schema.object(
|
const recursiveSchema: Type<RecursiveType> = schema.object(
|
||||||
{
|
{
|
||||||
|
@ -149,7 +150,7 @@ describe('generateOpenApiDocument', () => {
|
||||||
{ meta: { id } }
|
{ meta: { id } }
|
||||||
);
|
);
|
||||||
expect(
|
expect(
|
||||||
generateOpenApiDocument(
|
await generateOpenApiDocument(
|
||||||
{
|
{
|
||||||
routers: [
|
routers: [
|
||||||
createRouter({
|
createRouter({
|
||||||
|
@ -187,7 +188,7 @@ describe('generateOpenApiDocument', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Zod', () => {
|
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({
|
const [routers, versionedRouters] = createTestRouters({
|
||||||
routers: { testRouter: { routes: [{ method: 'get' }, { method: 'post' }] } },
|
routers: { testRouter: { routes: [{ method: 'get' }, { method: 'post' }] } },
|
||||||
versionedRouters: { testVersionedRouter: { routes: [{}] } },
|
versionedRouters: { testVersionedRouter: { routes: [{}] } },
|
||||||
|
@ -195,7 +196,7 @@ describe('generateOpenApiDocument', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
generateOpenApiDocument(
|
await generateOpenApiDocument(
|
||||||
{
|
{
|
||||||
routers,
|
routers,
|
||||||
versionedRouters,
|
versionedRouters,
|
||||||
|
@ -211,9 +212,9 @@ describe('generateOpenApiDocument', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('unknown schema/validation', () => {
|
describe('unknown schema/validation', () => {
|
||||||
it('produces the expected output', () => {
|
it('produces the expected output', async () => {
|
||||||
expect(
|
expect(
|
||||||
generateOpenApiDocument(
|
await generateOpenApiDocument(
|
||||||
{
|
{
|
||||||
routers: [
|
routers: [
|
||||||
createRouter({
|
createRouter({
|
||||||
|
@ -275,7 +276,7 @@ describe('generateOpenApiDocument', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('tags', () => {
|
describe('tags', () => {
|
||||||
it('handles tags as expected', () => {
|
it('handles tags as expected', async () => {
|
||||||
const [routers, versionedRouters] = createTestRouters({
|
const [routers, versionedRouters] = createTestRouters({
|
||||||
routers: {
|
routers: {
|
||||||
testRouter1: {
|
testRouter1: {
|
||||||
|
@ -314,7 +315,7 @@ describe('generateOpenApiDocument', () => {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const result = generateOpenApiDocument(
|
const result = await generateOpenApiDocument(
|
||||||
{
|
{
|
||||||
routers,
|
routers,
|
||||||
versionedRouters,
|
versionedRouters,
|
||||||
|
@ -337,7 +338,7 @@ describe('generateOpenApiDocument', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('availability', () => {
|
describe('availability', () => {
|
||||||
it('creates the expected availability entries', () => {
|
it('creates the expected availability entries', async () => {
|
||||||
const [routers, versionedRouters] = createTestRouters({
|
const [routers, versionedRouters] = createTestRouters({
|
||||||
routers: {
|
routers: {
|
||||||
testRouter1: {
|
testRouter1: {
|
||||||
|
@ -391,7 +392,7 @@ describe('generateOpenApiDocument', () => {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const result = generateOpenApiDocument(
|
const result = await generateOpenApiDocument(
|
||||||
{
|
{
|
||||||
routers,
|
routers,
|
||||||
versionedRouters,
|
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;
|
filters?: GenerateOpenApiDocumentOptionsFilters;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const generateOpenApiDocument = (
|
export const generateOpenApiDocument = async (
|
||||||
appRouters: { routers: Router[]; versionedRouters: CoreVersionedRouter[] },
|
appRouters: { routers: Router[]; versionedRouters: CoreVersionedRouter[] },
|
||||||
opts: GenerateOpenApiDocumentOptions
|
opts: GenerateOpenApiDocumentOptions
|
||||||
): OpenAPIV3.Document => {
|
): Promise<OpenAPIV3.Document> => {
|
||||||
let { filters = { access: 'public' } } = opts;
|
let { filters = { access: 'public' } } = opts;
|
||||||
if (filters.access === 'public' && !filters.version) {
|
if (filters.access === 'public' && !filters.version) {
|
||||||
filters = { ...filters, version: SERVERLESS_VERSION_2023_10_31 };
|
filters = { ...filters, version: SERVERLESS_VERSION_2023_10_31 };
|
||||||
|
@ -51,11 +51,11 @@ export const generateOpenApiDocument = (
|
||||||
const paths: OpenAPIV3.PathsObject = {};
|
const paths: OpenAPIV3.PathsObject = {};
|
||||||
const getOpId = createOpIdGenerator();
|
const getOpId = createOpIdGenerator();
|
||||||
for (const router of appRouters.routers) {
|
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);
|
Object.assign(paths, result.paths);
|
||||||
}
|
}
|
||||||
for (const router of appRouters.versionedRouters) {
|
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);
|
Object.assign(paths, result.paths);
|
||||||
}
|
}
|
||||||
const tags = buildGlobalTags(paths, opts.tags);
|
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;
|
} as unknown as Router;
|
||||||
|
|
||||||
it('only provides routes for version 2023-10-31', () => {
|
it('only provides routes for version 2023-10-31', async () => {
|
||||||
const result1 = processRouter(testRouter, new OasConverter(), createOpIdGenerator(), {
|
const result1 = await processRouter(testRouter, new OasConverter(), createOpIdGenerator(), {
|
||||||
version: '2023-10-31',
|
version: '2023-10-31',
|
||||||
access: 'public',
|
access: 'public',
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(Object.keys(result1.paths!)).toHaveLength(5);
|
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',
|
version: '2024-10-31',
|
||||||
access: 'public',
|
access: 'public',
|
||||||
});
|
});
|
||||||
expect(Object.keys(result2.paths!)).toHaveLength(0);
|
expect(Object.keys(result2.paths!)).toHaveLength(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('updates description with privileges required', () => {
|
it('updates description with privileges required', async () => {
|
||||||
const result = processRouter(testRouter, new OasConverter(), createOpIdGenerator(), {
|
const result = await processRouter(testRouter, new OasConverter(), createOpIdGenerator(), {
|
||||||
version: '2023-10-31',
|
version: '2023-10-31',
|
||||||
access: 'public',
|
access: 'public',
|
||||||
});
|
});
|
||||||
|
|
|
@ -28,8 +28,9 @@ import {
|
||||||
import type { GenerateOpenApiDocumentOptionsFilters } from './generate_oas';
|
import type { GenerateOpenApiDocumentOptionsFilters } from './generate_oas';
|
||||||
import type { CustomOperationObject, InternalRouterRoute } from './type';
|
import type { CustomOperationObject, InternalRouterRoute } from './type';
|
||||||
import { extractAuthzDescription } from './extract_authz_description';
|
import { extractAuthzDescription } from './extract_authz_description';
|
||||||
|
import { mergeOperation } from './merge_operation';
|
||||||
|
|
||||||
export const processRouter = (
|
export const processRouter = async (
|
||||||
appRouter: Router,
|
appRouter: Router,
|
||||||
converter: OasConverter,
|
converter: OasConverter,
|
||||||
getOpId: GetOpId,
|
getOpId: GetOpId,
|
||||||
|
@ -99,6 +100,10 @@ export const processRouter = (
|
||||||
|
|
||||||
setXState(route.options.availability, operation);
|
setXState(route.options.availability, operation);
|
||||||
|
|
||||||
|
if (route.options.oasOperationObject) {
|
||||||
|
await mergeOperation(route.options.oasOperationObject(), operation);
|
||||||
|
}
|
||||||
|
|
||||||
const path: OpenAPIV3.PathItemObject = {
|
const path: OpenAPIV3.PathItemObject = {
|
||||||
[route.method]: operation,
|
[route.method]: operation,
|
||||||
};
|
};
|
||||||
|
|
|
@ -121,8 +121,8 @@ describe('extractVersionedResponses', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('processVersionedRouter', () => {
|
describe('processVersionedRouter', () => {
|
||||||
it('correctly extracts the version based on the version filter', () => {
|
it('correctly extracts the version based on the version filter', async () => {
|
||||||
const baseCase = processVersionedRouter(
|
const baseCase = await processVersionedRouter(
|
||||||
{ getRoutes: () => [createTestRoute()] } as unknown as CoreVersionedRouter,
|
{ getRoutes: () => [createTestRoute()] } as unknown as CoreVersionedRouter,
|
||||||
new OasConverter(),
|
new OasConverter(),
|
||||||
createOpIdGenerator(),
|
createOpIdGenerator(),
|
||||||
|
@ -133,7 +133,7 @@ describe('processVersionedRouter', () => {
|
||||||
'application/test+json',
|
'application/test+json',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const filteredCase = processVersionedRouter(
|
const filteredCase = await processVersionedRouter(
|
||||||
{ getRoutes: () => [createTestRoute()] } as unknown as CoreVersionedRouter,
|
{ getRoutes: () => [createTestRoute()] } as unknown as CoreVersionedRouter,
|
||||||
new OasConverter(),
|
new OasConverter(),
|
||||||
createOpIdGenerator(),
|
createOpIdGenerator(),
|
||||||
|
@ -144,8 +144,8 @@ describe('processVersionedRouter', () => {
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('correctly updates the authz description for routes that require privileges', () => {
|
it('correctly updates the authz description for routes that require privileges', async () => {
|
||||||
const results = processVersionedRouter(
|
const results = await processVersionedRouter(
|
||||||
{ getRoutes: () => [createTestRoute()] } as unknown as CoreVersionedRouter,
|
{ getRoutes: () => [createTestRoute()] } as unknown as CoreVersionedRouter,
|
||||||
new OasConverter(),
|
new OasConverter(),
|
||||||
createOpIdGenerator(),
|
createOpIdGenerator(),
|
||||||
|
|
|
@ -31,8 +31,9 @@ import {
|
||||||
GetOpId,
|
GetOpId,
|
||||||
} from './util';
|
} from './util';
|
||||||
import { isReferenceObject } from './oas_converter/common';
|
import { isReferenceObject } from './oas_converter/common';
|
||||||
|
import { mergeOperation } from './merge_operation';
|
||||||
|
|
||||||
export const processVersionedRouter = (
|
export const processVersionedRouter = async (
|
||||||
appRouter: CoreVersionedRouter,
|
appRouter: CoreVersionedRouter,
|
||||||
converter: OasConverter,
|
converter: OasConverter,
|
||||||
getOpId: GetOpId,
|
getOpId: GetOpId,
|
||||||
|
@ -130,6 +131,10 @@ export const processVersionedRouter = (
|
||||||
|
|
||||||
setXState(route.options.options?.availability, operation);
|
setXState(route.options.options?.availability, operation);
|
||||||
|
|
||||||
|
if (handler.options.options?.oasOperationObject) {
|
||||||
|
await mergeOperation(handler.options.options.oasOperationObject(), operation);
|
||||||
|
}
|
||||||
|
|
||||||
const path: OpenAPIV3.PathItemObject = {
|
const path: OpenAPIV3.PathItemObject = {
|
||||||
[route.method]: operation,
|
[route.method]: operation,
|
||||||
};
|
};
|
||||||
|
|
|
@ -19,5 +19,6 @@
|
||||||
"@kbn/config-schema",
|
"@kbn/config-schema",
|
||||||
"@kbn/zod",
|
"@kbn/zod",
|
||||||
"@kbn/zod-helpers",
|
"@kbn/zod-helpers",
|
||||||
|
"@kbn/utility-types",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -203,7 +203,6 @@ export function registerRoutes<TDependencies extends Record<string, any>>({
|
||||||
access,
|
access,
|
||||||
summary: options.summary,
|
summary: options.summary,
|
||||||
description: options.description,
|
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'),
|
options: omit(options, 'access', 'description', 'summary', 'deprecated', 'discontinued'),
|
||||||
security,
|
security,
|
||||||
}).addVersion(
|
}).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 {
|
export {
|
||||||
ruleParamsSchema as ruleParamsSchemaV1,
|
ruleParamsSchema as ruleParamsSchemaV1,
|
||||||
ruleParamsSchemaWithDefaultValue as ruleParamsSchemaWithDefaultValueV1,
|
ruleParamsSchemaWithDefaultValue as ruleParamsSchemaWithDefaultValueV1,
|
||||||
|
createRuleParamsExamples as createRuleParamsExamplesV1,
|
||||||
} from './v1';
|
} from './v1';
|
||||||
|
|
||||||
export type { RuleParams } from './latest';
|
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
|
* your election, the "Elastic License 2.0", the "GNU Affero General Public
|
||||||
* License v3.0 only", or the "Server Side Public License, v 1".
|
* 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 type { TypeOf } from '@kbn/config-schema';
|
||||||
import { schema } 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 RuleParams = TypeOf<typeof ruleParamsSchema>;
|
||||||
export type RuleParamsWithDefaultValue = TypeOf<typeof ruleParamsSchemaWithDefaultValue>;
|
export type RuleParamsWithDefaultValue = TypeOf<typeof ruleParamsSchemaWithDefaultValue>;
|
||||||
|
|
|
@ -27,6 +27,7 @@ export {
|
||||||
actionSchema as actionSchemaV1,
|
actionSchema as actionSchemaV1,
|
||||||
createParamsSchema as createParamsSchemaV1,
|
createParamsSchema as createParamsSchemaV1,
|
||||||
createBodySchema as createBodySchemaV1,
|
createBodySchema as createBodySchemaV1,
|
||||||
|
createRuleParamsExamplesV1,
|
||||||
} from './schemas/v1';
|
} from './schemas/v1';
|
||||||
|
|
||||||
export type {
|
export type {
|
||||||
|
|
|
@ -6,7 +6,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { schema } from '@kbn/config-schema';
|
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 { validateDurationV1, validateHoursV1, validateTimezoneV1 } from '../../../validation';
|
||||||
import { notifyWhenSchemaV1, alertDelaySchemaV1 } from '../../../response';
|
import { notifyWhenSchemaV1, alertDelaySchemaV1 } from '../../../response';
|
||||||
import { alertsFilterQuerySchemaV1 } from '../../../../alerts_filter_query';
|
import { alertsFilterQuerySchemaV1 } from '../../../../alerts_filter_query';
|
||||||
|
@ -188,6 +191,8 @@ export const createBodySchema = schema.object({
|
||||||
flapping: schema.maybe(schema.nullable(flappingSchemaV1)),
|
flapping: schema.maybe(schema.nullable(flappingSchemaV1)),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export { createRuleParamsExamplesV1 };
|
||||||
|
|
||||||
export const createParamsSchema = schema.object({
|
export const createParamsSchema = schema.object({
|
||||||
id: schema.maybe(
|
id: schema.maybe(
|
||||||
schema.string({
|
schema.string({
|
||||||
|
|
|
@ -11,6 +11,7 @@ export type { FindRulesRequestQuery, FindRulesResponse } from './types/latest';
|
||||||
export {
|
export {
|
||||||
findRulesRequestQuerySchema as findRulesRequestQuerySchemaV1,
|
findRulesRequestQuerySchema as findRulesRequestQuerySchemaV1,
|
||||||
findRulesInternalRequestBodySchema as findRulesInternalRequestBodySchemaV1,
|
findRulesInternalRequestBodySchema as findRulesInternalRequestBodySchemaV1,
|
||||||
|
findRuleParamsExamples as findRuleParamsExamplesV1,
|
||||||
} from './schemas/v1';
|
} from './schemas/v1';
|
||||||
|
|
||||||
export type {
|
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; you may not use this file except in compliance with the Elastic License
|
||||||
* 2.0.
|
* 2.0.
|
||||||
*/
|
*/
|
||||||
|
import path from 'node:path';
|
||||||
import { schema } from '@kbn/config-schema';
|
import { schema } from '@kbn/config-schema';
|
||||||
|
|
||||||
|
export const findRuleParamsExamples = () => path.join(__dirname, 'examples_find_rules.yaml');
|
||||||
|
|
||||||
export const findRulesRequestQuerySchema = schema.object({
|
export const findRulesRequestQuerySchema = schema.object({
|
||||||
per_page: schema.number({
|
per_page: schema.number({
|
||||||
defaultValue: 10,
|
defaultValue: 10,
|
||||||
|
|
|
@ -26,6 +26,7 @@ export {
|
||||||
actionAlertsFilterSchema as actionAlertsFilterSchemaV1,
|
actionAlertsFilterSchema as actionAlertsFilterSchemaV1,
|
||||||
actionSchema as actionSchemaV1,
|
actionSchema as actionSchemaV1,
|
||||||
updateBodySchema as updateBodySchemaV1,
|
updateBodySchema as updateBodySchemaV1,
|
||||||
|
updateRuleParamsExamples as updateRuleParamsExamplesV1,
|
||||||
updateParamsSchema as updateParamsSchemaV1,
|
updateParamsSchema as updateParamsSchemaV1,
|
||||||
} from './schemas/v1';
|
} 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.
|
* 2.0.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import path from 'node:path';
|
||||||
import { schema } from '@kbn/config-schema';
|
import { schema } from '@kbn/config-schema';
|
||||||
import { ruleParamsSchemaWithDefaultValueV1 } from '@kbn/response-ops-rule-params';
|
import { ruleParamsSchemaWithDefaultValueV1 } from '@kbn/response-ops-rule-params';
|
||||||
import { validateDurationV1, validateHoursV1, validateTimezoneV1 } from '../../../validation';
|
import { validateDurationV1, validateHoursV1, validateTimezoneV1 } from '../../../validation';
|
||||||
|
@ -12,6 +13,8 @@ import { notifyWhenSchemaV1, alertDelaySchemaV1 } from '../../../response';
|
||||||
import { alertsFilterQuerySchemaV1 } from '../../../../alerts_filter_query';
|
import { alertsFilterQuerySchemaV1 } from '../../../../alerts_filter_query';
|
||||||
import { flappingSchemaV1 } from '../../../common';
|
import { flappingSchemaV1 } from '../../../common';
|
||||||
|
|
||||||
|
export const updateRuleParamsExamples = () => path.join(__dirname, 'examples_update_rule.yaml');
|
||||||
|
|
||||||
export const actionFrequencySchema = schema.object({
|
export const actionFrequencySchema = schema.object({
|
||||||
summary: schema.boolean({
|
summary: schema.boolean({
|
||||||
meta: { description: 'Indicates whether the action is a summary.' },
|
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({
|
export const updateBodySchema = schema.object({
|
||||||
name: schema.string({
|
name: schema.string({
|
||||||
meta: {
|
meta: {
|
||||||
|
|
|
@ -14,6 +14,7 @@ import type {
|
||||||
import {
|
import {
|
||||||
createBodySchemaV1,
|
createBodySchemaV1,
|
||||||
createParamsSchemaV1,
|
createParamsSchemaV1,
|
||||||
|
createRuleParamsExamplesV1,
|
||||||
} from '../../../../../common/routes/rule/apis/create';
|
} from '../../../../../common/routes/rule/apis/create';
|
||||||
import type { RuleParamsV1 } from '../../../../../common/routes/rule/response';
|
import type { RuleParamsV1 } from '../../../../../common/routes/rule/response';
|
||||||
import { ruleResponseSchemaV1 } 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',
|
access: 'public',
|
||||||
summary: `Create a rule`,
|
summary: `Create a rule`,
|
||||||
tags: ['oas-tag:alerting'],
|
tags: ['oas-tag:alerting'],
|
||||||
|
oasOperationObject: createRuleParamsExamplesV1,
|
||||||
},
|
},
|
||||||
validate: {
|
validate: {
|
||||||
request: {
|
request: {
|
||||||
|
|
|
@ -11,7 +11,10 @@ import type {
|
||||||
FindRulesRequestQueryV1,
|
FindRulesRequestQueryV1,
|
||||||
FindRulesResponseV1,
|
FindRulesResponseV1,
|
||||||
} from '../../../../../common/routes/rule/apis/find';
|
} 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 type { RuleParamsV1 } from '../../../../../common/routes/rule/response';
|
||||||
import { ruleResponseSchemaV1 } from '../../../../../common/routes/rule/response';
|
import { ruleResponseSchemaV1 } from '../../../../../common/routes/rule/response';
|
||||||
import type { ILicenseState } from '../../../../lib';
|
import type { ILicenseState } from '../../../../lib';
|
||||||
|
@ -35,6 +38,7 @@ export const findRulesRoute = (
|
||||||
access: 'public',
|
access: 'public',
|
||||||
summary: 'Get information about rules',
|
summary: 'Get information about rules',
|
||||||
tags: ['oas-tag:alerting'],
|
tags: ['oas-tag:alerting'],
|
||||||
|
oasOperationObject: findRuleParamsExamplesV1,
|
||||||
},
|
},
|
||||||
validate: {
|
validate: {
|
||||||
request: {
|
request: {
|
||||||
|
|
|
@ -14,6 +14,7 @@ import type {
|
||||||
import {
|
import {
|
||||||
updateBodySchemaV1,
|
updateBodySchemaV1,
|
||||||
updateParamsSchemaV1,
|
updateParamsSchemaV1,
|
||||||
|
updateRuleParamsExamplesV1,
|
||||||
} from '../../../../../common/routes/rule/apis/update';
|
} from '../../../../../common/routes/rule/apis/update';
|
||||||
import type { RuleParamsV1 } from '../../../../../common/routes/rule/response';
|
import type { RuleParamsV1 } from '../../../../../common/routes/rule/response';
|
||||||
import { ruleResponseSchemaV1 } from '../../../../../common/routes/rule/response';
|
import { ruleResponseSchemaV1 } from '../../../../../common/routes/rule/response';
|
||||||
|
@ -40,6 +41,7 @@ export const updateRuleRoute = (
|
||||||
access: 'public',
|
access: 'public',
|
||||||
summary: `Update a rule`,
|
summary: `Update a rule`,
|
||||||
tags: ['oas-tag:alerting'],
|
tags: ['oas-tag:alerting'],
|
||||||
|
oasOperationObject: updateRuleParamsExamplesV1,
|
||||||
},
|
},
|
||||||
validate: {
|
validate: {
|
||||||
request: {
|
request: {
|
||||||
|
|
11
yarn.lock
11
yarn.lock
|
@ -71,7 +71,7 @@
|
||||||
"@jridgewell/gen-mapping" "^0.1.0"
|
"@jridgewell/gen-mapping" "^0.1.0"
|
||||||
"@jridgewell/trace-mapping" "^0.3.9"
|
"@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"
|
version "11.7.2"
|
||||||
resolved "https://registry.yarnpkg.com/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-11.7.2.tgz#cdf3e0aded21492364a70e193b45b7cf4177f031"
|
resolved "https://registry.yarnpkg.com/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-11.7.2.tgz#cdf3e0aded21492364a70e193b45b7cf4177f031"
|
||||||
integrity sha512-4gY54eEGEstClvEkGnwVkTkrx0sqwemEFG5OSRRn3tD91XH0+Q8XIkYIfo7IwEWPpJZwILb9GUXeShtplRc/eA==
|
integrity sha512-4gY54eEGEstClvEkGnwVkTkrx0sqwemEFG5OSRRn3tD91XH0+Q8XIkYIfo7IwEWPpJZwILb9GUXeShtplRc/eA==
|
||||||
|
@ -80,6 +80,15 @@
|
||||||
"@types/json-schema" "^7.0.15"
|
"@types/json-schema" "^7.0.15"
|
||||||
js-yaml "^4.1.0"
|
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":
|
"@apidevtools/json-schema-ref-parser@^9.0.6":
|
||||||
version "9.0.9"
|
version "9.0.9"
|
||||||
resolved "https://registry.yarnpkg.com/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.0.9.tgz#d720f9256e3609621280584f2b47ae165359268b"
|
resolved "https://registry.yarnpkg.com/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.0.9.tgz#d720f9256e3609621280584f2b47ae165359268b"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue