mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 09:19:04 -04:00
[8.x] [Threat Hunting Investigations] Migrate all timeline routes to OpenAPI types (#190238) (#194606)
# Backport This will backport the following commits from `main` to `8.x`: - [[Threat Hunting Investigations] Migrate all timeline routes to OpenAPI types (#190238)](https://github.com/elastic/kibana/pull/190238) <!--- Backport version: 8.9.8 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) <!--BACKPORT [{"author":{"name":"Jan Monschke","email":"jan.monschke@elastic.co"},"sourceCommit":{"committedDate":"2024-09-30T18:55:23Z","message":"[Threat Hunting Investigations] Migrate all timeline routes to OpenAPI types (#190238)\n\n## Summary\r\n\r\nfixes: https://github.com/elastic/security-team/issues/10235\r\nfixes: https://github.com/elastic/security-team/issues/10237\r\n\r\nThis is the final PR for migrating over all timeline-related schemas and\r\ntypes to the new generated zod schemas from our OpenAPI specs. (see\r\nhttps://github.com/elastic/security-team/issues/10110)\r\nOn top of moving to the new schemas/types, this PR also cleans up usage\r\nof now outdated types.\r\n\r\nI'm aware of the size of this PR but rest assured, the changes are easy\r\nto review and for most teams, only a handful of files need to be\r\nreviewed:\r\n\r\n```markdown\r\n### elastic/security-defend-workflows\r\n\r\n* x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_solution_integrations.ts\r\n\r\n### elastic/security-detection-rule-management\r\n\r\n* x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/get_prebuilt_rules_and_timelines_status/get_prebuilt_rules_and_timelines_status_route.ts\r\n* x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/perform_timelines_installation.ts\r\n\r\n### elastic/security-detections-response\r\n\r\n* x-pack/test/security_solution_cypress/cypress/objects/timeline.ts\r\n\r\n### elastic/security-engineering-productivity\r\n\r\n* x-pack/test/security_solution_cypress/cypress/objects/timeline.ts\r\n* x-pack/test/security_solution_cypress/cypress/tasks/api_calls/timelines.ts\r\n```\r\n\r\n\r\n### Checklist\r\n\r\n- [x] [Unit or functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere updated or added to match the most common scenarios\r\n\r\n---------\r\n\r\nCo-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>\r\nCo-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>","sha":"00789609ad663efffd7b3997ca773fe3ea5511e2","branchLabelMapping":{"^v9.0.0$":"main","^v8.16.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","backport:skip","v9.0.0","Team:Threat Hunting:Investigations","v8.16.0"],"number":190238,"url":"https://github.com/elastic/kibana/pull/190238","mergeCommit":{"message":"[Threat Hunting Investigations] Migrate all timeline routes to OpenAPI types (#190238)\n\n## Summary\r\n\r\nfixes: https://github.com/elastic/security-team/issues/10235\r\nfixes: https://github.com/elastic/security-team/issues/10237\r\n\r\nThis is the final PR for migrating over all timeline-related schemas and\r\ntypes to the new generated zod schemas from our OpenAPI specs. (see\r\nhttps://github.com/elastic/security-team/issues/10110)\r\nOn top of moving to the new schemas/types, this PR also cleans up usage\r\nof now outdated types.\r\n\r\nI'm aware of the size of this PR but rest assured, the changes are easy\r\nto review and for most teams, only a handful of files need to be\r\nreviewed:\r\n\r\n```markdown\r\n### elastic/security-defend-workflows\r\n\r\n* x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_solution_integrations.ts\r\n\r\n### elastic/security-detection-rule-management\r\n\r\n* x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/get_prebuilt_rules_and_timelines_status/get_prebuilt_rules_and_timelines_status_route.ts\r\n* x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/perform_timelines_installation.ts\r\n\r\n### elastic/security-detections-response\r\n\r\n* x-pack/test/security_solution_cypress/cypress/objects/timeline.ts\r\n\r\n### elastic/security-engineering-productivity\r\n\r\n* x-pack/test/security_solution_cypress/cypress/objects/timeline.ts\r\n* x-pack/test/security_solution_cypress/cypress/tasks/api_calls/timelines.ts\r\n```\r\n\r\n\r\n### Checklist\r\n\r\n- [x] [Unit or functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere updated or added to match the most common scenarios\r\n\r\n---------\r\n\r\nCo-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>\r\nCo-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>","sha":"00789609ad663efffd7b3997ca773fe3ea5511e2"}},"sourceBranch":"main","suggestedTargetBranches":["8.x"],"targetPullRequestStates":[{"branch":"main","label":"v9.0.0","labelRegex":"^v9.0.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/190238","number":190238,"mergeCommit":{"message":"[Threat Hunting Investigations] Migrate all timeline routes to OpenAPI types (#190238)\n\n## Summary\r\n\r\nfixes: https://github.com/elastic/security-team/issues/10235\r\nfixes: https://github.com/elastic/security-team/issues/10237\r\n\r\nThis is the final PR for migrating over all timeline-related schemas and\r\ntypes to the new generated zod schemas from our OpenAPI specs. (see\r\nhttps://github.com/elastic/security-team/issues/10110)\r\nOn top of moving to the new schemas/types, this PR also cleans up usage\r\nof now outdated types.\r\n\r\nI'm aware of the size of this PR but rest assured, the changes are easy\r\nto review and for most teams, only a handful of files need to be\r\nreviewed:\r\n\r\n```markdown\r\n### elastic/security-defend-workflows\r\n\r\n* x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_solution_integrations.ts\r\n\r\n### elastic/security-detection-rule-management\r\n\r\n* x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/get_prebuilt_rules_and_timelines_status/get_prebuilt_rules_and_timelines_status_route.ts\r\n* x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/perform_timelines_installation.ts\r\n\r\n### elastic/security-detections-response\r\n\r\n* x-pack/test/security_solution_cypress/cypress/objects/timeline.ts\r\n\r\n### elastic/security-engineering-productivity\r\n\r\n* x-pack/test/security_solution_cypress/cypress/objects/timeline.ts\r\n* x-pack/test/security_solution_cypress/cypress/tasks/api_calls/timelines.ts\r\n```\r\n\r\n\r\n### Checklist\r\n\r\n- [x] [Unit or functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere updated or added to match the most common scenarios\r\n\r\n---------\r\n\r\nCo-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>\r\nCo-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>","sha":"00789609ad663efffd7b3997ca773fe3ea5511e2"}},{"branch":"8.x","label":"v8.16.0","labelRegex":"^v8.16.0$","isSourceBranch":false,"state":"NOT_CREATED"}]}] BACKPORT-->
This commit is contained in:
parent
5f0493655d
commit
1186ed4504
106 changed files with 2041 additions and 2689 deletions
|
@ -16233,19 +16233,21 @@ paths:
|
|||
content:
|
||||
application/json; Elastic-Api-Version=2023-10-31:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
type: object
|
||||
oneOf:
|
||||
- type: object
|
||||
properties:
|
||||
getOneTimeline:
|
||||
$ref: >-
|
||||
#/components/schemas/Security_Timeline_API_TimelineResponse
|
||||
nullable: true
|
||||
data:
|
||||
type: object
|
||||
properties:
|
||||
getOneTimeline:
|
||||
$ref: >-
|
||||
#/components/schemas/Security_Timeline_API_TimelineResponse
|
||||
required:
|
||||
- getOneTimeline
|
||||
required:
|
||||
- getOneTimeline
|
||||
required:
|
||||
- data
|
||||
- data
|
||||
- additionalProperties: false
|
||||
type: object
|
||||
description: Indicates that the (template) timeline was found and returned.
|
||||
summary: >-
|
||||
Get an existing saved timeline or timeline template. This API is used to
|
||||
|
@ -16284,23 +16286,8 @@ paths:
|
|||
content:
|
||||
application/json; Elastic-Api-Version=2023-10-31:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
type: object
|
||||
properties:
|
||||
persistTimeline:
|
||||
type: object
|
||||
properties:
|
||||
timeline:
|
||||
$ref: >-
|
||||
#/components/schemas/Security_Timeline_API_TimelineResponse
|
||||
required:
|
||||
- timeline
|
||||
required:
|
||||
- persistTimeline
|
||||
required:
|
||||
- data
|
||||
$ref: >-
|
||||
#/components/schemas/Security_Timeline_API_PersistTimelineResponse
|
||||
description: >-
|
||||
Indicates that the draft timeline was successfully created. In the
|
||||
event the user already has a draft timeline, the existing draft
|
||||
|
@ -16361,21 +16348,8 @@ paths:
|
|||
content:
|
||||
application/json; Elastic-Api-Version=2023-10-31:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
type: object
|
||||
properties:
|
||||
persistTimeline:
|
||||
type: object
|
||||
properties:
|
||||
timeline:
|
||||
$ref: >-
|
||||
#/components/schemas/Security_Timeline_API_TimelineResponse
|
||||
required:
|
||||
- persistTimeline
|
||||
required:
|
||||
- data
|
||||
$ref: >-
|
||||
#/components/schemas/Security_Timeline_API_PersistTimelineResponse
|
||||
description: Indicates the timeline was successfully created.
|
||||
'405':
|
||||
content:
|
||||
|
@ -16392,6 +16366,37 @@ paths:
|
|||
tags:
|
||||
- Security Timeline API
|
||||
- 'access:securitySolution'
|
||||
/api/timeline/_copy:
|
||||
get:
|
||||
description: |
|
||||
Copies and returns a timeline or timeline template.
|
||||
operationId: CopyTimeline
|
||||
requestBody:
|
||||
content:
|
||||
application/json; Elastic-Api-Version=2023-10-31:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
timeline:
|
||||
$ref: '#/components/schemas/Security_Timeline_API_SavedTimeline'
|
||||
timelineIdToCopy:
|
||||
type: string
|
||||
required:
|
||||
- timeline
|
||||
- timelineIdToCopy
|
||||
required: true
|
||||
responses:
|
||||
'200':
|
||||
content:
|
||||
application/json; Elastic-Api-Version=2023-10-31:
|
||||
schema:
|
||||
$ref: >-
|
||||
#/components/schemas/Security_Timeline_API_PersistTimelineResponse
|
||||
description: Indicates that the timeline has been successfully copied.
|
||||
summary: Copies timeline or timeline template
|
||||
tags:
|
||||
- Security Timeline API
|
||||
- 'access:securitySolution'
|
||||
/api/timeline/_draft:
|
||||
get:
|
||||
operationId: GetDraftTimelines
|
||||
|
@ -16406,23 +16411,8 @@ paths:
|
|||
content:
|
||||
application/json; Elastic-Api-Version=2023-10-31:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
type: object
|
||||
properties:
|
||||
persistTimeline:
|
||||
type: object
|
||||
properties:
|
||||
timeline:
|
||||
$ref: >-
|
||||
#/components/schemas/Security_Timeline_API_TimelineResponse
|
||||
required:
|
||||
- timeline
|
||||
required:
|
||||
- persistTimeline
|
||||
required:
|
||||
- data
|
||||
$ref: >-
|
||||
#/components/schemas/Security_Timeline_API_PersistTimelineResponse
|
||||
description: Indicates that the draft timeline was successfully retrieved.
|
||||
'403':
|
||||
content:
|
||||
|
@ -16482,23 +16472,8 @@ paths:
|
|||
content:
|
||||
application/json; Elastic-Api-Version=2023-10-31:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
type: object
|
||||
properties:
|
||||
persistTimeline:
|
||||
type: object
|
||||
properties:
|
||||
timeline:
|
||||
$ref: >-
|
||||
#/components/schemas/Security_Timeline_API_TimelineResponse
|
||||
required:
|
||||
- timeline
|
||||
required:
|
||||
- persistTimeline
|
||||
required:
|
||||
- data
|
||||
$ref: >-
|
||||
#/components/schemas/Security_Timeline_API_PersistTimelineResponse
|
||||
description: >-
|
||||
Indicates that the draft timeline was successfully created. In the
|
||||
event the user already has a draft timeline, the existing draft
|
||||
|
@ -16651,28 +16626,14 @@ paths:
|
|||
schema:
|
||||
type: object
|
||||
properties:
|
||||
file:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/Security_Timeline_API_Readable'
|
||||
- type: object
|
||||
properties:
|
||||
hapi:
|
||||
type: object
|
||||
properties:
|
||||
filename:
|
||||
type: string
|
||||
headers:
|
||||
type: object
|
||||
isImmutable:
|
||||
enum:
|
||||
- 'true'
|
||||
- 'false'
|
||||
type: string
|
||||
required:
|
||||
- filename
|
||||
- headers
|
||||
required:
|
||||
- hapi
|
||||
file: {}
|
||||
isImmutable:
|
||||
enum:
|
||||
- 'true'
|
||||
- 'false'
|
||||
type: string
|
||||
required:
|
||||
- file
|
||||
description: The timelines to import as a readable stream.
|
||||
required: true
|
||||
responses:
|
||||
|
@ -16680,13 +16641,8 @@ paths:
|
|||
content:
|
||||
application/json; Elastic-Api-Version=2023-10-31:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
$ref: >-
|
||||
#/components/schemas/Security_Timeline_API_ImportTimelineResult
|
||||
required:
|
||||
- data
|
||||
$ref: >-
|
||||
#/components/schemas/Security_Timeline_API_ImportTimelineResult
|
||||
description: Indicates the import of timelines was successful.
|
||||
'400':
|
||||
content:
|
||||
|
@ -16744,7 +16700,9 @@ paths:
|
|||
properties:
|
||||
prepackagedTimelines:
|
||||
items:
|
||||
$ref: '#/components/schemas/Security_Timeline_API_SavedTimeline'
|
||||
$ref: >-
|
||||
#/components/schemas/Security_Timeline_API_TimelineSavedToReturnObject
|
||||
nullable: true
|
||||
type: array
|
||||
timelinesToInstall:
|
||||
items:
|
||||
|
@ -16767,13 +16725,8 @@ paths:
|
|||
content:
|
||||
application/json; Elastic-Api-Version=2023-10-31:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
$ref: >-
|
||||
#/components/schemas/Security_Timeline_API_ImportTimelineResult
|
||||
required:
|
||||
- data
|
||||
$ref: >-
|
||||
#/components/schemas/Security_Timeline_API_ImportTimelineResult
|
||||
description: Indicates the installation of prepackaged timelines was successful.
|
||||
'500':
|
||||
content:
|
||||
|
@ -16811,19 +16764,16 @@ paths:
|
|||
content:
|
||||
application/json; Elastic-Api-Version=2023-10-31:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
type: object
|
||||
oneOf:
|
||||
- type: object
|
||||
properties:
|
||||
getOneTimeline:
|
||||
data:
|
||||
$ref: >-
|
||||
#/components/schemas/Security_Timeline_API_TimelineResponse
|
||||
nullable: true
|
||||
#/components/schemas/Security_Timeline_API_ResolvedTimeline
|
||||
required:
|
||||
- getOneTimeline
|
||||
required:
|
||||
- data
|
||||
- data
|
||||
- additionalProperties: false
|
||||
type: object
|
||||
description: The (template) timeline has been found
|
||||
'400':
|
||||
description: The request is missing parameters
|
||||
|
@ -16891,36 +16841,26 @@ paths:
|
|||
schema:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
type: object
|
||||
properties:
|
||||
customTemplateTimelineCount:
|
||||
type: number
|
||||
defaultTimelineCount:
|
||||
type: number
|
||||
elasticTemplateTimelineCount:
|
||||
type: number
|
||||
favoriteCount:
|
||||
type: number
|
||||
templateTimelineCount:
|
||||
type: number
|
||||
timelines:
|
||||
items:
|
||||
$ref: >-
|
||||
#/components/schemas/Security_Timeline_API_TimelineResponse
|
||||
type: array
|
||||
totalCount:
|
||||
type: number
|
||||
required:
|
||||
- timelines
|
||||
- totalCount
|
||||
- defaultTimelineCount
|
||||
- templateTimelineCount
|
||||
- favoriteCount
|
||||
- elasticTemplateTimelineCount
|
||||
- customTemplateTimelineCount
|
||||
customTemplateTimelineCount:
|
||||
type: number
|
||||
defaultTimelineCount:
|
||||
type: number
|
||||
elasticTemplateTimelineCount:
|
||||
type: number
|
||||
favoriteCount:
|
||||
type: number
|
||||
templateTimelineCount:
|
||||
type: number
|
||||
timeline:
|
||||
items:
|
||||
$ref: >-
|
||||
#/components/schemas/Security_Timeline_API_TimelineResponse
|
||||
type: array
|
||||
totalCount:
|
||||
type: number
|
||||
required:
|
||||
- data
|
||||
- timeline
|
||||
- totalCount
|
||||
description: Indicates that the (template) timelines were found and returned.
|
||||
'400':
|
||||
content:
|
||||
|
@ -31204,30 +31144,39 @@ components:
|
|||
type: object
|
||||
properties:
|
||||
aggregatable:
|
||||
nullable: true
|
||||
type: boolean
|
||||
category:
|
||||
nullable: true
|
||||
type: string
|
||||
columnHeaderType:
|
||||
nullable: true
|
||||
type: string
|
||||
description:
|
||||
nullable: true
|
||||
type: string
|
||||
example:
|
||||
oneOf:
|
||||
- type: string
|
||||
- type: number
|
||||
nullable: true
|
||||
type: string
|
||||
id:
|
||||
nullable: true
|
||||
type: string
|
||||
indexes:
|
||||
items:
|
||||
type: string
|
||||
nullable: true
|
||||
type: array
|
||||
name:
|
||||
nullable: true
|
||||
type: string
|
||||
placeholder:
|
||||
nullable: true
|
||||
type: string
|
||||
searchable:
|
||||
nullable: true
|
||||
type: boolean
|
||||
type:
|
||||
nullable: true
|
||||
type: string
|
||||
Security_Timeline_API_DataProviderQueryMatch:
|
||||
type: object
|
||||
|
@ -31249,6 +31198,10 @@ components:
|
|||
type: string
|
||||
queryMatch:
|
||||
$ref: '#/components/schemas/Security_Timeline_API_QueryMatchResult'
|
||||
nullable: true
|
||||
type:
|
||||
$ref: '#/components/schemas/Security_Timeline_API_DataProviderType'
|
||||
nullable: true
|
||||
Security_Timeline_API_DataProviderResult:
|
||||
type: object
|
||||
properties:
|
||||
|
@ -31336,41 +31289,59 @@ components:
|
|||
type: object
|
||||
properties:
|
||||
exists:
|
||||
type: boolean
|
||||
nullable: true
|
||||
type: string
|
||||
match_all:
|
||||
nullable: true
|
||||
type: string
|
||||
meta:
|
||||
nullable: true
|
||||
type: object
|
||||
properties:
|
||||
alias:
|
||||
nullable: true
|
||||
type: string
|
||||
controlledBy:
|
||||
nullable: true
|
||||
type: string
|
||||
disabled:
|
||||
nullable: true
|
||||
type: boolean
|
||||
field:
|
||||
nullable: true
|
||||
type: string
|
||||
formattedValue:
|
||||
nullable: true
|
||||
type: string
|
||||
index:
|
||||
nullable: true
|
||||
type: string
|
||||
key:
|
||||
nullable: true
|
||||
type: string
|
||||
negate:
|
||||
nullable: true
|
||||
type: boolean
|
||||
params:
|
||||
nullable: true
|
||||
type: string
|
||||
type:
|
||||
nullable: true
|
||||
type: string
|
||||
value:
|
||||
nullable: true
|
||||
type: string
|
||||
missing:
|
||||
nullable: true
|
||||
type: string
|
||||
query:
|
||||
nullable: true
|
||||
type: string
|
||||
range:
|
||||
nullable: true
|
||||
type: string
|
||||
script:
|
||||
nullable: true
|
||||
type: string
|
||||
Security_Timeline_API_GetNotesResult:
|
||||
type: object
|
||||
|
@ -31435,6 +31406,12 @@ components:
|
|||
version:
|
||||
nullable: true
|
||||
type: string
|
||||
required:
|
||||
- savedObjectId
|
||||
- version
|
||||
- pinnedEventIds
|
||||
- eventNotes
|
||||
- globalNotes
|
||||
Security_Timeline_API_Note:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/Security_Timeline_API_BareNote'
|
||||
|
@ -31455,6 +31432,23 @@ components:
|
|||
#/components/schemas/Security_Timeline_API_PinnedEventBaseResponseBody
|
||||
- nullable: true
|
||||
type: object
|
||||
Security_Timeline_API_PersistTimelineResponse:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
type: object
|
||||
properties:
|
||||
persistTimeline:
|
||||
type: object
|
||||
properties:
|
||||
timeline:
|
||||
$ref: '#/components/schemas/Security_Timeline_API_TimelineResponse'
|
||||
required:
|
||||
- timeline
|
||||
required:
|
||||
- persistTimeline
|
||||
required:
|
||||
- data
|
||||
Security_Timeline_API_PinnedEvent:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/Security_Timeline_API_BarePinnedEvent'
|
||||
|
@ -31492,34 +31486,29 @@ components:
|
|||
nullable: true
|
||||
type: string
|
||||
value:
|
||||
nullable: true
|
||||
type: string
|
||||
Security_Timeline_API_Readable:
|
||||
oneOf:
|
||||
- nullable: true
|
||||
type: string
|
||||
- items:
|
||||
type: string
|
||||
nullable: true
|
||||
type: array
|
||||
Security_Timeline_API_ResolvedTimeline:
|
||||
type: object
|
||||
properties:
|
||||
_data:
|
||||
additionalProperties: true
|
||||
type: object
|
||||
_encoding:
|
||||
alias_purpose:
|
||||
$ref: >-
|
||||
#/components/schemas/Security_Timeline_API_SavedObjectResolveAliasPurpose
|
||||
alias_target_id:
|
||||
type: string
|
||||
_events:
|
||||
additionalProperties: true
|
||||
type: object
|
||||
_eventsCount:
|
||||
type: number
|
||||
_maxListeners:
|
||||
additionalProperties: true
|
||||
type: object
|
||||
_position:
|
||||
type: number
|
||||
_read:
|
||||
additionalProperties: true
|
||||
type: object
|
||||
_readableState:
|
||||
additionalProperties: true
|
||||
type: object
|
||||
readable:
|
||||
type: boolean
|
||||
outcome:
|
||||
$ref: '#/components/schemas/Security_Timeline_API_SavedObjectResolveOutcome'
|
||||
timeline:
|
||||
$ref: >-
|
||||
#/components/schemas/Security_Timeline_API_TimelineSavedToReturnObject
|
||||
required:
|
||||
- timeline
|
||||
- outcome
|
||||
Security_Timeline_API_ResponseNote:
|
||||
type: object
|
||||
properties:
|
||||
|
@ -31554,6 +31543,17 @@ components:
|
|||
- threat_match
|
||||
- zeek
|
||||
type: string
|
||||
Security_Timeline_API_SavedObjectResolveAliasPurpose:
|
||||
enum:
|
||||
- savedObjectConversion
|
||||
- savedObjectImport
|
||||
type: string
|
||||
Security_Timeline_API_SavedObjectResolveOutcome:
|
||||
enum:
|
||||
- exactMatch
|
||||
- aliasMatch
|
||||
- conflict
|
||||
type: string
|
||||
Security_Timeline_API_SavedTimeline:
|
||||
type: object
|
||||
properties:
|
||||
|
@ -31582,12 +31582,16 @@ components:
|
|||
properties:
|
||||
end:
|
||||
oneOf:
|
||||
- type: string
|
||||
- type: number
|
||||
- nullable: true
|
||||
type: string
|
||||
- nullable: true
|
||||
type: number
|
||||
start:
|
||||
oneOf:
|
||||
- type: string
|
||||
- type: number
|
||||
- nullable: true
|
||||
type: string
|
||||
- nullable: true
|
||||
type: number
|
||||
description:
|
||||
nullable: true
|
||||
type: string
|
||||
|
@ -31677,6 +31681,18 @@ components:
|
|||
updatedBy:
|
||||
nullable: true
|
||||
type: string
|
||||
Security_Timeline_API_SavedTimelineWithSavedObjectId:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/Security_Timeline_API_SavedTimeline'
|
||||
- type: object
|
||||
properties:
|
||||
savedObjectId:
|
||||
type: string
|
||||
version:
|
||||
type: string
|
||||
required:
|
||||
- savedObjectId
|
||||
- version
|
||||
Security_Timeline_API_SerializedFilterQueryResult:
|
||||
type: object
|
||||
properties:
|
||||
|
@ -31726,27 +31742,64 @@ components:
|
|||
Security_Timeline_API_TimelineResponse:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/Security_Timeline_API_SavedTimeline'
|
||||
- $ref: >-
|
||||
#/components/schemas/Security_Timeline_API_SavedTimelineWithSavedObjectId
|
||||
- type: object
|
||||
properties:
|
||||
eventIdToNoteIds:
|
||||
items:
|
||||
$ref: '#/components/schemas/Security_Timeline_API_Note'
|
||||
nullable: true
|
||||
type: array
|
||||
noteIds:
|
||||
items:
|
||||
type: string
|
||||
nullable: true
|
||||
type: array
|
||||
notes:
|
||||
items:
|
||||
$ref: '#/components/schemas/Security_Timeline_API_Note'
|
||||
nullable: true
|
||||
type: array
|
||||
pinnedEventIds:
|
||||
items:
|
||||
type: string
|
||||
nullable: true
|
||||
type: array
|
||||
pinnedEventsSaveObject:
|
||||
items:
|
||||
$ref: '#/components/schemas/Security_Timeline_API_PinnedEvent'
|
||||
nullable: true
|
||||
type: array
|
||||
Security_Timeline_API_TimelineSavedToReturnObject:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/Security_Timeline_API_SavedTimeline'
|
||||
- type: object
|
||||
properties:
|
||||
eventIdToNoteIds:
|
||||
items:
|
||||
$ref: '#/components/schemas/Security_Timeline_API_Note'
|
||||
nullable: true
|
||||
type: array
|
||||
noteIds:
|
||||
items:
|
||||
type: string
|
||||
nullable: true
|
||||
type: array
|
||||
notes:
|
||||
items:
|
||||
$ref: '#/components/schemas/Security_Timeline_API_Note'
|
||||
nullable: true
|
||||
type: array
|
||||
pinnedEventIds:
|
||||
items:
|
||||
type: string
|
||||
nullable: true
|
||||
type: array
|
||||
pinnedEventsSaveObject:
|
||||
items:
|
||||
$ref: '#/components/schemas/Security_Timeline_API_PinnedEvent'
|
||||
nullable: true
|
||||
type: array
|
||||
savedObjectId:
|
||||
type: string
|
||||
|
|
|
@ -20322,19 +20322,21 @@ paths:
|
|||
content:
|
||||
application/json; Elastic-Api-Version=2023-10-31:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
type: object
|
||||
oneOf:
|
||||
- type: object
|
||||
properties:
|
||||
getOneTimeline:
|
||||
$ref: >-
|
||||
#/components/schemas/Security_Timeline_API_TimelineResponse
|
||||
nullable: true
|
||||
data:
|
||||
type: object
|
||||
properties:
|
||||
getOneTimeline:
|
||||
$ref: >-
|
||||
#/components/schemas/Security_Timeline_API_TimelineResponse
|
||||
required:
|
||||
- getOneTimeline
|
||||
required:
|
||||
- getOneTimeline
|
||||
required:
|
||||
- data
|
||||
- data
|
||||
- additionalProperties: false
|
||||
type: object
|
||||
description: Indicates that the (template) timeline was found and returned.
|
||||
summary: >-
|
||||
Get an existing saved timeline or timeline template. This API is used to
|
||||
|
@ -20373,23 +20375,8 @@ paths:
|
|||
content:
|
||||
application/json; Elastic-Api-Version=2023-10-31:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
type: object
|
||||
properties:
|
||||
persistTimeline:
|
||||
type: object
|
||||
properties:
|
||||
timeline:
|
||||
$ref: >-
|
||||
#/components/schemas/Security_Timeline_API_TimelineResponse
|
||||
required:
|
||||
- timeline
|
||||
required:
|
||||
- persistTimeline
|
||||
required:
|
||||
- data
|
||||
$ref: >-
|
||||
#/components/schemas/Security_Timeline_API_PersistTimelineResponse
|
||||
description: >-
|
||||
Indicates that the draft timeline was successfully created. In the
|
||||
event the user already has a draft timeline, the existing draft
|
||||
|
@ -20450,21 +20437,8 @@ paths:
|
|||
content:
|
||||
application/json; Elastic-Api-Version=2023-10-31:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
type: object
|
||||
properties:
|
||||
persistTimeline:
|
||||
type: object
|
||||
properties:
|
||||
timeline:
|
||||
$ref: >-
|
||||
#/components/schemas/Security_Timeline_API_TimelineResponse
|
||||
required:
|
||||
- persistTimeline
|
||||
required:
|
||||
- data
|
||||
$ref: >-
|
||||
#/components/schemas/Security_Timeline_API_PersistTimelineResponse
|
||||
description: Indicates the timeline was successfully created.
|
||||
'405':
|
||||
content:
|
||||
|
@ -20481,6 +20455,37 @@ paths:
|
|||
tags:
|
||||
- Security Timeline API
|
||||
- 'access:securitySolution'
|
||||
/api/timeline/_copy:
|
||||
get:
|
||||
description: |
|
||||
Copies and returns a timeline or timeline template.
|
||||
operationId: CopyTimeline
|
||||
requestBody:
|
||||
content:
|
||||
application/json; Elastic-Api-Version=2023-10-31:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
timeline:
|
||||
$ref: '#/components/schemas/Security_Timeline_API_SavedTimeline'
|
||||
timelineIdToCopy:
|
||||
type: string
|
||||
required:
|
||||
- timeline
|
||||
- timelineIdToCopy
|
||||
required: true
|
||||
responses:
|
||||
'200':
|
||||
content:
|
||||
application/json; Elastic-Api-Version=2023-10-31:
|
||||
schema:
|
||||
$ref: >-
|
||||
#/components/schemas/Security_Timeline_API_PersistTimelineResponse
|
||||
description: Indicates that the timeline has been successfully copied.
|
||||
summary: Copies timeline or timeline template
|
||||
tags:
|
||||
- Security Timeline API
|
||||
- 'access:securitySolution'
|
||||
/api/timeline/_draft:
|
||||
get:
|
||||
operationId: GetDraftTimelines
|
||||
|
@ -20495,23 +20500,8 @@ paths:
|
|||
content:
|
||||
application/json; Elastic-Api-Version=2023-10-31:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
type: object
|
||||
properties:
|
||||
persistTimeline:
|
||||
type: object
|
||||
properties:
|
||||
timeline:
|
||||
$ref: >-
|
||||
#/components/schemas/Security_Timeline_API_TimelineResponse
|
||||
required:
|
||||
- timeline
|
||||
required:
|
||||
- persistTimeline
|
||||
required:
|
||||
- data
|
||||
$ref: >-
|
||||
#/components/schemas/Security_Timeline_API_PersistTimelineResponse
|
||||
description: Indicates that the draft timeline was successfully retrieved.
|
||||
'403':
|
||||
content:
|
||||
|
@ -20571,23 +20561,8 @@ paths:
|
|||
content:
|
||||
application/json; Elastic-Api-Version=2023-10-31:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
type: object
|
||||
properties:
|
||||
persistTimeline:
|
||||
type: object
|
||||
properties:
|
||||
timeline:
|
||||
$ref: >-
|
||||
#/components/schemas/Security_Timeline_API_TimelineResponse
|
||||
required:
|
||||
- timeline
|
||||
required:
|
||||
- persistTimeline
|
||||
required:
|
||||
- data
|
||||
$ref: >-
|
||||
#/components/schemas/Security_Timeline_API_PersistTimelineResponse
|
||||
description: >-
|
||||
Indicates that the draft timeline was successfully created. In the
|
||||
event the user already has a draft timeline, the existing draft
|
||||
|
@ -20740,28 +20715,14 @@ paths:
|
|||
schema:
|
||||
type: object
|
||||
properties:
|
||||
file:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/Security_Timeline_API_Readable'
|
||||
- type: object
|
||||
properties:
|
||||
hapi:
|
||||
type: object
|
||||
properties:
|
||||
filename:
|
||||
type: string
|
||||
headers:
|
||||
type: object
|
||||
isImmutable:
|
||||
enum:
|
||||
- 'true'
|
||||
- 'false'
|
||||
type: string
|
||||
required:
|
||||
- filename
|
||||
- headers
|
||||
required:
|
||||
- hapi
|
||||
file: {}
|
||||
isImmutable:
|
||||
enum:
|
||||
- 'true'
|
||||
- 'false'
|
||||
type: string
|
||||
required:
|
||||
- file
|
||||
description: The timelines to import as a readable stream.
|
||||
required: true
|
||||
responses:
|
||||
|
@ -20769,13 +20730,8 @@ paths:
|
|||
content:
|
||||
application/json; Elastic-Api-Version=2023-10-31:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
$ref: >-
|
||||
#/components/schemas/Security_Timeline_API_ImportTimelineResult
|
||||
required:
|
||||
- data
|
||||
$ref: >-
|
||||
#/components/schemas/Security_Timeline_API_ImportTimelineResult
|
||||
description: Indicates the import of timelines was successful.
|
||||
'400':
|
||||
content:
|
||||
|
@ -20833,7 +20789,9 @@ paths:
|
|||
properties:
|
||||
prepackagedTimelines:
|
||||
items:
|
||||
$ref: '#/components/schemas/Security_Timeline_API_SavedTimeline'
|
||||
$ref: >-
|
||||
#/components/schemas/Security_Timeline_API_TimelineSavedToReturnObject
|
||||
nullable: true
|
||||
type: array
|
||||
timelinesToInstall:
|
||||
items:
|
||||
|
@ -20856,13 +20814,8 @@ paths:
|
|||
content:
|
||||
application/json; Elastic-Api-Version=2023-10-31:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
$ref: >-
|
||||
#/components/schemas/Security_Timeline_API_ImportTimelineResult
|
||||
required:
|
||||
- data
|
||||
$ref: >-
|
||||
#/components/schemas/Security_Timeline_API_ImportTimelineResult
|
||||
description: Indicates the installation of prepackaged timelines was successful.
|
||||
'500':
|
||||
content:
|
||||
|
@ -20900,19 +20853,16 @@ paths:
|
|||
content:
|
||||
application/json; Elastic-Api-Version=2023-10-31:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
type: object
|
||||
oneOf:
|
||||
- type: object
|
||||
properties:
|
||||
getOneTimeline:
|
||||
data:
|
||||
$ref: >-
|
||||
#/components/schemas/Security_Timeline_API_TimelineResponse
|
||||
nullable: true
|
||||
#/components/schemas/Security_Timeline_API_ResolvedTimeline
|
||||
required:
|
||||
- getOneTimeline
|
||||
required:
|
||||
- data
|
||||
- data
|
||||
- additionalProperties: false
|
||||
type: object
|
||||
description: The (template) timeline has been found
|
||||
'400':
|
||||
description: The request is missing parameters
|
||||
|
@ -20980,36 +20930,26 @@ paths:
|
|||
schema:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
type: object
|
||||
properties:
|
||||
customTemplateTimelineCount:
|
||||
type: number
|
||||
defaultTimelineCount:
|
||||
type: number
|
||||
elasticTemplateTimelineCount:
|
||||
type: number
|
||||
favoriteCount:
|
||||
type: number
|
||||
templateTimelineCount:
|
||||
type: number
|
||||
timelines:
|
||||
items:
|
||||
$ref: >-
|
||||
#/components/schemas/Security_Timeline_API_TimelineResponse
|
||||
type: array
|
||||
totalCount:
|
||||
type: number
|
||||
required:
|
||||
- timelines
|
||||
- totalCount
|
||||
- defaultTimelineCount
|
||||
- templateTimelineCount
|
||||
- favoriteCount
|
||||
- elasticTemplateTimelineCount
|
||||
- customTemplateTimelineCount
|
||||
customTemplateTimelineCount:
|
||||
type: number
|
||||
defaultTimelineCount:
|
||||
type: number
|
||||
elasticTemplateTimelineCount:
|
||||
type: number
|
||||
favoriteCount:
|
||||
type: number
|
||||
templateTimelineCount:
|
||||
type: number
|
||||
timeline:
|
||||
items:
|
||||
$ref: >-
|
||||
#/components/schemas/Security_Timeline_API_TimelineResponse
|
||||
type: array
|
||||
totalCount:
|
||||
type: number
|
||||
required:
|
||||
- data
|
||||
- timeline
|
||||
- totalCount
|
||||
description: Indicates that the (template) timelines were found and returned.
|
||||
'400':
|
||||
content:
|
||||
|
@ -39213,30 +39153,39 @@ components:
|
|||
type: object
|
||||
properties:
|
||||
aggregatable:
|
||||
nullable: true
|
||||
type: boolean
|
||||
category:
|
||||
nullable: true
|
||||
type: string
|
||||
columnHeaderType:
|
||||
nullable: true
|
||||
type: string
|
||||
description:
|
||||
nullable: true
|
||||
type: string
|
||||
example:
|
||||
oneOf:
|
||||
- type: string
|
||||
- type: number
|
||||
nullable: true
|
||||
type: string
|
||||
id:
|
||||
nullable: true
|
||||
type: string
|
||||
indexes:
|
||||
items:
|
||||
type: string
|
||||
nullable: true
|
||||
type: array
|
||||
name:
|
||||
nullable: true
|
||||
type: string
|
||||
placeholder:
|
||||
nullable: true
|
||||
type: string
|
||||
searchable:
|
||||
nullable: true
|
||||
type: boolean
|
||||
type:
|
||||
nullable: true
|
||||
type: string
|
||||
Security_Timeline_API_DataProviderQueryMatch:
|
||||
type: object
|
||||
|
@ -39258,6 +39207,10 @@ components:
|
|||
type: string
|
||||
queryMatch:
|
||||
$ref: '#/components/schemas/Security_Timeline_API_QueryMatchResult'
|
||||
nullable: true
|
||||
type:
|
||||
$ref: '#/components/schemas/Security_Timeline_API_DataProviderType'
|
||||
nullable: true
|
||||
Security_Timeline_API_DataProviderResult:
|
||||
type: object
|
||||
properties:
|
||||
|
@ -39345,41 +39298,59 @@ components:
|
|||
type: object
|
||||
properties:
|
||||
exists:
|
||||
type: boolean
|
||||
nullable: true
|
||||
type: string
|
||||
match_all:
|
||||
nullable: true
|
||||
type: string
|
||||
meta:
|
||||
nullable: true
|
||||
type: object
|
||||
properties:
|
||||
alias:
|
||||
nullable: true
|
||||
type: string
|
||||
controlledBy:
|
||||
nullable: true
|
||||
type: string
|
||||
disabled:
|
||||
nullable: true
|
||||
type: boolean
|
||||
field:
|
||||
nullable: true
|
||||
type: string
|
||||
formattedValue:
|
||||
nullable: true
|
||||
type: string
|
||||
index:
|
||||
nullable: true
|
||||
type: string
|
||||
key:
|
||||
nullable: true
|
||||
type: string
|
||||
negate:
|
||||
nullable: true
|
||||
type: boolean
|
||||
params:
|
||||
nullable: true
|
||||
type: string
|
||||
type:
|
||||
nullable: true
|
||||
type: string
|
||||
value:
|
||||
nullable: true
|
||||
type: string
|
||||
missing:
|
||||
nullable: true
|
||||
type: string
|
||||
query:
|
||||
nullable: true
|
||||
type: string
|
||||
range:
|
||||
nullable: true
|
||||
type: string
|
||||
script:
|
||||
nullable: true
|
||||
type: string
|
||||
Security_Timeline_API_GetNotesResult:
|
||||
type: object
|
||||
|
@ -39444,6 +39415,12 @@ components:
|
|||
version:
|
||||
nullable: true
|
||||
type: string
|
||||
required:
|
||||
- savedObjectId
|
||||
- version
|
||||
- pinnedEventIds
|
||||
- eventNotes
|
||||
- globalNotes
|
||||
Security_Timeline_API_Note:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/Security_Timeline_API_BareNote'
|
||||
|
@ -39464,6 +39441,23 @@ components:
|
|||
#/components/schemas/Security_Timeline_API_PinnedEventBaseResponseBody
|
||||
- nullable: true
|
||||
type: object
|
||||
Security_Timeline_API_PersistTimelineResponse:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
type: object
|
||||
properties:
|
||||
persistTimeline:
|
||||
type: object
|
||||
properties:
|
||||
timeline:
|
||||
$ref: '#/components/schemas/Security_Timeline_API_TimelineResponse'
|
||||
required:
|
||||
- timeline
|
||||
required:
|
||||
- persistTimeline
|
||||
required:
|
||||
- data
|
||||
Security_Timeline_API_PinnedEvent:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/Security_Timeline_API_BarePinnedEvent'
|
||||
|
@ -39501,34 +39495,29 @@ components:
|
|||
nullable: true
|
||||
type: string
|
||||
value:
|
||||
nullable: true
|
||||
type: string
|
||||
Security_Timeline_API_Readable:
|
||||
oneOf:
|
||||
- nullable: true
|
||||
type: string
|
||||
- items:
|
||||
type: string
|
||||
nullable: true
|
||||
type: array
|
||||
Security_Timeline_API_ResolvedTimeline:
|
||||
type: object
|
||||
properties:
|
||||
_data:
|
||||
additionalProperties: true
|
||||
type: object
|
||||
_encoding:
|
||||
alias_purpose:
|
||||
$ref: >-
|
||||
#/components/schemas/Security_Timeline_API_SavedObjectResolveAliasPurpose
|
||||
alias_target_id:
|
||||
type: string
|
||||
_events:
|
||||
additionalProperties: true
|
||||
type: object
|
||||
_eventsCount:
|
||||
type: number
|
||||
_maxListeners:
|
||||
additionalProperties: true
|
||||
type: object
|
||||
_position:
|
||||
type: number
|
||||
_read:
|
||||
additionalProperties: true
|
||||
type: object
|
||||
_readableState:
|
||||
additionalProperties: true
|
||||
type: object
|
||||
readable:
|
||||
type: boolean
|
||||
outcome:
|
||||
$ref: '#/components/schemas/Security_Timeline_API_SavedObjectResolveOutcome'
|
||||
timeline:
|
||||
$ref: >-
|
||||
#/components/schemas/Security_Timeline_API_TimelineSavedToReturnObject
|
||||
required:
|
||||
- timeline
|
||||
- outcome
|
||||
Security_Timeline_API_ResponseNote:
|
||||
type: object
|
||||
properties:
|
||||
|
@ -39563,6 +39552,17 @@ components:
|
|||
- threat_match
|
||||
- zeek
|
||||
type: string
|
||||
Security_Timeline_API_SavedObjectResolveAliasPurpose:
|
||||
enum:
|
||||
- savedObjectConversion
|
||||
- savedObjectImport
|
||||
type: string
|
||||
Security_Timeline_API_SavedObjectResolveOutcome:
|
||||
enum:
|
||||
- exactMatch
|
||||
- aliasMatch
|
||||
- conflict
|
||||
type: string
|
||||
Security_Timeline_API_SavedTimeline:
|
||||
type: object
|
||||
properties:
|
||||
|
@ -39591,12 +39591,16 @@ components:
|
|||
properties:
|
||||
end:
|
||||
oneOf:
|
||||
- type: string
|
||||
- type: number
|
||||
- nullable: true
|
||||
type: string
|
||||
- nullable: true
|
||||
type: number
|
||||
start:
|
||||
oneOf:
|
||||
- type: string
|
||||
- type: number
|
||||
- nullable: true
|
||||
type: string
|
||||
- nullable: true
|
||||
type: number
|
||||
description:
|
||||
nullable: true
|
||||
type: string
|
||||
|
@ -39686,6 +39690,18 @@ components:
|
|||
updatedBy:
|
||||
nullable: true
|
||||
type: string
|
||||
Security_Timeline_API_SavedTimelineWithSavedObjectId:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/Security_Timeline_API_SavedTimeline'
|
||||
- type: object
|
||||
properties:
|
||||
savedObjectId:
|
||||
type: string
|
||||
version:
|
||||
type: string
|
||||
required:
|
||||
- savedObjectId
|
||||
- version
|
||||
Security_Timeline_API_SerializedFilterQueryResult:
|
||||
type: object
|
||||
properties:
|
||||
|
@ -39735,27 +39751,64 @@ components:
|
|||
Security_Timeline_API_TimelineResponse:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/Security_Timeline_API_SavedTimeline'
|
||||
- $ref: >-
|
||||
#/components/schemas/Security_Timeline_API_SavedTimelineWithSavedObjectId
|
||||
- type: object
|
||||
properties:
|
||||
eventIdToNoteIds:
|
||||
items:
|
||||
$ref: '#/components/schemas/Security_Timeline_API_Note'
|
||||
nullable: true
|
||||
type: array
|
||||
noteIds:
|
||||
items:
|
||||
type: string
|
||||
nullable: true
|
||||
type: array
|
||||
notes:
|
||||
items:
|
||||
$ref: '#/components/schemas/Security_Timeline_API_Note'
|
||||
nullable: true
|
||||
type: array
|
||||
pinnedEventIds:
|
||||
items:
|
||||
type: string
|
||||
nullable: true
|
||||
type: array
|
||||
pinnedEventsSaveObject:
|
||||
items:
|
||||
$ref: '#/components/schemas/Security_Timeline_API_PinnedEvent'
|
||||
nullable: true
|
||||
type: array
|
||||
Security_Timeline_API_TimelineSavedToReturnObject:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/Security_Timeline_API_SavedTimeline'
|
||||
- type: object
|
||||
properties:
|
||||
eventIdToNoteIds:
|
||||
items:
|
||||
$ref: '#/components/schemas/Security_Timeline_API_Note'
|
||||
nullable: true
|
||||
type: array
|
||||
noteIds:
|
||||
items:
|
||||
type: string
|
||||
nullable: true
|
||||
type: array
|
||||
notes:
|
||||
items:
|
||||
$ref: '#/components/schemas/Security_Timeline_API_Note'
|
||||
nullable: true
|
||||
type: array
|
||||
pinnedEventIds:
|
||||
items:
|
||||
type: string
|
||||
nullable: true
|
||||
type: array
|
||||
pinnedEventsSaveObject:
|
||||
items:
|
||||
$ref: '#/components/schemas/Security_Timeline_API_PinnedEvent'
|
||||
nullable: true
|
||||
type: array
|
||||
savedObjectId:
|
||||
type: string
|
||||
|
|
|
@ -296,6 +296,10 @@ import type {
|
|||
CleanDraftTimelinesRequestBodyInput,
|
||||
CleanDraftTimelinesResponse,
|
||||
} from './timeline/clean_draft_timelines/clean_draft_timelines_route.gen';
|
||||
import type {
|
||||
CopyTimelineRequestBodyInput,
|
||||
CopyTimelineResponse,
|
||||
} from './timeline/copy_timeline/copy_timeline_route.gen';
|
||||
import type {
|
||||
CreateTimelinesRequestBodyInput,
|
||||
CreateTimelinesResponse,
|
||||
|
@ -551,6 +555,23 @@ after 30 days. It also deletes other artifacts specific to the migration impleme
|
|||
})
|
||||
.catch(catchAxiosErrorFormatAndThrow);
|
||||
}
|
||||
/**
|
||||
* Copies and returns a timeline or timeline template.
|
||||
|
||||
*/
|
||||
async copyTimeline(props: CopyTimelineProps) {
|
||||
this.log.info(`${new Date().toISOString()} Calling API CopyTimeline`);
|
||||
return this.kbnClient
|
||||
.request<CopyTimelineResponse>({
|
||||
path: '/api/timeline/_copy',
|
||||
headers: {
|
||||
[ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31',
|
||||
},
|
||||
method: 'GET',
|
||||
body: props.body,
|
||||
})
|
||||
.catch(catchAxiosErrorFormatAndThrow);
|
||||
}
|
||||
async createAlertsIndex() {
|
||||
this.log.info(`${new Date().toISOString()} Calling API CreateAlertsIndex`);
|
||||
return this.kbnClient
|
||||
|
@ -1946,6 +1967,9 @@ export interface BulkUpsertAssetCriticalityRecordsProps {
|
|||
export interface CleanDraftTimelinesProps {
|
||||
body: CleanDraftTimelinesRequestBodyInput;
|
||||
}
|
||||
export interface CopyTimelineProps {
|
||||
body: CopyTimelineRequestBodyInput;
|
||||
}
|
||||
export interface CreateAlertsMigrationProps {
|
||||
body: CreateAlertsMigrationRequestBodyInput;
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
import { z } from '@kbn/zod';
|
||||
|
||||
import { TimelineType, TimelineResponse } from '../model/components.gen';
|
||||
import { TimelineType, PersistTimelineResponse } from '../model/components.gen';
|
||||
|
||||
export type CleanDraftTimelinesRequestBody = z.infer<typeof CleanDraftTimelinesRequestBody>;
|
||||
export const CleanDraftTimelinesRequestBody = z.object({
|
||||
|
@ -25,10 +25,4 @@ export const CleanDraftTimelinesRequestBody = z.object({
|
|||
export type CleanDraftTimelinesRequestBodyInput = z.input<typeof CleanDraftTimelinesRequestBody>;
|
||||
|
||||
export type CleanDraftTimelinesResponse = z.infer<typeof CleanDraftTimelinesResponse>;
|
||||
export const CleanDraftTimelinesResponse = z.object({
|
||||
data: z.object({
|
||||
persistTimeline: z.object({
|
||||
timeline: TimelineResponse,
|
||||
}),
|
||||
}),
|
||||
});
|
||||
export const CleanDraftTimelinesResponse = PersistTimelineResponse;
|
||||
|
|
|
@ -2,13 +2,6 @@ openapi: 3.0.0
|
|||
info:
|
||||
title: Elastic Security - Timeline - Draft Timeline API
|
||||
version: '2023-10-31'
|
||||
servers:
|
||||
- url: 'http://{kibana_host}:{port}'
|
||||
variables:
|
||||
kibana_host:
|
||||
default: localhost
|
||||
port:
|
||||
default: '5601'
|
||||
paths:
|
||||
/api/timeline/_draft:
|
||||
post:
|
||||
|
@ -37,19 +30,7 @@ paths:
|
|||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [data]
|
||||
properties:
|
||||
data:
|
||||
type: object
|
||||
required: [persistTimeline]
|
||||
properties:
|
||||
persistTimeline:
|
||||
type: object
|
||||
required: [timeline]
|
||||
properties:
|
||||
timeline:
|
||||
$ref: '../model/components.schema.yaml#/components/schemas/TimelineResponse'
|
||||
$ref: '../model/components.schema.yaml#/components/schemas/PersistTimelineResponse'
|
||||
'403':
|
||||
description: Indicates that the user does not have the required permissions to create a draft timeline.
|
||||
content:
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
/*
|
||||
* NOTICE: Do not edit this file manually.
|
||||
* This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator.
|
||||
*
|
||||
* info:
|
||||
* title: Elastic Security - Timeline - Copy Timeline API
|
||||
* version: 2023-10-31
|
||||
*/
|
||||
|
||||
import { z } from '@kbn/zod';
|
||||
|
||||
import { SavedTimeline, PersistTimelineResponse } from '../model/components.gen';
|
||||
|
||||
export type CopyTimelineRequestBody = z.infer<typeof CopyTimelineRequestBody>;
|
||||
export const CopyTimelineRequestBody = z.object({
|
||||
timeline: SavedTimeline,
|
||||
timelineIdToCopy: z.string(),
|
||||
});
|
||||
export type CopyTimelineRequestBodyInput = z.input<typeof CopyTimelineRequestBody>;
|
||||
|
||||
export type CopyTimelineResponse = z.infer<typeof CopyTimelineResponse>;
|
||||
export const CopyTimelineResponse = PersistTimelineResponse;
|
|
@ -0,0 +1,34 @@
|
|||
openapi: 3.0.0
|
||||
info:
|
||||
title: Elastic Security - Timeline - Copy Timeline API
|
||||
version: '2023-10-31'
|
||||
paths:
|
||||
/api/timeline/_copy:
|
||||
get:
|
||||
x-labels: [serverless, ess]
|
||||
x-codegen-enabled: true
|
||||
operationId: CopyTimeline
|
||||
summary: Copies timeline or timeline template
|
||||
description: |
|
||||
Copies and returns a timeline or timeline template.
|
||||
tags:
|
||||
- access:securitySolution
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [timeline, timelineIdToCopy]
|
||||
properties:
|
||||
timeline:
|
||||
$ref: '../model/components.schema.yaml#/components/schemas/SavedTimeline'
|
||||
timelineIdToCopy:
|
||||
type: string
|
||||
responses:
|
||||
'200':
|
||||
description: Indicates that the timeline has been successfully copied.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '../model/components.schema.yaml#/components/schemas/PersistTimelineResponse'
|
|
@ -1,15 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import * as rt from 'io-ts';
|
||||
|
||||
import { SavedTimelineRuntimeType } from '../model/api';
|
||||
|
||||
export const copyTimelineSchema = rt.type({
|
||||
timeline: SavedTimelineRuntimeType,
|
||||
timelineIdToCopy: rt.string,
|
||||
});
|
|
@ -17,29 +17,23 @@
|
|||
import { z } from '@kbn/zod';
|
||||
|
||||
import {
|
||||
SavedTimeline,
|
||||
TimelineStatus,
|
||||
TimelineType,
|
||||
SavedTimeline,
|
||||
TimelineResponse,
|
||||
PersistTimelineResponse,
|
||||
} from '../model/components.gen';
|
||||
|
||||
export type CreateTimelinesRequestBody = z.infer<typeof CreateTimelinesRequestBody>;
|
||||
export const CreateTimelinesRequestBody = z.object({
|
||||
timeline: SavedTimeline,
|
||||
status: TimelineStatus.nullable().optional(),
|
||||
timelineId: z.string().nullable().optional(),
|
||||
templateTimelineId: z.string().nullable().optional(),
|
||||
templateTimelineVersion: z.number().nullable().optional(),
|
||||
timelineType: TimelineType.nullable().optional(),
|
||||
version: z.string().nullable().optional(),
|
||||
timeline: SavedTimeline,
|
||||
});
|
||||
export type CreateTimelinesRequestBodyInput = z.input<typeof CreateTimelinesRequestBody>;
|
||||
|
||||
export type CreateTimelinesResponse = z.infer<typeof CreateTimelinesResponse>;
|
||||
export const CreateTimelinesResponse = z.object({
|
||||
data: z.object({
|
||||
persistTimeline: z.object({
|
||||
timeline: TimelineResponse.optional(),
|
||||
}),
|
||||
}),
|
||||
});
|
||||
export const CreateTimelinesResponse = PersistTimelineResponse;
|
||||
|
|
|
@ -5,13 +5,6 @@ info:
|
|||
externalDocs:
|
||||
url: https://www.elastic.co/guide/en/security/current/timeline-api-create.html
|
||||
description: Documentation
|
||||
servers:
|
||||
- url: 'http://{kibana_host}:{port}'
|
||||
variables:
|
||||
kibana_host:
|
||||
default: localhost
|
||||
port:
|
||||
default: '5601'
|
||||
paths:
|
||||
/api/timeline:
|
||||
post:
|
||||
|
@ -28,9 +21,10 @@ paths:
|
|||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required:
|
||||
- timeline
|
||||
required: [timeline]
|
||||
properties:
|
||||
timeline:
|
||||
$ref: '../model/components.schema.yaml#/components/schemas/SavedTimeline'
|
||||
status:
|
||||
$ref: '../model/components.schema.yaml#/components/schemas/TimelineStatus'
|
||||
nullable: true
|
||||
|
@ -49,26 +43,13 @@ paths:
|
|||
version:
|
||||
type: string
|
||||
nullable: true
|
||||
timeline:
|
||||
$ref: '../model/components.schema.yaml#/components/schemas/SavedTimeline'
|
||||
responses:
|
||||
'200':
|
||||
description: Indicates the timeline was successfully created.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [data]
|
||||
properties:
|
||||
data:
|
||||
type: object
|
||||
required: [persistTimeline]
|
||||
properties:
|
||||
persistTimeline:
|
||||
type: object
|
||||
properties:
|
||||
timeline:
|
||||
$ref: '../model/components.schema.yaml#/components/schemas/TimelineResponse'
|
||||
$ref: '../model/components.schema.yaml#/components/schemas/PersistTimelineResponse'
|
||||
'405':
|
||||
description: Indicates that there was an error in the timeline creation.
|
||||
content:
|
||||
|
|
|
@ -1,36 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import * as rt from 'io-ts';
|
||||
|
||||
import type { ResponseTimeline } from '../model/api';
|
||||
import {
|
||||
SavedTimelineRuntimeType,
|
||||
TimelineStatusLiteralRt,
|
||||
TimelineTypeLiteralRt,
|
||||
} from '../model/api';
|
||||
import { unionWithNullType } from '../../../utility_types';
|
||||
|
||||
export const createTimelineSchema = rt.intersection([
|
||||
rt.type({
|
||||
timeline: SavedTimelineRuntimeType,
|
||||
}),
|
||||
rt.partial({
|
||||
status: unionWithNullType(TimelineStatusLiteralRt),
|
||||
timelineId: unionWithNullType(rt.string),
|
||||
templateTimelineId: unionWithNullType(rt.string),
|
||||
templateTimelineVersion: unionWithNullType(rt.number),
|
||||
timelineType: unionWithNullType(TimelineTypeLiteralRt),
|
||||
version: unionWithNullType(rt.string),
|
||||
}),
|
||||
]);
|
||||
|
||||
export interface CreateTimelinesResponse {
|
||||
data: {
|
||||
persistTimeline: ResponseTimeline;
|
||||
};
|
||||
}
|
|
@ -2,13 +2,6 @@ openapi: 3.0.0
|
|||
info:
|
||||
title: Elastic Security - Timeline - Notes API
|
||||
version: '2023-10-31'
|
||||
servers:
|
||||
- url: 'http://{kibana_host}:{port}'
|
||||
variables:
|
||||
kibana_host:
|
||||
default: localhost
|
||||
port:
|
||||
default: '5601'
|
||||
paths:
|
||||
/api/note:
|
||||
delete:
|
||||
|
|
|
@ -5,13 +5,6 @@ info:
|
|||
externalDocs:
|
||||
url: https://www.elastic.co/guide/en/security/current/timeline-api-delete.html
|
||||
description: Documentation
|
||||
servers:
|
||||
- url: 'http://{kibana_host}:{port}'
|
||||
variables:
|
||||
kibana_host:
|
||||
default: localhost
|
||||
port:
|
||||
default: '5601'
|
||||
paths:
|
||||
/api/timeline:
|
||||
delete:
|
||||
|
|
|
@ -5,13 +5,6 @@ info:
|
|||
externalDocs:
|
||||
url: https://www.elastic.co/guide/en/security/current/timeline-api-import.html
|
||||
description: Documentation
|
||||
servers:
|
||||
- url: 'http://{kibana_host}:{port}'
|
||||
variables:
|
||||
kibana_host:
|
||||
default: localhost
|
||||
port:
|
||||
default: '5601'
|
||||
paths:
|
||||
/api/timeline/_export:
|
||||
post:
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
import { z } from '@kbn/zod';
|
||||
|
||||
import { TimelineType, TimelineResponse } from '../model/components.gen';
|
||||
import { TimelineType, PersistTimelineResponse } from '../model/components.gen';
|
||||
|
||||
export type GetDraftTimelinesRequestQuery = z.infer<typeof GetDraftTimelinesRequestQuery>;
|
||||
export const GetDraftTimelinesRequestQuery = z.object({
|
||||
|
@ -25,10 +25,4 @@ export const GetDraftTimelinesRequestQuery = z.object({
|
|||
export type GetDraftTimelinesRequestQueryInput = z.input<typeof GetDraftTimelinesRequestQuery>;
|
||||
|
||||
export type GetDraftTimelinesResponse = z.infer<typeof GetDraftTimelinesResponse>;
|
||||
export const GetDraftTimelinesResponse = z.object({
|
||||
data: z.object({
|
||||
persistTimeline: z.object({
|
||||
timeline: TimelineResponse,
|
||||
}),
|
||||
}),
|
||||
});
|
||||
export const GetDraftTimelinesResponse = PersistTimelineResponse;
|
||||
|
|
|
@ -2,13 +2,6 @@ openapi: 3.0.0
|
|||
info:
|
||||
title: Elastic Security - Timeline - Get Draft Timelines API
|
||||
version: '2023-10-31'
|
||||
servers:
|
||||
- url: 'http://{kibana_host}:{port}'
|
||||
variables:
|
||||
kibana_host:
|
||||
default: localhost
|
||||
port:
|
||||
default: '5601'
|
||||
paths:
|
||||
/api/timeline/_draft:
|
||||
get:
|
||||
|
@ -30,19 +23,7 @@ paths:
|
|||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [data]
|
||||
properties:
|
||||
data:
|
||||
type: object
|
||||
required: [persistTimeline]
|
||||
properties:
|
||||
persistTimeline:
|
||||
type: object
|
||||
required: [timeline]
|
||||
properties:
|
||||
timeline:
|
||||
$ref: '../model/components.schema.yaml#/components/schemas/TimelineResponse'
|
||||
$ref: '../model/components.schema.yaml#/components/schemas/PersistTimelineResponse'
|
||||
'403':
|
||||
description: If a draft timeline was not found and we attempted to create one, it indicates that the user does not have the required permissions to create a draft timeline.
|
||||
content:
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import * as rt from 'io-ts';
|
||||
|
||||
import { TimelineTypeLiteralRt } from '../model/api';
|
||||
|
||||
export const getDraftTimelineSchema = rt.type({
|
||||
timelineType: TimelineTypeLiteralRt,
|
||||
});
|
|
@ -2,13 +2,6 @@ openapi: 3.0.0
|
|||
info:
|
||||
title: Elastic Security - Timeline - Notes API
|
||||
version: '2023-10-31'
|
||||
servers:
|
||||
- url: 'http://{kibana_host}:{port}'
|
||||
variables:
|
||||
kibana_host:
|
||||
default: localhost
|
||||
port:
|
||||
default: '5601'
|
||||
paths:
|
||||
/api/note:
|
||||
get:
|
||||
|
|
|
@ -32,8 +32,11 @@ export const GetTimelineRequestQuery = z.object({
|
|||
export type GetTimelineRequestQueryInput = z.input<typeof GetTimelineRequestQuery>;
|
||||
|
||||
export type GetTimelineResponse = z.infer<typeof GetTimelineResponse>;
|
||||
export const GetTimelineResponse = z.object({
|
||||
data: z.object({
|
||||
getOneTimeline: TimelineResponse.nullable(),
|
||||
export const GetTimelineResponse = z.union([
|
||||
z.object({
|
||||
data: z.object({
|
||||
getOneTimeline: TimelineResponse,
|
||||
}),
|
||||
}),
|
||||
});
|
||||
z.object({}).strict(),
|
||||
]);
|
||||
|
|
|
@ -5,13 +5,6 @@ info:
|
|||
externalDocs:
|
||||
url: https://www.elastic.co/guide/en/security/current/_get_timeline_or_timeline_template_by_savedobjectid.html
|
||||
description: Documentation
|
||||
servers:
|
||||
- url: 'http://{kibana_host}:{port}'
|
||||
variables:
|
||||
kibana_host:
|
||||
default: localhost
|
||||
port:
|
||||
default: '5601'
|
||||
paths:
|
||||
/api/timeline:
|
||||
get:
|
||||
|
@ -38,13 +31,15 @@ paths:
|
|||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [data]
|
||||
properties:
|
||||
data:
|
||||
type: object
|
||||
required: [getOneTimeline]
|
||||
oneOf:
|
||||
- type: object
|
||||
required: [data]
|
||||
properties:
|
||||
getOneTimeline:
|
||||
$ref: '../model/components.schema.yaml#/components/schemas/TimelineResponse'
|
||||
nullable: true
|
||||
data:
|
||||
type: object
|
||||
required: [getOneTimeline]
|
||||
properties:
|
||||
getOneTimeline:
|
||||
$ref: '../model/components.schema.yaml#/components/schemas/TimelineResponse'
|
||||
- type: object
|
||||
additionalProperties: false
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import * as rt from 'io-ts';
|
||||
|
||||
export const getTimelineQuerySchema = rt.partial({
|
||||
template_timeline_id: rt.string,
|
||||
id: rt.string,
|
||||
});
|
||||
|
||||
export type GetTimelineQuery = rt.TypeOf<typeof getTimelineQuerySchema>;
|
|
@ -41,13 +41,11 @@ export type GetTimelinesRequestQueryInput = z.input<typeof GetTimelinesRequestQu
|
|||
|
||||
export type GetTimelinesResponse = z.infer<typeof GetTimelinesResponse>;
|
||||
export const GetTimelinesResponse = z.object({
|
||||
data: z.object({
|
||||
timelines: z.array(TimelineResponse),
|
||||
totalCount: z.number(),
|
||||
defaultTimelineCount: z.number(),
|
||||
templateTimelineCount: z.number(),
|
||||
favoriteCount: z.number(),
|
||||
elasticTemplateTimelineCount: z.number(),
|
||||
customTemplateTimelineCount: z.number(),
|
||||
}),
|
||||
timeline: z.array(TimelineResponse),
|
||||
totalCount: z.number(),
|
||||
defaultTimelineCount: z.number().optional(),
|
||||
templateTimelineCount: z.number().optional(),
|
||||
favoriteCount: z.number().optional(),
|
||||
elasticTemplateTimelineCount: z.number().optional(),
|
||||
customTemplateTimelineCount: z.number().optional(),
|
||||
});
|
||||
|
|
|
@ -5,13 +5,6 @@ info:
|
|||
externalDocs:
|
||||
url: https://www.elastic.co/guide/en/security/current/timeline-api-get.html
|
||||
description: Documentation
|
||||
servers:
|
||||
- url: 'http://{kibana_host}:{port}'
|
||||
variables:
|
||||
kibana_host:
|
||||
default: localhost
|
||||
port:
|
||||
default: '5601'
|
||||
paths:
|
||||
/api/timelines:
|
||||
get:
|
||||
|
@ -74,37 +67,27 @@ paths:
|
|||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [data]
|
||||
required: [
|
||||
timeline,
|
||||
totalCount,
|
||||
]
|
||||
properties:
|
||||
data:
|
||||
type: object
|
||||
required:
|
||||
[
|
||||
timelines,
|
||||
totalCount,
|
||||
defaultTimelineCount,
|
||||
templateTimelineCount,
|
||||
favoriteCount,
|
||||
elasticTemplateTimelineCount,
|
||||
customTemplateTimelineCount,
|
||||
]
|
||||
properties:
|
||||
timelines:
|
||||
type: array
|
||||
items:
|
||||
$ref: '../model/components.schema.yaml#/components/schemas/TimelineResponse'
|
||||
totalCount:
|
||||
type: number
|
||||
defaultTimelineCount:
|
||||
type: number
|
||||
templateTimelineCount:
|
||||
type: number
|
||||
favoriteCount:
|
||||
type: number
|
||||
elasticTemplateTimelineCount:
|
||||
type: number
|
||||
customTemplateTimelineCount:
|
||||
type: number
|
||||
timeline:
|
||||
type: array
|
||||
items:
|
||||
$ref: '../model/components.schema.yaml#/components/schemas/TimelineResponse'
|
||||
totalCount:
|
||||
type: number
|
||||
defaultTimelineCount:
|
||||
type: number
|
||||
templateTimelineCount:
|
||||
type: number
|
||||
favoriteCount:
|
||||
type: number
|
||||
elasticTemplateTimelineCount:
|
||||
type: number
|
||||
customTemplateTimelineCount:
|
||||
type: number
|
||||
'400':
|
||||
description: Bad request. The user supplied invalid data.
|
||||
content:
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import * as rt from 'io-ts';
|
||||
import {
|
||||
direction,
|
||||
sortFieldTimeline,
|
||||
TimelineStatusLiteralRt,
|
||||
TimelineTypeLiteralRt,
|
||||
} from '../model/api';
|
||||
import { unionWithNullType } from '../../../utility_types';
|
||||
|
||||
const BoolFromString = rt.union([rt.literal('true'), rt.literal('false')]);
|
||||
|
||||
export const getTimelinesQuerySchema = rt.partial({
|
||||
only_user_favorite: unionWithNullType(BoolFromString),
|
||||
page_index: unionWithNullType(rt.string),
|
||||
page_size: unionWithNullType(rt.string),
|
||||
search: unionWithNullType(rt.string),
|
||||
sort_field: sortFieldTimeline,
|
||||
sort_order: direction,
|
||||
status: unionWithNullType(TimelineStatusLiteralRt),
|
||||
timeline_type: unionWithNullType(TimelineTypeLiteralRt),
|
||||
});
|
|
@ -16,23 +16,14 @@
|
|||
|
||||
import { z } from '@kbn/zod';
|
||||
|
||||
import { Readable, ImportTimelineResult } from '../model/components.gen';
|
||||
import { ImportTimelineResult } from '../model/components.gen';
|
||||
|
||||
export type ImportTimelinesRequestBody = z.infer<typeof ImportTimelinesRequestBody>;
|
||||
export const ImportTimelinesRequestBody = z.object({
|
||||
file: Readable.merge(
|
||||
z.object({
|
||||
hapi: z.object({
|
||||
filename: z.string(),
|
||||
headers: z.object({}),
|
||||
isImmutable: z.enum(['true', 'false']).optional(),
|
||||
}),
|
||||
})
|
||||
),
|
||||
isImmutable: z.enum(['true', 'false']).optional(),
|
||||
file: z.unknown(),
|
||||
});
|
||||
export type ImportTimelinesRequestBodyInput = z.input<typeof ImportTimelinesRequestBody>;
|
||||
|
||||
export type ImportTimelinesResponse = z.infer<typeof ImportTimelinesResponse>;
|
||||
export const ImportTimelinesResponse = z.object({
|
||||
data: ImportTimelineResult,
|
||||
});
|
||||
export const ImportTimelinesResponse = ImportTimelineResult;
|
||||
|
|
|
@ -5,13 +5,6 @@ info:
|
|||
externalDocs:
|
||||
url: https://www.elastic.co/guide/en/security/current/timeline-api-import.html
|
||||
description: Documentation
|
||||
servers:
|
||||
- url: 'http://{kibana_host}:{port}'
|
||||
variables:
|
||||
kibana_host:
|
||||
default: localhost
|
||||
port:
|
||||
default: '5601'
|
||||
paths:
|
||||
/api/timeline/_import:
|
||||
post:
|
||||
|
@ -28,37 +21,21 @@ paths:
|
|||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [file]
|
||||
properties:
|
||||
file:
|
||||
allOf:
|
||||
- $ref: '../model/components.schema.yaml#/components/schemas/Readable'
|
||||
- type: object
|
||||
required: [hapi]
|
||||
properties:
|
||||
hapi:
|
||||
type: object
|
||||
required: [filename, headers]
|
||||
properties:
|
||||
filename:
|
||||
type: string
|
||||
headers:
|
||||
type: object
|
||||
isImmutable:
|
||||
type: string
|
||||
enum:
|
||||
- 'true'
|
||||
- 'false'
|
||||
isImmutable:
|
||||
type: string
|
||||
enum:
|
||||
- 'true'
|
||||
- 'false'
|
||||
file: {}
|
||||
responses:
|
||||
'200':
|
||||
description: Indicates the import of timelines was successful.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [data]
|
||||
properties:
|
||||
data:
|
||||
$ref: '../model/components.schema.yaml#/components/schemas/ImportTimelineResult'
|
||||
$ref: '../model/components.schema.yaml#/components/schemas/ImportTimelineResult'
|
||||
|
||||
'400':
|
||||
description: Indicates the import of timelines was unsuccessful because of an invalid file extension.
|
||||
|
|
|
@ -1,60 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import * as rt from 'io-ts';
|
||||
|
||||
import { BareNoteSchema, SavedTimelineRuntimeType } from '../model/api';
|
||||
import { unionWithNullType } from '../../../utility_types';
|
||||
|
||||
const pinnedEventIds = unionWithNullType(rt.array(rt.string));
|
||||
|
||||
export const eventNotes = unionWithNullType(rt.array(BareNoteSchema));
|
||||
export const globalNotes = unionWithNullType(rt.array(BareNoteSchema));
|
||||
|
||||
export const ImportTimelinesSchemaRt = rt.intersection([
|
||||
SavedTimelineRuntimeType,
|
||||
rt.type({
|
||||
savedObjectId: unionWithNullType(rt.string),
|
||||
version: unionWithNullType(rt.string),
|
||||
}),
|
||||
rt.type({
|
||||
globalNotes,
|
||||
eventNotes,
|
||||
pinnedEventIds,
|
||||
}),
|
||||
]);
|
||||
|
||||
export type ImportTimelinesSchema = rt.TypeOf<typeof ImportTimelinesSchemaRt>;
|
||||
|
||||
const ReadableRt = rt.partial({
|
||||
_maxListeners: rt.unknown,
|
||||
_readableState: rt.unknown,
|
||||
_read: rt.unknown,
|
||||
readable: rt.boolean,
|
||||
_events: rt.unknown,
|
||||
_eventsCount: rt.number,
|
||||
_data: rt.unknown,
|
||||
_position: rt.number,
|
||||
_encoding: rt.string,
|
||||
});
|
||||
|
||||
const booleanInString = rt.union([rt.literal('true'), rt.literal('false')]);
|
||||
|
||||
export const ImportTimelinesPayloadSchemaRt = rt.intersection([
|
||||
rt.type({
|
||||
file: rt.intersection([
|
||||
ReadableRt,
|
||||
rt.type({
|
||||
hapi: rt.type({
|
||||
filename: rt.string,
|
||||
headers: rt.unknown,
|
||||
}),
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
rt.partial({ isImmutable: booleanInString }),
|
||||
]);
|
|
@ -7,13 +7,3 @@
|
|||
|
||||
export * from './model/api';
|
||||
export * from './routes';
|
||||
|
||||
export * from './get_draft_timelines/get_draft_timelines_route';
|
||||
export * from './create_timelines/create_timelines_route';
|
||||
export * from './get_timeline/get_timeline_route';
|
||||
export * from './get_timelines/get_timelines_route';
|
||||
export * from './import_timelines/import_timelines_route';
|
||||
export * from './patch_timelines/patch_timelines_schema';
|
||||
export * from './pinned_events/pinned_events_route';
|
||||
export * from './install_prepackaged_timelines/install_prepackaged_timelines';
|
||||
export * from './copy_timeline/copy_timeline_route';
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import * as rt from 'io-ts';
|
||||
|
||||
import { unionWithNullType } from '../../../utility_types';
|
||||
import { ImportTimelinesSchemaRt, TimelineSavedToReturnObjectRuntimeType } from '..';
|
||||
|
||||
export const checkTimelineStatusRt = rt.type({
|
||||
timelinesToInstall: rt.array(unionWithNullType(ImportTimelinesSchemaRt)),
|
||||
timelinesToUpdate: rt.array(unionWithNullType(ImportTimelinesSchemaRt)),
|
||||
prepackagedTimelines: rt.array(unionWithNullType(TimelineSavedToReturnObjectRuntimeType)),
|
||||
});
|
||||
|
||||
export type CheckTimelineStatusRt = rt.TypeOf<typeof checkTimelineStatusRt>;
|
|
@ -16,7 +16,11 @@
|
|||
|
||||
import { z } from '@kbn/zod';
|
||||
|
||||
import { ImportTimelines, SavedTimeline, ImportTimelineResult } from '../model/components.gen';
|
||||
import {
|
||||
ImportTimelines,
|
||||
TimelineSavedToReturnObject,
|
||||
ImportTimelineResult,
|
||||
} from '../model/components.gen';
|
||||
|
||||
export type InstallPrepackedTimelinesRequestBody = z.infer<
|
||||
typeof InstallPrepackedTimelinesRequestBody
|
||||
|
@ -24,13 +28,11 @@ export type InstallPrepackedTimelinesRequestBody = z.infer<
|
|||
export const InstallPrepackedTimelinesRequestBody = z.object({
|
||||
timelinesToInstall: z.array(ImportTimelines.nullable()),
|
||||
timelinesToUpdate: z.array(ImportTimelines.nullable()),
|
||||
prepackagedTimelines: z.array(SavedTimeline),
|
||||
prepackagedTimelines: z.array(TimelineSavedToReturnObject.nullable()),
|
||||
});
|
||||
export type InstallPrepackedTimelinesRequestBodyInput = z.input<
|
||||
typeof InstallPrepackedTimelinesRequestBody
|
||||
>;
|
||||
|
||||
export type InstallPrepackedTimelinesResponse = z.infer<typeof InstallPrepackedTimelinesResponse>;
|
||||
export const InstallPrepackedTimelinesResponse = z.object({
|
||||
data: ImportTimelineResult,
|
||||
});
|
||||
export const InstallPrepackedTimelinesResponse = ImportTimelineResult;
|
||||
|
|
|
@ -2,13 +2,6 @@ openapi: 3.0.0
|
|||
info:
|
||||
title: Elastic Security - Timeline - Install Prepackaged Timelines API
|
||||
version: '2023-10-31'
|
||||
servers:
|
||||
- url: 'http://{kibana_host}:{port}'
|
||||
variables:
|
||||
kibana_host:
|
||||
default: localhost
|
||||
port:
|
||||
default: '5601'
|
||||
paths:
|
||||
/api/timeline/_prepackaged:
|
||||
post:
|
||||
|
@ -40,18 +33,15 @@ paths:
|
|||
prepackagedTimelines:
|
||||
type: array
|
||||
items:
|
||||
$ref: '../model/components.schema.yaml#/components/schemas/SavedTimeline'
|
||||
$ref: '../model/components.schema.yaml#/components/schemas/TimelineSavedToReturnObject'
|
||||
nullable: true
|
||||
responses:
|
||||
'200':
|
||||
description: Indicates the installation of prepackaged timelines was successful.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [data]
|
||||
properties:
|
||||
data:
|
||||
$ref: '../model/components.schema.yaml#/components/schemas/ImportTimelineResult'
|
||||
$ref: '../model/components.schema.yaml#/components/schemas/ImportTimelineResult'
|
||||
'500':
|
||||
description: Indicates the installation of prepackaged timelines was unsuccessful.
|
||||
content:
|
||||
|
|
|
@ -5,30 +5,35 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import * as runtimeTypes from 'io-ts';
|
||||
import { PositiveInteger } from '@kbn/securitysolution-io-ts-types';
|
||||
|
||||
import { stringEnum, unionWithNullType } from '../../../utility_types';
|
||||
|
||||
import type { Maybe } from '../../../search_strategy';
|
||||
import { Direction } from '../../../search_strategy';
|
||||
import { PinnedEventRuntimeType } from '../pinned_events/pinned_events_route';
|
||||
import { ErrorSchema } from './error_schema';
|
||||
import type { DataProviderType } from './components.gen';
|
||||
import {
|
||||
BareNote,
|
||||
BarePinnedEvent,
|
||||
ColumnHeaderResult,
|
||||
DataProviderTypeEnum,
|
||||
DataProviderResult,
|
||||
FavoriteTimelineResponse,
|
||||
type FavoriteTimelineResult,
|
||||
FilterTimelineResult,
|
||||
ImportTimelineResult,
|
||||
ImportTimelines,
|
||||
type Note,
|
||||
PinnedEvent,
|
||||
PersistTimelineResponse,
|
||||
QueryMatchResult,
|
||||
ResolvedTimeline,
|
||||
RowRendererId,
|
||||
RowRendererIdEnum,
|
||||
SavedTimeline,
|
||||
SavedTimelineWithSavedObjectId,
|
||||
Sort,
|
||||
SortDirection,
|
||||
SortFieldTimeline,
|
||||
SortFieldTimelineEnum,
|
||||
TemplateTimelineType,
|
||||
TemplateTimelineTypeEnum,
|
||||
TimelineErrorResponse,
|
||||
TimelineResponse,
|
||||
TimelineSavedToReturnObject,
|
||||
TimelineStatus,
|
||||
TimelineStatusEnum,
|
||||
TimelineType,
|
||||
|
@ -38,412 +43,54 @@ import {
|
|||
export {
|
||||
BareNote,
|
||||
BarePinnedEvent,
|
||||
ColumnHeaderResult,
|
||||
DataProviderResult,
|
||||
DataProviderType,
|
||||
DataProviderTypeEnum,
|
||||
FavoriteTimelineResponse,
|
||||
FilterTimelineResult,
|
||||
ImportTimelineResult,
|
||||
ImportTimelines,
|
||||
Note,
|
||||
PinnedEvent,
|
||||
PersistTimelineResponse,
|
||||
QueryMatchResult,
|
||||
ResolvedTimeline,
|
||||
RowRendererId,
|
||||
RowRendererIdEnum,
|
||||
SavedTimeline,
|
||||
SavedTimelineWithSavedObjectId,
|
||||
Sort,
|
||||
SortDirection,
|
||||
SortFieldTimeline,
|
||||
SortFieldTimelineEnum,
|
||||
TemplateTimelineType,
|
||||
TimelineErrorResponse,
|
||||
TimelineResponse,
|
||||
TemplateTimelineTypeEnum,
|
||||
TimelineSavedToReturnObject,
|
||||
TimelineStatus,
|
||||
TimelineStatusEnum,
|
||||
TimelineType,
|
||||
TimelineTypeEnum,
|
||||
};
|
||||
|
||||
export type BarePinnedEventWithoutExternalRefs = Omit<BarePinnedEvent, 'timelineId'>;
|
||||
|
||||
/**
|
||||
* Outcome is a property of the saved object resolve api
|
||||
* will tell us info about the rule after 8.0 migrations
|
||||
*/
|
||||
export type SavedObjectResolveOutcome = runtimeTypes.TypeOf<typeof SavedObjectResolveOutcome>;
|
||||
export const SavedObjectResolveOutcome = runtimeTypes.union([
|
||||
runtimeTypes.literal('exactMatch'),
|
||||
runtimeTypes.literal('aliasMatch'),
|
||||
runtimeTypes.literal('conflict'),
|
||||
]);
|
||||
|
||||
export type SavedObjectResolveAliasTargetId = runtimeTypes.TypeOf<
|
||||
typeof SavedObjectResolveAliasTargetId
|
||||
>;
|
||||
export const SavedObjectResolveAliasTargetId = runtimeTypes.string;
|
||||
|
||||
export type SavedObjectResolveAliasPurpose = runtimeTypes.TypeOf<
|
||||
typeof SavedObjectResolveAliasPurpose
|
||||
>;
|
||||
export const SavedObjectResolveAliasPurpose = runtimeTypes.union([
|
||||
runtimeTypes.literal('savedObjectConversion'),
|
||||
runtimeTypes.literal('savedObjectImport'),
|
||||
]);
|
||||
|
||||
export const BareNoteSchema = runtimeTypes.intersection([
|
||||
runtimeTypes.type({
|
||||
timelineId: runtimeTypes.string,
|
||||
}),
|
||||
runtimeTypes.partial({
|
||||
eventId: unionWithNullType(runtimeTypes.string),
|
||||
note: unionWithNullType(runtimeTypes.string),
|
||||
created: unionWithNullType(runtimeTypes.number),
|
||||
createdBy: unionWithNullType(runtimeTypes.string),
|
||||
updated: unionWithNullType(runtimeTypes.number),
|
||||
updatedBy: unionWithNullType(runtimeTypes.string),
|
||||
}),
|
||||
]);
|
||||
|
||||
/**
|
||||
* This type represents a note type stored in a saved object that does not include any fields that reference
|
||||
* other saved objects.
|
||||
*/
|
||||
export type BareNoteWithoutExternalRefs = Omit<BareNote, 'timelineId'>;
|
||||
|
||||
export const NoteRuntimeType = runtimeTypes.intersection([
|
||||
BareNoteSchema,
|
||||
runtimeTypes.type({
|
||||
noteId: runtimeTypes.string,
|
||||
version: runtimeTypes.string,
|
||||
}),
|
||||
]);
|
||||
|
||||
/*
|
||||
* ColumnHeader Types
|
||||
*/
|
||||
const SavedColumnHeaderRuntimeType = runtimeTypes.partial({
|
||||
aggregatable: unionWithNullType(runtimeTypes.boolean),
|
||||
category: unionWithNullType(runtimeTypes.string),
|
||||
columnHeaderType: unionWithNullType(runtimeTypes.string),
|
||||
description: unionWithNullType(runtimeTypes.string),
|
||||
example: unionWithNullType(runtimeTypes.string),
|
||||
indexes: unionWithNullType(runtimeTypes.array(runtimeTypes.string)),
|
||||
id: unionWithNullType(runtimeTypes.string),
|
||||
name: unionWithNullType(runtimeTypes.string),
|
||||
placeholder: unionWithNullType(runtimeTypes.string),
|
||||
searchable: unionWithNullType(runtimeTypes.boolean),
|
||||
type: unionWithNullType(runtimeTypes.string),
|
||||
});
|
||||
|
||||
/*
|
||||
* DataProvider Types
|
||||
*/
|
||||
const SavedDataProviderQueryMatchBasicRuntimeType = runtimeTypes.partial({
|
||||
field: unionWithNullType(runtimeTypes.string),
|
||||
displayField: unionWithNullType(runtimeTypes.string),
|
||||
value: runtimeTypes.union([
|
||||
runtimeTypes.null,
|
||||
runtimeTypes.string,
|
||||
runtimeTypes.array(runtimeTypes.string),
|
||||
]),
|
||||
displayValue: unionWithNullType(runtimeTypes.string),
|
||||
operator: unionWithNullType(runtimeTypes.string),
|
||||
});
|
||||
|
||||
const SavedDataProviderQueryMatchRuntimeType = runtimeTypes.partial({
|
||||
id: unionWithNullType(runtimeTypes.string),
|
||||
name: unionWithNullType(runtimeTypes.string),
|
||||
enabled: unionWithNullType(runtimeTypes.boolean),
|
||||
excluded: unionWithNullType(runtimeTypes.boolean),
|
||||
kqlQuery: unionWithNullType(runtimeTypes.string),
|
||||
queryMatch: unionWithNullType(SavedDataProviderQueryMatchBasicRuntimeType),
|
||||
});
|
||||
|
||||
export const DataProviderTypeLiteralRt = runtimeTypes.union([
|
||||
runtimeTypes.literal(DataProviderTypeEnum.default),
|
||||
runtimeTypes.literal(DataProviderTypeEnum.template),
|
||||
]);
|
||||
|
||||
const SavedDataProviderRuntimeType = runtimeTypes.partial({
|
||||
id: unionWithNullType(runtimeTypes.string),
|
||||
name: unionWithNullType(runtimeTypes.string),
|
||||
enabled: unionWithNullType(runtimeTypes.boolean),
|
||||
excluded: unionWithNullType(runtimeTypes.boolean),
|
||||
kqlQuery: unionWithNullType(runtimeTypes.string),
|
||||
queryMatch: unionWithNullType(SavedDataProviderQueryMatchBasicRuntimeType),
|
||||
and: unionWithNullType(runtimeTypes.array(SavedDataProviderQueryMatchRuntimeType)),
|
||||
type: unionWithNullType(DataProviderTypeLiteralRt),
|
||||
});
|
||||
|
||||
/*
|
||||
* Filters Types
|
||||
*/
|
||||
const SavedFilterMetaRuntimeType = runtimeTypes.partial({
|
||||
alias: unionWithNullType(runtimeTypes.string),
|
||||
controlledBy: unionWithNullType(runtimeTypes.string),
|
||||
disabled: unionWithNullType(runtimeTypes.boolean),
|
||||
field: unionWithNullType(runtimeTypes.string),
|
||||
formattedValue: unionWithNullType(runtimeTypes.string),
|
||||
index: unionWithNullType(runtimeTypes.string),
|
||||
key: unionWithNullType(runtimeTypes.string),
|
||||
negate: unionWithNullType(runtimeTypes.boolean),
|
||||
params: unionWithNullType(runtimeTypes.string),
|
||||
type: unionWithNullType(runtimeTypes.string),
|
||||
value: unionWithNullType(runtimeTypes.string),
|
||||
});
|
||||
|
||||
const SavedFilterRuntimeType = runtimeTypes.partial({
|
||||
exists: unionWithNullType(runtimeTypes.string),
|
||||
meta: unionWithNullType(SavedFilterMetaRuntimeType),
|
||||
match_all: unionWithNullType(runtimeTypes.string),
|
||||
missing: unionWithNullType(runtimeTypes.string),
|
||||
query: unionWithNullType(runtimeTypes.string),
|
||||
range: unionWithNullType(runtimeTypes.string),
|
||||
script: unionWithNullType(runtimeTypes.string),
|
||||
});
|
||||
|
||||
/*
|
||||
* eqlOptionsQuery -> filterQuery Types
|
||||
*/
|
||||
const EqlOptionsRuntimeType = runtimeTypes.partial({
|
||||
eventCategoryField: unionWithNullType(runtimeTypes.string),
|
||||
query: unionWithNullType(runtimeTypes.string),
|
||||
tiebreakerField: unionWithNullType(runtimeTypes.string),
|
||||
timestampField: unionWithNullType(runtimeTypes.string),
|
||||
size: unionWithNullType(runtimeTypes.union([runtimeTypes.string, runtimeTypes.number])),
|
||||
});
|
||||
|
||||
/*
|
||||
* kqlQuery -> filterQuery Types
|
||||
*/
|
||||
const SavedKueryFilterQueryRuntimeType = runtimeTypes.partial({
|
||||
kind: unionWithNullType(runtimeTypes.string),
|
||||
expression: unionWithNullType(runtimeTypes.string),
|
||||
});
|
||||
|
||||
const SavedSerializedFilterQueryQueryRuntimeType = runtimeTypes.partial({
|
||||
kuery: unionWithNullType(SavedKueryFilterQueryRuntimeType),
|
||||
serializedQuery: unionWithNullType(runtimeTypes.string),
|
||||
});
|
||||
|
||||
const SavedFilterQueryQueryRuntimeType = runtimeTypes.partial({
|
||||
filterQuery: unionWithNullType(SavedSerializedFilterQueryQueryRuntimeType),
|
||||
});
|
||||
|
||||
/*
|
||||
* DatePicker Range Types
|
||||
*/
|
||||
const SavedDateRangePickerRuntimeType = runtimeTypes.partial({
|
||||
/* Before the change of all timestamp to ISO string the values of start and from
|
||||
* attributes where a number. Specifically UNIX timestamps.
|
||||
* To support old timeline's saved object we need to add the number io-ts type
|
||||
*/
|
||||
start: unionWithNullType(runtimeTypes.union([runtimeTypes.string, runtimeTypes.number])),
|
||||
end: unionWithNullType(runtimeTypes.union([runtimeTypes.string, runtimeTypes.number])),
|
||||
});
|
||||
|
||||
/*
|
||||
* Favorite Types
|
||||
*/
|
||||
const SavedFavoriteRuntimeType = runtimeTypes.partial({
|
||||
keySearch: unionWithNullType(runtimeTypes.string),
|
||||
favoriteDate: unionWithNullType(runtimeTypes.number),
|
||||
fullName: unionWithNullType(runtimeTypes.string),
|
||||
userName: unionWithNullType(runtimeTypes.string),
|
||||
});
|
||||
|
||||
/*
|
||||
* Sort Types
|
||||
*/
|
||||
|
||||
const SavedSortObject = runtimeTypes.partial({
|
||||
columnId: unionWithNullType(runtimeTypes.string),
|
||||
columnType: unionWithNullType(runtimeTypes.string),
|
||||
sortDirection: unionWithNullType(runtimeTypes.string),
|
||||
});
|
||||
const SavedSortRuntimeType = runtimeTypes.union([
|
||||
runtimeTypes.array(SavedSortObject),
|
||||
SavedSortObject,
|
||||
]);
|
||||
|
||||
export type Sort = runtimeTypes.TypeOf<typeof SavedSortRuntimeType>;
|
||||
|
||||
/*
|
||||
* Timeline Statuses
|
||||
*/
|
||||
|
||||
export const TimelineStatusLiteralRt = runtimeTypes.union([
|
||||
runtimeTypes.literal(TimelineStatusEnum.active),
|
||||
runtimeTypes.literal(TimelineStatusEnum.draft),
|
||||
runtimeTypes.literal(TimelineStatusEnum.immutable),
|
||||
]);
|
||||
|
||||
export const RowRendererCount = Object.keys(RowRendererIdEnum).length;
|
||||
export const RowRendererValues = Object.values(RowRendererId.Values);
|
||||
|
||||
const RowRendererIdRuntimeType = stringEnum(RowRendererIdEnum, 'RowRendererId');
|
||||
|
||||
/**
|
||||
* Timeline types
|
||||
*/
|
||||
|
||||
export const TimelineTypeLiteralRt = runtimeTypes.union([
|
||||
runtimeTypes.literal(TimelineTypeEnum.template),
|
||||
runtimeTypes.literal(TimelineTypeEnum.default),
|
||||
]);
|
||||
|
||||
/**
|
||||
* This is the response type
|
||||
*/
|
||||
export const SavedTimelineRuntimeType = runtimeTypes.partial({
|
||||
columns: unionWithNullType(runtimeTypes.array(SavedColumnHeaderRuntimeType)),
|
||||
dataProviders: unionWithNullType(runtimeTypes.array(SavedDataProviderRuntimeType)),
|
||||
dataViewId: unionWithNullType(runtimeTypes.string),
|
||||
description: unionWithNullType(runtimeTypes.string),
|
||||
eqlOptions: unionWithNullType(EqlOptionsRuntimeType),
|
||||
eventType: unionWithNullType(runtimeTypes.string),
|
||||
excludedRowRendererIds: unionWithNullType(runtimeTypes.array(RowRendererIdRuntimeType)),
|
||||
favorite: unionWithNullType(runtimeTypes.array(SavedFavoriteRuntimeType)),
|
||||
filters: unionWithNullType(runtimeTypes.array(SavedFilterRuntimeType)),
|
||||
indexNames: unionWithNullType(runtimeTypes.array(runtimeTypes.string)),
|
||||
kqlMode: unionWithNullType(runtimeTypes.string),
|
||||
kqlQuery: unionWithNullType(SavedFilterQueryQueryRuntimeType),
|
||||
title: unionWithNullType(runtimeTypes.string),
|
||||
templateTimelineId: unionWithNullType(runtimeTypes.string),
|
||||
templateTimelineVersion: unionWithNullType(runtimeTypes.number),
|
||||
timelineType: unionWithNullType(TimelineTypeLiteralRt),
|
||||
dateRange: unionWithNullType(SavedDateRangePickerRuntimeType),
|
||||
savedQueryId: unionWithNullType(runtimeTypes.string),
|
||||
sort: unionWithNullType(SavedSortRuntimeType),
|
||||
status: unionWithNullType(TimelineStatusLiteralRt),
|
||||
created: unionWithNullType(runtimeTypes.number),
|
||||
createdBy: unionWithNullType(runtimeTypes.string),
|
||||
updated: unionWithNullType(runtimeTypes.number),
|
||||
updatedBy: unionWithNullType(runtimeTypes.string),
|
||||
savedSearchId: unionWithNullType(runtimeTypes.string),
|
||||
});
|
||||
|
||||
export type SavedTimeline = runtimeTypes.TypeOf<typeof SavedTimelineRuntimeType>;
|
||||
|
||||
export type SavedTimelineWithSavedObjectId = SavedTimeline & {
|
||||
savedObjectId?: string | null;
|
||||
};
|
||||
|
||||
/**
|
||||
* This type represents a timeline type stored in a saved object that does not include any fields that reference
|
||||
* other saved objects.
|
||||
*/
|
||||
export type TimelineWithoutExternalRefs = Omit<SavedTimeline, 'dataViewId' | 'savedQueryId'>;
|
||||
|
||||
export const TimelineSavedToReturnObjectRuntimeType = runtimeTypes.intersection([
|
||||
SavedTimelineRuntimeType,
|
||||
runtimeTypes.type({
|
||||
savedObjectId: runtimeTypes.string,
|
||||
version: runtimeTypes.string,
|
||||
}),
|
||||
runtimeTypes.partial({
|
||||
eventIdToNoteIds: runtimeTypes.array(NoteRuntimeType),
|
||||
noteIds: runtimeTypes.array(runtimeTypes.string),
|
||||
notes: runtimeTypes.array(NoteRuntimeType),
|
||||
pinnedEventIds: runtimeTypes.array(runtimeTypes.string),
|
||||
pinnedEventsSaveObject: runtimeTypes.array(PinnedEventRuntimeType),
|
||||
}),
|
||||
]);
|
||||
|
||||
export type TimelineSavedObject = runtimeTypes.TypeOf<
|
||||
typeof TimelineSavedToReturnObjectRuntimeType
|
||||
>;
|
||||
|
||||
export const SingleTimelineResponseType = runtimeTypes.type({
|
||||
data: runtimeTypes.type({
|
||||
getOneTimeline: TimelineSavedToReturnObjectRuntimeType,
|
||||
}),
|
||||
});
|
||||
|
||||
export type SingleTimelineResponse = runtimeTypes.TypeOf<typeof SingleTimelineResponseType>;
|
||||
|
||||
/** Resolved Timeline Response */
|
||||
export const ResolvedTimelineSavedObjectToReturnObjectRuntimeType = runtimeTypes.intersection([
|
||||
runtimeTypes.type({
|
||||
timeline: TimelineSavedToReturnObjectRuntimeType,
|
||||
outcome: SavedObjectResolveOutcome,
|
||||
}),
|
||||
runtimeTypes.partial({
|
||||
alias_target_id: SavedObjectResolveAliasTargetId,
|
||||
alias_purpose: SavedObjectResolveAliasPurpose,
|
||||
}),
|
||||
]);
|
||||
|
||||
export type ResolvedTimelineWithOutcomeSavedObject = runtimeTypes.TypeOf<
|
||||
typeof ResolvedTimelineSavedObjectToReturnObjectRuntimeType
|
||||
>;
|
||||
|
||||
export const ResolvedSingleTimelineResponseType = runtimeTypes.type({
|
||||
data: ResolvedTimelineSavedObjectToReturnObjectRuntimeType,
|
||||
});
|
||||
|
||||
export type SingleTimelineResolveResponse = runtimeTypes.TypeOf<
|
||||
typeof ResolvedSingleTimelineResponseType
|
||||
>;
|
||||
|
||||
const responseTimelines = runtimeTypes.type({
|
||||
timeline: runtimeTypes.array(TimelineSavedToReturnObjectRuntimeType),
|
||||
totalCount: runtimeTypes.number,
|
||||
});
|
||||
|
||||
export type ResponseTimelines = runtimeTypes.TypeOf<typeof responseTimelines>;
|
||||
|
||||
export const allTimelinesResponse = runtimeTypes.intersection([
|
||||
responseTimelines,
|
||||
runtimeTypes.type({
|
||||
defaultTimelineCount: runtimeTypes.number,
|
||||
templateTimelineCount: runtimeTypes.number,
|
||||
elasticTemplateTimelineCount: runtimeTypes.number,
|
||||
customTemplateTimelineCount: runtimeTypes.number,
|
||||
favoriteCount: runtimeTypes.number,
|
||||
}),
|
||||
]);
|
||||
|
||||
export type AllTimelinesResponse = runtimeTypes.TypeOf<typeof allTimelinesResponse>;
|
||||
export type BarePinnedEventWithoutExternalRefs = Omit<BarePinnedEvent, 'timelineId'>;
|
||||
|
||||
/**
|
||||
* All Timeline Saved object type with metadata
|
||||
* This type represents a note type stored in a saved object that does not include any fields that reference
|
||||
* other saved objects.
|
||||
*/
|
||||
export const TimelineResponseType = runtimeTypes.type({
|
||||
data: runtimeTypes.type({
|
||||
persistTimeline: runtimeTypes.intersection([
|
||||
runtimeTypes.partial({
|
||||
code: unionWithNullType(runtimeTypes.number),
|
||||
message: unionWithNullType(runtimeTypes.string),
|
||||
}),
|
||||
runtimeTypes.type({
|
||||
timeline: TimelineSavedToReturnObjectRuntimeType,
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
});
|
||||
export type BareNoteWithoutExternalRefs = Omit<BareNote, 'timelineId'>;
|
||||
|
||||
export const TimelineErrorResponseType = runtimeTypes.union([
|
||||
runtimeTypes.type({
|
||||
status_code: runtimeTypes.number,
|
||||
message: runtimeTypes.string,
|
||||
}),
|
||||
runtimeTypes.type({
|
||||
statusCode: runtimeTypes.number,
|
||||
message: runtimeTypes.string,
|
||||
}),
|
||||
]);
|
||||
|
||||
export type TimelineErrorResponse = runtimeTypes.TypeOf<typeof TimelineErrorResponseType>;
|
||||
export type TimelineResponse = runtimeTypes.TypeOf<typeof TimelineResponseType>;
|
||||
|
||||
export const sortFieldTimeline = runtimeTypes.union([
|
||||
runtimeTypes.literal(SortFieldTimelineEnum.title),
|
||||
runtimeTypes.literal(SortFieldTimelineEnum.description),
|
||||
runtimeTypes.literal(SortFieldTimelineEnum.updated),
|
||||
runtimeTypes.literal(SortFieldTimelineEnum.created),
|
||||
]);
|
||||
|
||||
export const direction = runtimeTypes.union([
|
||||
runtimeTypes.literal(Direction.asc),
|
||||
runtimeTypes.literal(Direction.desc),
|
||||
]);
|
||||
|
||||
export const sortTimeline = runtimeTypes.type({
|
||||
sortField: sortFieldTimeline,
|
||||
sortOrder: direction,
|
||||
});
|
||||
export const RowRendererCount = Object.keys(RowRendererIdEnum).length;
|
||||
export const RowRendererValues = Object.values(RowRendererId.Values);
|
||||
|
||||
/**
|
||||
* Import/export timelines
|
||||
|
@ -457,187 +104,17 @@ export interface ExportedNotes {
|
|||
globalNotes: ExportedGlobalNotes;
|
||||
}
|
||||
|
||||
export type ExportedTimelines = SavedTimeline &
|
||||
ExportedNotes & {
|
||||
pinnedEventIds: string[];
|
||||
};
|
||||
|
||||
export interface ExportTimelineNotFoundError {
|
||||
statusCode: number;
|
||||
message: string;
|
||||
}
|
||||
|
||||
export const importTimelineResultSchema = runtimeTypes.exact(
|
||||
runtimeTypes.type({
|
||||
success: runtimeTypes.boolean,
|
||||
success_count: PositiveInteger,
|
||||
timelines_installed: PositiveInteger,
|
||||
timelines_updated: PositiveInteger,
|
||||
errors: runtimeTypes.array(ErrorSchema),
|
||||
})
|
||||
);
|
||||
|
||||
export type ImportTimelineResultSchema = runtimeTypes.TypeOf<typeof importTimelineResultSchema>;
|
||||
|
||||
export const pageInfoTimeline = runtimeTypes.type({
|
||||
pageIndex: runtimeTypes.number,
|
||||
pageSize: runtimeTypes.number,
|
||||
});
|
||||
|
||||
export interface PageInfoTimeline {
|
||||
pageIndex: number;
|
||||
pageSize: number;
|
||||
}
|
||||
|
||||
export const getTimelinesArgs = runtimeTypes.partial({
|
||||
onlyUserFavorite: unionWithNullType(runtimeTypes.boolean),
|
||||
pageInfo: unionWithNullType(pageInfoTimeline),
|
||||
search: unionWithNullType(runtimeTypes.string),
|
||||
sort: unionWithNullType(sortTimeline),
|
||||
status: unionWithNullType(TimelineStatusLiteralRt),
|
||||
timelineType: unionWithNullType(TimelineTypeLiteralRt),
|
||||
});
|
||||
|
||||
export type GetTimelinesArgs = runtimeTypes.TypeOf<typeof getTimelinesArgs>;
|
||||
|
||||
export interface ColumnHeaderResult {
|
||||
aggregatable?: Maybe<boolean>;
|
||||
category?: Maybe<string>;
|
||||
columnHeaderType?: Maybe<string>;
|
||||
description?: Maybe<string>;
|
||||
example?: Maybe<string | number>;
|
||||
indexes?: Maybe<string[]>;
|
||||
id?: Maybe<string>;
|
||||
name?: Maybe<string>;
|
||||
placeholder?: Maybe<string>;
|
||||
searchable?: Maybe<boolean>;
|
||||
type?: Maybe<string>;
|
||||
}
|
||||
|
||||
export interface DataProviderResult {
|
||||
id?: Maybe<string>;
|
||||
name?: Maybe<string>;
|
||||
enabled?: Maybe<boolean>;
|
||||
excluded?: Maybe<boolean>;
|
||||
kqlQuery?: Maybe<string>;
|
||||
queryMatch?: Maybe<QueryMatchResult>;
|
||||
type?: Maybe<DataProviderType>;
|
||||
and?: Maybe<DataProviderResult[]>;
|
||||
}
|
||||
|
||||
export interface QueryMatchResult {
|
||||
field?: Maybe<string>;
|
||||
displayField?: Maybe<string>;
|
||||
value?: Maybe<string | string[]>;
|
||||
displayValue?: Maybe<string>;
|
||||
operator?: Maybe<string>;
|
||||
}
|
||||
|
||||
export interface DateRangePickerResult {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
start?: Maybe<any>;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
end?: Maybe<any>;
|
||||
}
|
||||
|
||||
export interface EqlOptionsResult {
|
||||
eventCategoryField?: Maybe<string>;
|
||||
tiebreakerField?: Maybe<string>;
|
||||
timestampField?: Maybe<string>;
|
||||
query?: Maybe<string>;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
size?: Maybe<any>;
|
||||
}
|
||||
|
||||
export interface FilterTimelineResult {
|
||||
exists?: Maybe<string>;
|
||||
meta?: Maybe<FilterMetaTimelineResult>;
|
||||
match_all?: Maybe<string>;
|
||||
missing?: Maybe<string>;
|
||||
query?: Maybe<string>;
|
||||
range?: Maybe<string>;
|
||||
script?: Maybe<string>;
|
||||
}
|
||||
|
||||
export interface FilterMetaTimelineResult {
|
||||
alias?: Maybe<string>;
|
||||
controlledBy?: Maybe<string>;
|
||||
disabled?: Maybe<boolean>;
|
||||
field?: Maybe<string>;
|
||||
formattedValue?: Maybe<string>;
|
||||
index?: Maybe<string>;
|
||||
key?: Maybe<string>;
|
||||
negate?: Maybe<boolean>;
|
||||
params?: Maybe<string>;
|
||||
type?: Maybe<string>;
|
||||
value?: Maybe<string>;
|
||||
}
|
||||
|
||||
export interface SerializedFilterQueryResult {
|
||||
filterQuery?: Maybe<SerializedKueryQueryResult>;
|
||||
}
|
||||
|
||||
export interface KueryFilterQueryResult {
|
||||
kind?: Maybe<string>;
|
||||
expression?: Maybe<string>;
|
||||
}
|
||||
|
||||
export interface SerializedKueryQueryResult {
|
||||
kuery?: Maybe<KueryFilterQueryResult>;
|
||||
serializedQuery?: Maybe<string>;
|
||||
}
|
||||
|
||||
export interface TimelineResult {
|
||||
columns?: Maybe<ColumnHeaderResult[]>;
|
||||
created?: Maybe<number>;
|
||||
createdBy?: Maybe<string>;
|
||||
dataProviders?: Maybe<DataProviderResult[]>;
|
||||
dataViewId?: Maybe<string>;
|
||||
dateRange?: Maybe<DateRangePickerResult>;
|
||||
description?: Maybe<string>;
|
||||
eqlOptions?: Maybe<EqlOptionsResult>;
|
||||
eventIdToNoteIds?: Maybe<Note[]>;
|
||||
eventType?: Maybe<string>;
|
||||
excludedRowRendererIds?: Maybe<RowRendererId[]>;
|
||||
favorite?: Maybe<FavoriteTimelineResult[]>;
|
||||
filters?: Maybe<FilterTimelineResult[]>;
|
||||
kqlMode?: Maybe<string>;
|
||||
kqlQuery?: Maybe<SerializedFilterQueryResult>;
|
||||
indexNames?: Maybe<string[]>;
|
||||
notes?: Maybe<Note[]>;
|
||||
noteIds?: Maybe<string[]>;
|
||||
pinnedEventIds?: Maybe<string[]>;
|
||||
pinnedEventsSaveObject?: Maybe<PinnedEvent[]>;
|
||||
savedQueryId?: Maybe<string>;
|
||||
savedObjectId: string;
|
||||
sort?: Maybe<Sort>;
|
||||
status?: Maybe<TimelineStatus>;
|
||||
title?: Maybe<string>;
|
||||
templateTimelineId?: Maybe<string>;
|
||||
templateTimelineVersion?: Maybe<number>;
|
||||
timelineType?: Maybe<TimelineType>;
|
||||
updated?: Maybe<number>;
|
||||
updatedBy?: Maybe<string>;
|
||||
version: string;
|
||||
savedSearchId?: Maybe<string>;
|
||||
}
|
||||
|
||||
export interface ResponseTimeline {
|
||||
code?: Maybe<number>;
|
||||
message?: Maybe<string>;
|
||||
timeline: TimelineResult;
|
||||
}
|
||||
|
||||
export interface SortTimeline {
|
||||
sortField: SortFieldTimeline;
|
||||
sortOrder: Direction;
|
||||
}
|
||||
|
||||
export interface GetAllTimelineVariables {
|
||||
pageInfo: PageInfoTimeline;
|
||||
search?: Maybe<string>;
|
||||
sort?: Maybe<SortTimeline>;
|
||||
onlyUserFavorite?: Maybe<boolean>;
|
||||
timelineType?: Maybe<TimelineType>;
|
||||
status?: Maybe<TimelineStatus>;
|
||||
sortOrder: SortDirection;
|
||||
}
|
||||
|
|
|
@ -42,24 +42,24 @@ export const TemplateTimelineTypeEnum = TemplateTimelineType.enum;
|
|||
|
||||
export type ColumnHeaderResult = z.infer<typeof ColumnHeaderResult>;
|
||||
export const ColumnHeaderResult = z.object({
|
||||
aggregatable: z.boolean().optional(),
|
||||
category: z.string().optional(),
|
||||
columnHeaderType: z.string().optional(),
|
||||
description: z.string().optional(),
|
||||
example: z.union([z.string(), z.number()]).optional(),
|
||||
indexes: z.array(z.string()).optional(),
|
||||
id: z.string().optional(),
|
||||
name: z.string().optional(),
|
||||
placeholder: z.string().optional(),
|
||||
searchable: z.boolean().optional(),
|
||||
type: z.string().optional(),
|
||||
aggregatable: z.boolean().nullable().optional(),
|
||||
category: z.string().nullable().optional(),
|
||||
columnHeaderType: z.string().nullable().optional(),
|
||||
description: z.string().nullable().optional(),
|
||||
example: z.string().nullable().optional(),
|
||||
indexes: z.array(z.string()).nullable().optional(),
|
||||
id: z.string().nullable().optional(),
|
||||
name: z.string().nullable().optional(),
|
||||
placeholder: z.string().nullable().optional(),
|
||||
searchable: z.boolean().nullable().optional(),
|
||||
type: z.string().nullable().optional(),
|
||||
});
|
||||
|
||||
export type QueryMatchResult = z.infer<typeof QueryMatchResult>;
|
||||
export const QueryMatchResult = z.object({
|
||||
field: z.string().nullable().optional(),
|
||||
displayField: z.string().nullable().optional(),
|
||||
value: z.string().nullable().optional(),
|
||||
value: z.union([z.string().nullable(), z.array(z.string()).nullable()]).optional(),
|
||||
displayValue: z.string().nullable().optional(),
|
||||
operator: z.string().nullable().optional(),
|
||||
});
|
||||
|
@ -71,7 +71,8 @@ export const DataProviderQueryMatch = z.object({
|
|||
id: z.string().nullable().optional(),
|
||||
kqlQuery: z.string().nullable().optional(),
|
||||
name: z.string().nullable().optional(),
|
||||
queryMatch: QueryMatchResult.optional(),
|
||||
queryMatch: QueryMatchResult.nullable().optional(),
|
||||
type: DataProviderType.nullable().optional(),
|
||||
});
|
||||
|
||||
export type DataProviderResult = z.infer<typeof DataProviderResult>;
|
||||
|
@ -119,27 +120,28 @@ export const FavoriteTimelineResult = z.object({
|
|||
|
||||
export type FilterTimelineResult = z.infer<typeof FilterTimelineResult>;
|
||||
export const FilterTimelineResult = z.object({
|
||||
exists: z.boolean().optional(),
|
||||
exists: z.string().nullable().optional(),
|
||||
meta: z
|
||||
.object({
|
||||
alias: z.string().optional(),
|
||||
controlledBy: z.string().optional(),
|
||||
disabled: z.boolean().optional(),
|
||||
field: z.string().optional(),
|
||||
formattedValue: z.string().optional(),
|
||||
index: z.string().optional(),
|
||||
key: z.string().optional(),
|
||||
negate: z.boolean().optional(),
|
||||
params: z.string().optional(),
|
||||
type: z.string().optional(),
|
||||
value: z.string().optional(),
|
||||
alias: z.string().nullable().optional(),
|
||||
controlledBy: z.string().nullable().optional(),
|
||||
disabled: z.boolean().nullable().optional(),
|
||||
field: z.string().nullable().optional(),
|
||||
formattedValue: z.string().nullable().optional(),
|
||||
index: z.string().nullable().optional(),
|
||||
key: z.string().nullable().optional(),
|
||||
negate: z.boolean().nullable().optional(),
|
||||
params: z.string().nullable().optional(),
|
||||
type: z.string().nullable().optional(),
|
||||
value: z.string().nullable().optional(),
|
||||
})
|
||||
.nullable()
|
||||
.optional(),
|
||||
match_all: z.string().optional(),
|
||||
missing: z.string().optional(),
|
||||
query: z.string().optional(),
|
||||
range: z.string().optional(),
|
||||
script: z.string().optional(),
|
||||
match_all: z.string().nullable().optional(),
|
||||
missing: z.string().nullable().optional(),
|
||||
query: z.string().nullable().optional(),
|
||||
range: z.string().nullable().optional(),
|
||||
script: z.string().nullable().optional(),
|
||||
});
|
||||
|
||||
export type SerializedFilterQueryResult = z.infer<typeof SerializedFilterQueryResult>;
|
||||
|
@ -178,8 +180,8 @@ export const SavedTimeline = z.object({
|
|||
dataViewId: z.string().nullable().optional(),
|
||||
dateRange: z
|
||||
.object({
|
||||
end: z.union([z.string(), z.number()]).optional(),
|
||||
start: z.union([z.string(), z.number()]).optional(),
|
||||
end: z.union([z.string().nullable(), z.number().nullable()]).optional(),
|
||||
start: z.union([z.string().nullable(), z.number().nullable()]).optional(),
|
||||
})
|
||||
.nullable()
|
||||
.optional(),
|
||||
|
@ -213,6 +215,14 @@ export const SavedTimeline = z.object({
|
|||
updatedBy: z.string().nullable().optional(),
|
||||
});
|
||||
|
||||
export type SavedTimelineWithSavedObjectId = z.infer<typeof SavedTimelineWithSavedObjectId>;
|
||||
export const SavedTimelineWithSavedObjectId = SavedTimeline.merge(
|
||||
z.object({
|
||||
savedObjectId: z.string(),
|
||||
version: z.string(),
|
||||
})
|
||||
);
|
||||
|
||||
export type BareNote = z.infer<typeof BareNote>;
|
||||
export const BareNote = z.object({
|
||||
eventId: z.string().nullable().optional(),
|
||||
|
@ -251,18 +261,50 @@ export const PinnedEvent = BarePinnedEvent.merge(
|
|||
);
|
||||
|
||||
export type TimelineResponse = z.infer<typeof TimelineResponse>;
|
||||
export const TimelineResponse = SavedTimeline.merge(
|
||||
export const TimelineResponse = SavedTimeline.merge(SavedTimelineWithSavedObjectId).merge(
|
||||
z.object({
|
||||
eventIdToNoteIds: z.array(Note).optional(),
|
||||
notes: z.array(Note).optional(),
|
||||
noteIds: z.array(z.string()).optional(),
|
||||
pinnedEventIds: z.array(z.string()).optional(),
|
||||
pinnedEventsSaveObject: z.array(PinnedEvent).optional(),
|
||||
savedObjectId: z.string(),
|
||||
version: z.string(),
|
||||
eventIdToNoteIds: z.array(Note).nullable().optional(),
|
||||
notes: z.array(Note).nullable().optional(),
|
||||
noteIds: z.array(z.string()).nullable().optional(),
|
||||
pinnedEventIds: z.array(z.string()).nullable().optional(),
|
||||
pinnedEventsSaveObject: z.array(PinnedEvent).nullable().optional(),
|
||||
})
|
||||
);
|
||||
|
||||
export type TimelineSavedToReturnObject = z.infer<typeof TimelineSavedToReturnObject>;
|
||||
export const TimelineSavedToReturnObject = SavedTimeline.merge(
|
||||
z.object({
|
||||
savedObjectId: z.string(),
|
||||
version: z.string(),
|
||||
eventIdToNoteIds: z.array(Note).nullable().optional(),
|
||||
notes: z.array(Note).nullable().optional(),
|
||||
noteIds: z.array(z.string()).nullable().optional(),
|
||||
pinnedEventIds: z.array(z.string()).nullable().optional(),
|
||||
pinnedEventsSaveObject: z.array(PinnedEvent).nullable().optional(),
|
||||
})
|
||||
);
|
||||
|
||||
export type SavedObjectResolveOutcome = z.infer<typeof SavedObjectResolveOutcome>;
|
||||
export const SavedObjectResolveOutcome = z.enum(['exactMatch', 'aliasMatch', 'conflict']);
|
||||
export type SavedObjectResolveOutcomeEnum = typeof SavedObjectResolveOutcome.enum;
|
||||
export const SavedObjectResolveOutcomeEnum = SavedObjectResolveOutcome.enum;
|
||||
|
||||
export type SavedObjectResolveAliasPurpose = z.infer<typeof SavedObjectResolveAliasPurpose>;
|
||||
export const SavedObjectResolveAliasPurpose = z.enum([
|
||||
'savedObjectConversion',
|
||||
'savedObjectImport',
|
||||
]);
|
||||
export type SavedObjectResolveAliasPurposeEnum = typeof SavedObjectResolveAliasPurpose.enum;
|
||||
export const SavedObjectResolveAliasPurposeEnum = SavedObjectResolveAliasPurpose.enum;
|
||||
|
||||
export type ResolvedTimeline = z.infer<typeof ResolvedTimeline>;
|
||||
export const ResolvedTimeline = z.object({
|
||||
timeline: TimelineSavedToReturnObject,
|
||||
outcome: SavedObjectResolveOutcome,
|
||||
alias_target_id: z.string().optional(),
|
||||
alias_purpose: SavedObjectResolveAliasPurpose.optional(),
|
||||
});
|
||||
|
||||
export type FavoriteTimelineResponse = z.infer<typeof FavoriteTimelineResponse>;
|
||||
export const FavoriteTimelineResponse = z.object({
|
||||
savedObjectId: z.string(),
|
||||
|
@ -275,6 +317,15 @@ export const FavoriteTimelineResponse = z.object({
|
|||
favorite: z.array(FavoriteTimelineResult).optional(),
|
||||
});
|
||||
|
||||
export type PersistTimelineResponse = z.infer<typeof PersistTimelineResponse>;
|
||||
export const PersistTimelineResponse = z.object({
|
||||
data: z.object({
|
||||
persistTimeline: z.object({
|
||||
timeline: TimelineResponse,
|
||||
}),
|
||||
}),
|
||||
});
|
||||
|
||||
export type BareNoteWithoutExternalRefs = z.infer<typeof BareNoteWithoutExternalRefs>;
|
||||
export const BareNoteWithoutExternalRefs = z.object({
|
||||
eventId: z.string().nullable().optional(),
|
||||
|
@ -306,6 +357,11 @@ export const SortFieldTimeline = z.enum(['title', 'description', 'updated', 'cre
|
|||
export type SortFieldTimelineEnum = typeof SortFieldTimeline.enum;
|
||||
export const SortFieldTimelineEnum = SortFieldTimeline.enum;
|
||||
|
||||
export type SortDirection = z.infer<typeof SortDirection>;
|
||||
export const SortDirection = z.enum(['asc', 'desc']);
|
||||
export type SortDirectionEnum = typeof SortDirection.enum;
|
||||
export const SortDirectionEnum = SortDirection.enum;
|
||||
|
||||
/**
|
||||
* The status of the timeline. Valid values are `active`, `draft`, and `immutable`.
|
||||
*/
|
||||
|
@ -317,11 +373,11 @@ export const TimelineStatusEnum = TimelineStatus.enum;
|
|||
export type ImportTimelines = z.infer<typeof ImportTimelines>;
|
||||
export const ImportTimelines = SavedTimeline.merge(
|
||||
z.object({
|
||||
savedObjectId: z.string().nullable().optional(),
|
||||
version: z.string().nullable().optional(),
|
||||
globalNotes: z.array(BareNote).nullable().optional(),
|
||||
eventNotes: z.array(BareNote).nullable().optional(),
|
||||
pinnedEventIds: z.array(z.string()).nullable().optional(),
|
||||
savedObjectId: z.string().nullable(),
|
||||
version: z.string().nullable(),
|
||||
pinnedEventIds: z.array(z.string()).nullable(),
|
||||
eventNotes: z.array(BareNote).nullable(),
|
||||
globalNotes: z.array(BareNote).nullable(),
|
||||
})
|
||||
);
|
||||
|
||||
|
@ -346,24 +402,14 @@ export const ImportTimelineResult = z.object({
|
|||
.optional(),
|
||||
});
|
||||
|
||||
export type ExportedTimelines = z.infer<typeof ExportedTimelines>;
|
||||
export const ExportedTimelines = SavedTimeline.merge(
|
||||
export type TimelineErrorResponse = z.infer<typeof TimelineErrorResponse>;
|
||||
export const TimelineErrorResponse = z.union([
|
||||
z.object({
|
||||
globalNotes: z.array(Note).optional(),
|
||||
eventNotes: z.array(Note).optional(),
|
||||
pinnedEventIds: z.array(z.string()).optional(),
|
||||
})
|
||||
);
|
||||
|
||||
export type Readable = z.infer<typeof Readable>;
|
||||
export const Readable = z.object({
|
||||
_maxListeners: z.object({}).catchall(z.unknown()).optional(),
|
||||
_readableState: z.object({}).catchall(z.unknown()).optional(),
|
||||
_read: z.object({}).catchall(z.unknown()).optional(),
|
||||
readable: z.boolean().optional(),
|
||||
_events: z.object({}).catchall(z.unknown()).optional(),
|
||||
_eventsCount: z.number().optional(),
|
||||
_data: z.object({}).catchall(z.unknown()).optional(),
|
||||
_position: z.number().optional(),
|
||||
_encoding: z.string().optional(),
|
||||
});
|
||||
message: z.string(),
|
||||
status_code: z.number(),
|
||||
}),
|
||||
z.object({
|
||||
message: z.string(),
|
||||
statusCode: z.number(),
|
||||
}),
|
||||
]);
|
||||
|
|
|
@ -56,11 +56,15 @@ components:
|
|||
end:
|
||||
oneOf:
|
||||
- type: string
|
||||
nullable: true
|
||||
- type: number
|
||||
nullable: true
|
||||
start:
|
||||
oneOf:
|
||||
- type: string
|
||||
nullable: true
|
||||
- type: number
|
||||
nullable: true
|
||||
description:
|
||||
type: string
|
||||
nullable: true
|
||||
|
@ -149,43 +153,73 @@ components:
|
|||
updatedBy:
|
||||
type: string
|
||||
nullable: true
|
||||
TimelineResponse:
|
||||
SavedTimelineWithSavedObjectId:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/SavedTimeline'
|
||||
- type: object
|
||||
required:
|
||||
- savedObjectId
|
||||
- version
|
||||
required: [savedObjectId, version]
|
||||
properties:
|
||||
eventIdToNoteIds:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Note'
|
||||
notes:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Note'
|
||||
noteIds:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
pinnedEventIds:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
pinnedEventsSaveObject:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/PinnedEvent'
|
||||
savedObjectId:
|
||||
type: string
|
||||
version:
|
||||
type: string
|
||||
TimelineResponse:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/SavedTimeline'
|
||||
- $ref: '#/components/schemas/SavedTimelineWithSavedObjectId'
|
||||
- type: object
|
||||
properties:
|
||||
eventIdToNoteIds:
|
||||
type: array
|
||||
nullable: true
|
||||
items:
|
||||
$ref: '#/components/schemas/Note'
|
||||
notes:
|
||||
type: array
|
||||
nullable: true
|
||||
items:
|
||||
$ref: '#/components/schemas/Note'
|
||||
noteIds:
|
||||
type: array
|
||||
nullable: true
|
||||
items:
|
||||
type: string
|
||||
pinnedEventIds:
|
||||
type: array
|
||||
nullable: true
|
||||
items:
|
||||
type: string
|
||||
pinnedEventsSaveObject:
|
||||
type: array
|
||||
nullable: true
|
||||
items:
|
||||
$ref: '#/components/schemas/PinnedEvent'
|
||||
ResolvedTimeline:
|
||||
type: object
|
||||
required: [timeline, outcome]
|
||||
properties:
|
||||
timeline:
|
||||
$ref: '#/components/schemas/TimelineSavedToReturnObject'
|
||||
outcome:
|
||||
$ref: '#/components/schemas/SavedObjectResolveOutcome'
|
||||
alias_target_id:
|
||||
type: string
|
||||
alias_purpose:
|
||||
$ref: '#/components/schemas/SavedObjectResolveAliasPurpose'
|
||||
SavedObjectResolveOutcome:
|
||||
type: string
|
||||
enum:
|
||||
- exactMatch
|
||||
- aliasMatch
|
||||
- conflict
|
||||
SavedObjectResolveAliasPurpose:
|
||||
type: string
|
||||
enum:
|
||||
- savedObjectConversion
|
||||
- savedObjectImport
|
||||
FavoriteTimelineResponse:
|
||||
type: object
|
||||
required:
|
||||
- savedObjectId
|
||||
- version
|
||||
required: [savedObjectId, version]
|
||||
properties:
|
||||
savedObjectId:
|
||||
type: string
|
||||
|
@ -209,35 +243,58 @@ components:
|
|||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/FavoriteTimelineResult'
|
||||
PersistTimelineResponse:
|
||||
type: object
|
||||
required: [data]
|
||||
properties:
|
||||
data:
|
||||
type: object
|
||||
required: [persistTimeline]
|
||||
properties:
|
||||
persistTimeline:
|
||||
type: object
|
||||
required: [timeline]
|
||||
properties:
|
||||
timeline:
|
||||
$ref: '#/components/schemas/TimelineResponse'
|
||||
ColumnHeaderResult:
|
||||
type: object
|
||||
properties:
|
||||
aggregatable:
|
||||
type: boolean
|
||||
nullable: true
|
||||
category:
|
||||
type: string
|
||||
nullable: true
|
||||
columnHeaderType:
|
||||
type: string
|
||||
nullable: true
|
||||
description:
|
||||
type: string
|
||||
nullable: true
|
||||
example:
|
||||
oneOf:
|
||||
- type: string
|
||||
- type: number
|
||||
type: string
|
||||
nullable: true
|
||||
indexes:
|
||||
type: array
|
||||
nullable: true
|
||||
items:
|
||||
type: string
|
||||
id:
|
||||
type: string
|
||||
nullable: true
|
||||
name:
|
||||
type: string
|
||||
nullable: true
|
||||
placeholder:
|
||||
type: string
|
||||
nullable: true
|
||||
searchable:
|
||||
type: boolean
|
||||
nullable: true
|
||||
type:
|
||||
type: string
|
||||
nullable: true
|
||||
QueryMatchResult:
|
||||
type: object
|
||||
properties:
|
||||
|
@ -248,8 +305,13 @@ components:
|
|||
type: string
|
||||
nullable: true
|
||||
value:
|
||||
type: string
|
||||
nullable: true
|
||||
oneOf:
|
||||
- type: string
|
||||
nullable: true
|
||||
- type: array
|
||||
nullable: true
|
||||
items:
|
||||
type: string
|
||||
displayValue:
|
||||
type: string
|
||||
nullable: true
|
||||
|
@ -305,6 +367,10 @@ components:
|
|||
nullable: true
|
||||
queryMatch:
|
||||
$ref: '#/components/schemas/QueryMatchResult'
|
||||
nullable: true
|
||||
type:
|
||||
$ref: '#/components/schemas/DataProviderType'
|
||||
nullable: true
|
||||
BareNoteWithoutExternalRefs:
|
||||
type: object
|
||||
properties:
|
||||
|
@ -419,42 +485,60 @@ components:
|
|||
type: object
|
||||
properties:
|
||||
exists:
|
||||
type: boolean
|
||||
type: string
|
||||
nullable: true
|
||||
meta:
|
||||
type: object
|
||||
nullable: true
|
||||
properties:
|
||||
alias:
|
||||
type: string
|
||||
nullable: true
|
||||
controlledBy:
|
||||
type: string
|
||||
nullable: true
|
||||
disabled:
|
||||
type: boolean
|
||||
nullable: true
|
||||
field:
|
||||
type: string
|
||||
nullable: true
|
||||
formattedValue:
|
||||
type: string
|
||||
nullable: true
|
||||
index:
|
||||
type: string
|
||||
nullable: true
|
||||
key:
|
||||
type: string
|
||||
nullable: true
|
||||
negate:
|
||||
type: boolean
|
||||
nullable: true
|
||||
params:
|
||||
type: string
|
||||
nullable: true
|
||||
type:
|
||||
type: string
|
||||
nullable: true
|
||||
value:
|
||||
type: string
|
||||
nullable: true
|
||||
match_all:
|
||||
type: string
|
||||
nullable: true
|
||||
missing:
|
||||
type: string
|
||||
nullable: true
|
||||
query:
|
||||
type: string
|
||||
nullable: true
|
||||
range:
|
||||
type: string
|
||||
nullable: true
|
||||
script:
|
||||
type: string
|
||||
nullable: true
|
||||
SerializedFilterQueryResult:
|
||||
type: object
|
||||
properties:
|
||||
|
@ -531,6 +615,11 @@ components:
|
|||
- description
|
||||
- updated
|
||||
- created
|
||||
SortDirection:
|
||||
type: string
|
||||
enum:
|
||||
- asc
|
||||
- desc
|
||||
TimelineStatus:
|
||||
type: string
|
||||
enum:
|
||||
|
@ -544,6 +633,7 @@ components:
|
|||
allOf:
|
||||
- $ref: '#/components/schemas/SavedTimeline'
|
||||
- type: object
|
||||
required: [savedObjectId, version, pinnedEventIds, eventNotes, globalNotes]
|
||||
properties:
|
||||
savedObjectId:
|
||||
type: string
|
||||
|
@ -551,21 +641,56 @@ components:
|
|||
version:
|
||||
type: string
|
||||
nullable: true
|
||||
globalNotes:
|
||||
nullable: true
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/BareNote'
|
||||
eventNotes:
|
||||
nullable: true
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/BareNote'
|
||||
pinnedEventIds:
|
||||
nullable: true
|
||||
type: array
|
||||
nullable: true
|
||||
items:
|
||||
type: string
|
||||
eventNotes:
|
||||
type: array
|
||||
nullable: true
|
||||
items:
|
||||
$ref: '#/components/schemas/BareNote'
|
||||
globalNotes:
|
||||
type: array
|
||||
nullable: true
|
||||
items:
|
||||
$ref: '#/components/schemas/BareNote'
|
||||
TimelineSavedToReturnObject:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/SavedTimeline'
|
||||
- type: object
|
||||
required: [savedObjectId, version]
|
||||
properties:
|
||||
savedObjectId:
|
||||
type: string
|
||||
version:
|
||||
type: string
|
||||
eventIdToNoteIds:
|
||||
type: array
|
||||
nullable: true
|
||||
items:
|
||||
$ref: '#/components/schemas/Note'
|
||||
notes:
|
||||
type: array
|
||||
nullable: true
|
||||
items:
|
||||
$ref: '#/components/schemas/Note'
|
||||
noteIds:
|
||||
type: array
|
||||
nullable: true
|
||||
items:
|
||||
type: string
|
||||
pinnedEventIds:
|
||||
type: array
|
||||
nullable: true
|
||||
items:
|
||||
type: string
|
||||
pinnedEventsSaveObject:
|
||||
type: array
|
||||
nullable: true
|
||||
items:
|
||||
$ref: '#/components/schemas/PinnedEvent'
|
||||
ImportTimelineResult:
|
||||
type: object
|
||||
properties:
|
||||
|
@ -591,46 +716,19 @@ components:
|
|||
type: string
|
||||
status_code:
|
||||
type: number
|
||||
ExportedTimelines:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/SavedTimeline'
|
||||
TimelineErrorResponse:
|
||||
oneOf:
|
||||
- type: object
|
||||
required: [message, status_code]
|
||||
properties:
|
||||
globalNotes:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Note'
|
||||
eventNotes:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Note'
|
||||
pinnedEventIds:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
Readable:
|
||||
type: object
|
||||
properties:
|
||||
_maxListeners:
|
||||
type: object
|
||||
additionalProperties: true
|
||||
_readableState:
|
||||
type: object
|
||||
additionalProperties: true
|
||||
_read:
|
||||
type: object
|
||||
additionalProperties: true
|
||||
readable:
|
||||
type: boolean
|
||||
_events:
|
||||
type: object
|
||||
additionalProperties: true
|
||||
_eventsCount:
|
||||
type: number
|
||||
_data:
|
||||
type: object
|
||||
additionalProperties: true
|
||||
_position:
|
||||
type: number
|
||||
_encoding:
|
||||
type: string
|
||||
message:
|
||||
type: string
|
||||
status_code:
|
||||
type: number
|
||||
- type: object
|
||||
required: [message, statusCode]
|
||||
properties:
|
||||
message:
|
||||
type: string
|
||||
statusCode:
|
||||
type: number
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
import { z } from '@kbn/zod';
|
||||
|
||||
import { SavedTimeline, TimelineResponse } from '../model/components.gen';
|
||||
import { SavedTimeline, PersistTimelineResponse } from '../model/components.gen';
|
||||
|
||||
export type PatchTimelineRequestBody = z.infer<typeof PatchTimelineRequestBody>;
|
||||
export const PatchTimelineRequestBody = z.object({
|
||||
|
@ -27,10 +27,4 @@ export const PatchTimelineRequestBody = z.object({
|
|||
export type PatchTimelineRequestBodyInput = z.input<typeof PatchTimelineRequestBody>;
|
||||
|
||||
export type PatchTimelineResponse = z.infer<typeof PatchTimelineResponse>;
|
||||
export const PatchTimelineResponse = z.object({
|
||||
data: z.object({
|
||||
persistTimeline: z.object({
|
||||
timeline: TimelineResponse,
|
||||
}),
|
||||
}),
|
||||
});
|
||||
export const PatchTimelineResponse = PersistTimelineResponse;
|
||||
|
|
|
@ -2,13 +2,6 @@ openapi: 3.0.0
|
|||
info:
|
||||
title: Elastic Security - Timeline - Patch Timeline API
|
||||
version: '2023-10-31'
|
||||
servers:
|
||||
- url: 'http://{kibana_host}:{port}'
|
||||
variables:
|
||||
kibana_host:
|
||||
default: localhost
|
||||
port:
|
||||
default: '5601'
|
||||
paths:
|
||||
/api/timeline:
|
||||
patch:
|
||||
|
@ -42,19 +35,7 @@ paths:
|
|||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [data]
|
||||
properties:
|
||||
data:
|
||||
type: object
|
||||
required: [persistTimeline]
|
||||
properties:
|
||||
persistTimeline:
|
||||
type: object
|
||||
required: [timeline]
|
||||
properties:
|
||||
timeline:
|
||||
$ref: '../model/components.schema.yaml#/components/schemas/TimelineResponse'
|
||||
$ref: '../model/components.schema.yaml#/components/schemas/PersistTimelineResponse'
|
||||
'405':
|
||||
description: Indicates that the user does not have the required access to create a draft timeline.
|
||||
content:
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import * as rt from 'io-ts';
|
||||
|
||||
import type { ResponseTimeline } from '../model/api';
|
||||
import { SavedTimelineRuntimeType } from '../model/api';
|
||||
import { unionWithNullType } from '../../../utility_types';
|
||||
|
||||
export const patchTimelineSchema = rt.type({
|
||||
timeline: SavedTimelineRuntimeType,
|
||||
timelineId: unionWithNullType(rt.string),
|
||||
version: unionWithNullType(rt.string),
|
||||
});
|
||||
|
||||
export interface PatchTimelinesResponse {
|
||||
data: {
|
||||
persistTimeline: ResponseTimeline;
|
||||
};
|
||||
}
|
|
@ -2,13 +2,6 @@ openapi: 3.0.0
|
|||
info:
|
||||
title: Elastic Security - Timeline - Favorite API
|
||||
version: '2023-10-31'
|
||||
servers:
|
||||
- url: 'http://{kibana_host}:{port}'
|
||||
variables:
|
||||
kibana_host:
|
||||
default: localhost
|
||||
port:
|
||||
default: '5601'
|
||||
paths:
|
||||
/api/timeline/_favorite:
|
||||
patch:
|
||||
|
|
|
@ -5,13 +5,6 @@ info:
|
|||
externalDocs:
|
||||
url: https://www.elastic.co/guide/en/security/current/timeline-api-update.html
|
||||
description: Documentation
|
||||
servers:
|
||||
- url: 'http://{kibana_host}:{port}'
|
||||
variables:
|
||||
kibana_host:
|
||||
default: localhost
|
||||
port:
|
||||
default: '5601'
|
||||
paths:
|
||||
/api/note:
|
||||
patch:
|
||||
|
|
|
@ -5,13 +5,6 @@ info:
|
|||
externalDocs:
|
||||
url: https://www.elastic.co/guide/en/security/current/_pin_an_event_to_an_existing_timeline.html
|
||||
description: Documentation
|
||||
servers:
|
||||
- url: 'http://{kibana_host}:{port}'
|
||||
variables:
|
||||
kibana_host:
|
||||
default: localhost
|
||||
port:
|
||||
default: '5601'
|
||||
paths:
|
||||
/api/pinned_event:
|
||||
patch:
|
||||
|
|
|
@ -1,34 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import * as runtimeTypes from 'io-ts';
|
||||
import { unionWithNullType } from '../../../utility_types';
|
||||
|
||||
/*
|
||||
* Pinned Event Types
|
||||
* TODO: remove these when the timeline types are moved to zod
|
||||
*/
|
||||
const BarePinnedEventType = runtimeTypes.intersection([
|
||||
runtimeTypes.type({
|
||||
timelineId: runtimeTypes.string,
|
||||
eventId: runtimeTypes.string,
|
||||
}),
|
||||
runtimeTypes.partial({
|
||||
created: unionWithNullType(runtimeTypes.number),
|
||||
createdBy: unionWithNullType(runtimeTypes.string),
|
||||
updated: unionWithNullType(runtimeTypes.number),
|
||||
updatedBy: unionWithNullType(runtimeTypes.string),
|
||||
}),
|
||||
]);
|
||||
|
||||
export const PinnedEventRuntimeType = runtimeTypes.intersection([
|
||||
runtimeTypes.type({
|
||||
pinnedEventId: runtimeTypes.string,
|
||||
version: runtimeTypes.string,
|
||||
}),
|
||||
BarePinnedEventType,
|
||||
]);
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
import { z } from '@kbn/zod';
|
||||
|
||||
import { TimelineResponse } from '../model/components.gen';
|
||||
import { ResolvedTimeline } from '../model/components.gen';
|
||||
|
||||
export type ResolveTimelineRequestQuery = z.infer<typeof ResolveTimelineRequestQuery>;
|
||||
export const ResolveTimelineRequestQuery = z.object({
|
||||
|
@ -32,8 +32,9 @@ export const ResolveTimelineRequestQuery = z.object({
|
|||
export type ResolveTimelineRequestQueryInput = z.input<typeof ResolveTimelineRequestQuery>;
|
||||
|
||||
export type ResolveTimelineResponse = z.infer<typeof ResolveTimelineResponse>;
|
||||
export const ResolveTimelineResponse = z.object({
|
||||
data: z.object({
|
||||
getOneTimeline: TimelineResponse.nullable(),
|
||||
export const ResolveTimelineResponse = z.union([
|
||||
z.object({
|
||||
data: ResolvedTimeline,
|
||||
}),
|
||||
});
|
||||
z.object({}).strict(),
|
||||
]);
|
||||
|
|
|
@ -2,13 +2,6 @@ openapi: 3.0.0
|
|||
info:
|
||||
title: Elastic Security - Timeline - Resolve Timeline API
|
||||
version: '2023-10-31'
|
||||
servers:
|
||||
- url: 'http://{kibana_host}:{port}'
|
||||
variables:
|
||||
kibana_host:
|
||||
default: localhost
|
||||
port:
|
||||
default: '5601'
|
||||
paths:
|
||||
/api/timeline/resolve:
|
||||
get:
|
||||
|
@ -35,16 +28,15 @@ paths:
|
|||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [data]
|
||||
properties:
|
||||
data:
|
||||
type: object
|
||||
required: [getOneTimeline]
|
||||
oneOf:
|
||||
- type: object
|
||||
required: [data]
|
||||
properties:
|
||||
getOneTimeline:
|
||||
$ref: '../model/components.schema.yaml#/components/schemas/TimelineResponse'
|
||||
nullable: true
|
||||
data:
|
||||
$ref: '../model/components.schema.yaml#/components/schemas/ResolvedTimeline'
|
||||
- type: object
|
||||
additionalProperties: false
|
||||
|
||||
'400':
|
||||
description: The request is missing parameters
|
||||
'404':
|
||||
|
|
|
@ -17,7 +17,10 @@ export {
|
|||
} from './persist_note/persist_note_route.gen';
|
||||
export { DeleteNoteRequestBody, DeleteNoteResponse } from './delete_note/delete_note_route.gen';
|
||||
|
||||
export { CleanDraftTimelinesRequestBody } from './clean_draft_timelines/clean_draft_timelines_route.gen';
|
||||
export {
|
||||
CleanDraftTimelinesResponse,
|
||||
CleanDraftTimelinesRequestBody,
|
||||
} from './clean_draft_timelines/clean_draft_timelines_route.gen';
|
||||
|
||||
export {
|
||||
ExportTimelinesRequestQuery,
|
||||
|
@ -40,3 +43,48 @@ export {
|
|||
GetNotesResponse,
|
||||
GetNotesResult,
|
||||
} from './get_notes/get_notes_route.gen';
|
||||
|
||||
export {
|
||||
CopyTimelineRequestBody,
|
||||
CopyTimelineResponse,
|
||||
} from './copy_timeline/copy_timeline_route.gen';
|
||||
|
||||
export {
|
||||
CreateTimelinesRequestBody,
|
||||
CreateTimelinesResponse,
|
||||
} from './create_timelines/create_timelines_route.gen';
|
||||
|
||||
export {
|
||||
PatchTimelineRequestBody,
|
||||
PatchTimelineResponse,
|
||||
} from './patch_timelines/patch_timeline_route.gen';
|
||||
|
||||
export {
|
||||
ImportTimelinesRequestBody,
|
||||
ImportTimelinesResponse,
|
||||
} from './import_timelines/import_timelines_route.gen';
|
||||
|
||||
export {
|
||||
InstallPrepackedTimelinesRequestBody,
|
||||
InstallPrepackedTimelinesResponse,
|
||||
} from './install_prepackaged_timelines/install_prepackaged_timelines_route.gen';
|
||||
|
||||
export {
|
||||
GetDraftTimelinesRequestQuery,
|
||||
GetDraftTimelinesResponse,
|
||||
} from './get_draft_timelines/get_draft_timelines_route.gen';
|
||||
|
||||
export {
|
||||
ResolveTimelineRequestQuery,
|
||||
ResolveTimelineResponse,
|
||||
} from './resolve_timeline/resolve_timeline_route.gen';
|
||||
|
||||
export {
|
||||
GetTimelineRequestQuery,
|
||||
GetTimelineResponse,
|
||||
} from './get_timeline/get_timeline_route.gen';
|
||||
|
||||
export {
|
||||
GetTimelinesRequestQuery,
|
||||
GetTimelinesResponse,
|
||||
} from './get_timelines/get_timelines_route.gen';
|
||||
|
|
|
@ -5,13 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import type { SortField, Maybe } from '../common';
|
||||
import type {
|
||||
DataProviderType,
|
||||
TimelineType,
|
||||
TimelineStatus,
|
||||
RowRendererId,
|
||||
} from '../../api/timeline';
|
||||
import type { SortField } from '../common';
|
||||
|
||||
export * from './events';
|
||||
|
||||
|
@ -20,122 +14,6 @@ export interface TimelineRequestSortField<Field = string> extends SortField<Fiel
|
|||
esTypes: string[];
|
||||
}
|
||||
|
||||
export interface ColumnHeaderInput {
|
||||
aggregatable?: Maybe<boolean>;
|
||||
category?: Maybe<string>;
|
||||
columnHeaderType?: Maybe<string>;
|
||||
description?: Maybe<string>;
|
||||
example?: Maybe<string>;
|
||||
indexes?: Maybe<string[]>;
|
||||
id?: Maybe<string>;
|
||||
name?: Maybe<string>;
|
||||
placeholder?: Maybe<string>;
|
||||
searchable?: Maybe<boolean>;
|
||||
type?: Maybe<string>;
|
||||
}
|
||||
|
||||
export interface QueryMatchInput {
|
||||
field?: Maybe<string>;
|
||||
|
||||
displayField?: Maybe<string>;
|
||||
|
||||
value?: Maybe<string>;
|
||||
|
||||
displayValue?: Maybe<string>;
|
||||
|
||||
operator?: Maybe<string>;
|
||||
}
|
||||
|
||||
export interface DataProviderInput {
|
||||
id?: Maybe<string>;
|
||||
name?: Maybe<string>;
|
||||
enabled?: Maybe<boolean>;
|
||||
excluded?: Maybe<boolean>;
|
||||
kqlQuery?: Maybe<string>;
|
||||
queryMatch?: Maybe<QueryMatchInput>;
|
||||
and?: Maybe<DataProviderInput[]>;
|
||||
type?: Maybe<DataProviderType>;
|
||||
}
|
||||
|
||||
export interface EqlOptionsInput {
|
||||
eventCategoryField?: Maybe<string>;
|
||||
tiebreakerField?: Maybe<string>;
|
||||
timestampField?: Maybe<string>;
|
||||
query?: Maybe<string>;
|
||||
size?: Maybe<number>;
|
||||
}
|
||||
|
||||
export interface FilterMetaTimelineInput {
|
||||
alias?: Maybe<string>;
|
||||
controlledBy?: Maybe<string>;
|
||||
disabled?: Maybe<boolean>;
|
||||
field?: Maybe<string>;
|
||||
formattedValue?: Maybe<string>;
|
||||
index?: Maybe<string>;
|
||||
key?: Maybe<string>;
|
||||
negate?: Maybe<boolean>;
|
||||
params?: Maybe<string>;
|
||||
type?: Maybe<string>;
|
||||
value?: Maybe<string>;
|
||||
}
|
||||
|
||||
export interface FilterTimelineInput {
|
||||
exists?: Maybe<string>;
|
||||
meta?: Maybe<FilterMetaTimelineInput>;
|
||||
match_all?: Maybe<string>;
|
||||
missing?: Maybe<string>;
|
||||
query?: Maybe<string>;
|
||||
range?: Maybe<string>;
|
||||
script?: Maybe<string>;
|
||||
}
|
||||
|
||||
export interface SerializedFilterQueryInput {
|
||||
filterQuery?: Maybe<SerializedKueryQueryInput>;
|
||||
}
|
||||
|
||||
export interface SerializedKueryQueryInput {
|
||||
kuery?: Maybe<KueryFilterQueryInput>;
|
||||
serializedQuery?: Maybe<string>;
|
||||
}
|
||||
|
||||
export interface KueryFilterQueryInput {
|
||||
kind?: Maybe<string>;
|
||||
expression?: Maybe<string>;
|
||||
}
|
||||
|
||||
export interface DateRangePickerInput {
|
||||
start?: Maybe<number>;
|
||||
end?: Maybe<number>;
|
||||
}
|
||||
|
||||
export interface SortTimelineInput {
|
||||
columnId?: Maybe<string>;
|
||||
sortDirection?: Maybe<string>;
|
||||
}
|
||||
|
||||
export interface TimelineInput {
|
||||
columns?: Maybe<ColumnHeaderInput[]>;
|
||||
dataProviders?: Maybe<DataProviderInput[]>;
|
||||
dataViewId?: Maybe<string>;
|
||||
description?: Maybe<string>;
|
||||
eqlOptions?: Maybe<EqlOptionsInput>;
|
||||
eventType?: Maybe<string>;
|
||||
excludedRowRendererIds?: Maybe<RowRendererId[]>;
|
||||
filters?: Maybe<FilterTimelineInput[]>;
|
||||
kqlMode?: Maybe<string>;
|
||||
kqlQuery?: Maybe<SerializedFilterQueryInput>;
|
||||
indexNames?: Maybe<string[]>;
|
||||
title?: Maybe<string>;
|
||||
templateTimelineId?: Maybe<string>;
|
||||
templateTimelineVersion?: Maybe<number>;
|
||||
timelineType?: Maybe<TimelineType>;
|
||||
dateRange?: Maybe<DateRangePickerInput>;
|
||||
savedQueryId?: Maybe<string>;
|
||||
sort?: Maybe<SortTimelineInput[]>;
|
||||
status?: Maybe<TimelineStatus>;
|
||||
savedSearchId: Maybe<string>;
|
||||
}
|
||||
|
||||
export enum FlowDirection {
|
||||
uniDirectional = 'uniDirectional',
|
||||
biDirectional = 'biDirectional',
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import type { ZodError, ZodType } from '@kbn/zod';
|
||||
import { stringifyZodError } from '@kbn/zod-helpers';
|
||||
import { type Either, fold, left, right } from 'fp-ts/lib/Either';
|
||||
import { identity } from 'fp-ts/lib/function';
|
||||
import { pipe } from 'fp-ts/lib/pipeable';
|
||||
|
||||
type ErrorFactory = (message: string) => Error;
|
||||
|
||||
const throwErrors = (createError: ErrorFactory) => (errors: ZodError) => {
|
||||
throw createError(stringifyZodError(errors));
|
||||
};
|
||||
|
||||
const parseRuntimeType =
|
||||
<T>(zodType: ZodType<T>) =>
|
||||
(v: unknown): Either<ZodError<T>, T> => {
|
||||
const result = zodType.safeParse(v);
|
||||
return result.success ? right(result.data) : left(result.error);
|
||||
};
|
||||
|
||||
export const parseOrThrowErrorFactory =
|
||||
(createError: ErrorFactory) => (runtimeType: ZodType) => (inputValue: unknown) =>
|
||||
pipe(parseRuntimeType(runtimeType)(inputValue), fold(throwErrors(createError), identity));
|
|
@ -263,18 +263,20 @@ paths:
|
|||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
type: object
|
||||
oneOf:
|
||||
- type: object
|
||||
properties:
|
||||
getOneTimeline:
|
||||
$ref: '#/components/schemas/TimelineResponse'
|
||||
nullable: true
|
||||
data:
|
||||
type: object
|
||||
properties:
|
||||
getOneTimeline:
|
||||
$ref: '#/components/schemas/TimelineResponse'
|
||||
required:
|
||||
- getOneTimeline
|
||||
required:
|
||||
- getOneTimeline
|
||||
required:
|
||||
- data
|
||||
- data
|
||||
- additionalProperties: false
|
||||
type: object
|
||||
description: Indicates that the (template) timeline was found and returned.
|
||||
summary: >-
|
||||
Get an existing saved timeline or timeline template. This API is used to
|
||||
|
@ -313,22 +315,7 @@ paths:
|
|||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
type: object
|
||||
properties:
|
||||
persistTimeline:
|
||||
type: object
|
||||
properties:
|
||||
timeline:
|
||||
$ref: '#/components/schemas/TimelineResponse'
|
||||
required:
|
||||
- timeline
|
||||
required:
|
||||
- persistTimeline
|
||||
required:
|
||||
- data
|
||||
$ref: '#/components/schemas/PersistTimelineResponse'
|
||||
description: >-
|
||||
Indicates that the draft timeline was successfully created. In the
|
||||
event the user already has a draft timeline, the existing draft
|
||||
|
@ -389,20 +376,7 @@ paths:
|
|||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
type: object
|
||||
properties:
|
||||
persistTimeline:
|
||||
type: object
|
||||
properties:
|
||||
timeline:
|
||||
$ref: '#/components/schemas/TimelineResponse'
|
||||
required:
|
||||
- persistTimeline
|
||||
required:
|
||||
- data
|
||||
$ref: '#/components/schemas/PersistTimelineResponse'
|
||||
description: Indicates the timeline was successfully created.
|
||||
'405':
|
||||
content:
|
||||
|
@ -419,6 +393,36 @@ paths:
|
|||
tags:
|
||||
- Security Timeline API
|
||||
- 'access:securitySolution'
|
||||
/api/timeline/_copy:
|
||||
get:
|
||||
description: |
|
||||
Copies and returns a timeline or timeline template.
|
||||
operationId: CopyTimeline
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
timeline:
|
||||
$ref: '#/components/schemas/SavedTimeline'
|
||||
timelineIdToCopy:
|
||||
type: string
|
||||
required:
|
||||
- timeline
|
||||
- timelineIdToCopy
|
||||
required: true
|
||||
responses:
|
||||
'200':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/PersistTimelineResponse'
|
||||
description: Indicates that the timeline has been successfully copied.
|
||||
summary: Copies timeline or timeline template
|
||||
tags:
|
||||
- Security Timeline API
|
||||
- 'access:securitySolution'
|
||||
/api/timeline/_draft:
|
||||
get:
|
||||
operationId: GetDraftTimelines
|
||||
|
@ -433,22 +437,7 @@ paths:
|
|||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
type: object
|
||||
properties:
|
||||
persistTimeline:
|
||||
type: object
|
||||
properties:
|
||||
timeline:
|
||||
$ref: '#/components/schemas/TimelineResponse'
|
||||
required:
|
||||
- timeline
|
||||
required:
|
||||
- persistTimeline
|
||||
required:
|
||||
- data
|
||||
$ref: '#/components/schemas/PersistTimelineResponse'
|
||||
description: Indicates that the draft timeline was successfully retrieved.
|
||||
'403':
|
||||
content:
|
||||
|
@ -508,22 +497,7 @@ paths:
|
|||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
type: object
|
||||
properties:
|
||||
persistTimeline:
|
||||
type: object
|
||||
properties:
|
||||
timeline:
|
||||
$ref: '#/components/schemas/TimelineResponse'
|
||||
required:
|
||||
- timeline
|
||||
required:
|
||||
- persistTimeline
|
||||
required:
|
||||
- data
|
||||
$ref: '#/components/schemas/PersistTimelineResponse'
|
||||
description: >-
|
||||
Indicates that the draft timeline was successfully created. In the
|
||||
event the user already has a draft timeline, the existing draft
|
||||
|
@ -675,28 +649,14 @@ paths:
|
|||
schema:
|
||||
type: object
|
||||
properties:
|
||||
file:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/Readable'
|
||||
- type: object
|
||||
properties:
|
||||
hapi:
|
||||
type: object
|
||||
properties:
|
||||
filename:
|
||||
type: string
|
||||
headers:
|
||||
type: object
|
||||
isImmutable:
|
||||
enum:
|
||||
- 'true'
|
||||
- 'false'
|
||||
type: string
|
||||
required:
|
||||
- filename
|
||||
- headers
|
||||
required:
|
||||
- hapi
|
||||
file: {}
|
||||
isImmutable:
|
||||
enum:
|
||||
- 'true'
|
||||
- 'false'
|
||||
type: string
|
||||
required:
|
||||
- file
|
||||
description: The timelines to import as a readable stream.
|
||||
required: true
|
||||
responses:
|
||||
|
@ -704,12 +664,7 @@ paths:
|
|||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
$ref: '#/components/schemas/ImportTimelineResult'
|
||||
required:
|
||||
- data
|
||||
$ref: '#/components/schemas/ImportTimelineResult'
|
||||
description: Indicates the import of timelines was successful.
|
||||
'400':
|
||||
content:
|
||||
|
@ -767,7 +722,8 @@ paths:
|
|||
properties:
|
||||
prepackagedTimelines:
|
||||
items:
|
||||
$ref: '#/components/schemas/SavedTimeline'
|
||||
$ref: '#/components/schemas/TimelineSavedToReturnObject'
|
||||
nullable: true
|
||||
type: array
|
||||
timelinesToInstall:
|
||||
items:
|
||||
|
@ -790,12 +746,7 @@ paths:
|
|||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
$ref: '#/components/schemas/ImportTimelineResult'
|
||||
required:
|
||||
- data
|
||||
$ref: '#/components/schemas/ImportTimelineResult'
|
||||
description: Indicates the installation of prepackaged timelines was successful.
|
||||
'500':
|
||||
content:
|
||||
|
@ -833,18 +784,15 @@ paths:
|
|||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
type: object
|
||||
oneOf:
|
||||
- type: object
|
||||
properties:
|
||||
getOneTimeline:
|
||||
$ref: '#/components/schemas/TimelineResponse'
|
||||
nullable: true
|
||||
data:
|
||||
$ref: '#/components/schemas/ResolvedTimeline'
|
||||
required:
|
||||
- getOneTimeline
|
||||
required:
|
||||
- data
|
||||
- data
|
||||
- additionalProperties: false
|
||||
type: object
|
||||
description: The (template) timeline has been found
|
||||
'400':
|
||||
description: The request is missing parameters
|
||||
|
@ -912,35 +860,25 @@ paths:
|
|||
schema:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
type: object
|
||||
properties:
|
||||
customTemplateTimelineCount:
|
||||
type: number
|
||||
defaultTimelineCount:
|
||||
type: number
|
||||
elasticTemplateTimelineCount:
|
||||
type: number
|
||||
favoriteCount:
|
||||
type: number
|
||||
templateTimelineCount:
|
||||
type: number
|
||||
timelines:
|
||||
items:
|
||||
$ref: '#/components/schemas/TimelineResponse'
|
||||
type: array
|
||||
totalCount:
|
||||
type: number
|
||||
required:
|
||||
- timelines
|
||||
- totalCount
|
||||
- defaultTimelineCount
|
||||
- templateTimelineCount
|
||||
- favoriteCount
|
||||
- elasticTemplateTimelineCount
|
||||
- customTemplateTimelineCount
|
||||
customTemplateTimelineCount:
|
||||
type: number
|
||||
defaultTimelineCount:
|
||||
type: number
|
||||
elasticTemplateTimelineCount:
|
||||
type: number
|
||||
favoriteCount:
|
||||
type: number
|
||||
templateTimelineCount:
|
||||
type: number
|
||||
timeline:
|
||||
items:
|
||||
$ref: '#/components/schemas/TimelineResponse'
|
||||
type: array
|
||||
totalCount:
|
||||
type: number
|
||||
required:
|
||||
- data
|
||||
- timeline
|
||||
- totalCount
|
||||
description: Indicates that the (template) timelines were found and returned.
|
||||
'400':
|
||||
content:
|
||||
|
@ -1012,30 +950,39 @@ components:
|
|||
type: object
|
||||
properties:
|
||||
aggregatable:
|
||||
nullable: true
|
||||
type: boolean
|
||||
category:
|
||||
nullable: true
|
||||
type: string
|
||||
columnHeaderType:
|
||||
nullable: true
|
||||
type: string
|
||||
description:
|
||||
nullable: true
|
||||
type: string
|
||||
example:
|
||||
oneOf:
|
||||
- type: string
|
||||
- type: number
|
||||
nullable: true
|
||||
type: string
|
||||
id:
|
||||
nullable: true
|
||||
type: string
|
||||
indexes:
|
||||
items:
|
||||
type: string
|
||||
nullable: true
|
||||
type: array
|
||||
name:
|
||||
nullable: true
|
||||
type: string
|
||||
placeholder:
|
||||
nullable: true
|
||||
type: string
|
||||
searchable:
|
||||
nullable: true
|
||||
type: boolean
|
||||
type:
|
||||
nullable: true
|
||||
type: string
|
||||
DataProviderQueryMatch:
|
||||
type: object
|
||||
|
@ -1057,6 +1004,10 @@ components:
|
|||
type: string
|
||||
queryMatch:
|
||||
$ref: '#/components/schemas/QueryMatchResult'
|
||||
nullable: true
|
||||
type:
|
||||
$ref: '#/components/schemas/DataProviderType'
|
||||
nullable: true
|
||||
DataProviderResult:
|
||||
type: object
|
||||
properties:
|
||||
|
@ -1144,41 +1095,59 @@ components:
|
|||
type: object
|
||||
properties:
|
||||
exists:
|
||||
type: boolean
|
||||
nullable: true
|
||||
type: string
|
||||
match_all:
|
||||
nullable: true
|
||||
type: string
|
||||
meta:
|
||||
nullable: true
|
||||
type: object
|
||||
properties:
|
||||
alias:
|
||||
nullable: true
|
||||
type: string
|
||||
controlledBy:
|
||||
nullable: true
|
||||
type: string
|
||||
disabled:
|
||||
nullable: true
|
||||
type: boolean
|
||||
field:
|
||||
nullable: true
|
||||
type: string
|
||||
formattedValue:
|
||||
nullable: true
|
||||
type: string
|
||||
index:
|
||||
nullable: true
|
||||
type: string
|
||||
key:
|
||||
nullable: true
|
||||
type: string
|
||||
negate:
|
||||
nullable: true
|
||||
type: boolean
|
||||
params:
|
||||
nullable: true
|
||||
type: string
|
||||
type:
|
||||
nullable: true
|
||||
type: string
|
||||
value:
|
||||
nullable: true
|
||||
type: string
|
||||
missing:
|
||||
nullable: true
|
||||
type: string
|
||||
query:
|
||||
nullable: true
|
||||
type: string
|
||||
range:
|
||||
nullable: true
|
||||
type: string
|
||||
script:
|
||||
nullable: true
|
||||
type: string
|
||||
GetNotesResult:
|
||||
type: object
|
||||
|
@ -1243,6 +1212,12 @@ components:
|
|||
version:
|
||||
nullable: true
|
||||
type: string
|
||||
required:
|
||||
- savedObjectId
|
||||
- version
|
||||
- pinnedEventIds
|
||||
- eventNotes
|
||||
- globalNotes
|
||||
Note:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/BareNote'
|
||||
|
@ -1262,6 +1237,23 @@ components:
|
|||
- $ref: '#/components/schemas/PinnedEventBaseResponseBody'
|
||||
- nullable: true
|
||||
type: object
|
||||
PersistTimelineResponse:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
type: object
|
||||
properties:
|
||||
persistTimeline:
|
||||
type: object
|
||||
properties:
|
||||
timeline:
|
||||
$ref: '#/components/schemas/TimelineResponse'
|
||||
required:
|
||||
- timeline
|
||||
required:
|
||||
- persistTimeline
|
||||
required:
|
||||
- data
|
||||
PinnedEvent:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/BarePinnedEvent'
|
||||
|
@ -1299,34 +1291,27 @@ components:
|
|||
nullable: true
|
||||
type: string
|
||||
value:
|
||||
nullable: true
|
||||
type: string
|
||||
Readable:
|
||||
oneOf:
|
||||
- nullable: true
|
||||
type: string
|
||||
- items:
|
||||
type: string
|
||||
nullable: true
|
||||
type: array
|
||||
ResolvedTimeline:
|
||||
type: object
|
||||
properties:
|
||||
_data:
|
||||
additionalProperties: true
|
||||
type: object
|
||||
_encoding:
|
||||
alias_purpose:
|
||||
$ref: '#/components/schemas/SavedObjectResolveAliasPurpose'
|
||||
alias_target_id:
|
||||
type: string
|
||||
_events:
|
||||
additionalProperties: true
|
||||
type: object
|
||||
_eventsCount:
|
||||
type: number
|
||||
_maxListeners:
|
||||
additionalProperties: true
|
||||
type: object
|
||||
_position:
|
||||
type: number
|
||||
_read:
|
||||
additionalProperties: true
|
||||
type: object
|
||||
_readableState:
|
||||
additionalProperties: true
|
||||
type: object
|
||||
readable:
|
||||
type: boolean
|
||||
outcome:
|
||||
$ref: '#/components/schemas/SavedObjectResolveOutcome'
|
||||
timeline:
|
||||
$ref: '#/components/schemas/TimelineSavedToReturnObject'
|
||||
required:
|
||||
- timeline
|
||||
- outcome
|
||||
ResponseNote:
|
||||
type: object
|
||||
properties:
|
||||
|
@ -1361,6 +1346,17 @@ components:
|
|||
- threat_match
|
||||
- zeek
|
||||
type: string
|
||||
SavedObjectResolveAliasPurpose:
|
||||
enum:
|
||||
- savedObjectConversion
|
||||
- savedObjectImport
|
||||
type: string
|
||||
SavedObjectResolveOutcome:
|
||||
enum:
|
||||
- exactMatch
|
||||
- aliasMatch
|
||||
- conflict
|
||||
type: string
|
||||
SavedTimeline:
|
||||
type: object
|
||||
properties:
|
||||
|
@ -1389,12 +1385,16 @@ components:
|
|||
properties:
|
||||
end:
|
||||
oneOf:
|
||||
- type: string
|
||||
- type: number
|
||||
- nullable: true
|
||||
type: string
|
||||
- nullable: true
|
||||
type: number
|
||||
start:
|
||||
oneOf:
|
||||
- type: string
|
||||
- type: number
|
||||
- nullable: true
|
||||
type: string
|
||||
- nullable: true
|
||||
type: number
|
||||
description:
|
||||
nullable: true
|
||||
type: string
|
||||
|
@ -1483,6 +1483,18 @@ components:
|
|||
updatedBy:
|
||||
nullable: true
|
||||
type: string
|
||||
SavedTimelineWithSavedObjectId:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/SavedTimeline'
|
||||
- type: object
|
||||
properties:
|
||||
savedObjectId:
|
||||
type: string
|
||||
version:
|
||||
type: string
|
||||
required:
|
||||
- savedObjectId
|
||||
- version
|
||||
SerializedFilterQueryResult:
|
||||
type: object
|
||||
properties:
|
||||
|
@ -1532,27 +1544,63 @@ components:
|
|||
TimelineResponse:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/SavedTimeline'
|
||||
- $ref: '#/components/schemas/SavedTimelineWithSavedObjectId'
|
||||
- type: object
|
||||
properties:
|
||||
eventIdToNoteIds:
|
||||
items:
|
||||
$ref: '#/components/schemas/Note'
|
||||
nullable: true
|
||||
type: array
|
||||
noteIds:
|
||||
items:
|
||||
type: string
|
||||
nullable: true
|
||||
type: array
|
||||
notes:
|
||||
items:
|
||||
$ref: '#/components/schemas/Note'
|
||||
nullable: true
|
||||
type: array
|
||||
pinnedEventIds:
|
||||
items:
|
||||
type: string
|
||||
nullable: true
|
||||
type: array
|
||||
pinnedEventsSaveObject:
|
||||
items:
|
||||
$ref: '#/components/schemas/PinnedEvent'
|
||||
nullable: true
|
||||
type: array
|
||||
TimelineSavedToReturnObject:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/SavedTimeline'
|
||||
- type: object
|
||||
properties:
|
||||
eventIdToNoteIds:
|
||||
items:
|
||||
$ref: '#/components/schemas/Note'
|
||||
nullable: true
|
||||
type: array
|
||||
noteIds:
|
||||
items:
|
||||
type: string
|
||||
nullable: true
|
||||
type: array
|
||||
notes:
|
||||
items:
|
||||
$ref: '#/components/schemas/Note'
|
||||
nullable: true
|
||||
type: array
|
||||
pinnedEventIds:
|
||||
items:
|
||||
type: string
|
||||
nullable: true
|
||||
type: array
|
||||
pinnedEventsSaveObject:
|
||||
items:
|
||||
$ref: '#/components/schemas/PinnedEvent'
|
||||
nullable: true
|
||||
type: array
|
||||
savedObjectId:
|
||||
type: string
|
||||
|
|
|
@ -263,18 +263,20 @@ paths:
|
|||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
type: object
|
||||
oneOf:
|
||||
- type: object
|
||||
properties:
|
||||
getOneTimeline:
|
||||
$ref: '#/components/schemas/TimelineResponse'
|
||||
nullable: true
|
||||
data:
|
||||
type: object
|
||||
properties:
|
||||
getOneTimeline:
|
||||
$ref: '#/components/schemas/TimelineResponse'
|
||||
required:
|
||||
- getOneTimeline
|
||||
required:
|
||||
- getOneTimeline
|
||||
required:
|
||||
- data
|
||||
- data
|
||||
- additionalProperties: false
|
||||
type: object
|
||||
description: Indicates that the (template) timeline was found and returned.
|
||||
summary: >-
|
||||
Get an existing saved timeline or timeline template. This API is used to
|
||||
|
@ -313,22 +315,7 @@ paths:
|
|||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
type: object
|
||||
properties:
|
||||
persistTimeline:
|
||||
type: object
|
||||
properties:
|
||||
timeline:
|
||||
$ref: '#/components/schemas/TimelineResponse'
|
||||
required:
|
||||
- timeline
|
||||
required:
|
||||
- persistTimeline
|
||||
required:
|
||||
- data
|
||||
$ref: '#/components/schemas/PersistTimelineResponse'
|
||||
description: >-
|
||||
Indicates that the draft timeline was successfully created. In the
|
||||
event the user already has a draft timeline, the existing draft
|
||||
|
@ -389,20 +376,7 @@ paths:
|
|||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
type: object
|
||||
properties:
|
||||
persistTimeline:
|
||||
type: object
|
||||
properties:
|
||||
timeline:
|
||||
$ref: '#/components/schemas/TimelineResponse'
|
||||
required:
|
||||
- persistTimeline
|
||||
required:
|
||||
- data
|
||||
$ref: '#/components/schemas/PersistTimelineResponse'
|
||||
description: Indicates the timeline was successfully created.
|
||||
'405':
|
||||
content:
|
||||
|
@ -419,6 +393,36 @@ paths:
|
|||
tags:
|
||||
- Security Timeline API
|
||||
- 'access:securitySolution'
|
||||
/api/timeline/_copy:
|
||||
get:
|
||||
description: |
|
||||
Copies and returns a timeline or timeline template.
|
||||
operationId: CopyTimeline
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
timeline:
|
||||
$ref: '#/components/schemas/SavedTimeline'
|
||||
timelineIdToCopy:
|
||||
type: string
|
||||
required:
|
||||
- timeline
|
||||
- timelineIdToCopy
|
||||
required: true
|
||||
responses:
|
||||
'200':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/PersistTimelineResponse'
|
||||
description: Indicates that the timeline has been successfully copied.
|
||||
summary: Copies timeline or timeline template
|
||||
tags:
|
||||
- Security Timeline API
|
||||
- 'access:securitySolution'
|
||||
/api/timeline/_draft:
|
||||
get:
|
||||
operationId: GetDraftTimelines
|
||||
|
@ -433,22 +437,7 @@ paths:
|
|||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
type: object
|
||||
properties:
|
||||
persistTimeline:
|
||||
type: object
|
||||
properties:
|
||||
timeline:
|
||||
$ref: '#/components/schemas/TimelineResponse'
|
||||
required:
|
||||
- timeline
|
||||
required:
|
||||
- persistTimeline
|
||||
required:
|
||||
- data
|
||||
$ref: '#/components/schemas/PersistTimelineResponse'
|
||||
description: Indicates that the draft timeline was successfully retrieved.
|
||||
'403':
|
||||
content:
|
||||
|
@ -508,22 +497,7 @@ paths:
|
|||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
type: object
|
||||
properties:
|
||||
persistTimeline:
|
||||
type: object
|
||||
properties:
|
||||
timeline:
|
||||
$ref: '#/components/schemas/TimelineResponse'
|
||||
required:
|
||||
- timeline
|
||||
required:
|
||||
- persistTimeline
|
||||
required:
|
||||
- data
|
||||
$ref: '#/components/schemas/PersistTimelineResponse'
|
||||
description: >-
|
||||
Indicates that the draft timeline was successfully created. In the
|
||||
event the user already has a draft timeline, the existing draft
|
||||
|
@ -675,28 +649,14 @@ paths:
|
|||
schema:
|
||||
type: object
|
||||
properties:
|
||||
file:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/Readable'
|
||||
- type: object
|
||||
properties:
|
||||
hapi:
|
||||
type: object
|
||||
properties:
|
||||
filename:
|
||||
type: string
|
||||
headers:
|
||||
type: object
|
||||
isImmutable:
|
||||
enum:
|
||||
- 'true'
|
||||
- 'false'
|
||||
type: string
|
||||
required:
|
||||
- filename
|
||||
- headers
|
||||
required:
|
||||
- hapi
|
||||
file: {}
|
||||
isImmutable:
|
||||
enum:
|
||||
- 'true'
|
||||
- 'false'
|
||||
type: string
|
||||
required:
|
||||
- file
|
||||
description: The timelines to import as a readable stream.
|
||||
required: true
|
||||
responses:
|
||||
|
@ -704,12 +664,7 @@ paths:
|
|||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
$ref: '#/components/schemas/ImportTimelineResult'
|
||||
required:
|
||||
- data
|
||||
$ref: '#/components/schemas/ImportTimelineResult'
|
||||
description: Indicates the import of timelines was successful.
|
||||
'400':
|
||||
content:
|
||||
|
@ -767,7 +722,8 @@ paths:
|
|||
properties:
|
||||
prepackagedTimelines:
|
||||
items:
|
||||
$ref: '#/components/schemas/SavedTimeline'
|
||||
$ref: '#/components/schemas/TimelineSavedToReturnObject'
|
||||
nullable: true
|
||||
type: array
|
||||
timelinesToInstall:
|
||||
items:
|
||||
|
@ -790,12 +746,7 @@ paths:
|
|||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
$ref: '#/components/schemas/ImportTimelineResult'
|
||||
required:
|
||||
- data
|
||||
$ref: '#/components/schemas/ImportTimelineResult'
|
||||
description: Indicates the installation of prepackaged timelines was successful.
|
||||
'500':
|
||||
content:
|
||||
|
@ -833,18 +784,15 @@ paths:
|
|||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
type: object
|
||||
oneOf:
|
||||
- type: object
|
||||
properties:
|
||||
getOneTimeline:
|
||||
$ref: '#/components/schemas/TimelineResponse'
|
||||
nullable: true
|
||||
data:
|
||||
$ref: '#/components/schemas/ResolvedTimeline'
|
||||
required:
|
||||
- getOneTimeline
|
||||
required:
|
||||
- data
|
||||
- data
|
||||
- additionalProperties: false
|
||||
type: object
|
||||
description: The (template) timeline has been found
|
||||
'400':
|
||||
description: The request is missing parameters
|
||||
|
@ -912,35 +860,25 @@ paths:
|
|||
schema:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
type: object
|
||||
properties:
|
||||
customTemplateTimelineCount:
|
||||
type: number
|
||||
defaultTimelineCount:
|
||||
type: number
|
||||
elasticTemplateTimelineCount:
|
||||
type: number
|
||||
favoriteCount:
|
||||
type: number
|
||||
templateTimelineCount:
|
||||
type: number
|
||||
timelines:
|
||||
items:
|
||||
$ref: '#/components/schemas/TimelineResponse'
|
||||
type: array
|
||||
totalCount:
|
||||
type: number
|
||||
required:
|
||||
- timelines
|
||||
- totalCount
|
||||
- defaultTimelineCount
|
||||
- templateTimelineCount
|
||||
- favoriteCount
|
||||
- elasticTemplateTimelineCount
|
||||
- customTemplateTimelineCount
|
||||
customTemplateTimelineCount:
|
||||
type: number
|
||||
defaultTimelineCount:
|
||||
type: number
|
||||
elasticTemplateTimelineCount:
|
||||
type: number
|
||||
favoriteCount:
|
||||
type: number
|
||||
templateTimelineCount:
|
||||
type: number
|
||||
timeline:
|
||||
items:
|
||||
$ref: '#/components/schemas/TimelineResponse'
|
||||
type: array
|
||||
totalCount:
|
||||
type: number
|
||||
required:
|
||||
- data
|
||||
- timeline
|
||||
- totalCount
|
||||
description: Indicates that the (template) timelines were found and returned.
|
||||
'400':
|
||||
content:
|
||||
|
@ -1012,30 +950,39 @@ components:
|
|||
type: object
|
||||
properties:
|
||||
aggregatable:
|
||||
nullable: true
|
||||
type: boolean
|
||||
category:
|
||||
nullable: true
|
||||
type: string
|
||||
columnHeaderType:
|
||||
nullable: true
|
||||
type: string
|
||||
description:
|
||||
nullable: true
|
||||
type: string
|
||||
example:
|
||||
oneOf:
|
||||
- type: string
|
||||
- type: number
|
||||
nullable: true
|
||||
type: string
|
||||
id:
|
||||
nullable: true
|
||||
type: string
|
||||
indexes:
|
||||
items:
|
||||
type: string
|
||||
nullable: true
|
||||
type: array
|
||||
name:
|
||||
nullable: true
|
||||
type: string
|
||||
placeholder:
|
||||
nullable: true
|
||||
type: string
|
||||
searchable:
|
||||
nullable: true
|
||||
type: boolean
|
||||
type:
|
||||
nullable: true
|
||||
type: string
|
||||
DataProviderQueryMatch:
|
||||
type: object
|
||||
|
@ -1057,6 +1004,10 @@ components:
|
|||
type: string
|
||||
queryMatch:
|
||||
$ref: '#/components/schemas/QueryMatchResult'
|
||||
nullable: true
|
||||
type:
|
||||
$ref: '#/components/schemas/DataProviderType'
|
||||
nullable: true
|
||||
DataProviderResult:
|
||||
type: object
|
||||
properties:
|
||||
|
@ -1144,41 +1095,59 @@ components:
|
|||
type: object
|
||||
properties:
|
||||
exists:
|
||||
type: boolean
|
||||
nullable: true
|
||||
type: string
|
||||
match_all:
|
||||
nullable: true
|
||||
type: string
|
||||
meta:
|
||||
nullable: true
|
||||
type: object
|
||||
properties:
|
||||
alias:
|
||||
nullable: true
|
||||
type: string
|
||||
controlledBy:
|
||||
nullable: true
|
||||
type: string
|
||||
disabled:
|
||||
nullable: true
|
||||
type: boolean
|
||||
field:
|
||||
nullable: true
|
||||
type: string
|
||||
formattedValue:
|
||||
nullable: true
|
||||
type: string
|
||||
index:
|
||||
nullable: true
|
||||
type: string
|
||||
key:
|
||||
nullable: true
|
||||
type: string
|
||||
negate:
|
||||
nullable: true
|
||||
type: boolean
|
||||
params:
|
||||
nullable: true
|
||||
type: string
|
||||
type:
|
||||
nullable: true
|
||||
type: string
|
||||
value:
|
||||
nullable: true
|
||||
type: string
|
||||
missing:
|
||||
nullable: true
|
||||
type: string
|
||||
query:
|
||||
nullable: true
|
||||
type: string
|
||||
range:
|
||||
nullable: true
|
||||
type: string
|
||||
script:
|
||||
nullable: true
|
||||
type: string
|
||||
GetNotesResult:
|
||||
type: object
|
||||
|
@ -1243,6 +1212,12 @@ components:
|
|||
version:
|
||||
nullable: true
|
||||
type: string
|
||||
required:
|
||||
- savedObjectId
|
||||
- version
|
||||
- pinnedEventIds
|
||||
- eventNotes
|
||||
- globalNotes
|
||||
Note:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/BareNote'
|
||||
|
@ -1262,6 +1237,23 @@ components:
|
|||
- $ref: '#/components/schemas/PinnedEventBaseResponseBody'
|
||||
- nullable: true
|
||||
type: object
|
||||
PersistTimelineResponse:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
type: object
|
||||
properties:
|
||||
persistTimeline:
|
||||
type: object
|
||||
properties:
|
||||
timeline:
|
||||
$ref: '#/components/schemas/TimelineResponse'
|
||||
required:
|
||||
- timeline
|
||||
required:
|
||||
- persistTimeline
|
||||
required:
|
||||
- data
|
||||
PinnedEvent:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/BarePinnedEvent'
|
||||
|
@ -1299,34 +1291,27 @@ components:
|
|||
nullable: true
|
||||
type: string
|
||||
value:
|
||||
nullable: true
|
||||
type: string
|
||||
Readable:
|
||||
oneOf:
|
||||
- nullable: true
|
||||
type: string
|
||||
- items:
|
||||
type: string
|
||||
nullable: true
|
||||
type: array
|
||||
ResolvedTimeline:
|
||||
type: object
|
||||
properties:
|
||||
_data:
|
||||
additionalProperties: true
|
||||
type: object
|
||||
_encoding:
|
||||
alias_purpose:
|
||||
$ref: '#/components/schemas/SavedObjectResolveAliasPurpose'
|
||||
alias_target_id:
|
||||
type: string
|
||||
_events:
|
||||
additionalProperties: true
|
||||
type: object
|
||||
_eventsCount:
|
||||
type: number
|
||||
_maxListeners:
|
||||
additionalProperties: true
|
||||
type: object
|
||||
_position:
|
||||
type: number
|
||||
_read:
|
||||
additionalProperties: true
|
||||
type: object
|
||||
_readableState:
|
||||
additionalProperties: true
|
||||
type: object
|
||||
readable:
|
||||
type: boolean
|
||||
outcome:
|
||||
$ref: '#/components/schemas/SavedObjectResolveOutcome'
|
||||
timeline:
|
||||
$ref: '#/components/schemas/TimelineSavedToReturnObject'
|
||||
required:
|
||||
- timeline
|
||||
- outcome
|
||||
ResponseNote:
|
||||
type: object
|
||||
properties:
|
||||
|
@ -1361,6 +1346,17 @@ components:
|
|||
- threat_match
|
||||
- zeek
|
||||
type: string
|
||||
SavedObjectResolveAliasPurpose:
|
||||
enum:
|
||||
- savedObjectConversion
|
||||
- savedObjectImport
|
||||
type: string
|
||||
SavedObjectResolveOutcome:
|
||||
enum:
|
||||
- exactMatch
|
||||
- aliasMatch
|
||||
- conflict
|
||||
type: string
|
||||
SavedTimeline:
|
||||
type: object
|
||||
properties:
|
||||
|
@ -1389,12 +1385,16 @@ components:
|
|||
properties:
|
||||
end:
|
||||
oneOf:
|
||||
- type: string
|
||||
- type: number
|
||||
- nullable: true
|
||||
type: string
|
||||
- nullable: true
|
||||
type: number
|
||||
start:
|
||||
oneOf:
|
||||
- type: string
|
||||
- type: number
|
||||
- nullable: true
|
||||
type: string
|
||||
- nullable: true
|
||||
type: number
|
||||
description:
|
||||
nullable: true
|
||||
type: string
|
||||
|
@ -1483,6 +1483,18 @@ components:
|
|||
updatedBy:
|
||||
nullable: true
|
||||
type: string
|
||||
SavedTimelineWithSavedObjectId:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/SavedTimeline'
|
||||
- type: object
|
||||
properties:
|
||||
savedObjectId:
|
||||
type: string
|
||||
version:
|
||||
type: string
|
||||
required:
|
||||
- savedObjectId
|
||||
- version
|
||||
SerializedFilterQueryResult:
|
||||
type: object
|
||||
properties:
|
||||
|
@ -1532,27 +1544,63 @@ components:
|
|||
TimelineResponse:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/SavedTimeline'
|
||||
- $ref: '#/components/schemas/SavedTimelineWithSavedObjectId'
|
||||
- type: object
|
||||
properties:
|
||||
eventIdToNoteIds:
|
||||
items:
|
||||
$ref: '#/components/schemas/Note'
|
||||
nullable: true
|
||||
type: array
|
||||
noteIds:
|
||||
items:
|
||||
type: string
|
||||
nullable: true
|
||||
type: array
|
||||
notes:
|
||||
items:
|
||||
$ref: '#/components/schemas/Note'
|
||||
nullable: true
|
||||
type: array
|
||||
pinnedEventIds:
|
||||
items:
|
||||
type: string
|
||||
nullable: true
|
||||
type: array
|
||||
pinnedEventsSaveObject:
|
||||
items:
|
||||
$ref: '#/components/schemas/PinnedEvent'
|
||||
nullable: true
|
||||
type: array
|
||||
TimelineSavedToReturnObject:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/SavedTimeline'
|
||||
- type: object
|
||||
properties:
|
||||
eventIdToNoteIds:
|
||||
items:
|
||||
$ref: '#/components/schemas/Note'
|
||||
nullable: true
|
||||
type: array
|
||||
noteIds:
|
||||
items:
|
||||
type: string
|
||||
nullable: true
|
||||
type: array
|
||||
notes:
|
||||
items:
|
||||
$ref: '#/components/schemas/Note'
|
||||
nullable: true
|
||||
type: array
|
||||
pinnedEventIds:
|
||||
items:
|
||||
type: string
|
||||
nullable: true
|
||||
type: array
|
||||
pinnedEventsSaveObject:
|
||||
items:
|
||||
$ref: '#/components/schemas/PinnedEvent'
|
||||
nullable: true
|
||||
type: array
|
||||
savedObjectId:
|
||||
type: string
|
||||
|
|
|
@ -9,9 +9,10 @@ import { FilterStateStore } from '@kbn/es-query';
|
|||
|
||||
import type { DataTableModel } from '@kbn/securitysolution-data-table';
|
||||
import { VIEW_SELECTION } from '../../../common/constants';
|
||||
import type { TimelineResult } from '../../../common/api/timeline';
|
||||
import { TimelineId, TimelineTabs } from '../../../common/types/timeline';
|
||||
import type { TimelineResponse } from '../../../common/api/timeline';
|
||||
import {
|
||||
type ColumnHeaderResult,
|
||||
RowRendererIdEnum,
|
||||
TimelineTypeEnum,
|
||||
TimelineStatusEnum,
|
||||
|
@ -1986,9 +1987,11 @@ export const mockDataTableModel: DataTableModel = {
|
|||
},
|
||||
};
|
||||
|
||||
export const mockGetOneTimelineResult: TimelineResult = {
|
||||
export const mockGetOneTimelineResult: TimelineResponse = {
|
||||
savedObjectId: 'ef579e40-jibber-jabber',
|
||||
columns: timelineDefaults.columns.filter((column) => column.id !== 'event.action'),
|
||||
columns: timelineDefaults.columns.filter(
|
||||
(column) => column.id !== 'event.action'
|
||||
) as ColumnHeaderResult[],
|
||||
dateRange: { start: '2020-03-18T13:46:38.929Z', end: '2020-03-18T13:52:38.929Z' },
|
||||
description: 'This is a sample rule description',
|
||||
eventType: 'all',
|
||||
|
|
|
@ -50,8 +50,8 @@ import {
|
|||
isNewTermsRule,
|
||||
isThresholdRule,
|
||||
} from '../../../../common/detection_engine/utils';
|
||||
import type { TimelineResult } from '../../../../common/api/timeline';
|
||||
import { TimelineId } from '../../../../common/types/timeline';
|
||||
import type { TimelineResponse } from '../../../../common/api/timeline';
|
||||
import { TimelineStatusEnum, TimelineTypeEnum } from '../../../../common/api/timeline';
|
||||
import type {
|
||||
SendAlertToTimelineActionProps,
|
||||
|
@ -69,7 +69,7 @@ import { TimelineEventsQueries } from '../../../../common/search_strategy/timeli
|
|||
import { timelineDefaults } from '../../../timelines/store/defaults';
|
||||
import {
|
||||
omitTypenameInTimeline,
|
||||
formatTimelineResultToModel,
|
||||
formatTimelineResponseToModel,
|
||||
} from '../../../timelines/components/open_timeline/helpers';
|
||||
import { convertKueryToElasticSearchQuery } from '../../../common/lib/kuery';
|
||||
import { getField, getFieldKey } from '../../../helpers';
|
||||
|
@ -983,11 +983,15 @@ export const sendAlertToTimelineAction = async ({
|
|||
),
|
||||
]);
|
||||
|
||||
const resultingTimeline: TimelineResult = getOr({}, 'data.getOneTimeline', responseTimeline);
|
||||
const resultingTimeline: TimelineResponse = getOr(
|
||||
{},
|
||||
'data.getOneTimeline',
|
||||
responseTimeline
|
||||
);
|
||||
const eventData: TimelineEventsDetailsItem[] = eventDataResp.data ?? [];
|
||||
if (!isEmpty(resultingTimeline)) {
|
||||
const timelineTemplate: TimelineResult = omitTypenameInTimeline(resultingTimeline);
|
||||
const { timeline, notes } = formatTimelineResultToModel(
|
||||
const timelineTemplate = omitTypenameInTimeline(resultingTimeline);
|
||||
const { timeline, notes } = formatTimelineResponseToModel(
|
||||
timelineTemplate,
|
||||
true,
|
||||
timelineTemplate.timelineType ?? TimelineTypeEnum.default
|
||||
|
|
|
@ -20,12 +20,16 @@ import {
|
|||
isUntitled,
|
||||
omitTypenameInTimeline,
|
||||
useQueryTimelineById,
|
||||
formatTimelineResultToModel,
|
||||
formatTimelineResponseToModel,
|
||||
} from './helpers';
|
||||
import type { OpenTimelineResult } from './types';
|
||||
import { TimelineId } from '../../../../common/types/timeline';
|
||||
import type { RowRendererId } from '../../../../common/api/timeline';
|
||||
import { TimelineTypeEnum, TimelineStatusEnum } from '../../../../common/api/timeline';
|
||||
import {
|
||||
TimelineTypeEnum,
|
||||
TimelineStatusEnum,
|
||||
type ColumnHeaderResult,
|
||||
type RowRendererId,
|
||||
} from '../../../../common/api/timeline';
|
||||
import {
|
||||
mockTimeline as mockSelectedTimeline,
|
||||
mockTemplate as mockSelectedTemplate,
|
||||
|
@ -379,7 +383,7 @@ describe('helpers', () => {
|
|||
);
|
||||
const timeline = {
|
||||
savedObjectId: 'savedObject-1',
|
||||
columns: columnsWithoutEventAction,
|
||||
columns: columnsWithoutEventAction as ColumnHeaderResult[],
|
||||
version: '1',
|
||||
};
|
||||
|
||||
|
@ -396,7 +400,7 @@ describe('helpers', () => {
|
|||
);
|
||||
const timeline = {
|
||||
savedObjectId: 'savedObject-1',
|
||||
columns: columnsWithoutEventAction,
|
||||
columns: columnsWithoutEventAction as ColumnHeaderResult[],
|
||||
filters: [
|
||||
{
|
||||
meta: {
|
||||
|
@ -568,7 +572,7 @@ describe('helpers', () => {
|
|||
version: '1',
|
||||
status: TimelineStatusEnum.active,
|
||||
timelineType: TimelineTypeEnum.default,
|
||||
columns: customColumns,
|
||||
columns: customColumns as ColumnHeaderResult[],
|
||||
};
|
||||
|
||||
const newTimeline = defaultTimelineToTimelineModel(
|
||||
|
@ -691,7 +695,7 @@ describe('helpers', () => {
|
|||
});
|
||||
|
||||
test('Do not override daterange if TimelineStatus is active', () => {
|
||||
const { timeline } = formatTimelineResultToModel(
|
||||
const { timeline } = formatTimelineResponseToModel(
|
||||
omitTypenameInTimeline(getOr({}, 'data.timeline', selectedTimeline)),
|
||||
args.duplicate,
|
||||
args.timelineType
|
||||
|
@ -744,7 +748,7 @@ describe('helpers', () => {
|
|||
});
|
||||
|
||||
test('should not override daterange if TimelineStatus is active', () => {
|
||||
const { timeline } = formatTimelineResultToModel(
|
||||
const { timeline } = formatTimelineResponseToModel(
|
||||
omitTypenameInTimeline(getOr({}, 'data.timeline', selectedTimeline)),
|
||||
args.duplicate,
|
||||
args.timelineType
|
||||
|
@ -818,7 +822,7 @@ describe('helpers', () => {
|
|||
});
|
||||
|
||||
test('override daterange if TimelineStatus is immutable', () => {
|
||||
const { timeline } = formatTimelineResultToModel(
|
||||
const { timeline } = formatTimelineResponseToModel(
|
||||
omitTypenameInTimeline(getOr({}, 'data.timeline', template)),
|
||||
args.duplicate,
|
||||
args.timelineType
|
||||
|
|
|
@ -14,8 +14,8 @@ import { useCallback } from 'react';
|
|||
import { useDiscoverInTimelineContext } from '../../../common/components/discover_in_timeline/use_discover_in_timeline_context';
|
||||
import type { ColumnHeaderOptions } from '../../../../common/types/timeline';
|
||||
import type {
|
||||
TimelineResult,
|
||||
SingleTimelineResolveResponse,
|
||||
TimelineResponse,
|
||||
ResolvedTimeline,
|
||||
ColumnHeaderResult,
|
||||
FilterTimelineResult,
|
||||
DataProviderResult,
|
||||
|
@ -80,7 +80,7 @@ export const isUntitled = ({ title }: OpenTimelineResult): boolean =>
|
|||
const omitTypename = (key: string, value: keyof TimelineModel) =>
|
||||
key === '__typename' ? undefined : value;
|
||||
|
||||
export const omitTypenameInTimeline = (timeline: TimelineResult): TimelineResult =>
|
||||
export const omitTypenameInTimeline = (timeline: TimelineResponse): TimelineResponse =>
|
||||
JSON.parse(JSON.stringify(timeline), omitTypename);
|
||||
|
||||
const parseString = (params: string) => {
|
||||
|
@ -164,7 +164,7 @@ const setPinnedEventIds = (duplicate: boolean, pinnedEventIds: string[] | null |
|
|||
: {};
|
||||
|
||||
const getTemplateTimelineId = (
|
||||
timeline: TimelineResult,
|
||||
timeline: TimelineResponse,
|
||||
duplicate: boolean,
|
||||
targetTimelineType?: TimelineType
|
||||
) => {
|
||||
|
@ -200,7 +200,7 @@ const convertToDefaultField = ({ and, ...dataProvider }: DataProviderResult) =>
|
|||
|
||||
const getDataProviders = (
|
||||
duplicate: boolean,
|
||||
dataProviders: TimelineResult['dataProviders'],
|
||||
dataProviders: TimelineResponse['dataProviders'],
|
||||
timelineType?: TimelineType
|
||||
) => {
|
||||
if (duplicate && dataProviders && timelineType === TimelineTypeEnum.default) {
|
||||
|
@ -214,7 +214,7 @@ const getDataProviders = (
|
|||
};
|
||||
|
||||
export const getTimelineTitle = (
|
||||
timeline: TimelineResult,
|
||||
timeline: TimelineResponse,
|
||||
duplicate: boolean,
|
||||
timelineType?: TimelineType
|
||||
) => {
|
||||
|
@ -225,7 +225,7 @@ export const getTimelineTitle = (
|
|||
};
|
||||
|
||||
export const getTimelineStatus = (
|
||||
timeline: TimelineResult,
|
||||
timeline: TimelineResponse,
|
||||
duplicate: boolean,
|
||||
timelineType?: TimelineType
|
||||
) => {
|
||||
|
@ -236,7 +236,7 @@ export const getTimelineStatus = (
|
|||
};
|
||||
|
||||
export const defaultTimelineToTimelineModel = (
|
||||
timeline: TimelineResult,
|
||||
timeline: TimelineResponse,
|
||||
duplicate: boolean,
|
||||
timelineType?: TimelineType,
|
||||
unifiedComponentsInTimelineDisabled?: boolean
|
||||
|
@ -291,8 +291,8 @@ export const defaultTimelineToTimelineModel = (
|
|||
);
|
||||
};
|
||||
|
||||
export const formatTimelineResultToModel = (
|
||||
timelineToOpen: TimelineResult,
|
||||
export const formatTimelineResponseToModel = (
|
||||
timelineToOpen: TimelineResponse,
|
||||
duplicate: boolean = false,
|
||||
timelineType?: TimelineType,
|
||||
unifiedComponentsInTimelineDisabled?: boolean
|
||||
|
@ -376,12 +376,12 @@ export const useQueryTimelineById = () => {
|
|||
} else {
|
||||
return Promise.resolve(resolveTimeline(timelineId))
|
||||
.then((result) => {
|
||||
const data: SingleTimelineResolveResponse['data'] | null = getOr(null, 'data', result);
|
||||
const data: ResolvedTimeline | null = getOr(null, 'data', result);
|
||||
if (!data) return;
|
||||
|
||||
const timelineToOpen = omitTypenameInTimeline(data.timeline);
|
||||
|
||||
const { timeline, notes } = formatTimelineResultToModel(
|
||||
const { timeline, notes } = formatTimelineResponseToModel(
|
||||
timelineToOpen,
|
||||
duplicate,
|
||||
timelineType,
|
||||
|
|
|
@ -10,7 +10,7 @@ import type { IconType } from '@elastic/eui';
|
|||
import type { TimelineModel } from '../../store/model';
|
||||
import type {
|
||||
RowRendererId,
|
||||
SingleTimelineResolveResponse,
|
||||
ResolvedTimeline,
|
||||
TimelineType,
|
||||
TimelineStatus,
|
||||
TemplateTimelineType,
|
||||
|
@ -210,9 +210,9 @@ export interface OpenTimelineProps {
|
|||
}
|
||||
|
||||
export interface ResolveTimelineConfig {
|
||||
alias_target_id: SingleTimelineResolveResponse['data']['alias_target_id'];
|
||||
outcome: SingleTimelineResolveResponse['data']['outcome'];
|
||||
alias_purpose: SingleTimelineResolveResponse['data']['alias_purpose'];
|
||||
alias_target_id: ResolvedTimeline['alias_target_id'];
|
||||
outcome: ResolvedTimeline['outcome'];
|
||||
alias_purpose: ResolvedTimeline['alias_purpose'];
|
||||
}
|
||||
export interface UpdateTimeline {
|
||||
duplicate: boolean;
|
||||
|
|
|
@ -21,9 +21,9 @@ import type {
|
|||
TimelineType,
|
||||
TimelineStatus,
|
||||
PageInfoTimeline,
|
||||
TimelineResult,
|
||||
TimelineResponse,
|
||||
SortTimeline,
|
||||
GetAllTimelineVariables,
|
||||
GetTimelinesRequestQuery,
|
||||
} from '../../../../common/api/timeline';
|
||||
import { TimelineTypeEnum } from '../../../../common/api/timeline';
|
||||
import { getAllTimelines } from '../api';
|
||||
|
@ -59,7 +59,7 @@ export interface AllTimelinesVariables {
|
|||
export const ALL_TIMELINE_QUERY_ID = 'FETCH_ALL_TIMELINES';
|
||||
|
||||
export const getAllTimeline = memoizeOne(
|
||||
(_variables: string, timelines: TimelineResult[]): OpenTimelineResult[] =>
|
||||
(_variables: string, timelines: TimelineResponse[]): OpenTimelineResult[] =>
|
||||
timelines.map((timeline) => ({
|
||||
created: timeline.created,
|
||||
description: timeline.description,
|
||||
|
@ -132,13 +132,15 @@ export const useGetAllTimeline = (): AllTimelinesArgs => {
|
|||
loading: true,
|
||||
}));
|
||||
|
||||
const variables: GetAllTimelineVariables = {
|
||||
onlyUserFavorite,
|
||||
pageInfo,
|
||||
const variables: GetTimelinesRequestQuery = {
|
||||
only_user_favorite: onlyUserFavorite ? 'true' : 'false',
|
||||
page_size: pageInfo.pageSize.toString(),
|
||||
page_index: pageInfo.pageIndex.toString(),
|
||||
search,
|
||||
sort,
|
||||
status,
|
||||
timelineType,
|
||||
sort_field: sort.sortField,
|
||||
sort_order: sort.sortOrder,
|
||||
status: status || undefined,
|
||||
timeline_type: timelineType,
|
||||
};
|
||||
const getAllTimelineResponse = await getAllTimelines(variables, abortCtrl.signal);
|
||||
const totalCount = getAllTimelineResponse?.totalCount ?? 0;
|
||||
|
@ -163,7 +165,7 @@ export const useGetAllTimeline = (): AllTimelinesArgs => {
|
|||
setAllTimelines({
|
||||
loading: false,
|
||||
totalCount,
|
||||
timelines: getAllTimeline(JSON.stringify(variables), timelines as TimelineResult[]),
|
||||
timelines: getAllTimeline(JSON.stringify(variables), timelines as TimelineResponse[]),
|
||||
customTemplateTimelineCount,
|
||||
defaultTimelineCount,
|
||||
elasticTemplateTimelineCount,
|
||||
|
|
|
@ -5,34 +5,30 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { fold } from 'fp-ts/lib/Either';
|
||||
import { identity } from 'fp-ts/lib/function';
|
||||
import { pipe } from 'fp-ts/lib/pipeable';
|
||||
import { isEmpty } from 'lodash';
|
||||
|
||||
import { throwErrors } from '@kbn/cases-plugin/common';
|
||||
import type { SavedSearch } from '@kbn/saved-search-plugin/common';
|
||||
|
||||
import type {
|
||||
TimelineResponse,
|
||||
TimelineErrorResponse,
|
||||
ImportTimelineResultSchema,
|
||||
AllTimelinesResponse,
|
||||
SingleTimelineResponse,
|
||||
SingleTimelineResolveResponse,
|
||||
GetTimelinesArgs,
|
||||
CleanDraftTimelinesResponse,
|
||||
TimelineType,
|
||||
PatchTimelineResponse,
|
||||
CreateTimelinesResponse,
|
||||
CopyTimelineResponse,
|
||||
GetDraftTimelinesResponse,
|
||||
GetTimelinesRequestQuery,
|
||||
SavedTimeline,
|
||||
} from '../../../common/api/timeline';
|
||||
import {
|
||||
TimelineResponseType,
|
||||
ImportTimelineResult,
|
||||
TimelineErrorResponse,
|
||||
TimelineStatusEnum,
|
||||
TimelineErrorResponseType,
|
||||
importTimelineResultSchema,
|
||||
allTimelinesResponse,
|
||||
PersistFavoriteRouteResponse,
|
||||
SingleTimelineResponseType,
|
||||
type TimelineType,
|
||||
TimelineTypeEnum,
|
||||
ResolvedSingleTimelineResponseType,
|
||||
GetTimelineResponse,
|
||||
ResolveTimelineResponse,
|
||||
GetTimelinesResponse,
|
||||
PersistTimelineResponse,
|
||||
} from '../../../common/api/timeline';
|
||||
import {
|
||||
TIMELINE_URL,
|
||||
|
@ -48,15 +44,15 @@ import {
|
|||
|
||||
import { KibanaServices } from '../../common/lib/kibana';
|
||||
import { ToasterError } from '../../common/components/toasters';
|
||||
import { parseOrThrowErrorFactory } from '../../../common/timelines/zod_errors';
|
||||
import type {
|
||||
ExportDocumentsProps,
|
||||
ImportDataProps,
|
||||
ImportDataResponse,
|
||||
} from '../../detection_engine/rule_management/logic';
|
||||
import type { TimelineInput } from '../../../common/search_strategy';
|
||||
|
||||
interface RequestPostTimeline {
|
||||
timeline: TimelineInput;
|
||||
timeline: SavedTimeline;
|
||||
signal?: AbortSignal;
|
||||
}
|
||||
|
||||
|
@ -68,48 +64,33 @@ interface RequestPatchTimeline<T = string> extends RequestPostTimeline {
|
|||
|
||||
type RequestPersistTimeline = RequestPostTimeline & Partial<RequestPatchTimeline<null | string>>;
|
||||
const createToasterPlainError = (message: string) => new ToasterError([message]);
|
||||
const decodeTimelineResponse = (respTimeline?: TimelineResponse | TimelineErrorResponse) =>
|
||||
pipe(
|
||||
TimelineResponseType.decode(respTimeline),
|
||||
fold(throwErrors(createToasterPlainError), identity)
|
||||
);
|
||||
|
||||
const decodeSingleTimelineResponse = (respTimeline?: SingleTimelineResponse) =>
|
||||
pipe(
|
||||
SingleTimelineResponseType.decode(respTimeline),
|
||||
fold(throwErrors(createToasterPlainError), identity)
|
||||
);
|
||||
const parseOrThrow = parseOrThrowErrorFactory(createToasterPlainError);
|
||||
|
||||
const decodeResolvedSingleTimelineResponse = (respTimeline?: SingleTimelineResolveResponse) =>
|
||||
pipe(
|
||||
ResolvedSingleTimelineResponseType.decode(respTimeline),
|
||||
fold(throwErrors(createToasterPlainError), identity)
|
||||
);
|
||||
const decodeTimelineResponse = (respTimeline?: PersistTimelineResponse | TimelineErrorResponse) =>
|
||||
parseOrThrow(PersistTimelineResponse)(respTimeline);
|
||||
|
||||
const decodeAllTimelinesResponse = (respTimeline: AllTimelinesResponse) =>
|
||||
pipe(
|
||||
allTimelinesResponse.decode(respTimeline),
|
||||
fold(throwErrors(createToasterPlainError), identity)
|
||||
);
|
||||
const decodeSingleTimelineResponse = (respTimeline?: GetTimelineResponse) =>
|
||||
parseOrThrow(GetTimelineResponse)(respTimeline);
|
||||
|
||||
const decodeResolvedSingleTimelineResponse = (respTimeline?: ResolveTimelineResponse) =>
|
||||
parseOrThrow(ResolveTimelineResponse)(respTimeline);
|
||||
|
||||
const decodeGetTimelinesResponse = (respTimeline: GetTimelinesResponse) =>
|
||||
parseOrThrow(GetTimelinesResponse)(respTimeline);
|
||||
|
||||
const decodeTimelineErrorResponse = (respTimeline?: TimelineErrorResponse) =>
|
||||
pipe(
|
||||
TimelineErrorResponseType.decode(respTimeline),
|
||||
fold(throwErrors(createToasterPlainError), identity)
|
||||
);
|
||||
parseOrThrow(TimelineErrorResponse)(respTimeline);
|
||||
|
||||
const decodePrepackedTimelineResponse = (respTimeline?: ImportTimelineResultSchema) =>
|
||||
pipe(
|
||||
importTimelineResultSchema.decode(respTimeline),
|
||||
fold(throwErrors(createToasterPlainError), identity)
|
||||
);
|
||||
const decodePrepackedTimelineResponse = (respTimeline?: ImportTimelineResult) =>
|
||||
parseOrThrow(ImportTimelineResult)(respTimeline);
|
||||
|
||||
const decodeResponseFavoriteTimeline = (respTimeline?: PersistFavoriteRouteResponse) =>
|
||||
PersistFavoriteRouteResponse.parse(respTimeline);
|
||||
parseOrThrow(PersistFavoriteRouteResponse)(respTimeline);
|
||||
|
||||
const postTimeline = async ({
|
||||
timeline,
|
||||
}: RequestPostTimeline): Promise<TimelineResponse | TimelineErrorResponse> => {
|
||||
}: RequestPostTimeline): Promise<CreateTimelinesResponse | TimelineErrorResponse> => {
|
||||
let requestBody;
|
||||
try {
|
||||
requestBody = JSON.stringify({ timeline });
|
||||
|
@ -117,7 +98,7 @@ const postTimeline = async ({
|
|||
return Promise.reject(new Error(`Failed to stringify query: ${JSON.stringify(err)}`));
|
||||
}
|
||||
|
||||
const response = await KibanaServices.get().http.post<TimelineResponse>(TIMELINE_URL, {
|
||||
const response = await KibanaServices.get().http.post<CreateTimelinesResponse>(TIMELINE_URL, {
|
||||
method: 'POST',
|
||||
body: requestBody,
|
||||
version: '2023-10-31',
|
||||
|
@ -131,7 +112,7 @@ const patchTimeline = async ({
|
|||
timeline,
|
||||
version,
|
||||
savedSearch,
|
||||
}: RequestPatchTimeline): Promise<TimelineResponse | TimelineErrorResponse> => {
|
||||
}: RequestPatchTimeline): Promise<PatchTimelineResponse | TimelineErrorResponse> => {
|
||||
let response = null;
|
||||
let requestBody = null;
|
||||
try {
|
||||
|
@ -153,7 +134,7 @@ const patchTimeline = async ({
|
|||
}
|
||||
|
||||
try {
|
||||
response = await KibanaServices.get().http.patch<TimelineResponse>(TIMELINE_URL, {
|
||||
response = await KibanaServices.get().http.patch<PatchTimelineResponse>(TIMELINE_URL, {
|
||||
method: 'PATCH',
|
||||
body: requestBody,
|
||||
version: '2023-10-31',
|
||||
|
@ -175,7 +156,7 @@ export const copyTimeline = async ({
|
|||
timelineId,
|
||||
timeline,
|
||||
savedSearch,
|
||||
}: RequestPersistTimeline): Promise<TimelineResponse | TimelineErrorResponse> => {
|
||||
}: RequestPersistTimeline): Promise<CopyTimelineResponse | TimelineErrorResponse> => {
|
||||
let response = null;
|
||||
let requestBody = null;
|
||||
let newSavedSearchId = null;
|
||||
|
@ -205,7 +186,7 @@ export const copyTimeline = async ({
|
|||
}
|
||||
|
||||
try {
|
||||
response = await KibanaServices.get().http.post<TimelineResponse>(TIMELINE_COPY_URL, {
|
||||
response = await KibanaServices.get().http.post<CopyTimelineResponse>(TIMELINE_COPY_URL, {
|
||||
method: 'POST',
|
||||
body: requestBody,
|
||||
version: '1',
|
||||
|
@ -224,10 +205,10 @@ export const persistTimeline = async ({
|
|||
timeline,
|
||||
version,
|
||||
savedSearch,
|
||||
}: RequestPersistTimeline): Promise<TimelineResponse | TimelineErrorResponse> => {
|
||||
}: RequestPersistTimeline): Promise<PersistTimelineResponse | TimelineErrorResponse> => {
|
||||
try {
|
||||
if (isEmpty(timelineId) && timeline.status === TimelineStatusEnum.draft && timeline) {
|
||||
const temp: TimelineResponse | TimelineErrorResponse = await cleanDraftTimeline({
|
||||
const temp: CleanDraftTimelinesResponse | TimelineErrorResponse = await cleanDraftTimeline({
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
timelineType: timeline.timelineType!,
|
||||
templateTimelineId: timeline.templateTimelineId ?? undefined,
|
||||
|
@ -330,13 +311,16 @@ export const getDraftTimeline = async ({
|
|||
timelineType,
|
||||
}: {
|
||||
timelineType: TimelineType;
|
||||
}): Promise<TimelineResponse> => {
|
||||
const response = await KibanaServices.get().http.get<TimelineResponse>(TIMELINE_DRAFT_URL, {
|
||||
query: {
|
||||
timelineType,
|
||||
},
|
||||
version: '2023-10-31',
|
||||
});
|
||||
}): Promise<GetDraftTimelinesResponse> => {
|
||||
const response = await KibanaServices.get().http.get<GetDraftTimelinesResponse>(
|
||||
TIMELINE_DRAFT_URL,
|
||||
{
|
||||
query: {
|
||||
timelineType,
|
||||
},
|
||||
version: '2023-10-31',
|
||||
}
|
||||
);
|
||||
|
||||
return decodeTimelineResponse(response);
|
||||
};
|
||||
|
@ -349,7 +333,7 @@ export const cleanDraftTimeline = async ({
|
|||
timelineType: TimelineType;
|
||||
templateTimelineId?: string;
|
||||
templateTimelineVersion?: number;
|
||||
}): Promise<TimelineResponse | TimelineErrorResponse> => {
|
||||
}): Promise<CleanDraftTimelinesResponse | TimelineErrorResponse> => {
|
||||
let requestBody;
|
||||
const templateTimelineInfo =
|
||||
timelineType === TimelineTypeEnum.template
|
||||
|
@ -366,16 +350,19 @@ export const cleanDraftTimeline = async ({
|
|||
} catch (err) {
|
||||
return Promise.reject(new Error(`Failed to stringify query: ${JSON.stringify(err)}`));
|
||||
}
|
||||
const response = await KibanaServices.get().http.post<TimelineResponse>(TIMELINE_DRAFT_URL, {
|
||||
body: requestBody,
|
||||
version: '2023-10-31',
|
||||
});
|
||||
const response = await KibanaServices.get().http.post<CleanDraftTimelinesResponse>(
|
||||
TIMELINE_DRAFT_URL,
|
||||
{
|
||||
body: requestBody,
|
||||
version: '2023-10-31',
|
||||
}
|
||||
);
|
||||
|
||||
return decodeTimelineResponse(response);
|
||||
};
|
||||
|
||||
export const installPrepackedTimelines = async (): Promise<ImportTimelineResultSchema> => {
|
||||
const response = await KibanaServices.get().http.post<ImportTimelineResultSchema>(
|
||||
export const installPrepackedTimelines = async (): Promise<ImportTimelineResult> => {
|
||||
const response = await KibanaServices.get().http.post<ImportTimelineResult>(
|
||||
TIMELINE_PREPACKAGED_URL,
|
||||
{
|
||||
version: '2023-10-31',
|
||||
|
@ -386,7 +373,7 @@ export const installPrepackedTimelines = async (): Promise<ImportTimelineResultS
|
|||
};
|
||||
|
||||
export const getTimeline = async (id: string) => {
|
||||
const response = await KibanaServices.get().http.get<SingleTimelineResponse>(TIMELINE_URL, {
|
||||
const response = await KibanaServices.get().http.get<GetTimelineResponse>(TIMELINE_URL, {
|
||||
query: {
|
||||
id,
|
||||
},
|
||||
|
@ -397,7 +384,7 @@ export const getTimeline = async (id: string) => {
|
|||
};
|
||||
|
||||
export const resolveTimeline = async (id: string) => {
|
||||
const response = await KibanaServices.get().http.get<SingleTimelineResolveResponse>(
|
||||
const response = await KibanaServices.get().http.get<ResolveTimelineResponse>(
|
||||
TIMELINE_RESOLVE_URL,
|
||||
{
|
||||
query: {
|
||||
|
@ -411,7 +398,7 @@ export const resolveTimeline = async (id: string) => {
|
|||
};
|
||||
|
||||
export const getTimelineTemplate = async (templateTimelineId: string) => {
|
||||
const response = await KibanaServices.get().http.get<SingleTimelineResponse>(TIMELINE_URL, {
|
||||
const response = await KibanaServices.get().http.get<GetTimelineResponse>(TIMELINE_URL, {
|
||||
query: {
|
||||
template_timeline_id: templateTimelineId,
|
||||
},
|
||||
|
@ -421,24 +408,18 @@ export const getTimelineTemplate = async (templateTimelineId: string) => {
|
|||
return decodeSingleTimelineResponse(response);
|
||||
};
|
||||
|
||||
export const getAllTimelines = async (args: GetTimelinesArgs, abortSignal: AbortSignal) => {
|
||||
const response = await KibanaServices.get().http.fetch<AllTimelinesResponse>(TIMELINES_URL, {
|
||||
export const getAllTimelines = async (
|
||||
query: GetTimelinesRequestQuery,
|
||||
abortSignal: AbortSignal
|
||||
) => {
|
||||
const response = await KibanaServices.get().http.fetch<GetTimelinesResponse>(TIMELINES_URL, {
|
||||
method: 'GET',
|
||||
query: {
|
||||
...(args.onlyUserFavorite ? { only_user_favorite: args.onlyUserFavorite } : {}),
|
||||
...(args?.pageInfo?.pageSize ? { page_size: args.pageInfo.pageSize } : {}),
|
||||
...(args?.pageInfo?.pageIndex ? { page_index: args.pageInfo.pageIndex } : {}),
|
||||
...(args.search ? { search: args.search } : {}),
|
||||
...(args?.sort?.sortField ? { sort_field: args?.sort?.sortField } : {}),
|
||||
...(args?.sort?.sortOrder ? { sort_order: args?.sort?.sortOrder } : {}),
|
||||
...(args.status ? { status: args.status } : {}),
|
||||
...(args.timelineType ? { timeline_type: args.timelineType } : {}),
|
||||
},
|
||||
query,
|
||||
signal: abortSignal,
|
||||
version: '2023-10-31',
|
||||
});
|
||||
|
||||
return decodeAllTimelinesResponse(response);
|
||||
return decodeGetTimelinesResponse(response);
|
||||
};
|
||||
|
||||
export const persistFavorite = async ({
|
||||
|
|
|
@ -6,10 +6,10 @@
|
|||
*/
|
||||
|
||||
import { TableId } from '@kbn/securitysolution-data-table';
|
||||
import type { TimelineResult } from '../../../common/api/timeline';
|
||||
import type { TimelineResponse } from '../../../common/api/timeline';
|
||||
import { DEFAULT_ALERTS_INDEX } from '../../../common/constants';
|
||||
|
||||
export const getTimelineQueryTypes = (timeline: TimelineResult) => ({
|
||||
export const getTimelineQueryTypes = (timeline: TimelineResponse) => ({
|
||||
hasQuery:
|
||||
(timeline.kqlQuery != null &&
|
||||
timeline.kqlQuery.filterQuery != null &&
|
||||
|
|
|
@ -66,6 +66,7 @@ describe('Timeline pinned event middleware', () => {
|
|||
data: {
|
||||
persistPinnedEventOnTimeline: {
|
||||
code: 200,
|
||||
eventId: testEventId,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
|
@ -74,7 +74,7 @@ export const addPinnedEventToTimelineMiddleware: (kibana: CoreStart) => Middlewa
|
|||
const currentTimeline = selectTimelineById(store.getState(), action.payload.id);
|
||||
// The response is null or empty in case we unpinned an event.
|
||||
// In that case we want to remove the locally pinned event.
|
||||
if (!response || !('code' in response)) {
|
||||
if (!response || !('eventId' in response)) {
|
||||
return store.dispatch(
|
||||
updateTimeline({
|
||||
id: action.payload.id,
|
||||
|
|
|
@ -167,7 +167,7 @@ describe('Timeline save middleware', () => {
|
|||
});
|
||||
|
||||
it('should show an error message when the call is unauthorized', async () => {
|
||||
(persistTimeline as jest.Mock).mockResolvedValue({ data: { persistTimeline: { code: 403 } } });
|
||||
(persistTimeline as jest.Mock).mockResolvedValue({ status_code: 403 });
|
||||
await store.dispatch(saveTimeline({ id: TimelineId.test, saveAsNew: false }));
|
||||
|
||||
expect(refreshTimelines as unknown as jest.Mock).not.toHaveBeenCalled();
|
||||
|
@ -175,7 +175,7 @@ describe('Timeline save middleware', () => {
|
|||
});
|
||||
|
||||
describe('#convertTimelineAsInput ', () => {
|
||||
test('should return a TimelineInput instead of TimelineModel ', () => {
|
||||
test('should return a SavedTimeline instead of TimelineModel ', () => {
|
||||
const columns: TimelineModel['columns'] = [
|
||||
{
|
||||
columnHeaderType: 'not-filtered',
|
||||
|
|
|
@ -34,8 +34,11 @@ import { selectTimelineById } from '../selectors';
|
|||
import * as i18n from '../../pages/translations';
|
||||
import type { inputsModel } from '../../../common/store/inputs';
|
||||
import { TimelineStatusEnum, TimelineTypeEnum } from '../../../../common/api/timeline';
|
||||
import type { TimelineErrorResponse, TimelineResponse } from '../../../../common/api/timeline';
|
||||
import type { TimelineInput } from '../../../../common/search_strategy';
|
||||
import type {
|
||||
TimelineErrorResponse,
|
||||
PersistTimelineResponse,
|
||||
SavedTimeline,
|
||||
} from '../../../../common/api/timeline';
|
||||
import type { TimelineModel } from '../model';
|
||||
import type { ColumnHeaderOptions } from '../../../../common/types/timeline';
|
||||
import { refreshTimelines } from './helpers';
|
||||
|
@ -83,6 +86,9 @@ export const saveTimelineMiddleware: (kibana: CoreStart) => Middleware<{}, State
|
|||
if (isTimelineErrorResponse(result)) {
|
||||
const error = getErrorFromResponse(result);
|
||||
switch (error?.errorCode) {
|
||||
case 403:
|
||||
store.dispatch(showCallOutUnauthorizedMsg());
|
||||
break;
|
||||
// conflict
|
||||
case 409:
|
||||
kibana.notifications.toasts.addDanger({
|
||||
|
@ -108,11 +114,6 @@ export const saveTimelineMiddleware: (kibana: CoreStart) => Middleware<{}, State
|
|||
return;
|
||||
}
|
||||
|
||||
if (response && response.code === 403) {
|
||||
store.dispatch(showCallOutUnauthorizedMsg());
|
||||
return;
|
||||
}
|
||||
|
||||
refreshTimelines(store.getState());
|
||||
|
||||
store.dispatch(
|
||||
|
@ -155,7 +156,7 @@ export const saveTimelineMiddleware: (kibana: CoreStart) => Middleware<{}, State
|
|||
return ret;
|
||||
};
|
||||
|
||||
const timelineInput: TimelineInput = {
|
||||
const timelineInput: SavedTimeline = {
|
||||
columns: null,
|
||||
dataProviders: null,
|
||||
dataViewId: null,
|
||||
|
@ -181,8 +182,8 @@ const timelineInput: TimelineInput = {
|
|||
export const convertTimelineAsInput = (
|
||||
timeline: TimelineModel,
|
||||
timelineTimeRange: inputsModel.TimeRange
|
||||
): TimelineInput =>
|
||||
Object.keys(timelineInput).reduce<TimelineInput>((acc, key) => {
|
||||
): SavedTimeline =>
|
||||
Object.keys(timelineInput).reduce<SavedTimeline>((acc, key) => {
|
||||
if (has(key, timeline)) {
|
||||
if (key === 'kqlQuery') {
|
||||
return set(`${key}.filterQuery`, get(`${key}.filterQuery`, timeline), acc);
|
||||
|
@ -270,7 +271,7 @@ const convertToString = (obj: unknown) => {
|
|||
}
|
||||
};
|
||||
|
||||
type PossibleResponse = TimelineResponse | TimelineErrorResponse;
|
||||
type PossibleResponse = PersistTimelineResponse | TimelineErrorResponse;
|
||||
|
||||
function isTimelineErrorResponse(response: PossibleResponse): response is TimelineErrorResponse {
|
||||
return response && ('status_code' in response || 'statusCode' in response);
|
||||
|
|
|
@ -6,8 +6,7 @@
|
|||
*/
|
||||
|
||||
import { transformError } from '@kbn/securitysolution-es-utils';
|
||||
import { validate } from '@kbn/securitysolution-io-ts-utils';
|
||||
import { checkTimelineStatusRt } from '../../../../../../common/api/timeline';
|
||||
import { InstallPrepackedTimelinesRequestBody } from '../../../../../../common/api/timeline';
|
||||
import { buildSiemResponse } from '../../../routes/utils';
|
||||
import type { SecuritySolutionPluginRouter } from '../../../../../types';
|
||||
|
||||
|
@ -69,10 +68,8 @@ export const getPrebuiltRulesAndTimelinesStatusRoute = (router: SecuritySolution
|
|||
|
||||
const frameworkRequest = await buildFrameworkRequest(context, request);
|
||||
const prebuiltTimelineStatus = await checkTimelinesStatus(frameworkRequest);
|
||||
const [validatedPrebuiltTimelineStatus] = validate(
|
||||
prebuiltTimelineStatus,
|
||||
checkTimelineStatusRt
|
||||
);
|
||||
const validatedPrebuiltTimelineStatus =
|
||||
InstallPrepackedTimelinesRequestBody.parse(prebuiltTimelineStatus);
|
||||
|
||||
const responseBody: ReadPrebuiltRulesAndTimelinesStatusResponse = {
|
||||
rules_custom_installed: customRules.total,
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { validate } from '@kbn/securitysolution-io-ts-utils';
|
||||
import { importTimelineResultSchema } from '../../../../../common/api/timeline';
|
||||
import { stringifyZodError } from '@kbn/zod-helpers';
|
||||
import { ImportTimelineResult } from '../../../../../common/api/timeline';
|
||||
import type { SecuritySolutionApiRequestHandlerContext } from '../../../../types';
|
||||
import { installPrepackagedTimelines } from '../../../timeline/routes/prepackaged_timelines/install_prepackaged_timelines';
|
||||
|
||||
|
@ -18,10 +18,10 @@ export const performTimelinesInstallation = async (
|
|||
securitySolutionContext.getFrameworkRequest(),
|
||||
true
|
||||
);
|
||||
const [result, error] = validate(timeline, importTimelineResultSchema);
|
||||
const parsed = ImportTimelineResult.safeParse(timeline);
|
||||
|
||||
return {
|
||||
result,
|
||||
error,
|
||||
result: parsed.data,
|
||||
error: parsed.error && stringifyZodError(parsed.error),
|
||||
};
|
||||
};
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
*/
|
||||
|
||||
import path, { join, resolve } from 'path';
|
||||
import type * as rt from 'io-ts';
|
||||
|
||||
import {
|
||||
TIMELINE_DRAFT_URL,
|
||||
|
@ -17,9 +16,9 @@ import {
|
|||
} from '../../../../common/constants';
|
||||
import type {
|
||||
SavedTimeline,
|
||||
patchTimelineSchema,
|
||||
createTimelineSchema,
|
||||
GetTimelineQuery,
|
||||
PatchTimelineRequestBody,
|
||||
CreateTimelinesRequestBody,
|
||||
GetTimelineRequestQuery,
|
||||
} from '../../../../common/api/timeline';
|
||||
import {
|
||||
type TimelineType,
|
||||
|
@ -135,14 +134,14 @@ export const updateTemplateTimelineWithTimelineId = {
|
|||
version: 'WzEyMjUsMV0=',
|
||||
};
|
||||
|
||||
export const getCreateTimelinesRequest = (mockBody: rt.TypeOf<typeof createTimelineSchema>) =>
|
||||
export const getCreateTimelinesRequest = (mockBody: CreateTimelinesRequestBody) =>
|
||||
requestMock.create({
|
||||
method: 'post',
|
||||
path: TIMELINE_URL,
|
||||
body: mockBody,
|
||||
});
|
||||
|
||||
export const getUpdateTimelinesRequest = (mockBody: rt.TypeOf<typeof patchTimelineSchema>) =>
|
||||
export const getUpdateTimelinesRequest = (mockBody: PatchTimelineRequestBody) =>
|
||||
requestMock.create({
|
||||
method: 'patch',
|
||||
path: TIMELINE_URL,
|
||||
|
@ -167,7 +166,7 @@ export const cleanDraftTimelinesRequest = (timelineType: TimelineType) =>
|
|||
},
|
||||
});
|
||||
|
||||
export const getTimelineRequest = (query?: GetTimelineQuery) =>
|
||||
export const getTimelineRequest = (query?: GetTimelineRequestQuery) =>
|
||||
requestMock.create({
|
||||
method: 'get',
|
||||
path: TIMELINE_URL,
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import type { ResolvedTimelineWithOutcomeSavedObject } from '../../../../common/api/timeline';
|
||||
import type { ResolvedTimeline } from '../../../../common/api/timeline';
|
||||
import { TimelineStatusEnum, TimelineTypeEnum } from '../../../../common/api/timeline';
|
||||
|
||||
export const mockResolvedSavedObject = {
|
||||
|
@ -117,7 +117,7 @@ export const mockPopulatedTimeline = {
|
|||
pinnedEventsSaveObject: [],
|
||||
};
|
||||
|
||||
export const mockResolveTimelineResponse: ResolvedTimelineWithOutcomeSavedObject = {
|
||||
export const mockResolveTimelineResponse: ResolvedTimeline = {
|
||||
timeline: mockPopulatedTimeline,
|
||||
outcome: 'aliasMatch',
|
||||
alias_target_id: 'new-saved-object-id',
|
||||
|
|
|
@ -6,10 +6,10 @@
|
|||
*/
|
||||
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import type { IKibanaResponse } from '@kbn/core-http-server';
|
||||
import { transformError } from '@kbn/securitysolution-es-utils';
|
||||
import { buildRouteValidationWithZod } from '@kbn/zod-helpers';
|
||||
import type { SecuritySolutionPluginRouter } from '../../../../../types';
|
||||
import type { ConfigType } from '../../../../..';
|
||||
import { buildSiemResponse } from '../../../../detection_engine/routes/utils';
|
||||
|
||||
import { TIMELINE_DRAFT_URL } from '../../../../../../common/constants';
|
||||
|
@ -21,12 +21,13 @@ import {
|
|||
persistTimeline,
|
||||
} from '../../../saved_object/timelines';
|
||||
import { draftTimelineDefaults } from '../../../utils/default_timeline';
|
||||
import type { CleanDraftTimelinesResponse } from '../../../../../../common/api/timeline';
|
||||
import {
|
||||
CleanDraftTimelinesRequestBody,
|
||||
TimelineTypeEnum,
|
||||
} from '../../../../../../common/api/timeline';
|
||||
|
||||
export const cleanDraftTimelinesRoute = (router: SecuritySolutionPluginRouter, _: ConfigType) => {
|
||||
export const cleanDraftTimelinesRoute = (router: SecuritySolutionPluginRouter) => {
|
||||
router.versioned
|
||||
.post({
|
||||
path: TIMELINE_DRAFT_URL,
|
||||
|
@ -42,7 +43,7 @@ export const cleanDraftTimelinesRoute = (router: SecuritySolutionPluginRouter, _
|
|||
},
|
||||
version: '2023-10-31',
|
||||
},
|
||||
async (context, request, response) => {
|
||||
async (context, request, response): Promise<IKibanaResponse<CleanDraftTimelinesResponse>> => {
|
||||
const frameworkRequest = await buildFrameworkRequest(context, request);
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
|
||||
|
|
|
@ -5,19 +5,22 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import type { IKibanaResponse } from '@kbn/core-http-server';
|
||||
import { transformError } from '@kbn/securitysolution-es-utils';
|
||||
import { buildRouteValidationWithZod } from '@kbn/zod-helpers';
|
||||
import type { SecuritySolutionPluginRouter } from '../../../../../types';
|
||||
import type { ConfigType } from '../../../../..';
|
||||
import { buildSiemResponse } from '../../../../detection_engine/routes/utils';
|
||||
|
||||
import { TIMELINE_DRAFT_URL } from '../../../../../../common/constants';
|
||||
import { buildFrameworkRequest } from '../../../utils/common';
|
||||
import { buildRouteValidationWithExcess } from '../../../../../utils/build_validation/route_validation';
|
||||
import { getDraftTimeline, persistTimeline } from '../../../saved_object/timelines';
|
||||
import { draftTimelineDefaults } from '../../../utils/default_timeline';
|
||||
import { getDraftTimelineSchema } from '../../../../../../common/api/timeline';
|
||||
import {
|
||||
GetDraftTimelinesRequestQuery,
|
||||
type GetDraftTimelinesResponse,
|
||||
} from '../../../../../../common/api/timeline';
|
||||
|
||||
export const getDraftTimelinesRoute = (router: SecuritySolutionPluginRouter, _: ConfigType) => {
|
||||
export const getDraftTimelinesRoute = (router: SecuritySolutionPluginRouter) => {
|
||||
router.versioned
|
||||
.get({
|
||||
path: TIMELINE_DRAFT_URL,
|
||||
|
@ -29,11 +32,11 @@ export const getDraftTimelinesRoute = (router: SecuritySolutionPluginRouter, _:
|
|||
.addVersion(
|
||||
{
|
||||
validate: {
|
||||
request: { query: buildRouteValidationWithExcess(getDraftTimelineSchema) },
|
||||
request: { query: buildRouteValidationWithZod(GetDraftTimelinesRequestQuery) },
|
||||
},
|
||||
version: '2023-10-31',
|
||||
},
|
||||
async (context, request, response) => {
|
||||
async (context, request, response): Promise<IKibanaResponse<GetDraftTimelinesResponse>> => {
|
||||
const frameworkRequest = await buildFrameworkRequest(context, request);
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
|
||||
|
|
|
@ -28,25 +28,25 @@ import { persistNoteRoute, deleteNoteRoute, getNotesRoute } from './notes';
|
|||
import { persistPinnedEventRoute } from './pinned_events';
|
||||
|
||||
export function registerTimelineRoutes(router: SecuritySolutionPluginRouter, config: ConfigType) {
|
||||
createTimelinesRoute(router, config);
|
||||
patchTimelinesRoute(router, config);
|
||||
createTimelinesRoute(router);
|
||||
patchTimelinesRoute(router);
|
||||
|
||||
importTimelinesRoute(router, config);
|
||||
exportTimelinesRoute(router, config);
|
||||
getDraftTimelinesRoute(router, config);
|
||||
getTimelineRoute(router, config);
|
||||
resolveTimelineRoute(router, config);
|
||||
getTimelinesRoute(router, config);
|
||||
cleanDraftTimelinesRoute(router, config);
|
||||
deleteTimelinesRoute(router, config);
|
||||
persistFavoriteRoute(router, config);
|
||||
copyTimelineRoute(router, config);
|
||||
getDraftTimelinesRoute(router);
|
||||
getTimelineRoute(router);
|
||||
resolveTimelineRoute(router);
|
||||
getTimelinesRoute(router);
|
||||
cleanDraftTimelinesRoute(router);
|
||||
deleteTimelinesRoute(router);
|
||||
persistFavoriteRoute(router);
|
||||
copyTimelineRoute(router);
|
||||
|
||||
installPrepackedTimelinesRoute(router, config);
|
||||
|
||||
persistNoteRoute(router, config);
|
||||
deleteNoteRoute(router, config);
|
||||
getNotesRoute(router, config);
|
||||
persistNoteRoute(router);
|
||||
deleteNoteRoute(router);
|
||||
getNotesRoute(router);
|
||||
|
||||
persistPinnedEventRoute(router, config);
|
||||
persistPinnedEventRoute(router);
|
||||
}
|
||||
|
|
|
@ -5,21 +5,20 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import type { IKibanaResponse } from '@kbn/core-http-server';
|
||||
import { transformError } from '@kbn/securitysolution-es-utils';
|
||||
import { buildRouteValidationWithZod } from '@kbn/zod-helpers';
|
||||
import type { SecuritySolutionPluginRouter } from '../../../../types';
|
||||
|
||||
import { NOTE_URL } from '../../../../../common/constants';
|
||||
|
||||
import type { ConfigType } from '../../../..';
|
||||
|
||||
import { buildSiemResponse } from '../../../detection_engine/routes/utils';
|
||||
|
||||
import { buildFrameworkRequest } from '../../utils/common';
|
||||
import { DeleteNoteRequestBody, type DeleteNoteResponse } from '../../../../../common/api/timeline';
|
||||
import { deleteNote } from '../../saved_object/notes';
|
||||
|
||||
export const deleteNoteRoute = (router: SecuritySolutionPluginRouter, config: ConfigType) => {
|
||||
export const deleteNoteRoute = (router: SecuritySolutionPluginRouter) => {
|
||||
router.versioned
|
||||
.delete({
|
||||
path: NOTE_URL,
|
||||
|
@ -35,7 +34,7 @@ export const deleteNoteRoute = (router: SecuritySolutionPluginRouter, config: Co
|
|||
},
|
||||
version: '2023-10-31',
|
||||
},
|
||||
async (context, request, response) => {
|
||||
async (context, request, response): Promise<IKibanaResponse<DeleteNoteResponse>> => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
|
||||
try {
|
||||
|
@ -55,9 +54,8 @@ export const deleteNoteRoute = (router: SecuritySolutionPluginRouter, config: Co
|
|||
noteIds,
|
||||
});
|
||||
|
||||
const body: DeleteNoteResponse = { data: {} };
|
||||
return response.ok({
|
||||
body,
|
||||
body: { data: {} },
|
||||
});
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
|
|
|
@ -5,21 +5,20 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import type { IKibanaResponse } from '@kbn/core-http-server';
|
||||
import { transformError } from '@kbn/securitysolution-es-utils';
|
||||
import type { SortOrder } from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
|
||||
import { buildRouteValidationWithZod } from '@kbn/zod-helpers';
|
||||
import type { SecuritySolutionPluginRouter } from '../../../../types';
|
||||
import { NOTE_URL } from '../../../../../common/constants';
|
||||
|
||||
import type { ConfigType } from '../../../..';
|
||||
|
||||
import { buildSiemResponse } from '../../../detection_engine/routes/utils';
|
||||
import { buildFrameworkRequest } from '../../utils/common';
|
||||
import { getAllSavedNote, MAX_UNASSOCIATED_NOTES } from '../../saved_object/notes';
|
||||
import { noteSavedObjectType } from '../../saved_object_mappings/notes';
|
||||
import { GetNotesRequestQuery, type GetNotesResponse } from '../../../../../common/api/timeline';
|
||||
|
||||
export const getNotesRoute = (router: SecuritySolutionPluginRouter, _: ConfigType) => {
|
||||
export const getNotesRoute = (router: SecuritySolutionPluginRouter) => {
|
||||
router.versioned
|
||||
.get({
|
||||
path: NOTE_URL,
|
||||
|
@ -35,7 +34,7 @@ export const getNotesRoute = (router: SecuritySolutionPluginRouter, _: ConfigTyp
|
|||
},
|
||||
version: '2023-10-31',
|
||||
},
|
||||
async (context, request, response) => {
|
||||
async (context, request, response): Promise<IKibanaResponse<GetNotesResponse>> => {
|
||||
try {
|
||||
const queryParams = request.query;
|
||||
const frameworkRequest = await buildFrameworkRequest(context, request);
|
||||
|
@ -60,8 +59,7 @@ export const getNotesRoute = (router: SecuritySolutionPluginRouter, _: ConfigTyp
|
|||
perPage: MAX_UNASSOCIATED_NOTES,
|
||||
};
|
||||
const res = await getAllSavedNote(frameworkRequest, options);
|
||||
const body: GetNotesResponse = res ?? {};
|
||||
return response.ok({ body });
|
||||
return response.ok({ body: res ?? {} });
|
||||
}
|
||||
} else {
|
||||
const perPage = queryParams?.perPage ? parseInt(queryParams.perPage, 10) : 10;
|
||||
|
|
|
@ -5,14 +5,13 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import type { IKibanaResponse } from '@kbn/core-http-server';
|
||||
import { transformError } from '@kbn/securitysolution-es-utils';
|
||||
import { buildRouteValidationWithZod } from '@kbn/zod-helpers';
|
||||
import type { SecuritySolutionPluginRouter } from '../../../../types';
|
||||
|
||||
import { NOTE_URL } from '../../../../../common/constants';
|
||||
|
||||
import type { ConfigType } from '../../../..';
|
||||
|
||||
import { buildSiemResponse } from '../../../detection_engine/routes/utils';
|
||||
|
||||
import { buildFrameworkRequest } from '../../utils/common';
|
||||
|
@ -22,7 +21,7 @@ import {
|
|||
} from '../../../../../common/api/timeline';
|
||||
import { persistNote } from '../../saved_object/notes';
|
||||
|
||||
export const persistNoteRoute = (router: SecuritySolutionPluginRouter, _: ConfigType) => {
|
||||
export const persistNoteRoute = (router: SecuritySolutionPluginRouter) => {
|
||||
router.versioned
|
||||
.patch({
|
||||
path: NOTE_URL,
|
||||
|
@ -38,7 +37,7 @@ export const persistNoteRoute = (router: SecuritySolutionPluginRouter, _: Config
|
|||
},
|
||||
version: '2023-10-31',
|
||||
},
|
||||
async (context, request, response) => {
|
||||
async (context, request, response): Promise<IKibanaResponse<PersistNoteRouteResponse>> => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
|
||||
try {
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import type { IKibanaResponse } from '@kbn/core-http-server';
|
||||
import { transformError } from '@kbn/securitysolution-es-utils';
|
||||
import { buildRouteValidationWithZod } from '@kbn/zod-helpers';
|
||||
|
||||
|
@ -12,8 +13,6 @@ import type { SecuritySolutionPluginRouter } from '../../../../types';
|
|||
|
||||
import { PINNED_EVENT_URL } from '../../../../../common/constants';
|
||||
|
||||
import type { ConfigType } from '../../../..';
|
||||
|
||||
import { buildSiemResponse } from '../../../detection_engine/routes/utils';
|
||||
|
||||
import { buildFrameworkRequest } from '../../utils/common';
|
||||
|
@ -23,10 +22,7 @@ import {
|
|||
} from '../../../../../common/api/timeline';
|
||||
import { persistPinnedEventOnTimeline } from '../../saved_object/pinned_events';
|
||||
|
||||
export const persistPinnedEventRoute = (
|
||||
router: SecuritySolutionPluginRouter,
|
||||
config: ConfigType
|
||||
) => {
|
||||
export const persistPinnedEventRoute = (router: SecuritySolutionPluginRouter) => {
|
||||
router.versioned
|
||||
.patch({
|
||||
path: PINNED_EVENT_URL,
|
||||
|
@ -42,7 +38,11 @@ export const persistPinnedEventRoute = (
|
|||
},
|
||||
version: '2023-10-31',
|
||||
},
|
||||
async (context, request, response) => {
|
||||
async (
|
||||
context,
|
||||
request,
|
||||
response
|
||||
): Promise<IKibanaResponse<PersistPinnedEventRouteResponse>> => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
|
||||
try {
|
||||
|
@ -58,12 +58,10 @@ export const persistPinnedEventRoute = (
|
|||
timelineId
|
||||
);
|
||||
|
||||
const body: PersistPinnedEventRouteResponse = {
|
||||
data: { persistPinnedEventOnTimeline: res },
|
||||
};
|
||||
|
||||
return response.ok({
|
||||
body,
|
||||
body: {
|
||||
data: { persistPinnedEventOnTimeline: res },
|
||||
},
|
||||
});
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
|
|
|
@ -20,7 +20,6 @@ import {
|
|||
import * as helpers from './helpers';
|
||||
import { importTimelines } from '../../timelines/import_timelines/helpers';
|
||||
import { buildFrameworkRequest } from '../../../utils/common';
|
||||
import type { ImportTimelineResultSchema } from '../../../../../../common/api/timeline';
|
||||
|
||||
jest.mock('../../timelines/import_timelines/helpers');
|
||||
|
||||
|
@ -231,9 +230,8 @@ describe('installPrepackagedTimelines', () => {
|
|||
);
|
||||
|
||||
expect(
|
||||
(result as ImportTimelineResultSchema).errors[0].error.message.includes(
|
||||
'read prepackaged timelines error:'
|
||||
)
|
||||
'errors' in result &&
|
||||
result.errors?.[0].error?.message?.includes('read prepackaged timelines error:')
|
||||
).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
import path, { join, resolve } from 'path';
|
||||
import { Readable } from 'stream';
|
||||
|
||||
import type { ImportTimelineResultSchema } from '../../../../../../common/api/timeline';
|
||||
import type { ImportTimelineResult } from '../../../../../../common/api/timeline';
|
||||
|
||||
import type { FrameworkRequest } from '../../../../framework';
|
||||
|
||||
|
@ -22,7 +22,7 @@ export const installPrepackagedTimelines = async (
|
|||
isImmutable: boolean,
|
||||
filePath?: string,
|
||||
fileName?: string
|
||||
): Promise<ImportTimelineResultSchema | Error> => {
|
||||
): Promise<ImportTimelineResult | Error> => {
|
||||
let readStream;
|
||||
const dir = resolve(
|
||||
join(
|
||||
|
@ -47,7 +47,7 @@ export const installPrepackagedTimelines = async (
|
|||
],
|
||||
};
|
||||
}
|
||||
return loadData<null, ImportTimelineResultSchema>(readStream, <T>(docs: T) =>
|
||||
return loadData<null, ImportTimelineResult>(readStream, <T>(docs: T) =>
|
||||
docs instanceof Readable
|
||||
? importTimelines(docs, maxTimelineImportExportSize, frameworkRequest, isImmutable)
|
||||
: Promise.reject(new Error(`read prepackaged timelines error`))
|
||||
|
|
|
@ -6,14 +6,17 @@
|
|||
*/
|
||||
|
||||
import { transformError } from '@kbn/securitysolution-es-utils';
|
||||
import { validate } from '@kbn/securitysolution-io-ts-utils';
|
||||
import { checkTimelineStatusRt } from '../../../../../../common/api/timeline';
|
||||
import type { IKibanaResponse } from '@kbn/core-http-server';
|
||||
|
||||
import type { SecuritySolutionPluginRouter } from '../../../../../types';
|
||||
|
||||
import { TIMELINE_PREPACKAGED_URL } from '../../../../../../common/constants';
|
||||
|
||||
import type { ConfigType } from '../../../../../config';
|
||||
|
||||
import {
|
||||
InstallPrepackedTimelinesRequestBody,
|
||||
type InstallPrepackedTimelinesResponse,
|
||||
} from '../../../../../../common/api/timeline';
|
||||
import { buildSiemResponse } from '../../../../detection_engine/routes/utils';
|
||||
|
||||
import { installPrepackagedTimelines } from './helpers';
|
||||
|
@ -45,23 +48,24 @@ export const installPrepackedTimelinesRoute = (
|
|||
validate: {},
|
||||
version: '2023-10-31',
|
||||
},
|
||||
async (context, request, response) => {
|
||||
async (
|
||||
context,
|
||||
request,
|
||||
response
|
||||
): Promise<IKibanaResponse<InstallPrepackedTimelinesResponse>> => {
|
||||
try {
|
||||
const frameworkRequest = await buildFrameworkRequest(context, request);
|
||||
const prepackagedTimelineStatus = await checkTimelinesStatus(frameworkRequest);
|
||||
const [validatedprepackagedTimelineStatus, prepackagedTimelineStatusError] = validate(
|
||||
prepackagedTimelineStatus,
|
||||
checkTimelineStatusRt
|
||||
);
|
||||
|
||||
if (prepackagedTimelineStatusError != null) {
|
||||
throw prepackagedTimelineStatusError;
|
||||
const installResult =
|
||||
InstallPrepackedTimelinesRequestBody.safeParse(prepackagedTimelineStatus);
|
||||
|
||||
if (installResult.error) {
|
||||
throw installResult.error;
|
||||
}
|
||||
|
||||
const timelinesToInstalled =
|
||||
validatedprepackagedTimelineStatus?.timelinesToInstall.length ?? 0;
|
||||
const timelinesNotUpdated =
|
||||
validatedprepackagedTimelineStatus?.timelinesToUpdate.length ?? 0;
|
||||
const timelinesToInstalled = installResult.data.timelinesToInstall.length ?? 0;
|
||||
const timelinesNotUpdated = installResult.data.timelinesToUpdate.length ?? 0;
|
||||
let res = null;
|
||||
|
||||
if (timelinesToInstalled > 0 || timelinesNotUpdated > 0) {
|
||||
|
|
|
@ -5,10 +5,13 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import type { IKibanaResponse } from '@kbn/core-http-server';
|
||||
import { transformError } from '@kbn/securitysolution-es-utils';
|
||||
import { buildRouteValidationWithExcess } from '../../../../../utils/build_validation/route_validation';
|
||||
import type { ConfigType } from '../../../../..';
|
||||
import { copyTimelineSchema } from '../../../../../../common/api/timeline';
|
||||
import { buildRouteValidationWithZod } from '@kbn/zod-helpers';
|
||||
import {
|
||||
CopyTimelineRequestBody,
|
||||
type CopyTimelineResponse,
|
||||
} from '../../../../../../common/api/timeline';
|
||||
import { copyTimeline } from '../../../saved_object/timelines';
|
||||
import type { SecuritySolutionPluginRouter } from '../../../../../types';
|
||||
import { TIMELINE_COPY_URL } from '../../../../../../common/constants';
|
||||
|
@ -16,7 +19,7 @@ import { buildSiemResponse } from '../../../../detection_engine/routes/utils';
|
|||
|
||||
import { buildFrameworkRequest } from '../../../utils/common';
|
||||
|
||||
export const copyTimelineRoute = (router: SecuritySolutionPluginRouter, _: ConfigType) => {
|
||||
export const copyTimelineRoute = (router: SecuritySolutionPluginRouter) => {
|
||||
router.versioned
|
||||
.post({
|
||||
path: TIMELINE_COPY_URL,
|
||||
|
@ -29,17 +32,16 @@ export const copyTimelineRoute = (router: SecuritySolutionPluginRouter, _: Confi
|
|||
{
|
||||
version: '1',
|
||||
validate: {
|
||||
request: { body: buildRouteValidationWithExcess(copyTimelineSchema) },
|
||||
request: { body: buildRouteValidationWithZod(CopyTimelineRequestBody) },
|
||||
},
|
||||
},
|
||||
async (context, request, response) => {
|
||||
async (context, request, response): Promise<IKibanaResponse<CopyTimelineResponse>> => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
|
||||
try {
|
||||
const frameworkRequest = await buildFrameworkRequest(context, request);
|
||||
const { timeline, timelineIdToCopy } = request.body;
|
||||
const copiedTimeline = await copyTimeline(frameworkRequest, timeline, timelineIdToCopy);
|
||||
|
||||
return response.ok({
|
||||
body: { data: { persistTimeline: copiedTimeline } },
|
||||
});
|
||||
|
|
|
@ -10,8 +10,9 @@ import { isEmpty } from 'lodash/fp';
|
|||
import moment from 'moment';
|
||||
import { timeline as timelineLib, pinnedEvent as pinnedEventLib } from '../../../saved_object';
|
||||
import type { FrameworkRequest } from '../../../../framework';
|
||||
import type { ResponseTimeline, SavedTimeline, Note } from '../../../../../../common/api/timeline';
|
||||
import type { SavedTimeline, Note } from '../../../../../../common/api/timeline';
|
||||
import { persistNotes } from '../../../saved_object/notes/persist_notes';
|
||||
import type { InternalTimelineResponse } from '../../../saved_object/timelines';
|
||||
|
||||
interface CreateTimelineProps {
|
||||
frameworkRequest: FrameworkRequest;
|
||||
|
@ -21,7 +22,7 @@ interface CreateTimelineProps {
|
|||
overrideNotesOwner?: boolean;
|
||||
pinnedEventIds?: string[] | null;
|
||||
notes?: Note[];
|
||||
existingNoteIds?: string[];
|
||||
existingNoteIds?: string[] | null;
|
||||
isImmutable?: boolean;
|
||||
}
|
||||
|
||||
|
@ -40,7 +41,7 @@ export const createTimelines = async ({
|
|||
existingNoteIds = [],
|
||||
isImmutable,
|
||||
overrideNotesOwner = true,
|
||||
}: CreateTimelineProps): Promise<ResponseTimeline> => {
|
||||
}: CreateTimelineProps): Promise<InternalTimelineResponse> => {
|
||||
const timerangeStart = isImmutable
|
||||
? moment().subtract(24, 'hours').toISOString()
|
||||
: timeline.dateRange?.start;
|
||||
|
|
|
@ -7,16 +7,13 @@
|
|||
|
||||
import { transformError } from '@kbn/securitysolution-es-utils';
|
||||
import type { IKibanaResponse } from '@kbn/core/server';
|
||||
import { buildRouteValidationWithZod } from '@kbn/zod-helpers';
|
||||
import type { SecuritySolutionPluginRouter } from '../../../../../types';
|
||||
|
||||
import { TIMELINE_URL } from '../../../../../../common/constants';
|
||||
|
||||
import type { ConfigType } from '../../../../..';
|
||||
import { buildRouteValidationWithExcess } from '../../../../../utils/build_validation/route_validation';
|
||||
|
||||
import { buildSiemResponse } from '../../../../detection_engine/routes/utils';
|
||||
|
||||
import { createTimelineSchema } from '../../../../../../common/api/timeline';
|
||||
import {
|
||||
buildFrameworkRequest,
|
||||
CompareTimelinesStatus,
|
||||
|
@ -24,11 +21,14 @@ import {
|
|||
} from '../../../utils/common';
|
||||
import { DEFAULT_ERROR } from '../../../utils/failure_cases';
|
||||
import { createTimelines } from './helpers';
|
||||
import type { CreateTimelinesResponse } from '../../../../../../common/api/timeline';
|
||||
import {
|
||||
CreateTimelinesRequestBody,
|
||||
type CreateTimelinesResponse,
|
||||
} from '../../../../../../common/api/timeline';
|
||||
|
||||
export * from './helpers';
|
||||
|
||||
export const createTimelinesRoute = (router: SecuritySolutionPluginRouter, _: ConfigType) => {
|
||||
export const createTimelinesRoute = (router: SecuritySolutionPluginRouter) => {
|
||||
router.versioned
|
||||
.post({
|
||||
path: TIMELINE_URL,
|
||||
|
@ -42,7 +42,7 @@ export const createTimelinesRoute = (router: SecuritySolutionPluginRouter, _: Co
|
|||
version: '2023-10-31',
|
||||
validate: {
|
||||
request: {
|
||||
body: buildRouteValidationWithExcess(createTimelineSchema),
|
||||
body: buildRouteValidationWithZod(CreateTimelinesRequestBody),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
@ -5,9 +5,9 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import type { IKibanaResponse } from '@kbn/core-http-server';
|
||||
import { transformError } from '@kbn/securitysolution-es-utils';
|
||||
import { buildRouteValidationWithZod } from '@kbn/zod-helpers';
|
||||
import type { ConfigType } from '../../../../..';
|
||||
import {
|
||||
DeleteTimelinesRequestBody,
|
||||
type DeleteTimelinesResponse,
|
||||
|
@ -19,7 +19,7 @@ import { buildSiemResponse } from '../../../../detection_engine/routes/utils';
|
|||
import { buildFrameworkRequest } from '../../../utils/common';
|
||||
import { deleteTimeline } from '../../../saved_object/timelines';
|
||||
|
||||
export const deleteTimelinesRoute = (router: SecuritySolutionPluginRouter, config: ConfigType) => {
|
||||
export const deleteTimelinesRoute = (router: SecuritySolutionPluginRouter) => {
|
||||
router.versioned
|
||||
.delete({
|
||||
path: TIMELINE_URL,
|
||||
|
@ -35,7 +35,7 @@ export const deleteTimelinesRoute = (router: SecuritySolutionPluginRouter, confi
|
|||
request: { body: buildRouteValidationWithZod(DeleteTimelinesRequestBody) },
|
||||
},
|
||||
},
|
||||
async (context, request, response) => {
|
||||
async (context, request, response): Promise<IKibanaResponse<DeleteTimelinesResponse>> => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
|
||||
try {
|
||||
|
|
|
@ -9,11 +9,11 @@ import { omit } from 'lodash/fp';
|
|||
import { transformDataToNdjson } from '@kbn/securitysolution-utils';
|
||||
|
||||
import type {
|
||||
ExportedTimelines,
|
||||
ExportedNotes,
|
||||
ExportTimelineNotFoundError,
|
||||
Note,
|
||||
PinnedEvent,
|
||||
TimelineResponse,
|
||||
} from '../../../../../../common/api/timeline';
|
||||
|
||||
import type { FrameworkRequest } from '../../../../framework';
|
||||
|
@ -45,7 +45,7 @@ const getPinnedEventsIdsByTimelineId = (currentPinnedEvents: PinnedEvent[]): str
|
|||
const getTimelinesFromObjects = async (
|
||||
request: FrameworkRequest,
|
||||
ids?: string[] | null
|
||||
): Promise<Array<ExportedTimelines | ExportTimelineNotFoundError>> => {
|
||||
): Promise<Array<TimelineResponse | ExportTimelineNotFoundError>> => {
|
||||
const { timelines, errors } = await getSelectedTimelines(request, ids);
|
||||
const exportedIds = timelines.map((t) => t.savedObjectId);
|
||||
|
||||
|
@ -65,7 +65,7 @@ const getTimelinesFromObjects = async (
|
|||
[]
|
||||
);
|
||||
|
||||
const myResponse = exportedIds.reduce<ExportedTimelines[]>((acc, timelineId) => {
|
||||
const myResponse = exportedIds.reduce<TimelineResponse[]>((acc, timelineId) => {
|
||||
const myTimeline = timelines.find((t) => t.savedObjectId === timelineId);
|
||||
if (myTimeline != null) {
|
||||
const timelineNotes = myNotes.filter((n) => n.timelineId === timelineId);
|
||||
|
|
|
@ -5,11 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import {
|
||||
serverMock,
|
||||
requestContextMock,
|
||||
createMockConfig,
|
||||
} from '../../../../detection_engine/routes/__mocks__';
|
||||
import { serverMock, requestContextMock } from '../../../../detection_engine/routes/__mocks__';
|
||||
import { getTimelineOrNull, getTimelineTemplateOrNull } from '../../../saved_object/timelines';
|
||||
|
||||
import { getTimelineRequest } from '../../../__mocks__/request_responses';
|
||||
|
@ -33,7 +29,7 @@ describe('get timeline', () => {
|
|||
server = serverMock.create();
|
||||
context = requestContextMock.createTools().context;
|
||||
|
||||
getTimelineRoute(server.router, createMockConfig());
|
||||
getTimelineRoute(server.router);
|
||||
});
|
||||
|
||||
test('should call getTimelineTemplateOrNull if templateTimelineId is given', async () => {
|
||||
|
|
|
@ -5,25 +5,24 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { buildRouteValidationWithZod } from '@kbn/zod-helpers';
|
||||
import type { IKibanaResponse } from '@kbn/core-http-server';
|
||||
import { transformError } from '@kbn/securitysolution-es-utils';
|
||||
import type { SecuritySolutionPluginRouter } from '../../../../../types';
|
||||
|
||||
import { TIMELINE_URL } from '../../../../../../common/constants';
|
||||
|
||||
import type { ConfigType } from '../../../../..';
|
||||
import { buildRouteValidationWithExcess } from '../../../../../utils/build_validation/route_validation';
|
||||
|
||||
import { buildSiemResponse } from '../../../../detection_engine/routes/utils';
|
||||
|
||||
import { buildFrameworkRequest } from '../../../utils/common';
|
||||
import { getTimelineQuerySchema } from '../../../../../../common/api/timeline';
|
||||
import { getTimelineTemplateOrNull, getTimelineOrNull } from '../../../saved_object/timelines';
|
||||
import type {
|
||||
TimelineSavedObject,
|
||||
ResolvedTimelineWithOutcomeSavedObject,
|
||||
import {
|
||||
GetTimelineRequestQuery,
|
||||
type GetTimelineResponse,
|
||||
} from '../../../../../../common/api/timeline';
|
||||
import { getTimelineTemplateOrNull, getTimelineOrNull } from '../../../saved_object/timelines';
|
||||
import type { ResolvedTimeline, TimelineResponse } from '../../../../../../common/api/timeline';
|
||||
|
||||
export const getTimelineRoute = (router: SecuritySolutionPluginRouter, _: ConfigType) => {
|
||||
export const getTimelineRoute = (router: SecuritySolutionPluginRouter) => {
|
||||
router.versioned
|
||||
.get({
|
||||
path: TIMELINE_URL,
|
||||
|
@ -36,16 +35,16 @@ export const getTimelineRoute = (router: SecuritySolutionPluginRouter, _: Config
|
|||
{
|
||||
version: '2023-10-31',
|
||||
validate: {
|
||||
request: { query: buildRouteValidationWithExcess(getTimelineQuerySchema) },
|
||||
request: { query: buildRouteValidationWithZod(GetTimelineRequestQuery) },
|
||||
},
|
||||
},
|
||||
async (context, request, response) => {
|
||||
async (context, request, response): Promise<IKibanaResponse<GetTimelineResponse>> => {
|
||||
try {
|
||||
const frameworkRequest = await buildFrameworkRequest(context, request);
|
||||
const query = request.query ?? {};
|
||||
const { template_timeline_id: templateTimelineId, id } = query;
|
||||
|
||||
let res: TimelineSavedObject | ResolvedTimelineWithOutcomeSavedObject | null = null;
|
||||
let res: TimelineResponse | ResolvedTimeline | null = null;
|
||||
|
||||
if (templateTimelineId != null && id == null) {
|
||||
res = await getTimelineTemplateOrNull(frameworkRequest, templateTimelineId);
|
||||
|
|
|
@ -5,11 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import {
|
||||
serverMock,
|
||||
requestContextMock,
|
||||
createMockConfig,
|
||||
} from '../../../../detection_engine/routes/__mocks__';
|
||||
import { serverMock, requestContextMock } from '../../../../detection_engine/routes/__mocks__';
|
||||
import { getAllTimeline } from '../../../saved_object/timelines';
|
||||
import { getTimelineRequest } from '../../../__mocks__/request_responses';
|
||||
import { getTimelinesRoute } from '.';
|
||||
|
@ -29,7 +25,7 @@ describe('get all timelines', () => {
|
|||
server = serverMock.create();
|
||||
context = requestContextMock.createTools().context;
|
||||
|
||||
getTimelinesRoute(server.router, createMockConfig());
|
||||
getTimelinesRoute(server.router);
|
||||
});
|
||||
|
||||
test('should get the total count', async () => {
|
||||
|
|
|
@ -5,24 +5,23 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { pipe } from 'fp-ts/lib/pipeable';
|
||||
import { fold } from 'fp-ts/lib/Either';
|
||||
import { identity } from 'fp-ts/lib/function';
|
||||
import type { IKibanaResponse } from '@kbn/core-http-server';
|
||||
import { buildRouteValidationWithZod } from '@kbn/zod-helpers';
|
||||
|
||||
import { transformError } from '@kbn/securitysolution-es-utils';
|
||||
import type { SecuritySolutionPluginRouter } from '../../../../../types';
|
||||
import { TIMELINES_URL } from '../../../../../../common/constants';
|
||||
|
||||
import type { ConfigType } from '../../../../..';
|
||||
|
||||
import { buildSiemResponse } from '../../../../detection_engine/routes/utils';
|
||||
|
||||
import { CustomHttpRequestError } from '../../../../../utils/custom_http_request_error';
|
||||
import { buildFrameworkRequest, escapeHatch, throwErrors } from '../../../utils/common';
|
||||
import { buildFrameworkRequest } from '../../../utils/common';
|
||||
import { getAllTimeline } from '../../../saved_object/timelines';
|
||||
import { getTimelinesQuerySchema } from '../../../../../../common/api/timeline';
|
||||
import {
|
||||
GetTimelinesRequestQuery,
|
||||
type GetTimelinesResponse,
|
||||
} from '../../../../../../common/api/timeline';
|
||||
|
||||
export const getTimelinesRoute = (router: SecuritySolutionPluginRouter, _: ConfigType) => {
|
||||
export const getTimelinesRoute = (router: SecuritySolutionPluginRouter) => {
|
||||
router.versioned
|
||||
.get({
|
||||
path: TIMELINES_URL,
|
||||
|
@ -34,27 +33,23 @@ export const getTimelinesRoute = (router: SecuritySolutionPluginRouter, _: Confi
|
|||
.addVersion(
|
||||
{
|
||||
validate: {
|
||||
request: { query: escapeHatch },
|
||||
request: { query: buildRouteValidationWithZod(GetTimelinesRequestQuery) },
|
||||
},
|
||||
version: '2023-10-31',
|
||||
},
|
||||
async (context, request, response) => {
|
||||
const customHttpRequestError = (message: string) =>
|
||||
new CustomHttpRequestError(message, 400);
|
||||
async (context, request, response): Promise<IKibanaResponse<GetTimelinesResponse>> => {
|
||||
try {
|
||||
const frameworkRequest = await buildFrameworkRequest(context, request);
|
||||
const queryParams = pipe(
|
||||
getTimelinesQuerySchema.decode(request.query),
|
||||
fold(throwErrors(customHttpRequestError), identity)
|
||||
);
|
||||
const onlyUserFavorite = queryParams?.only_user_favorite === 'true' ? true : false;
|
||||
const pageSize = queryParams?.page_size ? parseInt(queryParams.page_size, 10) : null;
|
||||
const pageIndex = queryParams?.page_index ? parseInt(queryParams.page_index, 10) : null;
|
||||
const search = queryParams?.search ?? null;
|
||||
const sortField = queryParams?.sort_field ?? null;
|
||||
const sortOrder = queryParams?.sort_order ?? null;
|
||||
const status = queryParams?.status ?? null;
|
||||
const timelineType = queryParams?.timeline_type ?? null;
|
||||
const onlyUserFavorite = request.query?.only_user_favorite === 'true';
|
||||
const pageSize = request.query?.page_size ? parseInt(request.query.page_size, 10) : null;
|
||||
const pageIndex = request.query?.page_index
|
||||
? parseInt(request.query.page_index, 10)
|
||||
: null;
|
||||
const search = request.query?.search ?? null;
|
||||
const sortField = request.query?.sort_field ?? null;
|
||||
const sortOrder = request.query?.sort_order ?? null;
|
||||
const status = request.query?.status ?? null;
|
||||
const timelineType = request.query?.timeline_type ?? null;
|
||||
const sort =
|
||||
sortField && sortOrder
|
||||
? {
|
||||
|
|
|
@ -5,11 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import type * as rt from 'io-ts';
|
||||
import type { Transform } from 'stream';
|
||||
import { pipe } from 'fp-ts/lib/pipeable';
|
||||
import { fold } from 'fp-ts/lib/Either';
|
||||
import { identity } from 'fp-ts/lib/function';
|
||||
import { createConcatStream, createSplitStream, createMapStream } from '@kbn/utils';
|
||||
import { BadRequestError } from '@kbn/securitysolution-es-utils';
|
||||
import {
|
||||
|
@ -19,23 +15,15 @@ import {
|
|||
} from '../../../../../utils/read_stream/create_stream_from_ndjson';
|
||||
|
||||
import type { ImportTimelineResponse } from './types';
|
||||
import { ImportTimelinesSchemaRt } from '../../../../../../common/api/timeline';
|
||||
import { throwErrors } from '../../../utils/common';
|
||||
import { ImportTimelines } from '../../../../../../common/api/timeline';
|
||||
import { parseOrThrowErrorFactory } from '../../../../../../common/timelines/zod_errors';
|
||||
|
||||
type ErrorFactory = (message: string) => Error;
|
||||
const createPlainError = (message: string) => new Error(message);
|
||||
const parseOrThrow = parseOrThrowErrorFactory(createPlainError);
|
||||
|
||||
export const createPlainError = (message: string) => new Error(message);
|
||||
|
||||
export const decodeOrThrow =
|
||||
<A, O, I>(runtimeType: rt.Type<A, O, I>, createError: ErrorFactory = createPlainError) =>
|
||||
(inputValue: I) =>
|
||||
pipe(runtimeType.decode(inputValue), fold(throwErrors(createError), identity));
|
||||
|
||||
export const validateTimelines = (): Transform =>
|
||||
const validateTimelines = (): Transform =>
|
||||
createMapStream((obj: ImportTimelineResponse) =>
|
||||
obj instanceof Error
|
||||
? new BadRequestError(obj.message)
|
||||
: decodeOrThrow(ImportTimelinesSchemaRt)(obj)
|
||||
obj instanceof Error ? new BadRequestError(obj.message) : parseOrThrow(ImportTimelines)(obj)
|
||||
);
|
||||
export const createTimelinesStreamFromNdJson = (ruleLimit: number) => {
|
||||
return [
|
||||
|
|
|
@ -10,12 +10,8 @@ import type { Readable } from 'stream';
|
|||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { createPromiseFromStreams } from '@kbn/utils';
|
||||
|
||||
import { validate } from '@kbn/securitysolution-io-ts-utils';
|
||||
import type { ImportTimelineResultSchema } from '../../../../../../common/api/timeline';
|
||||
import {
|
||||
importTimelineResultSchema,
|
||||
TimelineStatusEnum,
|
||||
} from '../../../../../../common/api/timeline';
|
||||
import { stringifyZodError } from '@kbn/zod-helpers';
|
||||
import { ImportTimelineResult, TimelineStatusEnum } from '../../../../../../common/api/timeline';
|
||||
|
||||
import type { BulkError } from '../../../../detection_engine/routes/utils';
|
||||
import { createBulkErrorObject } from '../../../../detection_engine/routes/utils';
|
||||
|
@ -88,7 +84,7 @@ export const importTimelines = async (
|
|||
maxTimelineImportExportSize: number,
|
||||
frameworkRequest: FrameworkRequest,
|
||||
isImmutable?: boolean
|
||||
): Promise<ImportTimelineResultSchema | Error> => {
|
||||
): Promise<ImportTimelineResult | Error> => {
|
||||
const readStream = createTimelinesStreamFromNdJson(maxTimelineImportExportSize);
|
||||
|
||||
const parsedObjects = await createPromiseFromStreams<PromiseFromStreams[]>([file, ...readStream]);
|
||||
|
@ -262,17 +258,17 @@ export const importTimelines = async (
|
|||
const timelinesUpdated = importTimelineResponse.filter(
|
||||
(resp) => isImportRegular(resp) && resp.action === 'updateViaImport'
|
||||
);
|
||||
const importTimelinesRes: ImportTimelineResultSchema = {
|
||||
const importTimelinesRes: ImportTimelineResult = {
|
||||
success: errorsResp.length === 0,
|
||||
success_count: successes.length,
|
||||
errors: errorsResp,
|
||||
timelines_installed: timelinesInstalled.length ?? 0,
|
||||
timelines_updated: timelinesUpdated.length ?? 0,
|
||||
};
|
||||
const [validated, errors] = validate(importTimelinesRes, importTimelineResultSchema);
|
||||
if (errors != null || validated == null) {
|
||||
return new Error(errors || 'Import timeline error');
|
||||
const parseResult = ImportTimelineResult.safeParse(importTimelinesRes);
|
||||
if (parseResult.success && parseResult.data) {
|
||||
return parseResult.data;
|
||||
} else {
|
||||
return validated;
|
||||
return new Error(stringifyZodError(parseResult.error) || 'Import timeline error');
|
||||
}
|
||||
};
|
||||
|
|
|
@ -39,7 +39,6 @@ import {
|
|||
|
||||
describe('import timelines', () => {
|
||||
let server: ReturnType<typeof serverMock.create>;
|
||||
let request: ReturnType<typeof requestMock.create>;
|
||||
let securitySetup: SecurityPluginSetup;
|
||||
let { context } = requestContextMock.createTools();
|
||||
let mockGetTimeline: jest.Mock;
|
||||
|
@ -452,48 +451,6 @@ describe('import timelines', () => {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('request validation', () => {
|
||||
beforeEach(() => {
|
||||
jest.doMock('../../../saved_object/timelines', () => {
|
||||
return {
|
||||
getTimelineOrNull: mockGetTimeline.mockReturnValue(null),
|
||||
persistTimeline: mockPersistTimeline.mockReturnValue({
|
||||
timeline: { savedObjectId: '79deb4c0-6bc1-11ea-9999-f5341fb7a189' },
|
||||
}),
|
||||
};
|
||||
});
|
||||
|
||||
jest.doMock('../../../saved_object/pinned_events', () => {
|
||||
return {
|
||||
savePinnedEvents: mockPersistPinnedEventOnTimeline.mockReturnValue(
|
||||
new Error('Test error')
|
||||
),
|
||||
};
|
||||
});
|
||||
|
||||
jest.doMock('../../../saved_object/notes/saved_object', () => {
|
||||
return {
|
||||
persistNote: mockPersistNote,
|
||||
};
|
||||
});
|
||||
});
|
||||
test('disallows invalid query', async () => {
|
||||
request = requestMock.create({
|
||||
method: 'post',
|
||||
path: TIMELINE_EXPORT_URL,
|
||||
body: { id: 'someId' },
|
||||
});
|
||||
const importTimelinesRoute = jest.requireActual('.').importTimelinesRoute;
|
||||
|
||||
importTimelinesRoute(server.router, createMockConfig(), securitySetup);
|
||||
const result = server.validate(request);
|
||||
|
||||
expect(result.badRequest).toHaveBeenCalledWith(
|
||||
'Invalid value {"id":"someId"}, excess properties: ["id"]'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('import timeline templates', () => {
|
||||
|
@ -904,7 +861,7 @@ describe('import timeline templates', () => {
|
|||
request = requestMock.create({
|
||||
method: 'post',
|
||||
path: TIMELINE_EXPORT_URL,
|
||||
body: { id: 'someId' },
|
||||
body: { isImmutable: 1 },
|
||||
});
|
||||
const importTimelinesRoute = jest.requireActual('.').importTimelinesRoute;
|
||||
|
||||
|
@ -912,7 +869,7 @@ describe('import timeline templates', () => {
|
|||
const result = server.validate(request);
|
||||
|
||||
expect(result.badRequest).toHaveBeenCalledWith(
|
||||
'Invalid value {"id":"someId"}, excess properties: ["id"]'
|
||||
"isImmutable: Expected 'true' | 'false', received number"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -7,18 +7,23 @@
|
|||
|
||||
import { extname } from 'path';
|
||||
import type { Readable } from 'stream';
|
||||
import { get } from 'lodash/fp';
|
||||
|
||||
import type { IKibanaResponse } from '@kbn/core-http-server';
|
||||
import { buildRouteValidationWithZod } from '@kbn/zod-helpers';
|
||||
import { transformError } from '@kbn/securitysolution-es-utils';
|
||||
import type { SecuritySolutionPluginRouter } from '../../../../../types';
|
||||
|
||||
import { TIMELINE_IMPORT_URL } from '../../../../../../common/constants';
|
||||
|
||||
import type { ConfigType } from '../../../../../config';
|
||||
import { buildRouteValidationWithExcess } from '../../../../../utils/build_validation/route_validation';
|
||||
import { buildSiemResponse } from '../../../../detection_engine/routes/utils';
|
||||
|
||||
import { importTimelines } from './helpers';
|
||||
import { ImportTimelinesPayloadSchemaRt } from '../../../../../../common/api/timeline';
|
||||
import {
|
||||
ImportTimelinesRequestBody,
|
||||
type ImportTimelinesResponse,
|
||||
} from '../../../../../../common/api/timeline';
|
||||
import { buildFrameworkRequest } from '../../../utils/common';
|
||||
|
||||
export { importTimelines } from './helpers';
|
||||
|
@ -39,11 +44,13 @@ export const importTimelinesRoute = (router: SecuritySolutionPluginRouter, confi
|
|||
.addVersion(
|
||||
{
|
||||
validate: {
|
||||
request: { body: buildRouteValidationWithExcess(ImportTimelinesPayloadSchemaRt) },
|
||||
request: {
|
||||
body: buildRouteValidationWithZod(ImportTimelinesRequestBody),
|
||||
},
|
||||
},
|
||||
version: '2023-10-31',
|
||||
},
|
||||
async (context, request, response) => {
|
||||
async (context, request, response): Promise<IKibanaResponse<ImportTimelinesResponse>> => {
|
||||
try {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
const savedObjectsClient = (await context.core).savedObjects.client;
|
||||
|
@ -52,7 +59,7 @@ export const importTimelinesRoute = (router: SecuritySolutionPluginRouter, confi
|
|||
}
|
||||
|
||||
const { file, isImmutable } = request.body;
|
||||
const { filename } = file.hapi;
|
||||
const filename = extractFilename(file);
|
||||
const fileExtension = extname(filename).toLowerCase();
|
||||
|
||||
if (fileExtension !== '.ndjson') {
|
||||
|
@ -69,8 +76,11 @@ export const importTimelinesRoute = (router: SecuritySolutionPluginRouter, confi
|
|||
frameworkRequest,
|
||||
isImmutable === 'true'
|
||||
);
|
||||
if (typeof res !== 'string') return response.ok({ body: res ?? {} });
|
||||
else throw res;
|
||||
if (res instanceof Error || typeof res === 'string') {
|
||||
throw res;
|
||||
} else {
|
||||
return response.ok({ body: res ?? {} });
|
||||
}
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
|
@ -82,3 +92,11 @@ export const importTimelinesRoute = (router: SecuritySolutionPluginRouter, confi
|
|||
}
|
||||
);
|
||||
};
|
||||
|
||||
function extractFilename(fileObj: unknown) {
|
||||
const filename = get('hapi.filename', fileObj);
|
||||
if (filename && typeof filename === 'string') {
|
||||
return filename;
|
||||
}
|
||||
throw new Error('`filename` missing in file');
|
||||
}
|
||||
|
|
|
@ -7,22 +7,22 @@
|
|||
|
||||
import { transformError } from '@kbn/securitysolution-es-utils';
|
||||
import type { IKibanaResponse } from '@kbn/core/server';
|
||||
import { buildRouteValidationWithZod } from '@kbn/zod-helpers';
|
||||
import type { SecuritySolutionPluginRouter } from '../../../../../types';
|
||||
|
||||
import { TIMELINE_URL } from '../../../../../../common/constants';
|
||||
|
||||
import { buildRouteValidationWithExcess } from '../../../../../utils/build_validation/route_validation';
|
||||
import type { ConfigType } from '../../../../..';
|
||||
|
||||
import { buildSiemResponse } from '../../../../detection_engine/routes/utils';
|
||||
|
||||
import { patchTimelineSchema } from '../../../../../../common/api/timeline';
|
||||
import {
|
||||
PatchTimelineRequestBody,
|
||||
type PatchTimelineResponse,
|
||||
} from '../../../../../../common/api/timeline';
|
||||
import { buildFrameworkRequest, TimelineStatusActions } from '../../../utils/common';
|
||||
import { createTimelines } from '../create_timelines';
|
||||
import { CompareTimelinesStatus } from '../../../utils/compare_timelines_status';
|
||||
import type { PatchTimelinesResponse } from '../../../../../../common/api/timeline';
|
||||
|
||||
export const patchTimelinesRoute = (router: SecuritySolutionPluginRouter, _: ConfigType) => {
|
||||
export const patchTimelinesRoute = (router: SecuritySolutionPluginRouter) => {
|
||||
router.versioned
|
||||
.patch({
|
||||
path: TIMELINE_URL,
|
||||
|
@ -34,11 +34,11 @@ export const patchTimelinesRoute = (router: SecuritySolutionPluginRouter, _: Con
|
|||
.addVersion(
|
||||
{
|
||||
validate: {
|
||||
request: { body: buildRouteValidationWithExcess(patchTimelineSchema) },
|
||||
request: { body: buildRouteValidationWithZod(PatchTimelineRequestBody) },
|
||||
},
|
||||
version: '2023-10-31',
|
||||
},
|
||||
async (context, request, response): Promise<IKibanaResponse<PatchTimelinesResponse>> => {
|
||||
async (context, request, response): Promise<IKibanaResponse<PatchTimelineResponse>> => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
|
||||
try {
|
||||
|
|
|
@ -5,14 +5,13 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import type { IKibanaResponse } from '@kbn/core-http-server';
|
||||
import { transformError } from '@kbn/securitysolution-es-utils';
|
||||
import { buildRouteValidationWithZod } from '@kbn/zod-helpers';
|
||||
import type { SecuritySolutionPluginRouter } from '../../../../../types';
|
||||
|
||||
import { TIMELINE_FAVORITE_URL } from '../../../../../../common/constants';
|
||||
|
||||
import type { ConfigType } from '../../../../..';
|
||||
|
||||
import { buildSiemResponse } from '../../../../detection_engine/routes/utils';
|
||||
|
||||
import { buildFrameworkRequest } from '../../../utils/common';
|
||||
|
@ -23,7 +22,7 @@ import {
|
|||
TimelineTypeEnum,
|
||||
} from '../../../../../../common/api/timeline';
|
||||
|
||||
export const persistFavoriteRoute = (router: SecuritySolutionPluginRouter, _: ConfigType) => {
|
||||
export const persistFavoriteRoute = (router: SecuritySolutionPluginRouter) => {
|
||||
router.versioned
|
||||
.patch({
|
||||
path: TIMELINE_FAVORITE_URL,
|
||||
|
@ -39,7 +38,11 @@ export const persistFavoriteRoute = (router: SecuritySolutionPluginRouter, _: Co
|
|||
request: { body: buildRouteValidationWithZod(PersistFavoriteRouteRequestBody) },
|
||||
},
|
||||
},
|
||||
async (context, request, response) => {
|
||||
async (
|
||||
context,
|
||||
request,
|
||||
response
|
||||
): Promise<IKibanaResponse<PersistFavoriteRouteResponse>> => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
|
||||
try {
|
||||
|
|
|
@ -6,24 +6,24 @@
|
|||
*/
|
||||
|
||||
import { transformError } from '@kbn/securitysolution-es-utils';
|
||||
import type { IKibanaResponse } from '@kbn/core-http-server';
|
||||
import { buildRouteValidationWithZod } from '@kbn/zod-helpers';
|
||||
|
||||
import type { SecuritySolutionPluginRouter } from '../../../../../types';
|
||||
|
||||
import { TIMELINE_RESOLVE_URL } from '../../../../../../common/constants';
|
||||
|
||||
import type { ConfigType } from '../../../../..';
|
||||
import { buildRouteValidationWithExcess } from '../../../../../utils/build_validation/route_validation';
|
||||
|
||||
import { buildSiemResponse } from '../../../../detection_engine/routes/utils';
|
||||
|
||||
import { buildFrameworkRequest } from '../../../utils/common';
|
||||
import { getTimelineQuerySchema } from '../../../../../../common/api/timeline';
|
||||
import { getTimelineTemplateOrNull, resolveTimelineOrNull } from '../../../saved_object/timelines';
|
||||
import type {
|
||||
SavedTimeline,
|
||||
ResolvedTimelineWithOutcomeSavedObject,
|
||||
import {
|
||||
ResolveTimelineRequestQuery,
|
||||
type ResolveTimelineResponse,
|
||||
} from '../../../../../../common/api/timeline';
|
||||
import { getTimelineTemplateOrNull, resolveTimelineOrNull } from '../../../saved_object/timelines';
|
||||
import type { SavedTimeline, ResolvedTimeline } from '../../../../../../common/api/timeline';
|
||||
|
||||
export const resolveTimelineRoute = (router: SecuritySolutionPluginRouter, _: ConfigType) => {
|
||||
export const resolveTimelineRoute = (router: SecuritySolutionPluginRouter) => {
|
||||
router.versioned
|
||||
.get({
|
||||
path: TIMELINE_RESOLVE_URL,
|
||||
|
@ -36,16 +36,16 @@ export const resolveTimelineRoute = (router: SecuritySolutionPluginRouter, _: Co
|
|||
{
|
||||
version: '2023-10-31',
|
||||
validate: {
|
||||
request: { query: buildRouteValidationWithExcess(getTimelineQuerySchema) },
|
||||
request: { query: buildRouteValidationWithZod(ResolveTimelineRequestQuery) },
|
||||
},
|
||||
},
|
||||
async (context, request, response) => {
|
||||
async (context, request, response): Promise<IKibanaResponse<ResolveTimelineResponse>> => {
|
||||
try {
|
||||
const frameworkRequest = await buildFrameworkRequest(context, request);
|
||||
const query = request.query ?? {};
|
||||
const { template_timeline_id: templateTimelineId, id } = query;
|
||||
|
||||
let res: SavedTimeline | ResolvedTimelineWithOutcomeSavedObject | null = null;
|
||||
let res: SavedTimeline | ResolvedTimeline | null = null;
|
||||
|
||||
if (templateTimelineId != null && id == null) {
|
||||
// Template timelineId is not a SO id, so it does not need to be updated to use resolve
|
||||
|
|
|
@ -13,7 +13,7 @@ import type { Note } from '../../../../../common/api/timeline';
|
|||
export const persistNotes = async (
|
||||
frameworkRequest: FrameworkRequest,
|
||||
timelineSavedObjectId: string,
|
||||
existingNoteIds?: string[],
|
||||
existingNoteIds?: string[] | null,
|
||||
newNotes?: Note[],
|
||||
overrideOwner: boolean = true
|
||||
) => {
|
||||
|
|
|
@ -16,7 +16,7 @@ import {
|
|||
SavedObjectTimelineType,
|
||||
SavedObjectTimelineStatus,
|
||||
} from '../../../../../common/types/timeline/saved_object';
|
||||
import type { TimelineSavedObject } from '../../../../../common/api/timeline';
|
||||
import type { TimelineResponse } from '../../../../../common/api/timeline';
|
||||
import {
|
||||
type TimelineType,
|
||||
TimelineTypeEnum,
|
||||
|
@ -49,7 +49,7 @@ const getTimelineTypeAndStatus = (
|
|||
};
|
||||
};
|
||||
|
||||
export const convertSavedObjectToSavedTimeline = (savedObject: unknown): TimelineSavedObject =>
|
||||
export const convertSavedObjectToSavedTimeline = (savedObject: unknown): TimelineResponse =>
|
||||
pipe(
|
||||
TimelineSavedObjectWithDraftRuntime.decode(savedObject),
|
||||
map((savedTimeline) => {
|
||||
|
|
|
@ -23,8 +23,8 @@ import { getNotesByTimelineId, persistNote } from '../notes/saved_object';
|
|||
import { getAllPinnedEventsByTimelineId, persistPinnedEventOnTimeline } from '../pinned_events';
|
||||
import { TimelineTypeEnum } from '../../../../../common/api/timeline';
|
||||
import type {
|
||||
AllTimelinesResponse,
|
||||
ResolvedTimelineWithOutcomeSavedObject,
|
||||
GetTimelinesResponse,
|
||||
ResolvedTimeline,
|
||||
SavedTimeline,
|
||||
} from '../../../../../common/api/timeline';
|
||||
import {
|
||||
|
@ -141,7 +141,7 @@ describe('saved_object', () => {
|
|||
pageSize: 10,
|
||||
pageIndex: 1,
|
||||
};
|
||||
let result = null as unknown as AllTimelinesResponse;
|
||||
let result = null as unknown as GetTimelinesResponse;
|
||||
beforeEach(async () => {
|
||||
(convertSavedObjectToSavedTimeline as jest.Mock).mockReturnValue(mockGetTimelineValue);
|
||||
mockFindSavedObject = jest
|
||||
|
@ -275,7 +275,7 @@ describe('saved_object', () => {
|
|||
describe('resolveTimelineOrNull', () => {
|
||||
let mockResolveSavedObject: jest.Mock;
|
||||
let mockRequest: FrameworkRequest;
|
||||
let result: ResolvedTimelineWithOutcomeSavedObject | null = null;
|
||||
let result: ResolvedTimeline | null = null;
|
||||
beforeEach(async () => {
|
||||
(convertSavedObjectToSavedTimeline as jest.Mock).mockReturnValue(mockResolvedTimeline);
|
||||
mockResolveSavedObject = jest.fn().mockReturnValue(mockResolvedSavedObject);
|
||||
|
|
|
@ -19,20 +19,17 @@ import type {
|
|||
Note,
|
||||
BareNote,
|
||||
PinnedEvent,
|
||||
AllTimelinesResponse,
|
||||
GetTimelinesResponse,
|
||||
ExportTimelineNotFoundError,
|
||||
PageInfoTimeline,
|
||||
ResponseTimelines,
|
||||
FavoriteTimelineResponse,
|
||||
ResponseTimeline,
|
||||
SortTimeline,
|
||||
TimelineResult,
|
||||
TimelineResponse,
|
||||
TimelineType,
|
||||
TimelineStatus,
|
||||
ResolvedTimelineWithOutcomeSavedObject,
|
||||
TimelineSavedObject,
|
||||
ResolvedTimeline,
|
||||
SavedTimeline,
|
||||
TimelineWithoutExternalRefs,
|
||||
SavedTimelineWithSavedObjectId,
|
||||
} from '../../../../../common/api/timeline';
|
||||
import { TimelineStatusEnum, TimelineTypeEnum } from '../../../../../common/api/timeline';
|
||||
import type { SavedObjectTimelineWithoutExternalRefs } from '../../../../../common/types/timeline/saved_object';
|
||||
|
@ -49,11 +46,13 @@ import { timelineFieldsMigrator } from './field_migrator';
|
|||
export { pickSavedTimeline } from './pick_saved_timeline';
|
||||
export { convertSavedObjectToSavedTimeline } from './convert_saved_object_to_savedtimeline';
|
||||
|
||||
type TimelineWithoutExternalRefs = Omit<SavedTimeline, 'dataViewId' | 'savedQueryId'>;
|
||||
|
||||
export const getTimeline = async (
|
||||
request: FrameworkRequest,
|
||||
timelineId: string,
|
||||
timelineType: TimelineType | null = TimelineTypeEnum.default
|
||||
): Promise<TimelineSavedObject> => {
|
||||
): Promise<TimelineResponse> => {
|
||||
let timelineIdToUse = timelineId;
|
||||
try {
|
||||
if (timelineType === TimelineTypeEnum.template) {
|
||||
|
@ -77,7 +76,7 @@ export const getTimeline = async (
|
|||
export const getTimelineOrNull = async (
|
||||
frameworkRequest: FrameworkRequest,
|
||||
savedObjectId: string
|
||||
): Promise<TimelineSavedObject | null> => {
|
||||
): Promise<TimelineResponse | null> => {
|
||||
let timeline = null;
|
||||
try {
|
||||
timeline = await getTimeline(frameworkRequest, savedObjectId);
|
||||
|
@ -89,23 +88,19 @@ export const getTimelineOrNull = async (
|
|||
export const resolveTimelineOrNull = async (
|
||||
frameworkRequest: FrameworkRequest,
|
||||
savedObjectId: string
|
||||
): Promise<ResolvedTimelineWithOutcomeSavedObject | null> => {
|
||||
let resolvedTimeline = null;
|
||||
): Promise<ResolvedTimeline | null> => {
|
||||
try {
|
||||
resolvedTimeline = await resolveSavedTimeline(frameworkRequest, savedObjectId);
|
||||
// eslint-disable-next-line no-empty
|
||||
} catch (e) {}
|
||||
return resolvedTimeline;
|
||||
// }
|
||||
const resolvedTimeline = await resolveSavedTimeline(frameworkRequest, savedObjectId);
|
||||
return resolvedTimeline;
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
export const getTimelineByTemplateTimelineId = async (
|
||||
request: FrameworkRequest,
|
||||
templateTimelineId: string
|
||||
): Promise<{
|
||||
totalCount: number;
|
||||
timeline: TimelineSavedObject[];
|
||||
}> => {
|
||||
): Promise<GetTimelinesResponse> => {
|
||||
const options: SavedObjectsFindOptions = {
|
||||
type: timelineSavedObjectType,
|
||||
filter: `siem-ui-timeline.attributes.templateTimelineId: "${templateTimelineId}"`,
|
||||
|
@ -117,7 +112,7 @@ export const getTimelineByTemplateTimelineId = async (
|
|||
export const getTimelineTemplateOrNull = async (
|
||||
frameworkRequest: FrameworkRequest,
|
||||
templateTimelineId: string
|
||||
): Promise<TimelineSavedObject | null> => {
|
||||
): Promise<TimelineResponse | null> => {
|
||||
let templateTimeline = null;
|
||||
try {
|
||||
templateTimeline = await getTimelineByTemplateTimelineId(frameworkRequest, templateTimelineId);
|
||||
|
@ -190,10 +185,7 @@ export const getExistingPrepackagedTimelines = async (
|
|||
request: FrameworkRequest,
|
||||
countsOnly?: boolean,
|
||||
pageInfo?: PageInfoTimeline
|
||||
): Promise<{
|
||||
totalCount: number;
|
||||
timeline: TimelineSavedObject[];
|
||||
}> => {
|
||||
): Promise<GetTimelinesResponse> => {
|
||||
const queryPageInfo =
|
||||
countsOnly && pageInfo == null
|
||||
? {
|
||||
|
@ -218,7 +210,7 @@ export const getAllTimeline = async (
|
|||
sort: SortTimeline | null,
|
||||
status: TimelineStatus | null,
|
||||
timelineType: TimelineType | null
|
||||
): Promise<AllTimelinesResponse> => {
|
||||
): Promise<GetTimelinesResponse> => {
|
||||
const searchTerm = search != null ? search : undefined;
|
||||
const searchFields = ['title', 'description'];
|
||||
const filter = combineFilters([
|
||||
|
@ -291,7 +283,7 @@ export const getAllTimeline = async (
|
|||
export const getDraftTimeline = async (
|
||||
request: FrameworkRequest,
|
||||
timelineType: TimelineType | null
|
||||
): Promise<ResponseTimelines> => {
|
||||
): Promise<GetTimelinesResponse> => {
|
||||
const filter = combineFilters([
|
||||
getTimelineTypeFilter(timelineType ?? null, TimelineStatusEnum.draft),
|
||||
getTimelinesCreatedAndUpdatedByCurrentUser({ request }),
|
||||
|
@ -385,13 +377,19 @@ export const persistFavorite = async (
|
|||
}
|
||||
};
|
||||
|
||||
export interface InternalTimelineResponse {
|
||||
code: number;
|
||||
message: string;
|
||||
timeline: TimelineResponse;
|
||||
}
|
||||
|
||||
export const persistTimeline = async (
|
||||
request: FrameworkRequest,
|
||||
timelineId: string | null,
|
||||
version: string | null,
|
||||
timeline: SavedTimeline,
|
||||
isImmutable?: boolean
|
||||
): Promise<ResponseTimeline> => {
|
||||
): Promise<InternalTimelineResponse> => {
|
||||
const savedObjectsClient = (await request.context.core).savedObjects.client;
|
||||
const userInfo = isImmutable ? ({ username: 'Elastic' } as AuthenticatedUser) : request.user;
|
||||
try {
|
||||
|
@ -414,7 +412,7 @@ export const persistTimeline = async (
|
|||
timeline: await getSavedTimeline(request, timelineId),
|
||||
};
|
||||
} else if (getOr(null, 'output.statusCode', err) === 403) {
|
||||
const timelineToReturn: TimelineResult = {
|
||||
const timelineToReturn: TimelineResponse = {
|
||||
...timeline,
|
||||
savedObjectId: '',
|
||||
version: '',
|
||||
|
@ -439,7 +437,7 @@ export const createTimeline = async ({
|
|||
timeline: SavedTimeline;
|
||||
savedObjectsClient: SavedObjectsClientContract;
|
||||
userInfo: AuthenticatedUser | null;
|
||||
}) => {
|
||||
}): Promise<InternalTimelineResponse> => {
|
||||
const { transformedFields: migratedAttributes, references } =
|
||||
timelineFieldsMigrator.extractFieldsToReferences<TimelineWithoutExternalRefs>({
|
||||
data: pickSavedTimeline(timelineId, timeline, userInfo),
|
||||
|
@ -479,7 +477,7 @@ const updateTimeline = async ({
|
|||
savedObjectsClient: SavedObjectsClientContract;
|
||||
userInfo: AuthenticatedUser | null;
|
||||
version: string | null;
|
||||
}) => {
|
||||
}): Promise<InternalTimelineResponse> => {
|
||||
const rawTimelineSavedObject =
|
||||
await savedObjectsClient.get<SavedObjectTimelineWithoutExternalRefs>(
|
||||
timelineSavedObjectType,
|
||||
|
@ -516,11 +514,12 @@ export const updatePartialSavedTimeline = async (
|
|||
timelineId
|
||||
);
|
||||
|
||||
const { transformedFields, references } =
|
||||
timelineFieldsMigrator.extractFieldsToReferences<TimelineWithoutExternalRefs>({
|
||||
data: timeline,
|
||||
existingReferences: currentSavedTimeline.references,
|
||||
});
|
||||
const { transformedFields, references } = timelineFieldsMigrator.extractFieldsToReferences<
|
||||
Omit<SavedTimelineWithSavedObjectId, 'dataViewId' | 'savedQueryId'>
|
||||
>({
|
||||
data: timeline,
|
||||
existingReferences: currentSavedTimeline.references,
|
||||
});
|
||||
|
||||
const timelineUpdateAttributes = pickSavedTimeline(
|
||||
null,
|
||||
|
@ -588,7 +587,7 @@ export const copyTimeline = async (
|
|||
request: FrameworkRequest,
|
||||
timeline: SavedTimeline,
|
||||
timelineId: string
|
||||
): Promise<ResponseTimeline> => {
|
||||
): Promise<InternalTimelineResponse> => {
|
||||
const savedObjectsClient = (await request.context.core).savedObjects.client;
|
||||
|
||||
// Fetch all objects that need to be copied
|
||||
|
@ -658,7 +657,10 @@ const resolveBasicSavedTimeline = async (request: FrameworkRequest, timelineId:
|
|||
};
|
||||
};
|
||||
|
||||
const resolveSavedTimeline = async (request: FrameworkRequest, timelineId: string) => {
|
||||
const resolveSavedTimeline = async (
|
||||
request: FrameworkRequest,
|
||||
timelineId: string
|
||||
): Promise<ResolvedTimeline> => {
|
||||
const userName = request.user?.username ?? UNAUTHENTICATED_USER;
|
||||
|
||||
const { resolvedTimelineSavedObject, ...resolveAttributes } = await resolveBasicSavedTimeline(
|
||||
|
@ -673,7 +675,6 @@ const resolveSavedTimeline = async (request: FrameworkRequest, timelineId: strin
|
|||
]);
|
||||
|
||||
const [notes, pinnedEvents, timeline] = timelineWithNotesAndPinnedEvents;
|
||||
|
||||
return {
|
||||
timeline: timelineWithReduxProperties(notes, pinnedEvents, timeline, userName),
|
||||
...resolveAttributes,
|
||||
|
@ -742,9 +743,9 @@ export const convertStringToBase64 = (text: string): string => Buffer.from(text)
|
|||
export const timelineWithReduxProperties = (
|
||||
notes: Note[],
|
||||
pinnedEvents: PinnedEvent[],
|
||||
timeline: TimelineSavedObject,
|
||||
timeline: TimelineResponse,
|
||||
userName: string
|
||||
): TimelineSavedObject => ({
|
||||
): TimelineResponse => ({
|
||||
...timeline,
|
||||
favorite:
|
||||
timeline.favorite != null && userName != null
|
||||
|
@ -789,7 +790,7 @@ export const getSelectedTimelines = async (
|
|||
);
|
||||
|
||||
const timelineObjects: {
|
||||
timelines: TimelineSavedObject[];
|
||||
timelines: TimelineResponse[];
|
||||
errors: ExportTimelineNotFoundError[];
|
||||
} = savedObjects.saved_objects.reduce(
|
||||
(acc, savedObject) => {
|
||||
|
@ -805,7 +806,7 @@ export const getSelectedTimelines = async (
|
|||
return { errors: [...acc.errors, savedObject.error], timelines: acc.timelines };
|
||||
},
|
||||
{
|
||||
timelines: [] as TimelineSavedObject[],
|
||||
timelines: [] as TimelineResponse[],
|
||||
errors: [] as ExportTimelineNotFoundError[],
|
||||
}
|
||||
);
|
||||
|
|
|
@ -9,14 +9,14 @@ import { isEmpty } from 'lodash/fp';
|
|||
import type { AuthenticatedUser } from '@kbn/security-plugin/common';
|
||||
import { getUserDisplayName } from '@kbn/user-profile-components';
|
||||
import { UNAUTHENTICATED_USER } from '../../../../../common/constants';
|
||||
import type { SavedTimelineWithSavedObjectId } from '../../../../../common/api/timeline';
|
||||
import type { SavedTimeline } from '../../../../../common/api/timeline';
|
||||
import { TimelineTypeEnum, TimelineStatusEnum } from '../../../../../common/api/timeline';
|
||||
|
||||
export const pickSavedTimeline = (
|
||||
timelineId: string | null,
|
||||
savedTimeline: SavedTimelineWithSavedObjectId,
|
||||
savedTimeline: SavedTimeline,
|
||||
userInfo: AuthenticatedUser | null
|
||||
): SavedTimelineWithSavedObjectId => {
|
||||
): SavedTimeline => {
|
||||
const dateNow = new Date().valueOf();
|
||||
|
||||
if (timelineId == null) {
|
||||
|
|
|
@ -7,9 +7,9 @@
|
|||
|
||||
import path, { join, resolve } from 'path';
|
||||
import type {
|
||||
CheckTimelineStatusRt,
|
||||
TimelineSavedObject,
|
||||
ImportTimelinesSchema,
|
||||
TimelineResponse,
|
||||
ImportTimelines,
|
||||
InstallPrepackedTimelinesRequestBody,
|
||||
} from '../../../../common/api/timeline';
|
||||
|
||||
import type { FrameworkRequest } from '../../framework';
|
||||
|
@ -19,9 +19,9 @@ import { getExistingPrepackagedTimelines } from '../saved_object/timelines';
|
|||
import { loadData, getReadables } from './common';
|
||||
|
||||
export const getTimelinesToUpdate = (
|
||||
timelinesFromFileSystem: ImportTimelinesSchema[],
|
||||
installedTimelines: TimelineSavedObject[]
|
||||
): ImportTimelinesSchema[] => {
|
||||
timelinesFromFileSystem: ImportTimelines[],
|
||||
installedTimelines: TimelineResponse[]
|
||||
): ImportTimelines[] => {
|
||||
return timelinesFromFileSystem.filter((timeline) =>
|
||||
installedTimelines.some((installedTimeline) => {
|
||||
return (
|
||||
|
@ -34,9 +34,9 @@ export const getTimelinesToUpdate = (
|
|||
};
|
||||
|
||||
export const getTimelinesToInstall = (
|
||||
timelinesFromFileSystem: ImportTimelinesSchema[],
|
||||
installedTimelines: TimelineSavedObject[]
|
||||
): ImportTimelinesSchema[] => {
|
||||
timelinesFromFileSystem: ImportTimelines[],
|
||||
installedTimelines: TimelineResponse[]
|
||||
): ImportTimelines[] => {
|
||||
return timelinesFromFileSystem.filter(
|
||||
(timeline) =>
|
||||
!installedTimelines.some(
|
||||
|
@ -49,11 +49,11 @@ export const checkTimelinesStatus = async (
|
|||
frameworkRequest: FrameworkRequest,
|
||||
filePath?: string,
|
||||
fileName?: string
|
||||
): Promise<CheckTimelineStatusRt | Error> => {
|
||||
): Promise<InstallPrepackedTimelinesRequestBody | Error> => {
|
||||
let readStream;
|
||||
let timeline: {
|
||||
totalCount: number;
|
||||
timeline: TimelineSavedObject[];
|
||||
timeline: TimelineResponse[];
|
||||
};
|
||||
const dir = resolve(
|
||||
join(
|
||||
|
@ -75,7 +75,7 @@ export const checkTimelinesStatus = async (
|
|||
};
|
||||
}
|
||||
|
||||
return loadData<'utf-8', CheckTimelineStatusRt>(
|
||||
return loadData<'utf-8', InstallPrepackedTimelinesRequestBody>(
|
||||
readStream,
|
||||
<T>(timelinesFromFileSystem: T) => {
|
||||
if (Array.isArray(timelinesFromFileSystem)) {
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
import type * as rt from 'io-ts';
|
||||
|
||||
import { set } from '@kbn/safer-lodash-set/fp';
|
||||
import readline from 'readline';
|
||||
import fs from 'fs';
|
||||
|
@ -13,7 +13,6 @@ import { createListStream } from '@kbn/utils';
|
|||
import { schema } from '@kbn/config-schema';
|
||||
|
||||
import type { KibanaRequest, RequestHandlerContext } from '@kbn/core/server';
|
||||
import { formatErrors } from '@kbn/securitysolution-io-ts-utils';
|
||||
|
||||
import type { FrameworkRequest } from '../../framework';
|
||||
|
||||
|
@ -38,12 +37,6 @@ export const buildFrameworkRequest = async (
|
|||
|
||||
export const escapeHatch = schema.object({}, { unknowns: 'allow' });
|
||||
|
||||
type ErrorFactory = (message: string) => Error;
|
||||
|
||||
export const throwErrors = (createError: ErrorFactory) => (errors: rt.Errors) => {
|
||||
throw createError(formatErrors(errors).join('\n'));
|
||||
};
|
||||
|
||||
export const getReadables = (dataPath: string): Promise<Readable> =>
|
||||
new Promise((resolved, reject) => {
|
||||
const contents: string[] = [];
|
||||
|
|
|
@ -26,7 +26,7 @@ import {
|
|||
NOT_ALLOW_UPDATE_STATUS_ERROR_MESSAGE,
|
||||
TEMPLATE_TIMELINE_VERSION_CONFLICT_MESSAGE,
|
||||
} from './failure_cases';
|
||||
import type { TimelineSavedObject } from '../../../../common/api/timeline';
|
||||
import type { TimelineResponse } from '../../../../common/api/timeline';
|
||||
import { TimelineStatusEnum, TimelineTypeEnum } from '../../../../common/api/timeline';
|
||||
import { mockGetTimelineValue, mockGetTemplateTimelineValue } from '../__mocks__/import_timelines';
|
||||
|
||||
|
@ -69,7 +69,7 @@ describe('failure cases', () => {
|
|||
const version = null;
|
||||
const templateTimelineVersion = null;
|
||||
const templateTimelineId = null;
|
||||
const existTimeline = mockGetTimelineValue as TimelineSavedObject;
|
||||
const existTimeline = mockGetTimelineValue as TimelineResponse;
|
||||
const existTemplateTimeline = null;
|
||||
const result = checkIsCreateFailureCases(
|
||||
isHandlingTemplateTimeline,
|
||||
|
@ -94,7 +94,7 @@ describe('failure cases', () => {
|
|||
const templateTimelineVersion = 1;
|
||||
const templateTimelineId = 'template-timeline-id-one';
|
||||
const existTimeline = null;
|
||||
const existTemplateTimeline = mockGetTemplateTimelineValue as TimelineSavedObject;
|
||||
const existTemplateTimeline = mockGetTemplateTimelineValue as TimelineResponse;
|
||||
const result = checkIsCreateFailureCases(
|
||||
isHandlingTemplateTimeline,
|
||||
TimelineStatusEnum.active,
|
||||
|
@ -144,7 +144,7 @@ describe('failure cases', () => {
|
|||
const templateTimelineVersion = null;
|
||||
const templateTimelineId = null;
|
||||
const existTimeline = {
|
||||
...(mockGetTimelineValue as TimelineSavedObject),
|
||||
...(mockGetTimelineValue as TimelineResponse),
|
||||
status: TimelineStatusEnum.immutable,
|
||||
};
|
||||
const existTemplateTimeline = null;
|
||||
|
@ -172,7 +172,7 @@ describe('failure cases', () => {
|
|||
const templateTimelineId = mockGetTemplateTimelineValue.templateTimelineId;
|
||||
const existTimeline = null;
|
||||
const existTemplateTimeline = {
|
||||
...(mockGetTemplateTimelineValue as TimelineSavedObject),
|
||||
...(mockGetTemplateTimelineValue as TimelineResponse),
|
||||
status: TimelineStatusEnum.immutable,
|
||||
};
|
||||
const result = checkIsUpdateFailureCases(
|
||||
|
@ -198,7 +198,7 @@ describe('failure cases', () => {
|
|||
const templateTimelineVersion = mockGetTemplateTimelineValue.templateTimelineVersion;
|
||||
const templateTimelineId = mockGetTemplateTimelineValue.templateTimelineId;
|
||||
const existTimeline = null;
|
||||
const existTemplateTimeline = mockGetTemplateTimelineValue as TimelineSavedObject;
|
||||
const existTemplateTimeline = mockGetTemplateTimelineValue as TimelineResponse;
|
||||
const result = checkIsUpdateFailureCases(
|
||||
isHandlingTemplateTimeline,
|
||||
TimelineStatusEnum.active,
|
||||
|
@ -246,10 +246,10 @@ describe('failure cases', () => {
|
|||
const templateTimelineVersion = mockGetTemplateTimelineValue.templateTimelineVersion;
|
||||
const templateTimelineId = mockGetTemplateTimelineValue.templateTimelineId;
|
||||
const existTimeline = {
|
||||
...(mockGetTemplateTimelineValue as TimelineSavedObject),
|
||||
...(mockGetTemplateTimelineValue as TimelineResponse),
|
||||
savedObjectId: 'someOtherId',
|
||||
};
|
||||
const existTemplateTimeline = mockGetTemplateTimelineValue as TimelineSavedObject;
|
||||
const existTemplateTimeline = mockGetTemplateTimelineValue as TimelineResponse;
|
||||
const result = checkIsUpdateFailureCases(
|
||||
isHandlingTemplateTimeline,
|
||||
TimelineStatusEnum.active,
|
||||
|
@ -273,7 +273,7 @@ describe('failure cases', () => {
|
|||
const templateTimelineVersion = mockGetTemplateTimelineValue.templateTimelineVersion;
|
||||
const templateTimelineId = mockGetTemplateTimelineValue.templateTimelineId;
|
||||
const existTimeline = null;
|
||||
const existTemplateTimeline = mockGetTemplateTimelineValue as TimelineSavedObject;
|
||||
const existTemplateTimeline = mockGetTemplateTimelineValue as TimelineResponse;
|
||||
const result = checkIsUpdateFailureCases(
|
||||
isHandlingTemplateTimeline,
|
||||
TimelineStatusEnum.active,
|
||||
|
@ -297,7 +297,7 @@ describe('failure cases', () => {
|
|||
const templateTimelineVersion = null;
|
||||
const templateTimelineId = null;
|
||||
const existTimeline = {
|
||||
...(mockGetTemplateTimelineValue as TimelineSavedObject),
|
||||
...(mockGetTemplateTimelineValue as TimelineResponse),
|
||||
savedObjectId: 'someOtherId',
|
||||
};
|
||||
const existTemplateTimeline = null;
|
||||
|
@ -326,7 +326,7 @@ describe('failure cases', () => {
|
|||
const templateTimelineVersion = mockGetTemplateTimelineValue.templateTimelineVersion;
|
||||
const templateTimelineId = mockGetTemplateTimelineValue.templateTimelineId;
|
||||
const existTimeline = null;
|
||||
const existTemplateTimeline = mockGetTemplateTimelineValue as TimelineSavedObject;
|
||||
const existTemplateTimeline = mockGetTemplateTimelineValue as TimelineResponse;
|
||||
const result = checkIsCreateViaImportFailureCases(
|
||||
isHandlingTemplateTimeline,
|
||||
TimelineStatusEnum.draft,
|
||||
|
@ -350,7 +350,7 @@ describe('failure cases', () => {
|
|||
const templateTimelineVersion = mockGetTemplateTimelineValue.templateTimelineVersion;
|
||||
const templateTimelineId = mockGetTemplateTimelineValue.templateTimelineId;
|
||||
const existTimeline = null;
|
||||
const existTemplateTimeline = mockGetTemplateTimelineValue as TimelineSavedObject;
|
||||
const existTemplateTimeline = mockGetTemplateTimelineValue as TimelineResponse;
|
||||
const result = checkIsCreateViaImportFailureCases(
|
||||
isHandlingTemplateTimeline,
|
||||
TimelineStatusEnum.active,
|
||||
|
@ -373,7 +373,7 @@ describe('failure cases', () => {
|
|||
const version = mockGetTimelineValue.version;
|
||||
const templateTimelineVersion = null;
|
||||
const templateTimelineId = null;
|
||||
const existTimeline = mockGetTimelineValue as TimelineSavedObject;
|
||||
const existTimeline = mockGetTimelineValue as TimelineResponse;
|
||||
const existTemplateTimeline = null;
|
||||
const result = checkIsCreateViaImportFailureCases(
|
||||
isHandlingTemplateTimeline,
|
||||
|
@ -399,7 +399,7 @@ describe('failure cases', () => {
|
|||
const version = mockGetTimelineValue.version;
|
||||
const templateTimelineVersion = null;
|
||||
const templateTimelineId = null;
|
||||
const existTimeline = mockGetTimelineValue as TimelineSavedObject;
|
||||
const existTimeline = mockGetTimelineValue as TimelineResponse;
|
||||
const existTemplateTimeline = null;
|
||||
const result = checkIsUpdateViaImportFailureCases(
|
||||
isHandlingTemplateTimeline,
|
||||
|
@ -424,7 +424,7 @@ describe('failure cases', () => {
|
|||
const templateTimelineVersion = mockGetTemplateTimelineValue.templateTimelineVersion;
|
||||
const templateTimelineId = mockGetTemplateTimelineValue.templateTimelineId;
|
||||
const existTimeline = null;
|
||||
const existTemplateTimeline = mockGetTemplateTimelineValue as TimelineSavedObject;
|
||||
const existTemplateTimeline = mockGetTemplateTimelineValue as TimelineResponse;
|
||||
const result = checkIsUpdateViaImportFailureCases(
|
||||
isHandlingTemplateTimeline,
|
||||
TimelineStatusEnum.active,
|
||||
|
@ -448,7 +448,7 @@ describe('failure cases', () => {
|
|||
const templateTimelineVersion = mockGetTemplateTimelineValue.templateTimelineVersion;
|
||||
const templateTimelineId = mockGetTemplateTimelineValue.templateTimelineId;
|
||||
const existTimeline = null;
|
||||
const existTemplateTimeline = mockGetTemplateTimelineValue as TimelineSavedObject;
|
||||
const existTemplateTimeline = mockGetTemplateTimelineValue as TimelineResponse;
|
||||
const result = checkIsUpdateViaImportFailureCases(
|
||||
isHandlingTemplateTimeline,
|
||||
TimelineStatusEnum.immutable,
|
||||
|
@ -496,10 +496,10 @@ describe('failure cases', () => {
|
|||
const templateTimelineVersion = mockGetTemplateTimelineValue.templateTimelineVersion;
|
||||
const templateTimelineId = mockGetTemplateTimelineValue.templateTimelineId;
|
||||
const existTimeline = {
|
||||
...(mockGetTemplateTimelineValue as TimelineSavedObject),
|
||||
...(mockGetTemplateTimelineValue as TimelineResponse),
|
||||
savedObjectId: 'someOtherId',
|
||||
};
|
||||
const existTemplateTimeline = mockGetTemplateTimelineValue as TimelineSavedObject;
|
||||
const existTemplateTimeline = mockGetTemplateTimelineValue as TimelineResponse;
|
||||
const result = checkIsUpdateViaImportFailureCases(
|
||||
isHandlingTemplateTimeline,
|
||||
TimelineStatusEnum.active,
|
||||
|
@ -523,7 +523,7 @@ describe('failure cases', () => {
|
|||
const templateTimelineVersion = mockGetTemplateTimelineValue.templateTimelineVersion;
|
||||
const templateTimelineId = mockGetTemplateTimelineValue.templateTimelineId;
|
||||
const existTimeline = null;
|
||||
const existTemplateTimeline = mockGetTemplateTimelineValue as TimelineSavedObject;
|
||||
const existTemplateTimeline = mockGetTemplateTimelineValue as TimelineResponse;
|
||||
const result = checkIsUpdateViaImportFailureCases(
|
||||
isHandlingTemplateTimeline,
|
||||
TimelineStatusEnum.active,
|
||||
|
@ -547,7 +547,7 @@ describe('failure cases', () => {
|
|||
const templateTimelineVersion = mockGetTemplateTimelineValue.templateTimelineVersion;
|
||||
const templateTimelineId = mockGetTemplateTimelineValue.templateTimelineId;
|
||||
const existTimeline = null;
|
||||
const existTemplateTimeline = mockGetTemplateTimelineValue as TimelineSavedObject;
|
||||
const existTemplateTimeline = mockGetTemplateTimelineValue as TimelineResponse;
|
||||
const result = checkIsUpdateViaImportFailureCases(
|
||||
isHandlingTemplateTimeline,
|
||||
TimelineStatusEnum.active,
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
import { isEmpty } from 'lodash/fp';
|
||||
import type { TimelineType, TimelineSavedObject } from '../../../../common/api/timeline';
|
||||
import type { TimelineType, TimelineResponse } from '../../../../common/api/timeline';
|
||||
import { type TimelineStatus, TimelineStatusEnum } from '../../../../common/api/timeline';
|
||||
|
||||
export const UPDATE_TIMELINE_ERROR_MESSAGE =
|
||||
|
@ -42,8 +42,8 @@ export const DEFAULT_ERROR = `Something has gone wrong. We didn't handle somethi
|
|||
const isUpdatingStatus = (
|
||||
isHandlingTemplateTimeline: boolean,
|
||||
status: TimelineStatus | null | undefined,
|
||||
existTimeline: TimelineSavedObject | null,
|
||||
existTemplateTimeline: TimelineSavedObject | null
|
||||
existTimeline: TimelineResponse | null,
|
||||
existTemplateTimeline: TimelineResponse | null
|
||||
) => {
|
||||
const obj = isHandlingTemplateTimeline ? existTemplateTimeline : existTimeline;
|
||||
return obj?.status === TimelineStatusEnum.immutable ? UPDATE_STATUS_ERROR_MESSAGE : null;
|
||||
|
@ -76,8 +76,8 @@ const commonUpdateTemplateTimelineCheck = (
|
|||
version: string | null,
|
||||
templateTimelineVersion: number | null,
|
||||
templateTimelineId: string | null | undefined,
|
||||
existTimeline: TimelineSavedObject | null,
|
||||
existTemplateTimeline: TimelineSavedObject | null
|
||||
existTimeline: TimelineResponse | null,
|
||||
existTemplateTimeline: TimelineResponse | null
|
||||
) => {
|
||||
if (isHandlingTemplateTimeline) {
|
||||
if (
|
||||
|
@ -129,8 +129,8 @@ const commonUpdateTimelineCheck = (
|
|||
version: string | null,
|
||||
templateTimelineVersion: number | null,
|
||||
templateTimelineId: string | null | undefined,
|
||||
existTimeline: TimelineSavedObject | null,
|
||||
existTemplateTimeline: TimelineSavedObject | null
|
||||
existTimeline: TimelineResponse | null,
|
||||
existTemplateTimeline: TimelineResponse | null
|
||||
) => {
|
||||
if (existTimeline == null) {
|
||||
// timeline !exists
|
||||
|
@ -158,8 +158,8 @@ const commonUpdateCases = (
|
|||
version: string | null,
|
||||
templateTimelineVersion: number | null,
|
||||
templateTimelineId: string | null | undefined,
|
||||
existTimeline: TimelineSavedObject | null,
|
||||
existTemplateTimeline: TimelineSavedObject | null
|
||||
existTimeline: TimelineResponse | null,
|
||||
existTemplateTimeline: TimelineResponse | null
|
||||
) => {
|
||||
if (isHandlingTemplateTimeline) {
|
||||
return commonUpdateTemplateTimelineCheck(
|
||||
|
@ -193,8 +193,8 @@ const createTemplateTimelineCheck = (
|
|||
version: string | null,
|
||||
templateTimelineVersion: number | null,
|
||||
templateTimelineId: string | null | undefined,
|
||||
existTimeline: TimelineSavedObject | null,
|
||||
existTemplateTimeline: TimelineSavedObject | null
|
||||
existTimeline: TimelineResponse | null,
|
||||
existTemplateTimeline: TimelineResponse | null
|
||||
) => {
|
||||
if (isHandlingTemplateTimeline && existTemplateTimeline != null) {
|
||||
// Throw error to create timeline template in patch
|
||||
|
@ -219,8 +219,8 @@ export const checkIsUpdateViaImportFailureCases = (
|
|||
version: string | null,
|
||||
templateTimelineVersion: number | null,
|
||||
templateTimelineId: string | null | undefined,
|
||||
existTimeline: TimelineSavedObject | null,
|
||||
existTemplateTimeline: TimelineSavedObject | null
|
||||
existTimeline: TimelineResponse | null,
|
||||
existTemplateTimeline: TimelineResponse | null
|
||||
) => {
|
||||
if (!isHandlingTemplateTimeline) {
|
||||
if (existTimeline == null) {
|
||||
|
@ -281,8 +281,8 @@ export const checkIsUpdateFailureCases = (
|
|||
version: string | null,
|
||||
templateTimelineVersion: number | null,
|
||||
templateTimelineId: string | null | undefined,
|
||||
existTimeline: TimelineSavedObject | null,
|
||||
existTemplateTimeline: TimelineSavedObject | null
|
||||
existTimeline: TimelineResponse | null,
|
||||
existTemplateTimeline: TimelineResponse | null
|
||||
) => {
|
||||
const error = isUpdatingStatus(
|
||||
isHandlingTemplateTimeline,
|
||||
|
@ -315,8 +315,8 @@ export const checkIsCreateFailureCases = (
|
|||
version: string | null,
|
||||
templateTimelineVersion: number | null,
|
||||
templateTimelineId: string | null | undefined,
|
||||
existTimeline: TimelineSavedObject | null,
|
||||
existTemplateTimeline: TimelineSavedObject | null
|
||||
existTimeline: TimelineResponse | null,
|
||||
existTemplateTimeline: TimelineResponse | null
|
||||
) => {
|
||||
if (!isHandlingTemplateTimeline && existTimeline != null) {
|
||||
return {
|
||||
|
@ -346,8 +346,8 @@ export const checkIsCreateViaImportFailureCases = (
|
|||
version: string | null,
|
||||
templateTimelineVersion: number | null,
|
||||
templateTimelineId: string | null | undefined,
|
||||
existTimeline: TimelineSavedObject | null,
|
||||
existTemplateTimeline: TimelineSavedObject | null
|
||||
existTimeline: TimelineResponse | null,
|
||||
existTemplateTimeline: TimelineResponse | null
|
||||
) => {
|
||||
if (status === TimelineStatusEnum.draft) {
|
||||
return {
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import type { TimelineSavedObject } from '../../../../common/api/timeline';
|
||||
import type { TimelineResponse } from '../../../../common/api/timeline';
|
||||
import {
|
||||
type TimelineType,
|
||||
TimelineTypeEnum,
|
||||
|
@ -27,7 +27,7 @@ export class TimelineObject {
|
|||
public readonly version: string | number | null;
|
||||
private frameworkRequest: FrameworkRequest;
|
||||
|
||||
public data: TimelineSavedObject | null;
|
||||
public data: TimelineResponse | null;
|
||||
|
||||
constructor({
|
||||
id = null,
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue