Skip to content

Commit d63d2af

Browse files
[SIEM] Update readme for timeline apis (#67038)
* update doc * update unit test * remove redundant params * fix types * update readme * update readme Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
1 parent 39b2d71 commit d63d2af

File tree

5 files changed

+301
-14
lines changed

5 files changed

+301
-14
lines changed

x-pack/plugins/security_solution/public/timelines/containers/api.ts

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -103,40 +103,32 @@ export const persistTimeline = async ({
103103

104104
export const importTimelines = async ({
105105
fileToImport,
106-
overwrite = false,
107-
signal,
108106
}: ImportDataProps): Promise<ImportDataResponse> => {
109107
const formData = new FormData();
110108
formData.append('file', fileToImport);
111109

112110
return KibanaServices.get().http.fetch<ImportDataResponse>(`${TIMELINE_IMPORT_URL}`, {
113111
method: 'POST',
114112
headers: { 'Content-Type': undefined },
115-
query: { overwrite },
116113
body: formData,
117-
signal,
118114
});
119115
};
120116

121117
export const exportSelectedTimeline: ExportSelectedData = async ({
122-
excludeExportDetails = false,
123118
filename = `timelines_export.ndjson`,
124119
ids = [],
125120
signal,
126121
}): Promise<Blob> => {
127122
const body = ids.length > 0 ? JSON.stringify({ ids }) : undefined;
128-
const response = await KibanaServices.get().http.fetch<Blob>(`${TIMELINE_EXPORT_URL}`, {
123+
const response = await KibanaServices.get().http.fetch<{ body: Blob }>(`${TIMELINE_EXPORT_URL}`, {
129124
method: 'POST',
130125
body,
131126
query: {
132-
exclude_export_details: excludeExportDetails,
133127
file_name: filename,
134128
},
135-
signal,
136-
asResponse: true,
137129
});
138130

139-
return response.body!;
131+
return response.body;
140132
};
141133

142134
export const getDraftTimeline = async ({

x-pack/plugins/security_solution/server/lib/timeline/routes/README.md

Lines changed: 298 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -323,4 +323,301 @@ kbn-version: 8.0.0
323323
"timelineId":"f5a4bd10-83cd-11ea-bf78-0547a65f1281", // This is a must as well
324324
"version":"Wzg2LDFd" // Please provide the existing timeline version
325325
}
326-
```
326+
```
327+
328+
## Export timeline api
329+
330+
#### POST /api/timeline/_export
331+
332+
##### Authorization
333+
334+
Type: Basic Auth
335+
336+
username: Your Kibana username
337+
338+
password: Your Kibana password
339+
340+
341+
342+
343+
##### Request header
344+
345+
```
346+
347+
Content-Type: application/json
348+
349+
kbn-version: 8.0.0
350+
351+
```
352+
353+
##### Request param
354+
355+
```
356+
file_name: ${filename}.ndjson
357+
```
358+
359+
##### Request body
360+
```json
361+
{
362+
ids: [
363+
${timelineId}
364+
]
365+
}
366+
```
367+
368+
## Import timeline api
369+
370+
#### POST /api/timeline/_import
371+
372+
##### Authorization
373+
374+
Type: Basic Auth
375+
376+
username: Your Kibana username
377+
378+
password: Your Kibana password
379+
380+
381+
382+
383+
##### Request header
384+
385+
```
386+
387+
Content-Type: application/json
388+
389+
kbn-version: 8.0.0
390+
391+
```
392+
393+
##### Request body
394+
395+
```
396+
{
397+
file: sample.ndjson
398+
}
399+
```
400+
401+
402+
(each json in the file should match this format)
403+
example:
404+
```
405+
{"savedObjectId":"a3002fd0-781b-11ea-85e4-df9002f1452c","version":"WzIzLDFd","columns":[{"columnHeaderType":"not-filtered","id":"@timestamp"},{"columnHeaderType":"not-filtered","id":"message"},{"columnHeaderType":"not-filtered","id":"event.category"},{"columnHeaderType":"not-filtered","id":"event.action"},{"columnHeaderType":"not-filtered","id":"host.name"},{"columnHeaderType":"not-filtered","id":"source.ip"},{"columnHeaderType":"not-filtered","id":"destination.ip"},{"columnHeaderType":"not-filtered","id":"user.name"}],"dataProviders":[],"description":"tes description","eventType":"all","filters":[{"meta":{"field":null,"negate":false,"alias":null,"disabled":false,"params":"{\"query\":\"MacBook-Pro-de-Gloria.local\"}","type":"phrase","key":"host.name"},"query":"{\"match_phrase\":{\"host.name\":\"MacBook-Pro-de-Gloria.local\"}}","missing":null,"exists":null,"match_all":null,"range":null,"script":null}],"kqlMode":"filter","kqlQuery":{"filterQuery":{"serializedQuery":"{\"bool\":{\"should\":[{\"exists\":{\"field\":\"host.name\"}}],\"minimum_should_match\":1}}","kuery":{"expression":"host.name: *","kind":"kuery"}}},"title":"Test","dateRange":{"start":1585227005527,"end":1585313405527},"savedQueryId":null,"sort":{"columnId":"@timestamp","sortDirection":"desc"},"created":1586187068132,"createdBy":"angela","updated":1586187068132,"updatedBy":"angela","eventNotes":[],"globalNotes":[{"noteId":"a3b4d9d0-781b-11ea-85e4-df9002f1452c","version":"WzI1LDFd","note":"this is a note","timelineId":"a3002fd0-781b-11ea-85e4-df9002f1452c","created":1586187069313,"createdBy":"angela","updated":1586187069313,"updatedBy":"angela"}],"pinnedEventIds":[]}
406+
```
407+
408+
##### Response
409+
```
410+
{"success":true,"success_count":1,"errors":[]}
411+
```
412+
413+
## Get draft timeline api
414+
415+
#### GET /api/timeline/_draft
416+
417+
##### Authorization
418+
419+
Type: Basic Auth
420+
421+
username: Your Kibana username
422+
423+
password: Your Kibana password
424+
425+
426+
##### Request header
427+
428+
```
429+
430+
Content-Type: application/json
431+
432+
kbn-version: 8.0.0
433+
434+
```
435+
436+
##### Request param
437+
```
438+
timelineType: `default` or `template`
439+
```
440+
441+
##### Response
442+
```json
443+
{
444+
"data": {
445+
"persistTimeline": {
446+
"timeline": {
447+
"savedObjectId": "ababbd90-99de-11ea-8446-1d7fd9f03ebf",
448+
"version": "WzM2MiwzXQ==",
449+
"columns": [
450+
{
451+
"columnHeaderType": "not-filtered",
452+
"id": "@timestamp"
453+
},
454+
{
455+
"columnHeaderType": "not-filtered",
456+
"id": "message"
457+
},
458+
{
459+
"columnHeaderType": "not-filtered",
460+
"id": "event.category"
461+
},
462+
{
463+
"columnHeaderType": "not-filtered",
464+
"id": "event.action"
465+
},
466+
{
467+
"columnHeaderType": "not-filtered",
468+
"id": "host.name"
469+
},
470+
{
471+
"columnHeaderType": "not-filtered",
472+
"id": "source.ip"
473+
},
474+
{
475+
"columnHeaderType": "not-filtered",
476+
"id": "destination.ip"
477+
},
478+
{
479+
"columnHeaderType": "not-filtered",
480+
"id": "user.name"
481+
}
482+
],
483+
"dataProviders": [],
484+
"description": "",
485+
"eventType": "all",
486+
"filters": [],
487+
"kqlMode": "filter",
488+
"timelineType": "default",
489+
"kqlQuery": {
490+
"filterQuery": null
491+
},
492+
"title": "",
493+
"sort": {
494+
"columnId": "@timestamp",
495+
"sortDirection": "desc"
496+
},
497+
"status": "draft",
498+
"created": 1589899222908,
499+
"createdBy": "casetester",
500+
"updated": 1589899222908,
501+
"updatedBy": "casetester",
502+
"templateTimelineId": null,
503+
"templateTimelineVersion": null,
504+
"favorite": [],
505+
"eventIdToNoteIds": [],
506+
"noteIds": [],
507+
"notes": [],
508+
"pinnedEventIds": [],
509+
"pinnedEventsSaveObject": []
510+
}
511+
}
512+
}
513+
}
514+
```
515+
516+
## Create draft timeline api
517+
518+
#### POST /api/timeline/_draft
519+
520+
##### Authorization
521+
522+
Type: Basic Auth
523+
524+
username: Your Kibana username
525+
526+
password: Your Kibana password
527+
528+
529+
##### Request header
530+
531+
```
532+
533+
Content-Type: application/json
534+
535+
kbn-version: 8.0.0
536+
537+
```
538+
539+
##### Request body
540+
541+
```json
542+
{
543+
"timelineType": "default" or "template"
544+
}
545+
```
546+
547+
##### Response
548+
```json
549+
{
550+
"data": {
551+
"persistTimeline": {
552+
"timeline": {
553+
"savedObjectId": "ababbd90-99de-11ea-8446-1d7fd9f03ebf",
554+
"version": "WzQyMywzXQ==",
555+
"columns": [
556+
{
557+
"columnHeaderType": "not-filtered",
558+
"id": "@timestamp"
559+
},
560+
{
561+
"columnHeaderType": "not-filtered",
562+
"id": "message"
563+
},
564+
{
565+
"columnHeaderType": "not-filtered",
566+
"id": "event.category"
567+
},
568+
{
569+
"columnHeaderType": "not-filtered",
570+
"id": "event.action"
571+
},
572+
{
573+
"columnHeaderType": "not-filtered",
574+
"id": "host.name"
575+
},
576+
{
577+
"columnHeaderType": "not-filtered",
578+
"id": "source.ip"
579+
},
580+
{
581+
"columnHeaderType": "not-filtered",
582+
"id": "destination.ip"
583+
},
584+
{
585+
"columnHeaderType": "not-filtered",
586+
"id": "user.name"
587+
}
588+
],
589+
"dataProviders": [],
590+
"description": "",
591+
"eventType": "all",
592+
"filters": [],
593+
"kqlMode": "filter",
594+
"timelineType": "default",
595+
"kqlQuery": {
596+
"filterQuery": null
597+
},
598+
"title": "",
599+
"sort": {
600+
"columnId": "@timestamp",
601+
"sortDirection": "desc"
602+
},
603+
"status": "draft",
604+
"created": 1589903306582,
605+
"createdBy": "casetester",
606+
"updated": 1589903306582,
607+
"updatedBy": "casetester",
608+
"templateTimelineId": null,
609+
"templateTimelineVersion": null,
610+
"favorite": [],
611+
"eventIdToNoteIds": [],
612+
"noteIds": [],
613+
"notes": [],
614+
"pinnedEventIds": [],
615+
"pinnedEventsSaveObject": []
616+
}
617+
}
618+
}
619+
}
620+
```
621+
622+
623+

x-pack/plugins/security_solution/server/lib/timeline/routes/__mocks__/request_responses.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ export const getExportTimelinesRequest = () =>
2323
path: TIMELINE_EXPORT_URL,
2424
query: {
2525
file_name: 'mock_export_timeline.ndjson',
26-
exclude_export_details: 'false',
2726
},
2827
body: {
2928
ids: ['f0e58720-57b6-11ea-b88d-3f1a31716be8', '890b8ae0-57df-11ea-a7c9-3976b7f1cb37'],

x-pack/plugins/security_solution/server/lib/timeline/routes/export_timelines_route.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ describe('export timelines', () => {
9898
const result = server.validate(request);
9999

100100
expect(result.badRequest.mock.calls[1][0]).toEqual(
101-
'Invalid value "undefined" supplied to "file_name",Invalid value "undefined" supplied to "exclude_export_details",Invalid value "undefined" supplied to "exclude_export_details"'
101+
'Invalid value "undefined" supplied to "file_name"'
102102
);
103103
});
104104
});

x-pack/plugins/security_solution/server/lib/timeline/routes/schemas/export_timelines_schema.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import * as rt from 'io-ts';
88

99
export const exportTimelinesQuerySchema = rt.type({
1010
file_name: rt.string,
11-
exclude_export_details: rt.union([rt.literal('true'), rt.literal('false')]),
1211
});
1312

1413
export const exportTimelinesRequestBodySchema = rt.type({

0 commit comments

Comments
 (0)