Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Security Solution] Add versioned router for timelines #7144 #166729

Merged
merged 3 commits into from
Oct 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ describe('persistTimeline', () => {
body: JSON.stringify({
timelineType: initialDraftTimeline.timelineType,
}),
version: '2023-10-31',
});
});

Expand Down Expand Up @@ -346,6 +347,7 @@ describe('importTimelines', () => {
headers: { 'Content-Type': undefined },
body: new FormData(),
signal: undefined,
version: '2023-10-31',
})
);
});
Expand Down Expand Up @@ -377,6 +379,7 @@ describe('exportSelectedTimeline', () => {
method: 'POST',
query: { file_name: 'timelines_export.ndjson' },
signal: {},
version: '2023-10-31',
});
});
});
Expand All @@ -400,6 +403,7 @@ describe('getDraftTimeline', () => {
test('should pass correct args to KibanaServices', () => {
expect(getMock).toBeCalledWith('/api/timeline/_draft', {
query: timelineType,
version: '2023-10-31',
});
});
});
Expand All @@ -425,6 +429,7 @@ describe('cleanDraftTimeline', () => {

expect(postMock).toBeCalledWith('/api/timeline/_draft', {
body: JSON.stringify(args),
version: '2023-10-31',
});
});

Expand All @@ -439,6 +444,7 @@ describe('cleanDraftTimeline', () => {

expect(postMock).toBeCalledWith('/api/timeline/_draft', {
body: JSON.stringify(args),
version: '2023-10-31',
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { pipe } from 'fp-ts/lib/pipeable';
import { isEmpty } from 'lodash';

import { throwErrors } from '@kbn/cases-plugin/common';

import type {
TimelineResponse,
TimelineErrorResponse,
Expand Down Expand Up @@ -119,6 +120,7 @@ const postTimeline = async ({
const response = await KibanaServices.get().http.post<TimelineResponse>(TIMELINE_URL, {
method: 'POST',
body: requestBody,
version: '2023-10-31',
});

return decodeTimelineResponse(response);
Expand All @@ -140,6 +142,7 @@ const patchTimeline = async ({
response = await KibanaServices.get().http.patch<TimelineResponse>(TIMELINE_URL, {
method: 'PATCH',
body: requestBody,
version: '2023-10-31',
});
} catch (err) {
// For Future developer
Expand Down Expand Up @@ -228,6 +231,7 @@ export const importTimelines = async ({
headers: { 'Content-Type': undefined },
body: formData,
signal,
version: '2023-10-31',
});
};

Expand All @@ -249,6 +253,7 @@ export const exportSelectedTimeline = ({
file_name: filename,
},
signal,
version: '2023-10-31',
});
};

Expand All @@ -261,6 +266,7 @@ export const getDraftTimeline = async ({
query: {
timelineType,
},
version: '2023-10-31',
});

return decodeTimelineResponse(response);
Expand Down Expand Up @@ -293,6 +299,7 @@ export const cleanDraftTimeline = async ({
}
const response = await KibanaServices.get().http.post<TimelineResponse>(TIMELINE_DRAFT_URL, {
body: requestBody,
version: '2023-10-31',
});

return decodeTimelineResponse(response);
Expand All @@ -301,7 +308,9 @@ export const cleanDraftTimeline = async ({
export const installPrepackedTimelines = async (): Promise<ImportTimelineResultSchema> => {
const response = await KibanaServices.get().http.post<ImportTimelineResultSchema>(
TIMELINE_PREPACKAGED_URL,
{}
{
version: '2023-10-31',
}
);

return decodePrepackedTimelineResponse(response);
Expand All @@ -312,6 +321,7 @@ export const getTimeline = async (id: string) => {
query: {
id,
},
version: '2023-10-31',
});

return decodeSingleTimelineResponse(response);
Expand All @@ -324,6 +334,7 @@ export const resolveTimeline = async (id: string) => {
query: {
id,
},
version: '2023-10-31',
}
);

Expand All @@ -335,6 +346,7 @@ export const getTimelineTemplate = async (templateTimelineId: string) => {
query: {
template_timeline_id: templateTimelineId,
},
version: '2023-10-31',
});

return decodeSingleTimelineResponse(response);
Expand All @@ -354,6 +366,7 @@ export const getAllTimelines = async (args: GetTimelinesArgs, abortSignal: Abort
...(args.timelineType ? { timeline_type: args.timelineType } : {}),
},
signal: abortSignal,
version: '2023-10-31',
});

return decodeAllTimelinesResponse(response);
Expand Down Expand Up @@ -388,6 +401,7 @@ export const persistFavorite = async ({
{
method: 'PATCH',
body: requestBody,
version: '2023-10-31',
}
);

Expand All @@ -407,6 +421,7 @@ export const deleteTimelinesByIds = async (savedObjectIds: string[]) => {
const response = await KibanaServices.get().http.delete<boolean>(TIMELINE_URL, {
method: 'DELETE',
body: requestBody,
version: '2023-10-31',
});
return response;
};
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export const persistNote = async ({
const response = await KibanaServices.get().http.patch<Note[]>(NOTE_URL, {
method: 'PATCH',
body: requestBody,
version: '2023-10-31',
});
return response;
};
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export const persistPinnedEvent = async ({
const response = await KibanaServices.get().http.patch<PinnedEvent | null>(PINNED_EVENT_URL, {
method: 'PATCH',
body: requestBody,
version: '2023-10-31',
});
return response;
};
Original file line number Diff line number Diff line change
Expand Up @@ -29,81 +29,86 @@ export const cleanDraftTimelinesRoute = (
_: ConfigType,
security: SetupPlugins['security']
) => {
router.post(
{
router.versioned
.post({
path: TIMELINE_DRAFT_URL,
validate: {
body: buildRouteValidationWithExcess(cleanDraftTimelineSchema),
},
options: {
tags: ['access:securitySolution'],
},
},
async (context, request, response) => {
const frameworkRequest = await buildFrameworkRequest(context, security, request);
const siemResponse = buildSiemResponse(response);
access: 'public',
})
.addVersion(
{
validate: {
request: { body: buildRouteValidationWithExcess(cleanDraftTimelineSchema) },
},
version: '2023-10-31',
},
async (context, request, response) => {
const frameworkRequest = await buildFrameworkRequest(context, security, request);
const siemResponse = buildSiemResponse(response);

try {
const {
timeline: [draftTimeline],
} = await getDraftTimeline(frameworkRequest, request.body.timelineType);
try {
const {
timeline: [draftTimeline],
} = await getDraftTimeline(frameworkRequest, request.body.timelineType);

if (draftTimeline?.savedObjectId) {
await resetTimeline(
frameworkRequest,
[draftTimeline.savedObjectId],
request.body.timelineType
);
const cleanedDraftTimeline = await getTimeline(
frameworkRequest,
draftTimeline.savedObjectId
);
if (draftTimeline?.savedObjectId) {
await resetTimeline(
frameworkRequest,
[draftTimeline.savedObjectId],
request.body.timelineType
);
const cleanedDraftTimeline = await getTimeline(
frameworkRequest,
draftTimeline.savedObjectId
);

return response.ok({
body: {
data: {
persistTimeline: {
timeline: cleanedDraftTimeline,
return response.ok({
body: {
data: {
persistTimeline: {
timeline: cleanedDraftTimeline,
},
},
},
},
});
}
const templateTimelineData =
request.body.timelineType === TimelineType.template
? {
timelineType: request.body.timelineType,
templateTimelineId: uuidv4(),
templateTimelineVersion: 1,
}
: {};
});
}
const templateTimelineData =
request.body.timelineType === TimelineType.template
? {
timelineType: request.body.timelineType,
templateTimelineId: uuidv4(),
templateTimelineVersion: 1,
}
: {};

const newTimelineResponse = await persistTimeline(frameworkRequest, null, null, {
...draftTimelineDefaults,
...templateTimelineData,
});
const newTimelineResponse = await persistTimeline(frameworkRequest, null, null, {
...draftTimelineDefaults,
...templateTimelineData,
});

if (newTimelineResponse.code === 200) {
return response.ok({
body: {
data: {
persistTimeline: {
timeline: newTimelineResponse.timeline,
if (newTimelineResponse.code === 200) {
return response.ok({
body: {
data: {
persistTimeline: {
timeline: newTimelineResponse.timeline,
},
},
},
},
});
}
});
}

return response.ok({});
} catch (err) {
const error = transformError(err);
return response.ok({});
} catch (err) {
const error = transformError(err);

return siemResponse.error({
body: error.message,
statusCode: error.statusCode,
});
return siemResponse.error({
body: error.message,
statusCode: error.statusCode,
});
}
}
}
);
);
};
Loading
Loading