mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 09:19:04 -04:00
[Security Solution] Migrate lists plugin API to versioned router (#165160)
Closes https://github.com/elastic/security-team/issues/7176
This commit is contained in:
parent
deebbadc2d
commit
21879be883
47 changed files with 2289 additions and 1995 deletions
|
@ -581,6 +581,7 @@ export const getExceptionFilterFromExceptionListIds = async ({
|
|||
}: GetExceptionFilterFromExceptionListIdsProps): Promise<ExceptionFilterResponse> =>
|
||||
http.fetch(INTERNAL_EXCEPTION_FILTER, {
|
||||
method: 'POST',
|
||||
version: '1',
|
||||
body: JSON.stringify({
|
||||
exception_list_ids: exceptionListIds,
|
||||
type: 'exception_list_ids',
|
||||
|
@ -609,6 +610,7 @@ export const getExceptionFilterFromExceptions = async ({
|
|||
}: GetExceptionFilterFromExceptionsProps): Promise<ExceptionFilterResponse> =>
|
||||
http.fetch(INTERNAL_EXCEPTION_FILTER, {
|
||||
method: 'POST',
|
||||
version: '1',
|
||||
body: JSON.stringify({
|
||||
exceptions,
|
||||
type: 'exception_items',
|
||||
|
|
|
@ -117,6 +117,7 @@ const findListsBySize = async ({
|
|||
}: ApiParams & FindListSchemaEncoded): Promise<FoundListsBySizeSchema> => {
|
||||
return http.fetch(`${INTERNAL_FIND_LISTS_BY_SIZE}`, {
|
||||
method: 'GET',
|
||||
version: '1',
|
||||
query: {
|
||||
cursor,
|
||||
page,
|
||||
|
@ -272,6 +273,7 @@ export { readListIndexWithValidation as readListIndex };
|
|||
// TODO add types and validation
|
||||
export const readListPrivileges = async ({ http, signal }: ApiParams): Promise<unknown> =>
|
||||
http.fetch<unknown>(LIST_PRIVILEGES_URL, {
|
||||
version: '2023-10-31',
|
||||
method: 'GET',
|
||||
signal,
|
||||
});
|
||||
|
|
|
@ -20,81 +20,88 @@ import { buildRouteValidation, buildSiemResponse, getExceptionListClient } from
|
|||
import { validateExceptionListSize } from './validate';
|
||||
|
||||
export const createEndpointListItemRoute = (router: ListsPluginRouter): void => {
|
||||
router.post(
|
||||
{
|
||||
router.versioned
|
||||
.post({
|
||||
access: 'public',
|
||||
options: {
|
||||
tags: ['access:lists-all'],
|
||||
},
|
||||
path: ENDPOINT_LIST_ITEM_URL,
|
||||
validate: {
|
||||
body: buildRouteValidation<
|
||||
typeof createEndpointListItemRequest,
|
||||
CreateEndpointListItemRequestDecoded
|
||||
>(createEndpointListItemRequest),
|
||||
})
|
||||
.addVersion(
|
||||
{
|
||||
validate: {
|
||||
request: {
|
||||
body: buildRouteValidation<
|
||||
typeof createEndpointListItemRequest,
|
||||
CreateEndpointListItemRequestDecoded
|
||||
>(createEndpointListItemRequest),
|
||||
},
|
||||
},
|
||||
version: '2023-10-31',
|
||||
},
|
||||
},
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const {
|
||||
name,
|
||||
tags,
|
||||
meta,
|
||||
comments,
|
||||
description,
|
||||
entries,
|
||||
item_id: itemId,
|
||||
os_types: osTypes,
|
||||
type,
|
||||
} = request.body;
|
||||
const exceptionLists = await getExceptionListClient(context);
|
||||
const exceptionListItem = await exceptionLists.getEndpointListItem({
|
||||
id: undefined,
|
||||
itemId,
|
||||
});
|
||||
if (exceptionListItem != null) {
|
||||
return siemResponse.error({
|
||||
body: `exception list item id: "${itemId}" already exists`,
|
||||
statusCode: 409,
|
||||
});
|
||||
} else {
|
||||
const createdList = await exceptionLists.createEndpointListItem({
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const {
|
||||
name,
|
||||
tags,
|
||||
meta,
|
||||
comments,
|
||||
description,
|
||||
entries,
|
||||
itemId,
|
||||
meta,
|
||||
name,
|
||||
osTypes,
|
||||
tags,
|
||||
item_id: itemId,
|
||||
os_types: osTypes,
|
||||
type,
|
||||
} = request.body;
|
||||
const exceptionLists = await getExceptionListClient(context);
|
||||
const exceptionListItem = await exceptionLists.getEndpointListItem({
|
||||
id: undefined,
|
||||
itemId,
|
||||
});
|
||||
const [validated, errors] = validate(createdList, createEndpointListItemResponse);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
if (exceptionListItem != null) {
|
||||
return siemResponse.error({
|
||||
body: `exception list item id: "${itemId}" already exists`,
|
||||
statusCode: 409,
|
||||
});
|
||||
} else {
|
||||
const listSizeError = await validateExceptionListSize(
|
||||
exceptionLists,
|
||||
ENDPOINT_LIST_ID,
|
||||
'agnostic'
|
||||
);
|
||||
if (listSizeError != null) {
|
||||
await exceptionLists.deleteExceptionListItemById({
|
||||
id: createdList.id,
|
||||
namespaceType: 'agnostic',
|
||||
});
|
||||
return siemResponse.error(listSizeError);
|
||||
const createdList = await exceptionLists.createEndpointListItem({
|
||||
comments,
|
||||
description,
|
||||
entries,
|
||||
itemId,
|
||||
meta,
|
||||
name,
|
||||
osTypes,
|
||||
tags,
|
||||
type,
|
||||
});
|
||||
const [validated, errors] = validate(createdList, createEndpointListItemResponse);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
} else {
|
||||
const listSizeError = await validateExceptionListSize(
|
||||
exceptionLists,
|
||||
ENDPOINT_LIST_ID,
|
||||
'agnostic'
|
||||
);
|
||||
if (listSizeError != null) {
|
||||
await exceptionLists.deleteExceptionListItemById({
|
||||
id: createdList.id,
|
||||
namespaceType: 'agnostic',
|
||||
});
|
||||
return siemResponse.error(listSizeError);
|
||||
}
|
||||
return response.ok({ body: validated ?? {} });
|
||||
}
|
||||
return response.ok({ body: validated ?? {} });
|
||||
}
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
};
|
||||
|
|
|
@ -25,38 +25,43 @@ import { getExceptionListClient } from './utils/get_exception_list_client';
|
|||
* @param router The router to use.
|
||||
*/
|
||||
export const createEndpointListRoute = (router: ListsPluginRouter): void => {
|
||||
router.post(
|
||||
{
|
||||
router.versioned
|
||||
.post({
|
||||
access: 'public',
|
||||
options: {
|
||||
tags: ['access:lists-all'],
|
||||
},
|
||||
path: ENDPOINT_LIST_URL,
|
||||
validate: false,
|
||||
},
|
||||
async (context, _, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const exceptionLists = await getExceptionListClient(context);
|
||||
const createdList = await exceptionLists.createEndpointList();
|
||||
// We always return ok on a create endpoint list route but with an empty body as
|
||||
// an additional fetch of the full list would be slower and the UI has everything hard coded
|
||||
// within it to get the list if it needs details about it. Our goal is to be as fast as possible
|
||||
// and block the least amount of time with this route since it could end up in various parts of the
|
||||
// stack at some point such as repeatedly being called by endpoint agents.
|
||||
const body = createdList ?? {};
|
||||
const [validated, errors] = validate(body, createEndpointListResponse);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
})
|
||||
.addVersion(
|
||||
{
|
||||
validate: false,
|
||||
version: '2023-10-31',
|
||||
},
|
||||
async (context, _, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const exceptionLists = await getExceptionListClient(context);
|
||||
const createdList = await exceptionLists.createEndpointList();
|
||||
// We always return ok on a create endpoint list route but with an empty body as
|
||||
// an additional fetch of the full list would be slower and the UI has everything hard coded
|
||||
// within it to get the list if it needs details about it. Our goal is to be as fast as possible
|
||||
// and block the least amount of time with this route since it could end up in various parts of the
|
||||
// stack at some point such as repeatedly being called by endpoint agents.
|
||||
const body = createdList ?? {};
|
||||
const [validated, errors] = validate(body, createEndpointListResponse);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
}
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
};
|
||||
|
|
|
@ -22,114 +22,121 @@ import { endpointDisallowedFields } from './endpoint_disallowed_fields';
|
|||
import { validateEndpointExceptionItemEntries, validateExceptionListSize } from './validate';
|
||||
|
||||
export const createExceptionListItemRoute = (router: ListsPluginRouter): void => {
|
||||
router.post(
|
||||
{
|
||||
router.versioned
|
||||
.post({
|
||||
access: 'public',
|
||||
options: {
|
||||
tags: ['access:lists-all'],
|
||||
},
|
||||
path: EXCEPTION_LIST_ITEM_URL,
|
||||
validate: {
|
||||
body: buildRouteValidation<
|
||||
typeof createExceptionListItemRequest,
|
||||
CreateExceptionListItemRequestDecoded
|
||||
>(createExceptionListItemRequest),
|
||||
})
|
||||
.addVersion(
|
||||
{
|
||||
validate: {
|
||||
request: {
|
||||
body: buildRouteValidation<
|
||||
typeof createExceptionListItemRequest,
|
||||
CreateExceptionListItemRequestDecoded
|
||||
>(createExceptionListItemRequest),
|
||||
},
|
||||
},
|
||||
version: '2023-10-31',
|
||||
},
|
||||
},
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const {
|
||||
namespace_type: namespaceType,
|
||||
name,
|
||||
tags,
|
||||
meta,
|
||||
comments,
|
||||
description,
|
||||
entries,
|
||||
item_id: itemId,
|
||||
list_id: listId,
|
||||
os_types: osTypes,
|
||||
type,
|
||||
expire_time: expireTime,
|
||||
} = request.body;
|
||||
const exceptionLists = await getExceptionListClient(context);
|
||||
const exceptionList = await exceptionLists.getExceptionList({
|
||||
id: undefined,
|
||||
listId,
|
||||
namespaceType,
|
||||
});
|
||||
if (exceptionList == null) {
|
||||
return siemResponse.error({
|
||||
body: `exception list id: "${listId}" does not exist`,
|
||||
statusCode: 404,
|
||||
});
|
||||
} else {
|
||||
const exceptionListItem = await exceptionLists.getExceptionListItem({
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const {
|
||||
namespace_type: namespaceType,
|
||||
name,
|
||||
tags,
|
||||
meta,
|
||||
comments,
|
||||
description,
|
||||
entries,
|
||||
item_id: itemId,
|
||||
list_id: listId,
|
||||
os_types: osTypes,
|
||||
type,
|
||||
expire_time: expireTime,
|
||||
} = request.body;
|
||||
const exceptionLists = await getExceptionListClient(context);
|
||||
const exceptionList = await exceptionLists.getExceptionList({
|
||||
id: undefined,
|
||||
itemId,
|
||||
listId,
|
||||
namespaceType,
|
||||
});
|
||||
if (exceptionListItem != null) {
|
||||
if (exceptionList == null) {
|
||||
return siemResponse.error({
|
||||
body: `exception list item id: "${itemId}" already exists`,
|
||||
statusCode: 409,
|
||||
body: `exception list id: "${listId}" does not exist`,
|
||||
statusCode: 404,
|
||||
});
|
||||
} else {
|
||||
if (exceptionList.type === 'endpoint') {
|
||||
const error = validateEndpointExceptionItemEntries(request.body.entries);
|
||||
if (error != null) {
|
||||
return siemResponse.error(error);
|
||||
}
|
||||
for (const entry of entries) {
|
||||
if (endpointDisallowedFields.includes(entry.field)) {
|
||||
return siemResponse.error({
|
||||
body: `cannot add endpoint exception item on field ${entry.field}`,
|
||||
statusCode: 400,
|
||||
});
|
||||
const exceptionListItem = await exceptionLists.getExceptionListItem({
|
||||
id: undefined,
|
||||
itemId,
|
||||
namespaceType,
|
||||
});
|
||||
if (exceptionListItem != null) {
|
||||
return siemResponse.error({
|
||||
body: `exception list item id: "${itemId}" already exists`,
|
||||
statusCode: 409,
|
||||
});
|
||||
} else {
|
||||
if (exceptionList.type === 'endpoint') {
|
||||
const error = validateEndpointExceptionItemEntries(request.body.entries);
|
||||
if (error != null) {
|
||||
return siemResponse.error(error);
|
||||
}
|
||||
for (const entry of entries) {
|
||||
if (endpointDisallowedFields.includes(entry.field)) {
|
||||
return siemResponse.error({
|
||||
body: `cannot add endpoint exception item on field ${entry.field}`,
|
||||
statusCode: 400,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
const createdList = await exceptionLists.createExceptionListItem({
|
||||
comments,
|
||||
description,
|
||||
entries,
|
||||
expireTime,
|
||||
itemId,
|
||||
listId,
|
||||
meta,
|
||||
name,
|
||||
namespaceType,
|
||||
osTypes,
|
||||
tags,
|
||||
type,
|
||||
});
|
||||
const [validated, errors] = validate(createdList, createExceptionListItemResponse);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
} else {
|
||||
const listSizeError = await validateExceptionListSize(
|
||||
exceptionLists,
|
||||
const createdList = await exceptionLists.createExceptionListItem({
|
||||
comments,
|
||||
description,
|
||||
entries,
|
||||
expireTime,
|
||||
itemId,
|
||||
listId,
|
||||
namespaceType
|
||||
);
|
||||
if (listSizeError != null) {
|
||||
await exceptionLists.deleteExceptionListItemById({
|
||||
id: createdList.id,
|
||||
namespaceType,
|
||||
});
|
||||
return siemResponse.error(listSizeError);
|
||||
meta,
|
||||
name,
|
||||
namespaceType,
|
||||
osTypes,
|
||||
tags,
|
||||
type,
|
||||
});
|
||||
const [validated, errors] = validate(createdList, createExceptionListItemResponse);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
} else {
|
||||
const listSizeError = await validateExceptionListSize(
|
||||
exceptionLists,
|
||||
listId,
|
||||
namespaceType
|
||||
);
|
||||
if (listSizeError != null) {
|
||||
await exceptionLists.deleteExceptionListItemById({
|
||||
id: createdList.id,
|
||||
namespaceType,
|
||||
});
|
||||
return siemResponse.error(listSizeError);
|
||||
}
|
||||
return response.ok({ body: validated ?? {} });
|
||||
}
|
||||
return response.ok({ body: validated ?? {} });
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
};
|
||||
|
|
|
@ -15,30 +15,37 @@ import { createExceptionListHandler } from '../handlers/create_exception_list_ha
|
|||
import { buildRouteValidation, buildSiemResponse } from './utils';
|
||||
|
||||
export const createExceptionListRoute = (router: ListsPluginRouter): void => {
|
||||
router.post(
|
||||
{
|
||||
router.versioned
|
||||
.post({
|
||||
access: 'public',
|
||||
options: {
|
||||
tags: ['access:lists-all'],
|
||||
},
|
||||
path: EXCEPTION_LIST_URL,
|
||||
validate: {
|
||||
body: buildRouteValidation<
|
||||
typeof createExceptionListRequest,
|
||||
CreateExceptionListRequestDecoded
|
||||
>(createExceptionListRequest),
|
||||
})
|
||||
.addVersion(
|
||||
{
|
||||
validate: {
|
||||
request: {
|
||||
body: buildRouteValidation<
|
||||
typeof createExceptionListRequest,
|
||||
CreateExceptionListRequestDecoded
|
||||
>(createExceptionListRequest),
|
||||
},
|
||||
},
|
||||
version: '2023-10-31',
|
||||
},
|
||||
},
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
return await createExceptionListHandler(context, request, response, siemResponse);
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
return await createExceptionListHandler(context, request, response, siemResponse);
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
};
|
||||
|
|
|
@ -24,55 +24,62 @@ import {
|
|||
} from './utils';
|
||||
|
||||
export const deleteEndpointListItemRoute = (router: ListsPluginRouter): void => {
|
||||
router.delete(
|
||||
{
|
||||
router.versioned
|
||||
.delete({
|
||||
access: 'public',
|
||||
options: {
|
||||
tags: ['access:lists-all'],
|
||||
},
|
||||
path: ENDPOINT_LIST_ITEM_URL,
|
||||
validate: {
|
||||
query: buildRouteValidation<
|
||||
typeof deleteEndpointListItemRequestQuery,
|
||||
DeleteEndpointListItemRequestQueryDecoded
|
||||
>(deleteEndpointListItemRequestQuery),
|
||||
})
|
||||
.addVersion(
|
||||
{
|
||||
validate: {
|
||||
request: {
|
||||
query: buildRouteValidation<
|
||||
typeof deleteEndpointListItemRequestQuery,
|
||||
DeleteEndpointListItemRequestQueryDecoded
|
||||
>(deleteEndpointListItemRequestQuery),
|
||||
},
|
||||
},
|
||||
version: '2023-10-31',
|
||||
},
|
||||
},
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const exceptionLists = await getExceptionListClient(context);
|
||||
const { item_id: itemId, id } = request.query;
|
||||
if (itemId == null && id == null) {
|
||||
return siemResponse.error({
|
||||
body: 'Either "item_id" or "id" needs to be defined in the request',
|
||||
statusCode: 400,
|
||||
});
|
||||
} else {
|
||||
const deleted = await exceptionLists.deleteEndpointListItem({
|
||||
id,
|
||||
itemId,
|
||||
});
|
||||
if (deleted == null) {
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const exceptionLists = await getExceptionListClient(context);
|
||||
const { item_id: itemId, id } = request.query;
|
||||
if (itemId == null && id == null) {
|
||||
return siemResponse.error({
|
||||
body: getErrorMessageExceptionListItem({ id, itemId }),
|
||||
statusCode: 404,
|
||||
body: 'Either "item_id" or "id" needs to be defined in the request',
|
||||
statusCode: 400,
|
||||
});
|
||||
} else {
|
||||
const [validated, errors] = validate(deleted, deleteEndpointListItemResponse);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
const deleted = await exceptionLists.deleteEndpointListItem({
|
||||
id,
|
||||
itemId,
|
||||
});
|
||||
if (deleted == null) {
|
||||
return siemResponse.error({
|
||||
body: getErrorMessageExceptionListItem({ id, itemId }),
|
||||
statusCode: 404,
|
||||
});
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
const [validated, errors] = validate(deleted, deleteEndpointListItemResponse);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
};
|
||||
|
|
|
@ -24,56 +24,63 @@ import {
|
|||
} from './utils';
|
||||
|
||||
export const deleteExceptionListItemRoute = (router: ListsPluginRouter): void => {
|
||||
router.delete(
|
||||
{
|
||||
router.versioned
|
||||
.delete({
|
||||
access: 'public',
|
||||
options: {
|
||||
tags: ['access:lists-all'],
|
||||
},
|
||||
path: EXCEPTION_LIST_ITEM_URL,
|
||||
validate: {
|
||||
query: buildRouteValidation<
|
||||
typeof deleteExceptionListItemRequestQuery,
|
||||
DeleteExceptionListItemRequestQueryDecoded
|
||||
>(deleteExceptionListItemRequestQuery),
|
||||
})
|
||||
.addVersion(
|
||||
{
|
||||
validate: {
|
||||
request: {
|
||||
query: buildRouteValidation<
|
||||
typeof deleteExceptionListItemRequestQuery,
|
||||
DeleteExceptionListItemRequestQueryDecoded
|
||||
>(deleteExceptionListItemRequestQuery),
|
||||
},
|
||||
},
|
||||
version: '2023-10-31',
|
||||
},
|
||||
},
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const exceptionLists = await getExceptionListClient(context);
|
||||
const { item_id: itemId, id, namespace_type: namespaceType } = request.query;
|
||||
if (itemId == null && id == null) {
|
||||
return siemResponse.error({
|
||||
body: 'Either "item_id" or "id" needs to be defined in the request',
|
||||
statusCode: 400,
|
||||
});
|
||||
} else {
|
||||
const deleted = await exceptionLists.deleteExceptionListItem({
|
||||
id,
|
||||
itemId,
|
||||
namespaceType,
|
||||
});
|
||||
if (deleted == null) {
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const exceptionLists = await getExceptionListClient(context);
|
||||
const { item_id: itemId, id, namespace_type: namespaceType } = request.query;
|
||||
if (itemId == null && id == null) {
|
||||
return siemResponse.error({
|
||||
body: getErrorMessageExceptionListItem({ id, itemId }),
|
||||
statusCode: 404,
|
||||
body: 'Either "item_id" or "id" needs to be defined in the request',
|
||||
statusCode: 400,
|
||||
});
|
||||
} else {
|
||||
const [validated, errors] = validate(deleted, deleteExceptionListItemResponse);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
const deleted = await exceptionLists.deleteExceptionListItem({
|
||||
id,
|
||||
itemId,
|
||||
namespaceType,
|
||||
});
|
||||
if (deleted == null) {
|
||||
return siemResponse.error({
|
||||
body: getErrorMessageExceptionListItem({ id, itemId }),
|
||||
statusCode: 404,
|
||||
});
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
const [validated, errors] = validate(deleted, deleteExceptionListItemResponse);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
};
|
||||
|
|
|
@ -24,56 +24,63 @@ import {
|
|||
} from './utils';
|
||||
|
||||
export const deleteExceptionListRoute = (router: ListsPluginRouter): void => {
|
||||
router.delete(
|
||||
{
|
||||
router.versioned
|
||||
.delete({
|
||||
access: 'public',
|
||||
options: {
|
||||
tags: ['access:lists-all'],
|
||||
},
|
||||
path: EXCEPTION_LIST_URL,
|
||||
validate: {
|
||||
query: buildRouteValidation<
|
||||
typeof deleteExceptionListRequestQuery,
|
||||
DeleteExceptionListRequestQueryDecoded
|
||||
>(deleteExceptionListRequestQuery),
|
||||
})
|
||||
.addVersion(
|
||||
{
|
||||
validate: {
|
||||
request: {
|
||||
query: buildRouteValidation<
|
||||
typeof deleteExceptionListRequestQuery,
|
||||
DeleteExceptionListRequestQueryDecoded
|
||||
>(deleteExceptionListRequestQuery),
|
||||
},
|
||||
},
|
||||
version: '2023-10-31',
|
||||
},
|
||||
},
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const exceptionLists = await getExceptionListClient(context);
|
||||
const { list_id: listId, id, namespace_type: namespaceType } = request.query;
|
||||
if (listId == null && id == null) {
|
||||
return siemResponse.error({
|
||||
body: 'Either "list_id" or "id" needs to be defined in the request',
|
||||
statusCode: 400,
|
||||
});
|
||||
} else {
|
||||
const deleted = await exceptionLists.deleteExceptionList({
|
||||
id,
|
||||
listId,
|
||||
namespaceType,
|
||||
});
|
||||
if (deleted == null) {
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const exceptionLists = await getExceptionListClient(context);
|
||||
const { list_id: listId, id, namespace_type: namespaceType } = request.query;
|
||||
if (listId == null && id == null) {
|
||||
return siemResponse.error({
|
||||
body: getErrorMessageExceptionList({ id, listId }),
|
||||
statusCode: 404,
|
||||
body: 'Either "list_id" or "id" needs to be defined in the request',
|
||||
statusCode: 400,
|
||||
});
|
||||
} else {
|
||||
const [validated, errors] = validate(deleted, deleteExceptionListResponse);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
const deleted = await exceptionLists.deleteExceptionList({
|
||||
id,
|
||||
listId,
|
||||
namespaceType,
|
||||
});
|
||||
if (deleted == null) {
|
||||
return siemResponse.error({
|
||||
body: getErrorMessageExceptionList({ id, listId }),
|
||||
statusCode: 404,
|
||||
});
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
const [validated, errors] = validate(deleted, deleteExceptionListResponse);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
};
|
||||
|
|
|
@ -19,76 +19,83 @@ import {
|
|||
import { buildRouteValidation, buildSiemResponse, getExceptionListClient } from './utils';
|
||||
|
||||
export const duplicateExceptionsRoute = (router: ListsPluginRouter): void => {
|
||||
router.post(
|
||||
{
|
||||
router.versioned
|
||||
.post({
|
||||
access: 'public',
|
||||
options: {
|
||||
tags: ['access:lists-all'],
|
||||
},
|
||||
path: `${EXCEPTION_LIST_URL}/_duplicate`,
|
||||
validate: {
|
||||
query: buildRouteValidation<
|
||||
typeof duplicateExceptionListRequestQuery,
|
||||
DuplicateExceptionListRequestQueryDecoded
|
||||
>(duplicateExceptionListRequestQuery),
|
||||
})
|
||||
.addVersion(
|
||||
{
|
||||
validate: {
|
||||
request: {
|
||||
query: buildRouteValidation<
|
||||
typeof duplicateExceptionListRequestQuery,
|
||||
DuplicateExceptionListRequestQueryDecoded
|
||||
>(duplicateExceptionListRequestQuery),
|
||||
},
|
||||
},
|
||||
version: '2023-10-31',
|
||||
},
|
||||
},
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
|
||||
try {
|
||||
const {
|
||||
list_id: listId,
|
||||
namespace_type: namespaceType,
|
||||
include_expired_exceptions: includeExpiredExceptionsString,
|
||||
} = request.query;
|
||||
try {
|
||||
const {
|
||||
list_id: listId,
|
||||
namespace_type: namespaceType,
|
||||
include_expired_exceptions: includeExpiredExceptionsString,
|
||||
} = request.query;
|
||||
|
||||
const exceptionListsClient = await getExceptionListClient(context);
|
||||
const exceptionListsClient = await getExceptionListClient(context);
|
||||
|
||||
// fetch list container
|
||||
const listToDuplicate = await exceptionListsClient.getExceptionList({
|
||||
id: undefined,
|
||||
listId,
|
||||
namespaceType,
|
||||
});
|
||||
// fetch list container
|
||||
const listToDuplicate = await exceptionListsClient.getExceptionList({
|
||||
id: undefined,
|
||||
listId,
|
||||
namespaceType,
|
||||
});
|
||||
|
||||
if (listToDuplicate == null) {
|
||||
if (listToDuplicate == null) {
|
||||
return siemResponse.error({
|
||||
body: `exception list id: "${listId}" does not exist`,
|
||||
statusCode: 404,
|
||||
});
|
||||
}
|
||||
|
||||
// Defaults to including expired exceptions if query param is not present
|
||||
const includeExpiredExceptions =
|
||||
includeExpiredExceptionsString !== undefined
|
||||
? includeExpiredExceptionsString === 'true'
|
||||
: true;
|
||||
const duplicatedList = await exceptionListsClient.duplicateExceptionListAndItems({
|
||||
includeExpiredExceptions,
|
||||
list: listToDuplicate,
|
||||
namespaceType,
|
||||
});
|
||||
|
||||
if (duplicatedList == null) {
|
||||
return siemResponse.error({
|
||||
body: `unable to duplicate exception list with list_id: ${listId} - action not allowed`,
|
||||
statusCode: 405,
|
||||
});
|
||||
}
|
||||
|
||||
const [validated, errors] = validate(duplicatedList, duplicateExceptionListResponse);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
}
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: `exception list id: "${listId}" does not exist`,
|
||||
statusCode: 404,
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
|
||||
// Defaults to including expired exceptions if query param is not present
|
||||
const includeExpiredExceptions =
|
||||
includeExpiredExceptionsString !== undefined
|
||||
? includeExpiredExceptionsString === 'true'
|
||||
: true;
|
||||
const duplicatedList = await exceptionListsClient.duplicateExceptionListAndItems({
|
||||
includeExpiredExceptions,
|
||||
list: listToDuplicate,
|
||||
namespaceType,
|
||||
});
|
||||
|
||||
if (duplicatedList == null) {
|
||||
return siemResponse.error({
|
||||
body: `unable to duplicate exception list with list_id: ${listId} - action not allowed`,
|
||||
statusCode: 405,
|
||||
});
|
||||
}
|
||||
|
||||
const [validated, errors] = validate(duplicatedList, duplicateExceptionListResponse);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
}
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
};
|
||||
|
|
|
@ -14,61 +14,68 @@ import { exportExceptionListRequestQuery } from '../../common/api';
|
|||
import { buildRouteValidation, buildSiemResponse, getExceptionListClient } from './utils';
|
||||
|
||||
export const exportExceptionsRoute = (router: ListsPluginRouter): void => {
|
||||
router.post(
|
||||
{
|
||||
router.versioned
|
||||
.post({
|
||||
access: 'public',
|
||||
options: {
|
||||
tags: ['access:lists-read'],
|
||||
},
|
||||
path: `${EXCEPTION_LIST_URL}/_export`,
|
||||
validate: {
|
||||
query: buildRouteValidation(exportExceptionListRequestQuery),
|
||||
})
|
||||
.addVersion(
|
||||
{
|
||||
validate: {
|
||||
request: {
|
||||
query: buildRouteValidation(exportExceptionListRequestQuery),
|
||||
},
|
||||
},
|
||||
version: '2023-10-31',
|
||||
},
|
||||
},
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
|
||||
try {
|
||||
const {
|
||||
id,
|
||||
list_id: listId,
|
||||
namespace_type: namespaceType,
|
||||
include_expired_exceptions: includeExpiredExceptionsString,
|
||||
} = request.query;
|
||||
const exceptionListsClient = await getExceptionListClient(context);
|
||||
try {
|
||||
const {
|
||||
id,
|
||||
list_id: listId,
|
||||
namespace_type: namespaceType,
|
||||
include_expired_exceptions: includeExpiredExceptionsString,
|
||||
} = request.query;
|
||||
const exceptionListsClient = await getExceptionListClient(context);
|
||||
|
||||
// Defaults to including expired exceptions if query param is not present
|
||||
const includeExpiredExceptions =
|
||||
includeExpiredExceptionsString !== undefined
|
||||
? includeExpiredExceptionsString === 'true'
|
||||
: true;
|
||||
const exportContent = await exceptionListsClient.exportExceptionListAndItems({
|
||||
id,
|
||||
includeExpiredExceptions,
|
||||
listId,
|
||||
namespaceType,
|
||||
});
|
||||
// Defaults to including expired exceptions if query param is not present
|
||||
const includeExpiredExceptions =
|
||||
includeExpiredExceptionsString !== undefined
|
||||
? includeExpiredExceptionsString === 'true'
|
||||
: true;
|
||||
const exportContent = await exceptionListsClient.exportExceptionListAndItems({
|
||||
id,
|
||||
includeExpiredExceptions,
|
||||
listId,
|
||||
namespaceType,
|
||||
});
|
||||
|
||||
if (exportContent == null) {
|
||||
if (exportContent == null) {
|
||||
return siemResponse.error({
|
||||
body: `exception list with list_id: ${listId} or id: ${id} does not exist`,
|
||||
statusCode: 400,
|
||||
});
|
||||
}
|
||||
|
||||
return response.ok({
|
||||
body: `${exportContent.exportData}${JSON.stringify(exportContent.exportDetails)}\n`,
|
||||
headers: {
|
||||
'Content-Disposition': `attachment; filename="${listId}"`,
|
||||
'Content-Type': 'application/ndjson',
|
||||
},
|
||||
});
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: `exception list with list_id: ${listId} or id: ${id} does not exist`,
|
||||
statusCode: 400,
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
|
||||
return response.ok({
|
||||
body: `${exportContent.exportData}${JSON.stringify(exportContent.exportDetails)}\n`,
|
||||
headers: {
|
||||
'Content-Disposition': `attachment; filename="${listId}"`,
|
||||
'Content-Type': 'application/ndjson',
|
||||
},
|
||||
});
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
};
|
||||
|
|
|
@ -19,62 +19,69 @@ import {
|
|||
import { buildRouteValidation, buildSiemResponse, getExceptionListClient } from './utils';
|
||||
|
||||
export const findEndpointListItemRoute = (router: ListsPluginRouter): void => {
|
||||
router.get(
|
||||
{
|
||||
router.versioned
|
||||
.get({
|
||||
access: 'public',
|
||||
options: {
|
||||
tags: ['access:lists-read'],
|
||||
},
|
||||
path: `${ENDPOINT_LIST_ITEM_URL}/_find`,
|
||||
validate: {
|
||||
query: buildRouteValidation<
|
||||
typeof findEndpointListItemRequestQuery,
|
||||
FindEndpointListItemRequestQueryDecoded
|
||||
>(findEndpointListItemRequestQuery),
|
||||
})
|
||||
.addVersion(
|
||||
{
|
||||
validate: {
|
||||
request: {
|
||||
query: buildRouteValidation<
|
||||
typeof findEndpointListItemRequestQuery,
|
||||
FindEndpointListItemRequestQueryDecoded
|
||||
>(findEndpointListItemRequestQuery),
|
||||
},
|
||||
},
|
||||
version: '2023-10-31',
|
||||
},
|
||||
},
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const exceptionLists = await getExceptionListClient(context);
|
||||
const {
|
||||
filter,
|
||||
page,
|
||||
per_page: perPage,
|
||||
sort_field: sortField,
|
||||
sort_order: sortOrder,
|
||||
} = request.query;
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const exceptionLists = await getExceptionListClient(context);
|
||||
const {
|
||||
filter,
|
||||
page,
|
||||
per_page: perPage,
|
||||
sort_field: sortField,
|
||||
sort_order: sortOrder,
|
||||
} = request.query;
|
||||
|
||||
const exceptionListItems = await exceptionLists.findEndpointListItem({
|
||||
filter,
|
||||
page,
|
||||
perPage,
|
||||
pit: undefined,
|
||||
searchAfter: undefined,
|
||||
sortField,
|
||||
sortOrder,
|
||||
});
|
||||
if (exceptionListItems == null) {
|
||||
// Although I have this line of code here, this is an incredibly rare thing to have
|
||||
// happen as the findEndpointListItem tries to auto-create the endpoint list if
|
||||
// does not exist.
|
||||
const exceptionListItems = await exceptionLists.findEndpointListItem({
|
||||
filter,
|
||||
page,
|
||||
perPage,
|
||||
pit: undefined,
|
||||
searchAfter: undefined,
|
||||
sortField,
|
||||
sortOrder,
|
||||
});
|
||||
if (exceptionListItems == null) {
|
||||
// Although I have this line of code here, this is an incredibly rare thing to have
|
||||
// happen as the findEndpointListItem tries to auto-create the endpoint list if
|
||||
// does not exist.
|
||||
return siemResponse.error({
|
||||
body: `list id: "${ENDPOINT_LIST_ID}" does not exist`,
|
||||
statusCode: 404,
|
||||
});
|
||||
}
|
||||
const [validated, errors] = validate(exceptionListItems, findEndpointListItemResponse);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
}
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: `list id: "${ENDPOINT_LIST_ID}" does not exist`,
|
||||
statusCode: 404,
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
const [validated, errors] = validate(exceptionListItems, findEndpointListItemResponse);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
}
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
};
|
||||
|
|
|
@ -19,77 +19,84 @@ import {
|
|||
import { buildRouteValidation, buildSiemResponse, getExceptionListClient } from './utils';
|
||||
|
||||
export const findExceptionListItemRoute = (router: ListsPluginRouter): void => {
|
||||
router.get(
|
||||
{
|
||||
router.versioned
|
||||
.get({
|
||||
access: 'public',
|
||||
options: {
|
||||
tags: ['access:lists-read'],
|
||||
},
|
||||
path: `${EXCEPTION_LIST_ITEM_URL}/_find`,
|
||||
validate: {
|
||||
query: buildRouteValidation<
|
||||
typeof findExceptionListItemRequestQuery,
|
||||
FindExceptionListItemRequestQueryDecoded
|
||||
>(findExceptionListItemRequestQuery),
|
||||
})
|
||||
.addVersion(
|
||||
{
|
||||
validate: {
|
||||
request: {
|
||||
query: buildRouteValidation<
|
||||
typeof findExceptionListItemRequestQuery,
|
||||
FindExceptionListItemRequestQueryDecoded
|
||||
>(findExceptionListItemRequestQuery),
|
||||
},
|
||||
},
|
||||
version: '2023-10-31',
|
||||
},
|
||||
},
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const exceptionLists = await getExceptionListClient(context);
|
||||
const {
|
||||
filter,
|
||||
list_id: listId,
|
||||
namespace_type: namespaceType,
|
||||
page,
|
||||
per_page: perPage,
|
||||
search,
|
||||
sort_field: sortField,
|
||||
sort_order: sortOrder,
|
||||
} = request.query;
|
||||
|
||||
if (listId.length !== namespaceType.length) {
|
||||
return siemResponse.error({
|
||||
body: `list_id and namespace_id need to have the same comma separated number of values. Expected list_id length: ${listId.length} to equal namespace_type length: ${namespaceType.length}`,
|
||||
statusCode: 400,
|
||||
});
|
||||
} else if (listId.length !== filter.length && filter.length !== 0) {
|
||||
return siemResponse.error({
|
||||
body: `list_id and filter need to have the same comma separated number of values. Expected list_id length: ${listId.length} to equal filter length: ${filter.length}`,
|
||||
statusCode: 400,
|
||||
});
|
||||
} else {
|
||||
const exceptionListItems = await exceptionLists.findExceptionListsItem({
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const exceptionLists = await getExceptionListClient(context);
|
||||
const {
|
||||
filter,
|
||||
listId,
|
||||
namespaceType,
|
||||
list_id: listId,
|
||||
namespace_type: namespaceType,
|
||||
page,
|
||||
perPage,
|
||||
pit: undefined,
|
||||
per_page: perPage,
|
||||
search,
|
||||
searchAfter: undefined,
|
||||
sortField,
|
||||
sortOrder,
|
||||
});
|
||||
if (exceptionListItems == null) {
|
||||
sort_field: sortField,
|
||||
sort_order: sortOrder,
|
||||
} = request.query;
|
||||
|
||||
if (listId.length !== namespaceType.length) {
|
||||
return siemResponse.error({
|
||||
body: `exception list id: "${listId}" does not exist`,
|
||||
statusCode: 404,
|
||||
body: `list_id and namespace_id need to have the same comma separated number of values. Expected list_id length: ${listId.length} to equal namespace_type length: ${namespaceType.length}`,
|
||||
statusCode: 400,
|
||||
});
|
||||
} else if (listId.length !== filter.length && filter.length !== 0) {
|
||||
return siemResponse.error({
|
||||
body: `list_id and filter need to have the same comma separated number of values. Expected list_id length: ${listId.length} to equal filter length: ${filter.length}`,
|
||||
statusCode: 400,
|
||||
});
|
||||
}
|
||||
const [validated, errors] = validate(exceptionListItems, findExceptionListItemResponse);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
const exceptionListItems = await exceptionLists.findExceptionListsItem({
|
||||
filter,
|
||||
listId,
|
||||
namespaceType,
|
||||
page,
|
||||
perPage,
|
||||
pit: undefined,
|
||||
search,
|
||||
searchAfter: undefined,
|
||||
sortField,
|
||||
sortOrder,
|
||||
});
|
||||
if (exceptionListItems == null) {
|
||||
return siemResponse.error({
|
||||
body: `exception list id: "${listId}" does not exist`,
|
||||
statusCode: 404,
|
||||
});
|
||||
}
|
||||
const [validated, errors] = validate(exceptionListItems, findExceptionListItemResponse);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
};
|
||||
|
|
|
@ -19,54 +19,61 @@ import {
|
|||
import { buildRouteValidation, buildSiemResponse, getExceptionListClient } from './utils';
|
||||
|
||||
export const findExceptionListRoute = (router: ListsPluginRouter): void => {
|
||||
router.get(
|
||||
{
|
||||
router.versioned
|
||||
.get({
|
||||
access: 'public',
|
||||
options: {
|
||||
tags: ['access:lists-read'],
|
||||
},
|
||||
path: `${EXCEPTION_LIST_URL}/_find`,
|
||||
validate: {
|
||||
query: buildRouteValidation<
|
||||
typeof findExceptionListRequestQuery,
|
||||
FindExceptionListRequestQueryDecoded
|
||||
>(findExceptionListRequestQuery),
|
||||
})
|
||||
.addVersion(
|
||||
{
|
||||
validate: {
|
||||
request: {
|
||||
query: buildRouteValidation<
|
||||
typeof findExceptionListRequestQuery,
|
||||
FindExceptionListRequestQueryDecoded
|
||||
>(findExceptionListRequestQuery),
|
||||
},
|
||||
},
|
||||
version: '2023-10-31',
|
||||
},
|
||||
},
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const exceptionLists = await getExceptionListClient(context);
|
||||
const {
|
||||
filter,
|
||||
page,
|
||||
namespace_type: namespaceType,
|
||||
per_page: perPage,
|
||||
sort_field: sortField,
|
||||
sort_order: sortOrder,
|
||||
} = request.query;
|
||||
const exceptionListItems = await exceptionLists.findExceptionList({
|
||||
filter,
|
||||
namespaceType,
|
||||
page,
|
||||
perPage,
|
||||
pit: undefined,
|
||||
searchAfter: undefined,
|
||||
sortField,
|
||||
sortOrder,
|
||||
});
|
||||
const [validated, errors] = validate(exceptionListItems, findExceptionListResponse);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const exceptionLists = await getExceptionListClient(context);
|
||||
const {
|
||||
filter,
|
||||
page,
|
||||
namespace_type: namespaceType,
|
||||
per_page: perPage,
|
||||
sort_field: sortField,
|
||||
sort_order: sortOrder,
|
||||
} = request.query;
|
||||
const exceptionListItems = await exceptionLists.findExceptionList({
|
||||
filter,
|
||||
namespaceType,
|
||||
page,
|
||||
perPage,
|
||||
pit: undefined,
|
||||
searchAfter: undefined,
|
||||
sortField,
|
||||
sortOrder,
|
||||
});
|
||||
const [validated, errors] = validate(exceptionListItems, findExceptionListResponse);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
}
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
};
|
||||
|
|
|
@ -28,8 +28,9 @@ import { buildRouteValidation, buildSiemResponse, getExceptionListClient } from
|
|||
* choice to overwrite any matching lists
|
||||
*/
|
||||
export const importExceptionsRoute = (router: ListsPluginRouter, config: ConfigType): void => {
|
||||
router.post(
|
||||
{
|
||||
router.versioned
|
||||
.post({
|
||||
access: 'public',
|
||||
options: {
|
||||
body: {
|
||||
maxBytes: config.maxImportPayloadBytes,
|
||||
|
@ -38,49 +39,55 @@ export const importExceptionsRoute = (router: ListsPluginRouter, config: ConfigT
|
|||
tags: ['access:lists-all'],
|
||||
},
|
||||
path: `${EXCEPTION_LIST_URL}/_import`,
|
||||
validate: {
|
||||
body: schema.any(), // validation on file object is accomplished later in the handler.
|
||||
query: buildRouteValidation<
|
||||
typeof importExceptionsRequestQuery,
|
||||
ImportExceptionsRequestQueryDecoded
|
||||
>(importExceptionsRequestQuery),
|
||||
})
|
||||
.addVersion(
|
||||
{
|
||||
validate: {
|
||||
request: {
|
||||
body: schema.any(), // validation on file object is accomplished later in the handler.
|
||||
query: buildRouteValidation<
|
||||
typeof importExceptionsRequestQuery,
|
||||
ImportExceptionsRequestQueryDecoded
|
||||
>(importExceptionsRequestQuery),
|
||||
},
|
||||
},
|
||||
version: '2023-10-31',
|
||||
},
|
||||
},
|
||||
async (context, request, response) => {
|
||||
const exceptionListsClient = await getExceptionListClient(context);
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
async (context, request, response) => {
|
||||
const exceptionListsClient = await getExceptionListClient(context);
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
|
||||
try {
|
||||
const { filename } = request.body.file.hapi;
|
||||
const fileExtension = extname(filename).toLowerCase();
|
||||
if (fileExtension !== '.ndjson') {
|
||||
try {
|
||||
const { filename } = request.body.file.hapi;
|
||||
const fileExtension = extname(filename).toLowerCase();
|
||||
if (fileExtension !== '.ndjson') {
|
||||
return siemResponse.error({
|
||||
body: `Invalid file extension ${fileExtension}`,
|
||||
statusCode: 400,
|
||||
});
|
||||
}
|
||||
|
||||
const importsSummary = await exceptionListsClient.importExceptionListAndItems({
|
||||
exceptionsToImport: request.body.file,
|
||||
generateNewListId: request.query.as_new_list,
|
||||
maxExceptionsImportSize: config.maxExceptionsImportSize,
|
||||
overwrite: request.query.overwrite,
|
||||
});
|
||||
|
||||
const [validated, errors] = validate(importsSummary, importExceptionsResponse);
|
||||
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
}
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: `Invalid file extension ${fileExtension}`,
|
||||
statusCode: 400,
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
|
||||
const importsSummary = await exceptionListsClient.importExceptionListAndItems({
|
||||
exceptionsToImport: request.body.file,
|
||||
generateNewListId: request.query.as_new_list,
|
||||
maxExceptionsImportSize: config.maxExceptionsImportSize,
|
||||
overwrite: request.query.overwrite,
|
||||
});
|
||||
|
||||
const [validated, errors] = validate(importsSummary, importExceptionsResponse);
|
||||
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
}
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
};
|
||||
|
|
|
@ -19,79 +19,86 @@ import { getExceptionFilterRequest } from '../../../common/api';
|
|||
import { buildRouteValidation, buildSiemResponse } from '../utils';
|
||||
|
||||
export const getExceptionFilterRoute = (router: ListsPluginRouter): void => {
|
||||
router.post(
|
||||
{
|
||||
router.versioned
|
||||
.post({
|
||||
access: 'internal',
|
||||
options: {
|
||||
tags: ['access:securitySolution'],
|
||||
},
|
||||
path: INTERNAL_EXCEPTION_FILTER,
|
||||
validate: {
|
||||
body: buildRouteValidation(getExceptionFilterRequest),
|
||||
})
|
||||
.addVersion(
|
||||
{
|
||||
validate: {
|
||||
request: {
|
||||
body: buildRouteValidation(getExceptionFilterRequest),
|
||||
},
|
||||
},
|
||||
version: '1',
|
||||
},
|
||||
},
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const ctx = await context.resolve(['lists']);
|
||||
const listClient = ctx.lists?.getListClient();
|
||||
if (!listClient) {
|
||||
return siemResponse.error({ body: 'Cannot retrieve list client', statusCode: 500 });
|
||||
}
|
||||
const exceptionListClient = ctx.lists?.getExceptionListClient();
|
||||
const exceptionItems: Array<ExceptionListItemSchema | CreateExceptionListItemSchema> = [];
|
||||
const {
|
||||
type,
|
||||
alias = null,
|
||||
exclude_exceptions: excludeExceptions = true,
|
||||
chunk_size: chunkSize = 10,
|
||||
} = request.body;
|
||||
if (type === 'exception_list_ids') {
|
||||
const listIds = request.body.exception_list_ids.map(
|
||||
({ exception_list_id: listId }) => listId
|
||||
);
|
||||
const namespaceTypes = request.body.exception_list_ids.map(
|
||||
({ namespace_type: namespaceType }) => namespaceType
|
||||
);
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const ctx = await context.resolve(['lists']);
|
||||
const listClient = ctx.lists?.getListClient();
|
||||
if (!listClient) {
|
||||
return siemResponse.error({ body: 'Cannot retrieve list client', statusCode: 500 });
|
||||
}
|
||||
const exceptionListClient = ctx.lists?.getExceptionListClient();
|
||||
const exceptionItems: Array<ExceptionListItemSchema | CreateExceptionListItemSchema> = [];
|
||||
const {
|
||||
type,
|
||||
alias = null,
|
||||
exclude_exceptions: excludeExceptions = true,
|
||||
chunk_size: chunkSize = 10,
|
||||
} = request.body;
|
||||
if (type === 'exception_list_ids') {
|
||||
const listIds = request.body.exception_list_ids.map(
|
||||
({ exception_list_id: listId }) => listId
|
||||
);
|
||||
const namespaceTypes = request.body.exception_list_ids.map(
|
||||
({ namespace_type: namespaceType }) => namespaceType
|
||||
);
|
||||
|
||||
// Stream the results from the Point In Time (PIT) finder into this array
|
||||
let items: ExceptionListItemSchema[] = [];
|
||||
const executeFunctionOnStream = (responseBody: FoundExceptionListItemSchema): void => {
|
||||
items = [...items, ...responseBody.data];
|
||||
};
|
||||
// Stream the results from the Point In Time (PIT) finder into this array
|
||||
let items: ExceptionListItemSchema[] = [];
|
||||
const executeFunctionOnStream = (responseBody: FoundExceptionListItemSchema): void => {
|
||||
items = [...items, ...responseBody.data];
|
||||
};
|
||||
|
||||
await exceptionListClient?.findExceptionListsItemPointInTimeFinder({
|
||||
executeFunctionOnStream,
|
||||
filter: [],
|
||||
listId: listIds,
|
||||
maxSize: undefined, // NOTE: This is unbounded when it is "undefined"
|
||||
namespaceType: namespaceTypes,
|
||||
perPage: 1_000, // See https://github.com/elastic/kibana/issues/93770 for choice of 1k
|
||||
sortField: undefined,
|
||||
sortOrder: undefined,
|
||||
await exceptionListClient?.findExceptionListsItemPointInTimeFinder({
|
||||
executeFunctionOnStream,
|
||||
filter: [],
|
||||
listId: listIds,
|
||||
maxSize: undefined, // NOTE: This is unbounded when it is "undefined"
|
||||
namespaceType: namespaceTypes,
|
||||
perPage: 1_000, // See https://github.com/elastic/kibana/issues/93770 for choice of 1k
|
||||
sortField: undefined,
|
||||
sortOrder: undefined,
|
||||
});
|
||||
exceptionItems.push(...items);
|
||||
} else {
|
||||
const { exceptions } = request.body;
|
||||
exceptionItems.push(...exceptions);
|
||||
}
|
||||
|
||||
const { filter } = await buildExceptionFilter({
|
||||
alias,
|
||||
chunkSize,
|
||||
excludeExceptions,
|
||||
listClient,
|
||||
lists: exceptionItems,
|
||||
startedAt: new Date(),
|
||||
});
|
||||
|
||||
return response.ok({ body: { filter } ?? {} });
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
exceptionItems.push(...items);
|
||||
} else {
|
||||
const { exceptions } = request.body;
|
||||
exceptionItems.push(...exceptions);
|
||||
}
|
||||
|
||||
const { filter } = await buildExceptionFilter({
|
||||
alias,
|
||||
chunkSize,
|
||||
excludeExceptions,
|
||||
listClient,
|
||||
lists: exceptionItems,
|
||||
startedAt: new Date(),
|
||||
});
|
||||
|
||||
return response.ok({ body: { filter } ?? {} });
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
};
|
||||
|
|
|
@ -17,8 +17,9 @@ import type { ListsPluginRouter } from '../../types';
|
|||
import { buildRouteValidation, buildSiemResponse } from '../utils';
|
||||
|
||||
export const internalCreateExceptionListRoute = (router: ListsPluginRouter): void => {
|
||||
router.post(
|
||||
{
|
||||
router.versioned
|
||||
.post({
|
||||
access: 'internal',
|
||||
options: {
|
||||
// Access control is set to `read` on purpose, as this route is internal and meant to
|
||||
// ensure we have lists created (if not already) for Endpoint artifacts in order to support
|
||||
|
@ -26,26 +27,32 @@ export const internalCreateExceptionListRoute = (router: ListsPluginRouter): voi
|
|||
tags: ['access:lists-read'],
|
||||
},
|
||||
path: INTERNAL_EXCEPTIONS_LIST_ENSURE_CREATED_URL,
|
||||
validate: {
|
||||
body: buildRouteValidation<
|
||||
typeof internalCreateExceptionListSchema,
|
||||
InternalCreateExceptionListSchemaDecoded
|
||||
>(internalCreateExceptionListSchema),
|
||||
})
|
||||
.addVersion(
|
||||
{
|
||||
validate: {
|
||||
request: {
|
||||
body: buildRouteValidation<
|
||||
typeof internalCreateExceptionListSchema,
|
||||
InternalCreateExceptionListSchemaDecoded
|
||||
>(internalCreateExceptionListSchema),
|
||||
},
|
||||
},
|
||||
version: '1',
|
||||
},
|
||||
},
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
return await createExceptionListHandler(context, request, response, siemResponse, {
|
||||
ignoreExisting: true,
|
||||
});
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
return await createExceptionListHandler(context, request, response, siemResponse, {
|
||||
ignoreExisting: true,
|
||||
});
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
};
|
||||
|
|
|
@ -20,141 +20,152 @@ import { findListsBySizeRequestQuery, findListsBySizeResponse } from '../../../c
|
|||
import { buildRouteValidation, buildSiemResponse, getListClient } from '../utils';
|
||||
|
||||
export const findListsBySizeRoute = (router: ListsPluginRouter): void => {
|
||||
router.get(
|
||||
{
|
||||
router.versioned
|
||||
.get({
|
||||
access: 'internal',
|
||||
options: {
|
||||
tags: ['access:lists-read'],
|
||||
},
|
||||
path: INTERNAL_FIND_LISTS_BY_SIZE,
|
||||
validate: {
|
||||
query: buildRouteValidation(findListsBySizeRequestQuery),
|
||||
})
|
||||
.addVersion(
|
||||
{
|
||||
validate: {
|
||||
request: {
|
||||
query: buildRouteValidation(findListsBySizeRequestQuery),
|
||||
},
|
||||
},
|
||||
version: '1',
|
||||
},
|
||||
},
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const listClient = await getListClient(context);
|
||||
const {
|
||||
cursor,
|
||||
filter: filterOrUndefined,
|
||||
page: pageOrUndefined,
|
||||
per_page: perPageOrUndefined,
|
||||
sort_field: sortField,
|
||||
sort_order: sortOrder,
|
||||
} = request.query;
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const listClient = await getListClient(context);
|
||||
const {
|
||||
cursor,
|
||||
filter: filterOrUndefined,
|
||||
page: pageOrUndefined,
|
||||
per_page: perPageOrUndefined,
|
||||
sort_field: sortField,
|
||||
sort_order: sortOrder,
|
||||
} = request.query;
|
||||
|
||||
const page = pageOrUndefined ?? 1;
|
||||
const perPage = perPageOrUndefined ?? 20;
|
||||
const filter = filterOrUndefined ?? '';
|
||||
const {
|
||||
isValid,
|
||||
errorMessage,
|
||||
cursor: [currentIndexPosition, searchAfter],
|
||||
} = decodeCursor({
|
||||
cursor,
|
||||
page,
|
||||
perPage,
|
||||
sortField,
|
||||
});
|
||||
if (!isValid) {
|
||||
return siemResponse.error({
|
||||
body: errorMessage,
|
||||
statusCode: 400,
|
||||
});
|
||||
} else {
|
||||
const valueLists = await listClient.findList({
|
||||
currentIndexPosition,
|
||||
filter,
|
||||
const page = pageOrUndefined ?? 1;
|
||||
const perPage = perPageOrUndefined ?? 20;
|
||||
const filter = filterOrUndefined ?? '';
|
||||
const {
|
||||
isValid,
|
||||
errorMessage,
|
||||
cursor: [currentIndexPosition, searchAfter],
|
||||
} = decodeCursor({
|
||||
cursor,
|
||||
page,
|
||||
perPage,
|
||||
runtimeMappings: undefined,
|
||||
searchAfter,
|
||||
sortField,
|
||||
sortOrder,
|
||||
});
|
||||
if (!isValid) {
|
||||
return siemResponse.error({
|
||||
body: errorMessage,
|
||||
statusCode: 400,
|
||||
});
|
||||
} else {
|
||||
const valueLists = await listClient.findList({
|
||||
currentIndexPosition,
|
||||
filter,
|
||||
page,
|
||||
perPage,
|
||||
runtimeMappings: undefined,
|
||||
searchAfter,
|
||||
sortField,
|
||||
sortOrder,
|
||||
});
|
||||
|
||||
const listBooleans: boolean[] = [];
|
||||
const listBooleans: boolean[] = [];
|
||||
|
||||
const chunks = chunk(valueLists.data, 10);
|
||||
for (const listChunk of chunks) {
|
||||
const booleans = await Promise.all(
|
||||
listChunk.map(async (valueList) => {
|
||||
// Currently the only list types we support for exceptions
|
||||
if (
|
||||
valueList.type !== 'ip_range' &&
|
||||
valueList.type !== 'ip' &&
|
||||
valueList.type !== 'keyword'
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
const chunks = chunk(valueLists.data, 10);
|
||||
for (const listChunk of chunks) {
|
||||
const booleans = await Promise.all(
|
||||
listChunk.map(async (valueList) => {
|
||||
// Currently the only list types we support for exceptions
|
||||
if (
|
||||
valueList.type !== 'ip_range' &&
|
||||
valueList.type !== 'ip' &&
|
||||
valueList.type !== 'keyword'
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const list = await listClient.findListItem({
|
||||
currentIndexPosition: 0,
|
||||
filter: '',
|
||||
listId: valueList.id,
|
||||
page: 0,
|
||||
perPage: 0,
|
||||
runtimeMappings: undefined,
|
||||
searchAfter: [],
|
||||
sortField: undefined,
|
||||
sortOrder: undefined,
|
||||
});
|
||||
|
||||
if (
|
||||
valueList.type === 'ip_range' &&
|
||||
list &&
|
||||
list.total < MAXIMUM_SMALL_VALUE_LIST_SIZE
|
||||
) {
|
||||
const rangeList = await listClient.findListItem({
|
||||
const list = await listClient.findListItem({
|
||||
currentIndexPosition: 0,
|
||||
filter: 'is_cidr: false',
|
||||
filter: '',
|
||||
listId: valueList.id,
|
||||
page: 0,
|
||||
perPage: 0,
|
||||
runtimeMappings: {
|
||||
is_cidr: {
|
||||
script: `
|
||||
runtimeMappings: undefined,
|
||||
searchAfter: [],
|
||||
sortField: undefined,
|
||||
sortOrder: undefined,
|
||||
});
|
||||
|
||||
if (
|
||||
valueList.type === 'ip_range' &&
|
||||
list &&
|
||||
list.total < MAXIMUM_SMALL_VALUE_LIST_SIZE
|
||||
) {
|
||||
const rangeList = await listClient.findListItem({
|
||||
currentIndexPosition: 0,
|
||||
filter: 'is_cidr: false',
|
||||
listId: valueList.id,
|
||||
page: 0,
|
||||
perPage: 0,
|
||||
runtimeMappings: {
|
||||
is_cidr: {
|
||||
script: `
|
||||
if (params._source["ip_range"] instanceof String) {
|
||||
emit(true);
|
||||
} else {
|
||||
emit(false);
|
||||
}
|
||||
`,
|
||||
type: 'boolean',
|
||||
type: 'boolean',
|
||||
},
|
||||
},
|
||||
},
|
||||
searchAfter: [],
|
||||
sortField: undefined,
|
||||
sortOrder: undefined,
|
||||
});
|
||||
searchAfter: [],
|
||||
sortField: undefined,
|
||||
sortOrder: undefined,
|
||||
});
|
||||
|
||||
return rangeList && rangeList.total < MAXIMUM_SMALL_IP_RANGE_VALUE_LIST_DASH_SIZE
|
||||
? true
|
||||
: false;
|
||||
}
|
||||
return list && list.total < MAXIMUM_SMALL_VALUE_LIST_SIZE ? true : false;
|
||||
})
|
||||
return rangeList &&
|
||||
rangeList.total < MAXIMUM_SMALL_IP_RANGE_VALUE_LIST_DASH_SIZE
|
||||
? true
|
||||
: false;
|
||||
}
|
||||
return list && list.total < MAXIMUM_SMALL_VALUE_LIST_SIZE ? true : false;
|
||||
})
|
||||
);
|
||||
listBooleans.push(...booleans);
|
||||
}
|
||||
|
||||
const smallLists = valueLists.data.filter((valueList, index) => listBooleans[index]);
|
||||
const largeLists = valueLists.data.filter((valueList, index) => !listBooleans[index]);
|
||||
|
||||
const [validated, errors] = validate(
|
||||
{ largeLists, smallLists },
|
||||
findListsBySizeResponse
|
||||
);
|
||||
listBooleans.push(...booleans);
|
||||
}
|
||||
|
||||
const smallLists = valueLists.data.filter((valueList, index) => listBooleans[index]);
|
||||
const largeLists = valueLists.data.filter((valueList, index) => !listBooleans[index]);
|
||||
|
||||
const [validated, errors] = validate({ largeLists, smallLists }, findListsBySizeResponse);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
};
|
||||
|
|
|
@ -19,71 +19,78 @@ import { buildRouteValidation, buildSiemResponse } from '../utils';
|
|||
import { getListClient } from '..';
|
||||
|
||||
export const createListRoute = (router: ListsPluginRouter): void => {
|
||||
router.post(
|
||||
{
|
||||
router.versioned
|
||||
.post({
|
||||
access: 'public',
|
||||
options: {
|
||||
tags: ['access:lists-all'],
|
||||
},
|
||||
path: LIST_URL,
|
||||
validate: {
|
||||
body: buildRouteValidation<typeof createListRequest, CreateListRequestDecoded>(
|
||||
createListRequest
|
||||
),
|
||||
})
|
||||
.addVersion(
|
||||
{
|
||||
validate: {
|
||||
request: {
|
||||
body: buildRouteValidation<typeof createListRequest, CreateListRequestDecoded>(
|
||||
createListRequest
|
||||
),
|
||||
},
|
||||
},
|
||||
version: '2023-10-31',
|
||||
},
|
||||
},
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const { name, description, deserializer, id, serializer, type, meta, version } =
|
||||
request.body;
|
||||
const lists = await getListClient(context);
|
||||
const dataStreamExists = await lists.getListDataStreamExists();
|
||||
const indexExists = await lists.getListIndexExists();
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const { name, description, deserializer, id, serializer, type, meta, version } =
|
||||
request.body;
|
||||
const lists = await getListClient(context);
|
||||
const dataStreamExists = await lists.getListDataStreamExists();
|
||||
const indexExists = await lists.getListIndexExists();
|
||||
|
||||
if (!dataStreamExists && !indexExists) {
|
||||
return siemResponse.error({
|
||||
body: `To create a list, the data stream must exist first. Data stream "${lists.getListName()}" does not exist`,
|
||||
statusCode: 400,
|
||||
});
|
||||
} else {
|
||||
// needs to be migrated to data stream
|
||||
if (!dataStreamExists && indexExists) {
|
||||
await lists.migrateListIndexToDataStream();
|
||||
}
|
||||
if (id != null) {
|
||||
const list = await lists.getList({ id });
|
||||
if (list != null) {
|
||||
return siemResponse.error({
|
||||
body: `list id: "${id}" already exists`,
|
||||
statusCode: 409,
|
||||
});
|
||||
if (!dataStreamExists && !indexExists) {
|
||||
return siemResponse.error({
|
||||
body: `To create a list, the data stream must exist first. Data stream "${lists.getListName()}" does not exist`,
|
||||
statusCode: 400,
|
||||
});
|
||||
} else {
|
||||
// needs to be migrated to data stream
|
||||
if (!dataStreamExists && indexExists) {
|
||||
await lists.migrateListIndexToDataStream();
|
||||
}
|
||||
if (id != null) {
|
||||
const list = await lists.getList({ id });
|
||||
if (list != null) {
|
||||
return siemResponse.error({
|
||||
body: `list id: "${id}" already exists`,
|
||||
statusCode: 409,
|
||||
});
|
||||
}
|
||||
}
|
||||
const list = await lists.createList({
|
||||
description,
|
||||
deserializer,
|
||||
id,
|
||||
immutable: false,
|
||||
meta,
|
||||
name,
|
||||
serializer,
|
||||
type,
|
||||
version,
|
||||
});
|
||||
const [validated, errors] = validate(list, createListResponse);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
}
|
||||
}
|
||||
const list = await lists.createList({
|
||||
description,
|
||||
deserializer,
|
||||
id,
|
||||
immutable: false,
|
||||
meta,
|
||||
name,
|
||||
serializer,
|
||||
type,
|
||||
version,
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
const [validated, errors] = validate(list, createListResponse);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
};
|
||||
|
|
|
@ -26,112 +26,122 @@ import { buildRouteValidation, buildSiemResponse } from '../utils';
|
|||
import { getExceptionListClient, getListClient } from '..';
|
||||
|
||||
export const deleteListRoute = (router: ListsPluginRouter): void => {
|
||||
router.delete(
|
||||
{
|
||||
router.versioned
|
||||
.delete({
|
||||
access: 'public',
|
||||
options: {
|
||||
tags: ['access:lists-all'],
|
||||
},
|
||||
path: LIST_URL,
|
||||
validate: {
|
||||
query: buildRouteValidation(deleteListRequestQuery),
|
||||
})
|
||||
.addVersion(
|
||||
{
|
||||
validate: {
|
||||
request: {
|
||||
query: buildRouteValidation(deleteListRequestQuery),
|
||||
},
|
||||
},
|
||||
version: '2023-10-31',
|
||||
},
|
||||
},
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const lists = await getListClient(context);
|
||||
const exceptionLists = await getExceptionListClient(context);
|
||||
const { id, deleteReferences, ignoreReferences } = request.query;
|
||||
let deleteExceptionItemResponses;
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const lists = await getListClient(context);
|
||||
const exceptionLists = await getExceptionListClient(context);
|
||||
const { id, deleteReferences, ignoreReferences } = request.query;
|
||||
let deleteExceptionItemResponses;
|
||||
|
||||
// ignoreReferences=true maintains pre-7.11 behavior of deleting value list without performing any additional checks
|
||||
if (!ignoreReferences) {
|
||||
// Stream the results from the Point In Time (PIT) finder into this array
|
||||
let referencedExceptionListItems: ExceptionListItemSchema[] = [];
|
||||
const executeFunctionOnStream = (foundResponse: FoundExceptionListItemSchema): void => {
|
||||
referencedExceptionListItems = [...referencedExceptionListItems, ...foundResponse.data];
|
||||
};
|
||||
// ignoreReferences=true maintains pre-7.11 behavior of deleting value list without performing any additional checks
|
||||
if (!ignoreReferences) {
|
||||
// Stream the results from the Point In Time (PIT) finder into this array
|
||||
let referencedExceptionListItems: ExceptionListItemSchema[] = [];
|
||||
const executeFunctionOnStream = (foundResponse: FoundExceptionListItemSchema): void => {
|
||||
referencedExceptionListItems = [
|
||||
...referencedExceptionListItems,
|
||||
...foundResponse.data,
|
||||
];
|
||||
};
|
||||
|
||||
await exceptionLists.findValueListExceptionListItemsPointInTimeFinder({
|
||||
executeFunctionOnStream,
|
||||
maxSize: undefined, // NOTE: This is unbounded when it is "undefined"
|
||||
perPage: 1_000, // See https://github.com/elastic/kibana/issues/93770 for choice of 1k
|
||||
sortField: undefined,
|
||||
sortOrder: undefined,
|
||||
valueListId: id,
|
||||
});
|
||||
if (referencedExceptionListItems.length) {
|
||||
// deleteReferences=false to perform dry run and identify referenced exception lists/items
|
||||
if (deleteReferences) {
|
||||
// Delete referenced exception list items
|
||||
// TODO: Create deleteListItems to delete in batch
|
||||
deleteExceptionItemResponses = await Promise.all(
|
||||
referencedExceptionListItems.map(async (listItem) => {
|
||||
// Ensure only the single entry is deleted as there could be a separate value list referenced that is okay to keep // TODO: Add API to delete single entry
|
||||
const remainingEntries = listItem.entries.filter(
|
||||
(e) => e.type === 'list' && e.list.id !== id
|
||||
);
|
||||
if (remainingEntries.length === 0) {
|
||||
// All entries reference value list specified in request, delete entire exception list item
|
||||
return deleteExceptionListItem(exceptionLists, listItem);
|
||||
} else {
|
||||
// Contains more entries than just value list specified in request , patch (doesn't exist yet :) exception list item to remove entry
|
||||
return updateExceptionListItems(exceptionLists, listItem, remainingEntries);
|
||||
}
|
||||
})
|
||||
);
|
||||
} else {
|
||||
const referencedExceptionLists = await getReferencedExceptionLists(
|
||||
exceptionLists,
|
||||
referencedExceptionListItems
|
||||
);
|
||||
const refError = `Value list '${id}' is referenced in existing exception list(s)`;
|
||||
const references = referencedExceptionListItems.map((item) => ({
|
||||
exception_item: item,
|
||||
exception_list: referencedExceptionLists.find((l) => l.list_id === item.list_id),
|
||||
}));
|
||||
await exceptionLists.findValueListExceptionListItemsPointInTimeFinder({
|
||||
executeFunctionOnStream,
|
||||
maxSize: undefined, // NOTE: This is unbounded when it is "undefined"
|
||||
perPage: 1_000, // See https://github.com/elastic/kibana/issues/93770 for choice of 1k
|
||||
sortField: undefined,
|
||||
sortOrder: undefined,
|
||||
valueListId: id,
|
||||
});
|
||||
if (referencedExceptionListItems.length) {
|
||||
// deleteReferences=false to perform dry run and identify referenced exception lists/items
|
||||
if (deleteReferences) {
|
||||
// Delete referenced exception list items
|
||||
// TODO: Create deleteListItems to delete in batch
|
||||
deleteExceptionItemResponses = await Promise.all(
|
||||
referencedExceptionListItems.map(async (listItem) => {
|
||||
// Ensure only the single entry is deleted as there could be a separate value list referenced that is okay to keep // TODO: Add API to delete single entry
|
||||
const remainingEntries = listItem.entries.filter(
|
||||
(e) => e.type === 'list' && e.list.id !== id
|
||||
);
|
||||
if (remainingEntries.length === 0) {
|
||||
// All entries reference value list specified in request, delete entire exception list item
|
||||
return deleteExceptionListItem(exceptionLists, listItem);
|
||||
} else {
|
||||
// Contains more entries than just value list specified in request , patch (doesn't exist yet :) exception list item to remove entry
|
||||
return updateExceptionListItems(exceptionLists, listItem, remainingEntries);
|
||||
}
|
||||
})
|
||||
);
|
||||
} else {
|
||||
const referencedExceptionLists = await getReferencedExceptionLists(
|
||||
exceptionLists,
|
||||
referencedExceptionListItems
|
||||
);
|
||||
const refError = `Value list '${id}' is referenced in existing exception list(s)`;
|
||||
const references = referencedExceptionListItems.map((item) => ({
|
||||
exception_item: item,
|
||||
exception_list: referencedExceptionLists.find((l) => l.list_id === item.list_id),
|
||||
}));
|
||||
|
||||
return siemResponse.error({
|
||||
body: {
|
||||
error: {
|
||||
message: refError,
|
||||
references,
|
||||
value_list_id: id,
|
||||
return siemResponse.error({
|
||||
body: {
|
||||
error: {
|
||||
message: refError,
|
||||
references,
|
||||
value_list_id: id,
|
||||
},
|
||||
},
|
||||
statusCode: 409,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const deleted = await lists.deleteList({ id });
|
||||
if (deleted == null) {
|
||||
return siemResponse.error({
|
||||
body: `list id: "${id}" was not found`,
|
||||
statusCode: 404,
|
||||
});
|
||||
} else {
|
||||
const [validated, errors] = validate(deleted, deleteListResponse);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
} else {
|
||||
return response.ok({
|
||||
body: validated ?? {
|
||||
deleteItemResponses: deleteExceptionItemResponses,
|
||||
},
|
||||
statusCode: 409,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const deleted = await lists.deleteList({ id });
|
||||
if (deleted == null) {
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: `list id: "${id}" was not found`,
|
||||
statusCode: 404,
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
} else {
|
||||
const [validated, errors] = validate(deleted, deleteListResponse);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
} else {
|
||||
return response.ok({
|
||||
body: validated ?? {
|
||||
deleteItemResponses: deleteExceptionItemResponses,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -18,8 +18,9 @@ import { createStreamFromBuffer } from '../utils/create_stream_from_buffer';
|
|||
import { getListClient } from '..';
|
||||
|
||||
export const importListItemRoute = (router: ListsPluginRouter, config: ConfigType): void => {
|
||||
router.post(
|
||||
{
|
||||
router.versioned
|
||||
.post({
|
||||
access: 'public',
|
||||
options: {
|
||||
body: {
|
||||
accepts: ['multipart/form-data'],
|
||||
|
@ -32,103 +33,109 @@ export const importListItemRoute = (router: ListsPluginRouter, config: ConfigTyp
|
|||
},
|
||||
},
|
||||
path: `${LIST_ITEM_URL}/_import`,
|
||||
validate: {
|
||||
body: schema.buffer(),
|
||||
query: buildRouteValidation(importListItemRequestQuery),
|
||||
})
|
||||
.addVersion(
|
||||
{
|
||||
validate: {
|
||||
request: {
|
||||
body: schema.buffer(),
|
||||
query: buildRouteValidation(importListItemRequestQuery),
|
||||
},
|
||||
},
|
||||
version: '2023-10-31',
|
||||
},
|
||||
},
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const stream = createStreamFromBuffer(request.body);
|
||||
const { deserializer, list_id: listId, serializer, type } = request.query;
|
||||
const lists = await getListClient(context);
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const stream = createStreamFromBuffer(request.body);
|
||||
const { deserializer, list_id: listId, serializer, type } = request.query;
|
||||
const lists = await getListClient(context);
|
||||
|
||||
const listDataExists = await lists.getListDataStreamExists();
|
||||
if (!listDataExists) {
|
||||
const listIndexExists = await lists.getListIndexExists();
|
||||
if (!listIndexExists) {
|
||||
return siemResponse.error({
|
||||
body: `To import a list item, the data steam must exist first. Data stream "${lists.getListName()}" does not exist`,
|
||||
statusCode: 400,
|
||||
});
|
||||
const listDataExists = await lists.getListDataStreamExists();
|
||||
if (!listDataExists) {
|
||||
const listIndexExists = await lists.getListIndexExists();
|
||||
if (!listIndexExists) {
|
||||
return siemResponse.error({
|
||||
body: `To import a list item, the data steam must exist first. Data stream "${lists.getListName()}" does not exist`,
|
||||
statusCode: 400,
|
||||
});
|
||||
}
|
||||
// otherwise migration is needed
|
||||
await lists.migrateListIndexToDataStream();
|
||||
}
|
||||
// otherwise migration is needed
|
||||
await lists.migrateListIndexToDataStream();
|
||||
}
|
||||
|
||||
const listItemDataExists = await lists.getListItemDataStreamExists();
|
||||
if (!listItemDataExists) {
|
||||
const listItemIndexExists = await lists.getListItemIndexExists();
|
||||
if (!listItemIndexExists) {
|
||||
return siemResponse.error({
|
||||
body: `To import a list item, the data steam must exist first. Data stream "${lists.getListItemName()}" does not exist`,
|
||||
statusCode: 400,
|
||||
});
|
||||
const listItemDataExists = await lists.getListItemDataStreamExists();
|
||||
if (!listItemDataExists) {
|
||||
const listItemIndexExists = await lists.getListItemIndexExists();
|
||||
if (!listItemIndexExists) {
|
||||
return siemResponse.error({
|
||||
body: `To import a list item, the data steam must exist first. Data stream "${lists.getListItemName()}" does not exist`,
|
||||
statusCode: 400,
|
||||
});
|
||||
}
|
||||
// otherwise migration is needed
|
||||
await lists.migrateListItemIndexToDataStream();
|
||||
}
|
||||
// otherwise migration is needed
|
||||
await lists.migrateListItemIndexToDataStream();
|
||||
}
|
||||
|
||||
if (listId != null) {
|
||||
const list = await lists.getList({ id: listId });
|
||||
if (list == null) {
|
||||
return siemResponse.error({
|
||||
body: `list id: "${listId}" does not exist`,
|
||||
statusCode: 409,
|
||||
if (listId != null) {
|
||||
const list = await lists.getList({ id: listId });
|
||||
if (list == null) {
|
||||
return siemResponse.error({
|
||||
body: `list id: "${listId}" does not exist`,
|
||||
statusCode: 409,
|
||||
});
|
||||
}
|
||||
await lists.importListItemsToStream({
|
||||
deserializer: list.deserializer,
|
||||
listId,
|
||||
meta: undefined,
|
||||
serializer: list.serializer,
|
||||
stream,
|
||||
type: list.type,
|
||||
version: 1,
|
||||
});
|
||||
}
|
||||
await lists.importListItemsToStream({
|
||||
deserializer: list.deserializer,
|
||||
listId,
|
||||
meta: undefined,
|
||||
serializer: list.serializer,
|
||||
stream,
|
||||
type: list.type,
|
||||
version: 1,
|
||||
});
|
||||
|
||||
const [validated, errors] = validate(list, importListItemResponse);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
const [validated, errors] = validate(list, importListItemResponse);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
}
|
||||
} else if (type != null) {
|
||||
const importedList = await lists.importListItemsToStream({
|
||||
deserializer,
|
||||
listId: undefined,
|
||||
meta: undefined,
|
||||
serializer,
|
||||
stream,
|
||||
type,
|
||||
version: 1,
|
||||
});
|
||||
if (importedList == null) {
|
||||
return siemResponse.error({
|
||||
body: 'Unable to parse a valid fileName during import',
|
||||
statusCode: 400,
|
||||
});
|
||||
}
|
||||
const [validated, errors] = validate(importedList, importListItemResponse);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
}
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
}
|
||||
} else if (type != null) {
|
||||
const importedList = await lists.importListItemsToStream({
|
||||
deserializer,
|
||||
listId: undefined,
|
||||
meta: undefined,
|
||||
serializer,
|
||||
stream,
|
||||
type,
|
||||
version: 1,
|
||||
});
|
||||
if (importedList == null) {
|
||||
return siemResponse.error({
|
||||
body: 'Unable to parse a valid fileName during import',
|
||||
body: 'Either type or list_id need to be defined in the query',
|
||||
statusCode: 400,
|
||||
});
|
||||
}
|
||||
const [validated, errors] = validate(importedList, importListItemResponse);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
}
|
||||
} else {
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: 'Either type or list_id need to be defined in the query',
|
||||
statusCode: 400,
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
};
|
||||
|
|
|
@ -15,52 +15,59 @@ import { buildRouteValidation, buildSiemResponse } from '../utils';
|
|||
import { getListClient } from '..';
|
||||
|
||||
export const patchListRoute = (router: ListsPluginRouter): void => {
|
||||
router.patch(
|
||||
{
|
||||
router.versioned
|
||||
.patch({
|
||||
access: 'public',
|
||||
options: {
|
||||
tags: ['access:lists-all'],
|
||||
},
|
||||
path: LIST_URL,
|
||||
validate: {
|
||||
body: buildRouteValidation(patchListRequest),
|
||||
})
|
||||
.addVersion(
|
||||
{
|
||||
validate: {
|
||||
request: {
|
||||
body: buildRouteValidation(patchListRequest),
|
||||
},
|
||||
},
|
||||
version: '2023-10-31',
|
||||
},
|
||||
},
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const { name, description, id, meta, _version, version } = request.body;
|
||||
const lists = await getListClient(context);
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const { name, description, id, meta, _version, version } = request.body;
|
||||
const lists = await getListClient(context);
|
||||
|
||||
const dataStreamExists = await lists.getListDataStreamExists();
|
||||
// needs to be migrated to data stream if index exists
|
||||
if (!dataStreamExists) {
|
||||
const indexExists = await lists.getListIndexExists();
|
||||
if (indexExists) {
|
||||
await lists.migrateListIndexToDataStream();
|
||||
const dataStreamExists = await lists.getListDataStreamExists();
|
||||
// needs to be migrated to data stream if index exists
|
||||
if (!dataStreamExists) {
|
||||
const indexExists = await lists.getListIndexExists();
|
||||
if (indexExists) {
|
||||
await lists.migrateListIndexToDataStream();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const list = await lists.patchList({ _version, description, id, meta, name, version });
|
||||
if (list == null) {
|
||||
return siemResponse.error({
|
||||
body: `list id: "${id}" not found`,
|
||||
statusCode: 404,
|
||||
});
|
||||
} else {
|
||||
const [validated, errors] = validate(list, patchListResponse);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
const list = await lists.patchList({ _version, description, id, meta, name, version });
|
||||
if (list == null) {
|
||||
return siemResponse.error({
|
||||
body: `list id: "${id}" not found`,
|
||||
statusCode: 404,
|
||||
});
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
const [validated, errors] = validate(list, patchListResponse);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
};
|
||||
|
|
|
@ -15,42 +15,49 @@ import { buildRouteValidation, buildSiemResponse } from '../utils';
|
|||
import { getListClient } from '..';
|
||||
|
||||
export const readListRoute = (router: ListsPluginRouter): void => {
|
||||
router.get(
|
||||
{
|
||||
router.versioned
|
||||
.get({
|
||||
access: 'public',
|
||||
options: {
|
||||
tags: ['access:lists-read'],
|
||||
},
|
||||
path: LIST_URL,
|
||||
validate: {
|
||||
query: buildRouteValidation(readListRequestQuery),
|
||||
})
|
||||
.addVersion(
|
||||
{
|
||||
validate: {
|
||||
request: {
|
||||
query: buildRouteValidation(readListRequestQuery),
|
||||
},
|
||||
},
|
||||
version: '2023-10-31',
|
||||
},
|
||||
},
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const { id } = request.query;
|
||||
const lists = await getListClient(context);
|
||||
const list = await lists.getList({ id });
|
||||
if (list == null) {
|
||||
return siemResponse.error({
|
||||
body: `list id: "${id}" does not exist`,
|
||||
statusCode: 404,
|
||||
});
|
||||
} else {
|
||||
const [validated, errors] = validate(list, readListResponse);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const { id } = request.query;
|
||||
const lists = await getListClient(context);
|
||||
const list = await lists.getList({ id });
|
||||
if (list == null) {
|
||||
return siemResponse.error({
|
||||
body: `list id: "${id}" does not exist`,
|
||||
statusCode: 404,
|
||||
});
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
const [validated, errors] = validate(list, readListResponse);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
};
|
||||
|
|
|
@ -15,52 +15,59 @@ import { buildRouteValidation, buildSiemResponse } from '../utils';
|
|||
import { getListClient } from '..';
|
||||
|
||||
export const updateListRoute = (router: ListsPluginRouter): void => {
|
||||
router.put(
|
||||
{
|
||||
router.versioned
|
||||
.put({
|
||||
access: 'public',
|
||||
options: {
|
||||
tags: ['access:lists-all'],
|
||||
},
|
||||
path: LIST_URL,
|
||||
validate: {
|
||||
body: buildRouteValidation(updateListRequest),
|
||||
})
|
||||
.addVersion(
|
||||
{
|
||||
validate: {
|
||||
request: {
|
||||
body: buildRouteValidation(updateListRequest),
|
||||
},
|
||||
},
|
||||
version: '2023-10-31',
|
||||
},
|
||||
},
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const { name, description, id, meta, _version, version } = request.body;
|
||||
const lists = await getListClient(context);
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const { name, description, id, meta, _version, version } = request.body;
|
||||
const lists = await getListClient(context);
|
||||
|
||||
const dataStreamExists = await lists.getListDataStreamExists();
|
||||
// needs to be migrated to data stream if index exists
|
||||
if (!dataStreamExists) {
|
||||
const indexExists = await lists.getListIndexExists();
|
||||
if (indexExists) {
|
||||
await lists.migrateListIndexToDataStream();
|
||||
const dataStreamExists = await lists.getListDataStreamExists();
|
||||
// needs to be migrated to data stream if index exists
|
||||
if (!dataStreamExists) {
|
||||
const indexExists = await lists.getListIndexExists();
|
||||
if (indexExists) {
|
||||
await lists.migrateListIndexToDataStream();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const list = await lists.updateList({ _version, description, id, meta, name, version });
|
||||
if (list == null) {
|
||||
return siemResponse.error({
|
||||
body: `list id: "${id}" not found`,
|
||||
statusCode: 404,
|
||||
});
|
||||
} else {
|
||||
const [validated, errors] = validate(list, updateListResponse);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
const list = await lists.updateList({ _version, description, id, meta, name, version });
|
||||
if (list == null) {
|
||||
return siemResponse.error({
|
||||
body: `list id: "${id}" not found`,
|
||||
statusCode: 404,
|
||||
});
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
const [validated, errors] = validate(list, updateListResponse);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
};
|
||||
|
|
|
@ -15,15 +15,15 @@ import { buildSiemResponse } from '../utils';
|
|||
import { getListClient } from '..';
|
||||
|
||||
export const createListIndexRoute = (router: ListsPluginRouter): void => {
|
||||
router.post(
|
||||
{
|
||||
router.versioned
|
||||
.post({
|
||||
access: 'public',
|
||||
options: {
|
||||
tags: ['access:lists-all'],
|
||||
},
|
||||
path: LIST_INDEX,
|
||||
validate: false,
|
||||
},
|
||||
async (context, _, response) => {
|
||||
})
|
||||
.addVersion({ validate: false, version: '2023-10-31' }, async (context, _, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
|
||||
try {
|
||||
|
@ -77,6 +77,5 @@ export const createListIndexRoute = (router: ListsPluginRouter): void => {
|
|||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
};
|
||||
|
|
|
@ -32,67 +32,72 @@ import { getListClient } from '..';
|
|||
* And ensuring they're all gone
|
||||
*/
|
||||
export const deleteListIndexRoute = (router: ListsPluginRouter): void => {
|
||||
router.delete(
|
||||
{
|
||||
router.versioned
|
||||
.delete({
|
||||
access: 'public',
|
||||
options: {
|
||||
tags: ['access:lists-all'],
|
||||
},
|
||||
path: LIST_INDEX,
|
||||
validate: false,
|
||||
},
|
||||
async (context, _, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const lists = await getListClient(context);
|
||||
const listIndexExists = await lists.getListIndexExists();
|
||||
const listItemIndexExists = await lists.getListItemIndexExists();
|
||||
})
|
||||
.addVersion(
|
||||
{
|
||||
validate: false,
|
||||
version: '2023-10-31',
|
||||
},
|
||||
async (context, _, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const lists = await getListClient(context);
|
||||
const listIndexExists = await lists.getListIndexExists();
|
||||
const listItemIndexExists = await lists.getListItemIndexExists();
|
||||
|
||||
const listDataStreamExists = await lists.getListDataStreamExists();
|
||||
const listItemDataStreamExists = await lists.getListItemDataStreamExists();
|
||||
const listDataStreamExists = await lists.getListDataStreamExists();
|
||||
const listItemDataStreamExists = await lists.getListItemDataStreamExists();
|
||||
|
||||
// return early if no data stream or indices exist
|
||||
if (
|
||||
!listDataStreamExists &&
|
||||
!listItemDataStreamExists &&
|
||||
!listIndexExists &&
|
||||
!listItemIndexExists
|
||||
) {
|
||||
// return early if no data stream or indices exist
|
||||
if (
|
||||
!listDataStreamExists &&
|
||||
!listItemDataStreamExists &&
|
||||
!listIndexExists &&
|
||||
!listItemIndexExists
|
||||
) {
|
||||
return siemResponse.error({
|
||||
body: `index and data stream: "${lists.getListName()}" and "${lists.getListItemName()}" does not exist`,
|
||||
statusCode: 404,
|
||||
});
|
||||
}
|
||||
|
||||
// ensure data streams deleted if exist
|
||||
await deleteDataStreams(lists, listDataStreamExists, listItemDataStreamExists);
|
||||
|
||||
// we need to call this section only if any of these indices exist
|
||||
// to delete indices, ILM policies and legacy templates
|
||||
// ILM policies and legacy templates do not exist on serverless,
|
||||
// so by checking if any of index exists we ensure it is stateful
|
||||
if (listIndexExists || listItemIndexExists) {
|
||||
await deleteIndices(lists, listIndexExists, listItemIndexExists);
|
||||
await lists.deleteLegacyListTemplateIfExists();
|
||||
await lists.deleteLegacyListItemTemplateIfExists();
|
||||
}
|
||||
|
||||
await deleteIndexTemplates(lists);
|
||||
|
||||
const [validated, errors] = validate({ acknowledged: true }, deleteListIndexResponse);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
}
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: `index and data stream: "${lists.getListName()}" and "${lists.getListItemName()}" does not exist`,
|
||||
statusCode: 404,
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
|
||||
// ensure data streams deleted if exist
|
||||
await deleteDataStreams(lists, listDataStreamExists, listItemDataStreamExists);
|
||||
|
||||
// we need to call this section only if any of these indices exist
|
||||
// to delete indices, ILM policies and legacy templates
|
||||
// ILM policies and legacy templates do not exist on serverless,
|
||||
// so by checking if any of index exists we ensure it is stateful
|
||||
if (listIndexExists || listItemIndexExists) {
|
||||
await deleteIndices(lists, listIndexExists, listItemIndexExists);
|
||||
await lists.deleteLegacyListTemplateIfExists();
|
||||
await lists.deleteLegacyListItemTemplateIfExists();
|
||||
}
|
||||
|
||||
await deleteIndexTemplates(lists);
|
||||
|
||||
const [validated, errors] = validate({ acknowledged: true }, deleteListIndexResponse);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
}
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -16,48 +16,55 @@ import { buildRouteValidation, buildSiemResponse } from '../utils';
|
|||
import { getListClient } from '..';
|
||||
|
||||
export const exportListItemRoute = (router: ListsPluginRouter): void => {
|
||||
router.post(
|
||||
{
|
||||
router.versioned
|
||||
.post({
|
||||
access: 'public',
|
||||
options: {
|
||||
tags: ['access:lists-read'],
|
||||
},
|
||||
path: `${LIST_ITEM_URL}/_export`,
|
||||
validate: {
|
||||
query: buildRouteValidation(exportListItemRequestQuery),
|
||||
})
|
||||
.addVersion(
|
||||
{
|
||||
validate: {
|
||||
request: {
|
||||
query: buildRouteValidation(exportListItemRequestQuery),
|
||||
},
|
||||
},
|
||||
version: '2023-10-31',
|
||||
},
|
||||
},
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const { list_id: listId } = request.query;
|
||||
const lists = await getListClient(context);
|
||||
const list = await lists.getList({ id: listId });
|
||||
if (list == null) {
|
||||
return siemResponse.error({
|
||||
body: `list_id: ${listId} does not exist`,
|
||||
statusCode: 400,
|
||||
});
|
||||
} else {
|
||||
// TODO: Allow the API to override the name of the file to export
|
||||
const fileName = list.name;
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const { list_id: listId } = request.query;
|
||||
const lists = await getListClient(context);
|
||||
const list = await lists.getList({ id: listId });
|
||||
if (list == null) {
|
||||
return siemResponse.error({
|
||||
body: `list_id: ${listId} does not exist`,
|
||||
statusCode: 400,
|
||||
});
|
||||
} else {
|
||||
// TODO: Allow the API to override the name of the file to export
|
||||
const fileName = list.name;
|
||||
|
||||
const stream = new Stream.PassThrough();
|
||||
lists.exportListItemsToStream({ listId, stream, stringToAppend: '\n' });
|
||||
return response.ok({
|
||||
body: stream,
|
||||
headers: {
|
||||
'Content-Disposition': `attachment; filename="${fileName}"`,
|
||||
'Content-Type': 'application/ndjson',
|
||||
},
|
||||
const stream = new Stream.PassThrough();
|
||||
lists.exportListItemsToStream({ listId, stream, stringToAppend: '\n' });
|
||||
return response.ok({
|
||||
body: stream,
|
||||
headers: {
|
||||
'Content-Disposition': `attachment; filename="${fileName}"`,
|
||||
'Content-Type': 'application/ndjson',
|
||||
},
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
};
|
||||
|
|
|
@ -15,72 +15,79 @@ import { findListRequestQuery, findListResponse } from '../../../common/api';
|
|||
import { buildRouteValidation, buildSiemResponse, getListClient } from '../utils';
|
||||
|
||||
export const findListRoute = (router: ListsPluginRouter): void => {
|
||||
router.get(
|
||||
{
|
||||
router.versioned
|
||||
.get({
|
||||
access: 'public',
|
||||
options: {
|
||||
tags: ['access:lists-read'],
|
||||
},
|
||||
path: `${LIST_URL}/_find`,
|
||||
validate: {
|
||||
query: buildRouteValidation(findListRequestQuery),
|
||||
})
|
||||
.addVersion(
|
||||
{
|
||||
validate: {
|
||||
request: {
|
||||
query: buildRouteValidation(findListRequestQuery),
|
||||
},
|
||||
},
|
||||
version: '2023-10-31',
|
||||
},
|
||||
},
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const lists = await getListClient(context);
|
||||
const {
|
||||
cursor,
|
||||
filter: filterOrUndefined,
|
||||
page: pageOrUndefined,
|
||||
per_page: perPageOrUndefined,
|
||||
sort_field: sortField,
|
||||
sort_order: sortOrder,
|
||||
} = request.query;
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const lists = await getListClient(context);
|
||||
const {
|
||||
cursor,
|
||||
filter: filterOrUndefined,
|
||||
page: pageOrUndefined,
|
||||
per_page: perPageOrUndefined,
|
||||
sort_field: sortField,
|
||||
sort_order: sortOrder,
|
||||
} = request.query;
|
||||
|
||||
const page = pageOrUndefined ?? 1;
|
||||
const perPage = perPageOrUndefined ?? 20;
|
||||
const filter = filterOrUndefined ?? '';
|
||||
const {
|
||||
isValid,
|
||||
errorMessage,
|
||||
cursor: [currentIndexPosition, searchAfter],
|
||||
} = decodeCursor({
|
||||
cursor,
|
||||
page,
|
||||
perPage,
|
||||
sortField,
|
||||
});
|
||||
if (!isValid) {
|
||||
return siemResponse.error({
|
||||
body: errorMessage,
|
||||
statusCode: 400,
|
||||
});
|
||||
} else {
|
||||
const exceptionList = await lists.findList({
|
||||
currentIndexPosition,
|
||||
filter,
|
||||
const page = pageOrUndefined ?? 1;
|
||||
const perPage = perPageOrUndefined ?? 20;
|
||||
const filter = filterOrUndefined ?? '';
|
||||
const {
|
||||
isValid,
|
||||
errorMessage,
|
||||
cursor: [currentIndexPosition, searchAfter],
|
||||
} = decodeCursor({
|
||||
cursor,
|
||||
page,
|
||||
perPage,
|
||||
runtimeMappings: undefined,
|
||||
searchAfter,
|
||||
sortField,
|
||||
sortOrder,
|
||||
});
|
||||
const [validated, errors] = validate(exceptionList, findListResponse);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
if (!isValid) {
|
||||
return siemResponse.error({
|
||||
body: errorMessage,
|
||||
statusCode: 400,
|
||||
});
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
const exceptionList = await lists.findList({
|
||||
currentIndexPosition,
|
||||
filter,
|
||||
page,
|
||||
perPage,
|
||||
runtimeMappings: undefined,
|
||||
searchAfter,
|
||||
sortField,
|
||||
sortOrder,
|
||||
});
|
||||
const [validated, errors] = validate(exceptionList, findListResponse);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
};
|
||||
|
|
|
@ -15,55 +15,60 @@ import { buildSiemResponse } from '../utils';
|
|||
import { getListClient } from '..';
|
||||
|
||||
export const readListIndexRoute = (router: ListsPluginRouter): void => {
|
||||
router.get(
|
||||
{
|
||||
router.versioned
|
||||
.get({
|
||||
access: 'public',
|
||||
options: {
|
||||
tags: ['access:lists-read'],
|
||||
},
|
||||
path: LIST_INDEX,
|
||||
validate: false,
|
||||
},
|
||||
async (context, _, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
})
|
||||
.addVersion(
|
||||
{
|
||||
validate: false,
|
||||
version: '2023-10-31',
|
||||
},
|
||||
async (context, _, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
|
||||
try {
|
||||
const lists = await getListClient(context);
|
||||
const listDataStreamExists = await lists.getListDataStreamExists();
|
||||
const listItemDataStreamExists = await lists.getListItemDataStreamExists();
|
||||
try {
|
||||
const lists = await getListClient(context);
|
||||
const listDataStreamExists = await lists.getListDataStreamExists();
|
||||
const listItemDataStreamExists = await lists.getListItemDataStreamExists();
|
||||
|
||||
if (listDataStreamExists && listItemDataStreamExists) {
|
||||
const [validated, errors] = validate(
|
||||
{ list_index: listDataStreamExists, list_item_index: listItemDataStreamExists },
|
||||
readListIndexResponse
|
||||
);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
if (listDataStreamExists && listItemDataStreamExists) {
|
||||
const [validated, errors] = validate(
|
||||
{ list_index: listDataStreamExists, list_item_index: listItemDataStreamExists },
|
||||
readListIndexResponse
|
||||
);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
}
|
||||
} else if (!listDataStreamExists && listItemDataStreamExists) {
|
||||
return siemResponse.error({
|
||||
body: `data stream ${lists.getListName()} does not exist`,
|
||||
statusCode: 404,
|
||||
});
|
||||
} else if (!listItemDataStreamExists && listDataStreamExists) {
|
||||
return siemResponse.error({
|
||||
body: `data stream ${lists.getListItemName()} does not exist`,
|
||||
statusCode: 404,
|
||||
});
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
return siemResponse.error({
|
||||
body: `data stream ${lists.getListName()} and data stream ${lists.getListItemName()} does not exist`,
|
||||
statusCode: 404,
|
||||
});
|
||||
}
|
||||
} else if (!listDataStreamExists && listItemDataStreamExists) {
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: `data stream ${lists.getListName()} does not exist`,
|
||||
statusCode: 404,
|
||||
});
|
||||
} else if (!listItemDataStreamExists && listDataStreamExists) {
|
||||
return siemResponse.error({
|
||||
body: `data stream ${lists.getListItemName()} does not exist`,
|
||||
statusCode: 404,
|
||||
});
|
||||
} else {
|
||||
return siemResponse.error({
|
||||
body: `data stream ${lists.getListName()} and data stream ${lists.getListItemName()} does not exist`,
|
||||
statusCode: 404,
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
};
|
||||
|
|
|
@ -15,67 +15,74 @@ import { buildRouteValidation, buildSiemResponse } from '../utils';
|
|||
import { getListClient } from '..';
|
||||
|
||||
export const createListItemRoute = (router: ListsPluginRouter): void => {
|
||||
router.post(
|
||||
{
|
||||
router.versioned
|
||||
.post({
|
||||
access: 'public',
|
||||
options: {
|
||||
tags: ['access:lists-all'],
|
||||
},
|
||||
path: LIST_ITEM_URL,
|
||||
validate: {
|
||||
body: buildRouteValidation(createListItemRequest),
|
||||
})
|
||||
.addVersion(
|
||||
{
|
||||
validate: {
|
||||
request: {
|
||||
body: buildRouteValidation(createListItemRequest),
|
||||
},
|
||||
},
|
||||
version: '2023-10-31',
|
||||
},
|
||||
},
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const { id, list_id: listId, value, meta } = request.body;
|
||||
const lists = await getListClient(context);
|
||||
const list = await lists.getList({ id: listId });
|
||||
if (list == null) {
|
||||
return siemResponse.error({
|
||||
body: `list id: "${listId}" does not exist`,
|
||||
statusCode: 404,
|
||||
});
|
||||
} else {
|
||||
if (id != null) {
|
||||
const listItem = await lists.getListItem({ id });
|
||||
if (listItem != null) {
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const { id, list_id: listId, value, meta } = request.body;
|
||||
const lists = await getListClient(context);
|
||||
const list = await lists.getList({ id: listId });
|
||||
if (list == null) {
|
||||
return siemResponse.error({
|
||||
body: `list id: "${listId}" does not exist`,
|
||||
statusCode: 404,
|
||||
});
|
||||
} else {
|
||||
if (id != null) {
|
||||
const listItem = await lists.getListItem({ id });
|
||||
if (listItem != null) {
|
||||
return siemResponse.error({
|
||||
body: `list item id: "${id}" already exists`,
|
||||
statusCode: 409,
|
||||
});
|
||||
}
|
||||
}
|
||||
const createdListItem = await lists.createListItem({
|
||||
deserializer: list.deserializer,
|
||||
id,
|
||||
listId,
|
||||
meta,
|
||||
serializer: list.serializer,
|
||||
type: list.type,
|
||||
value,
|
||||
});
|
||||
if (createdListItem != null) {
|
||||
const [validated, errors] = validate(createdListItem, createListItemResponse);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
}
|
||||
} else {
|
||||
return siemResponse.error({
|
||||
body: `list item id: "${id}" already exists`,
|
||||
statusCode: 409,
|
||||
body: 'list item invalid',
|
||||
statusCode: 400,
|
||||
});
|
||||
}
|
||||
}
|
||||
const createdListItem = await lists.createListItem({
|
||||
deserializer: list.deserializer,
|
||||
id,
|
||||
listId,
|
||||
meta,
|
||||
serializer: list.serializer,
|
||||
type: list.type,
|
||||
value,
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
if (createdListItem != null) {
|
||||
const [validated, errors] = validate(createdListItem, createListItemResponse);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
}
|
||||
} else {
|
||||
return siemResponse.error({
|
||||
body: 'list item invalid',
|
||||
statusCode: 400,
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
};
|
||||
|
|
|
@ -19,76 +19,83 @@ import { buildRouteValidation, buildSiemResponse } from '../utils';
|
|||
import { getListClient } from '..';
|
||||
|
||||
export const deleteListItemRoute = (router: ListsPluginRouter): void => {
|
||||
router.delete(
|
||||
{
|
||||
router.versioned
|
||||
.delete({
|
||||
access: 'public',
|
||||
options: {
|
||||
tags: ['access:lists-all'],
|
||||
},
|
||||
path: LIST_ITEM_URL,
|
||||
validate: {
|
||||
query: buildRouteValidation(deleteListItemRequestQuery),
|
||||
})
|
||||
.addVersion(
|
||||
{
|
||||
validate: {
|
||||
request: {
|
||||
query: buildRouteValidation(deleteListItemRequestQuery),
|
||||
},
|
||||
},
|
||||
version: '2023-10-31',
|
||||
},
|
||||
},
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const { id, list_id: listId, value } = request.query;
|
||||
const lists = await getListClient(context);
|
||||
if (id != null) {
|
||||
const deleted = await lists.deleteListItem({ id });
|
||||
if (deleted == null) {
|
||||
return siemResponse.error({
|
||||
body: `list item with id: "${id}" not found`,
|
||||
statusCode: 404,
|
||||
});
|
||||
} else {
|
||||
const [validated, errors] = validate(deleted, deleteListItemResponse);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
}
|
||||
}
|
||||
} else if (listId != null && value != null) {
|
||||
const list = await lists.getList({ id: listId });
|
||||
if (list == null) {
|
||||
return siemResponse.error({
|
||||
body: `list_id: "${listId}" does not exist`,
|
||||
statusCode: 404,
|
||||
});
|
||||
} else {
|
||||
const deleted = await lists.deleteListItemByValue({
|
||||
listId,
|
||||
type: list.type,
|
||||
value,
|
||||
});
|
||||
if (deleted == null || deleted.length === 0) {
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const { id, list_id: listId, value } = request.query;
|
||||
const lists = await getListClient(context);
|
||||
if (id != null) {
|
||||
const deleted = await lists.deleteListItem({ id });
|
||||
if (deleted == null) {
|
||||
return siemResponse.error({
|
||||
body: `list_id: "${listId}" with ${value} was not found`,
|
||||
body: `list item with id: "${id}" not found`,
|
||||
statusCode: 404,
|
||||
});
|
||||
} else {
|
||||
const [validated, errors] = validate(deleted, deleteListItemArrayResponse);
|
||||
const [validated, errors] = validate(deleted, deleteListItemResponse);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
}
|
||||
}
|
||||
} else if (listId != null && value != null) {
|
||||
const list = await lists.getList({ id: listId });
|
||||
if (list == null) {
|
||||
return siemResponse.error({
|
||||
body: `list_id: "${listId}" does not exist`,
|
||||
statusCode: 404,
|
||||
});
|
||||
} else {
|
||||
const deleted = await lists.deleteListItemByValue({
|
||||
listId,
|
||||
type: list.type,
|
||||
value,
|
||||
});
|
||||
if (deleted == null || deleted.length === 0) {
|
||||
return siemResponse.error({
|
||||
body: `list_id: "${listId}" with ${value} was not found`,
|
||||
statusCode: 404,
|
||||
});
|
||||
} else {
|
||||
const [validated, errors] = validate(deleted, deleteListItemArrayResponse);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return siemResponse.error({
|
||||
body: 'Either "list_id" or "id" needs to be defined in the request',
|
||||
statusCode: 400,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: 'Either "list_id" or "id" needs to be defined in the request',
|
||||
statusCode: 400,
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
};
|
||||
|
|
|
@ -19,85 +19,92 @@ import {
|
|||
import { buildRouteValidation, buildSiemResponse, getListClient } from '../utils';
|
||||
|
||||
export const findListItemRoute = (router: ListsPluginRouter): void => {
|
||||
router.get(
|
||||
{
|
||||
router.versioned
|
||||
.get({
|
||||
access: 'public',
|
||||
options: {
|
||||
tags: ['access:lists-read'],
|
||||
},
|
||||
path: `${LIST_ITEM_URL}/_find`,
|
||||
validate: {
|
||||
query: buildRouteValidation<
|
||||
typeof findListItemRequestQuery,
|
||||
FindListItemRequestQueryDecoded
|
||||
>(findListItemRequestQuery),
|
||||
})
|
||||
.addVersion(
|
||||
{
|
||||
validate: {
|
||||
request: {
|
||||
query: buildRouteValidation<
|
||||
typeof findListItemRequestQuery,
|
||||
FindListItemRequestQueryDecoded
|
||||
>(findListItemRequestQuery),
|
||||
},
|
||||
},
|
||||
version: '2023-10-31',
|
||||
},
|
||||
},
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const lists = await getListClient(context);
|
||||
const {
|
||||
cursor,
|
||||
filter: filterOrUndefined,
|
||||
list_id: listId,
|
||||
page: pageOrUndefined,
|
||||
per_page: perPageOrUndefined,
|
||||
sort_field: sortField,
|
||||
sort_order: sortOrder,
|
||||
} = request.query;
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const lists = await getListClient(context);
|
||||
const {
|
||||
cursor,
|
||||
filter: filterOrUndefined,
|
||||
list_id: listId,
|
||||
page: pageOrUndefined,
|
||||
per_page: perPageOrUndefined,
|
||||
sort_field: sortField,
|
||||
sort_order: sortOrder,
|
||||
} = request.query;
|
||||
|
||||
const page = pageOrUndefined ?? 1;
|
||||
const perPage = perPageOrUndefined ?? 20;
|
||||
const filter = filterOrUndefined ?? '';
|
||||
const {
|
||||
isValid,
|
||||
errorMessage,
|
||||
cursor: [currentIndexPosition, searchAfter = []],
|
||||
} = decodeCursor({
|
||||
cursor,
|
||||
page,
|
||||
perPage,
|
||||
sortField,
|
||||
});
|
||||
|
||||
if (!isValid) {
|
||||
return siemResponse.error({
|
||||
body: errorMessage,
|
||||
statusCode: 400,
|
||||
});
|
||||
} else {
|
||||
const exceptionList = await lists.findListItem({
|
||||
currentIndexPosition,
|
||||
filter,
|
||||
listId,
|
||||
const page = pageOrUndefined ?? 1;
|
||||
const perPage = perPageOrUndefined ?? 20;
|
||||
const filter = filterOrUndefined ?? '';
|
||||
const {
|
||||
isValid,
|
||||
errorMessage,
|
||||
cursor: [currentIndexPosition, searchAfter = []],
|
||||
} = decodeCursor({
|
||||
cursor,
|
||||
page,
|
||||
perPage,
|
||||
runtimeMappings: undefined,
|
||||
searchAfter,
|
||||
sortField,
|
||||
sortOrder,
|
||||
});
|
||||
if (exceptionList == null) {
|
||||
|
||||
if (!isValid) {
|
||||
return siemResponse.error({
|
||||
body: `list id: "${listId}" does not exist`,
|
||||
statusCode: 404,
|
||||
body: errorMessage,
|
||||
statusCode: 400,
|
||||
});
|
||||
} else {
|
||||
const [validated, errors] = validate(exceptionList, findListItemResponse);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
const exceptionList = await lists.findListItem({
|
||||
currentIndexPosition,
|
||||
filter,
|
||||
listId,
|
||||
page,
|
||||
perPage,
|
||||
runtimeMappings: undefined,
|
||||
searchAfter,
|
||||
sortField,
|
||||
sortOrder,
|
||||
});
|
||||
if (exceptionList == null) {
|
||||
return siemResponse.error({
|
||||
body: `list id: "${listId}" does not exist`,
|
||||
statusCode: 404,
|
||||
});
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
const [validated, errors] = validate(exceptionList, findListItemResponse);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
};
|
||||
|
|
|
@ -15,57 +15,64 @@ import { buildRouteValidation, buildSiemResponse } from '../utils';
|
|||
import { getListClient } from '..';
|
||||
|
||||
export const patchListItemRoute = (router: ListsPluginRouter): void => {
|
||||
router.patch(
|
||||
{
|
||||
router.versioned
|
||||
.patch({
|
||||
access: 'public',
|
||||
options: {
|
||||
tags: ['access:lists-all'],
|
||||
},
|
||||
path: LIST_ITEM_URL,
|
||||
validate: {
|
||||
body: buildRouteValidation(patchListItemRequest),
|
||||
})
|
||||
.addVersion(
|
||||
{
|
||||
validate: {
|
||||
request: {
|
||||
body: buildRouteValidation(patchListItemRequest),
|
||||
},
|
||||
},
|
||||
version: '2023-10-31',
|
||||
},
|
||||
},
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const { value, id, meta, _version } = request.body;
|
||||
const lists = await getListClient(context);
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const { value, id, meta, _version } = request.body;
|
||||
const lists = await getListClient(context);
|
||||
|
||||
const dataStreamExists = await lists.getListItemDataStreamExists();
|
||||
// needs to be migrated to data stream if index exists
|
||||
if (!dataStreamExists) {
|
||||
const indexExists = await lists.getListItemIndexExists();
|
||||
if (indexExists) {
|
||||
await lists.migrateListItemIndexToDataStream();
|
||||
const dataStreamExists = await lists.getListItemDataStreamExists();
|
||||
// needs to be migrated to data stream if index exists
|
||||
if (!dataStreamExists) {
|
||||
const indexExists = await lists.getListItemIndexExists();
|
||||
if (indexExists) {
|
||||
await lists.migrateListItemIndexToDataStream();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const listItem = await lists.patchListItem({
|
||||
_version,
|
||||
id,
|
||||
meta,
|
||||
value,
|
||||
});
|
||||
if (listItem == null) {
|
||||
return siemResponse.error({
|
||||
body: `list item id: "${id}" not found`,
|
||||
statusCode: 404,
|
||||
const listItem = await lists.patchListItem({
|
||||
_version,
|
||||
id,
|
||||
meta,
|
||||
value,
|
||||
});
|
||||
} else {
|
||||
const [validated, errors] = validate(listItem, patchListItemResponse);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
if (listItem == null) {
|
||||
return siemResponse.error({
|
||||
body: `list item id: "${id}" not found`,
|
||||
statusCode: 404,
|
||||
});
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
const [validated, errors] = validate(listItem, patchListItemResponse);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
};
|
||||
|
|
|
@ -19,76 +19,83 @@ import { buildRouteValidation, buildSiemResponse } from '../utils';
|
|||
import { getListClient } from '..';
|
||||
|
||||
export const readListItemRoute = (router: ListsPluginRouter): void => {
|
||||
router.get(
|
||||
{
|
||||
router.versioned
|
||||
.get({
|
||||
access: 'public',
|
||||
options: {
|
||||
tags: ['access:lists-read'],
|
||||
},
|
||||
path: LIST_ITEM_URL,
|
||||
validate: {
|
||||
query: buildRouteValidation(readListItemRequestQuery),
|
||||
})
|
||||
.addVersion(
|
||||
{
|
||||
validate: {
|
||||
request: {
|
||||
query: buildRouteValidation(readListItemRequestQuery),
|
||||
},
|
||||
},
|
||||
version: '2023-10-31',
|
||||
},
|
||||
},
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const { id, list_id: listId, value } = request.query;
|
||||
const lists = await getListClient(context);
|
||||
if (id != null) {
|
||||
const listItem = await lists.getListItem({ id });
|
||||
if (listItem == null) {
|
||||
return siemResponse.error({
|
||||
body: `list item id: "${id}" does not exist`,
|
||||
statusCode: 404,
|
||||
});
|
||||
} else {
|
||||
const [validated, errors] = validate(listItem, readListItemResponse);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
}
|
||||
}
|
||||
} else if (listId != null && value != null) {
|
||||
const list = await lists.getList({ id: listId });
|
||||
if (list == null) {
|
||||
return siemResponse.error({
|
||||
body: `list id: "${listId}" does not exist`,
|
||||
statusCode: 404,
|
||||
});
|
||||
} else {
|
||||
const listItem = await lists.getListItemByValue({
|
||||
listId,
|
||||
type: list.type,
|
||||
value,
|
||||
});
|
||||
if (listItem.length === 0) {
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const { id, list_id: listId, value } = request.query;
|
||||
const lists = await getListClient(context);
|
||||
if (id != null) {
|
||||
const listItem = await lists.getListItem({ id });
|
||||
if (listItem == null) {
|
||||
return siemResponse.error({
|
||||
body: `list_id: "${listId}" item of ${value} does not exist`,
|
||||
body: `list item id: "${id}" does not exist`,
|
||||
statusCode: 404,
|
||||
});
|
||||
} else {
|
||||
const [validated, errors] = validate(listItem, readListItemArrayResponse);
|
||||
const [validated, errors] = validate(listItem, readListItemResponse);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
}
|
||||
}
|
||||
} else if (listId != null && value != null) {
|
||||
const list = await lists.getList({ id: listId });
|
||||
if (list == null) {
|
||||
return siemResponse.error({
|
||||
body: `list id: "${listId}" does not exist`,
|
||||
statusCode: 404,
|
||||
});
|
||||
} else {
|
||||
const listItem = await lists.getListItemByValue({
|
||||
listId,
|
||||
type: list.type,
|
||||
value,
|
||||
});
|
||||
if (listItem.length === 0) {
|
||||
return siemResponse.error({
|
||||
body: `list_id: "${listId}" item of ${value} does not exist`,
|
||||
statusCode: 404,
|
||||
});
|
||||
} else {
|
||||
const [validated, errors] = validate(listItem, readListItemArrayResponse);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return siemResponse.error({
|
||||
body: 'Either "list_id" or "id" needs to be defined in the request',
|
||||
statusCode: 400,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: 'Either "list_id" or "id" needs to be defined in the request',
|
||||
statusCode: 400,
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
};
|
||||
|
|
|
@ -15,57 +15,64 @@ import { buildRouteValidation, buildSiemResponse } from '../utils';
|
|||
import { getListClient } from '..';
|
||||
|
||||
export const updateListItemRoute = (router: ListsPluginRouter): void => {
|
||||
router.put(
|
||||
{
|
||||
router.versioned
|
||||
.put({
|
||||
access: 'public',
|
||||
options: {
|
||||
tags: ['access:lists-all'],
|
||||
},
|
||||
path: LIST_ITEM_URL,
|
||||
validate: {
|
||||
body: buildRouteValidation(updateListItemRequest),
|
||||
})
|
||||
.addVersion(
|
||||
{
|
||||
validate: {
|
||||
request: {
|
||||
body: buildRouteValidation(updateListItemRequest),
|
||||
},
|
||||
},
|
||||
version: '2023-10-31',
|
||||
},
|
||||
},
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const { value, id, meta, _version } = request.body;
|
||||
const lists = await getListClient(context);
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const { value, id, meta, _version } = request.body;
|
||||
const lists = await getListClient(context);
|
||||
|
||||
const dataStreamExists = await lists.getListItemDataStreamExists();
|
||||
// needs to be migrated to data stream if index exists
|
||||
if (!dataStreamExists) {
|
||||
const indexExists = await lists.getListItemIndexExists();
|
||||
if (indexExists) {
|
||||
await lists.migrateListItemIndexToDataStream();
|
||||
const dataStreamExists = await lists.getListItemDataStreamExists();
|
||||
// needs to be migrated to data stream if index exists
|
||||
if (!dataStreamExists) {
|
||||
const indexExists = await lists.getListItemIndexExists();
|
||||
if (indexExists) {
|
||||
await lists.migrateListItemIndexToDataStream();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const listItem = await lists.updateListItem({
|
||||
_version,
|
||||
id,
|
||||
meta,
|
||||
value,
|
||||
});
|
||||
if (listItem == null) {
|
||||
return siemResponse.error({
|
||||
body: `list item id: "${id}" not found`,
|
||||
statusCode: 404,
|
||||
const listItem = await lists.updateListItem({
|
||||
_version,
|
||||
id,
|
||||
meta,
|
||||
value,
|
||||
});
|
||||
} else {
|
||||
const [validated, errors] = validate(listItem, updateListItemResponse);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
if (listItem == null) {
|
||||
return siemResponse.error({
|
||||
body: `list item id: "${id}" not found`,
|
||||
statusCode: 404,
|
||||
});
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
const [validated, errors] = validate(listItem, updateListItemResponse);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
};
|
||||
|
|
|
@ -13,38 +13,46 @@ import type { ListsPluginRouter } from '../../types';
|
|||
import { buildSiemResponse, getListClient } from '../utils';
|
||||
|
||||
export const readPrivilegesRoute = (router: ListsPluginRouter): void => {
|
||||
router.get(
|
||||
{
|
||||
router.versioned
|
||||
.get({
|
||||
access: 'public',
|
||||
options: {
|
||||
tags: ['access:lists-read'],
|
||||
},
|
||||
path: LIST_PRIVILEGES_URL,
|
||||
validate: false,
|
||||
},
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const esClient = (await context.core).elasticsearch.client.asCurrentUser;
|
||||
const lists = await getListClient(context);
|
||||
const clusterPrivilegesLists = await readPrivileges(esClient, lists.getListName());
|
||||
const clusterPrivilegesListItems = await readPrivileges(esClient, lists.getListItemName());
|
||||
const privileges = merge(
|
||||
{
|
||||
listItems: clusterPrivilegesListItems,
|
||||
lists: clusterPrivilegesLists,
|
||||
},
|
||||
{
|
||||
is_authenticated: request.auth.isAuthenticated ?? false,
|
||||
}
|
||||
);
|
||||
return response.ok({ body: privileges });
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
})
|
||||
.addVersion(
|
||||
{
|
||||
validate: false,
|
||||
version: '2023-10-31',
|
||||
},
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const esClient = (await context.core).elasticsearch.client.asCurrentUser;
|
||||
const lists = await getListClient(context);
|
||||
const clusterPrivilegesLists = await readPrivileges(esClient, lists.getListName());
|
||||
const clusterPrivilegesListItems = await readPrivileges(
|
||||
esClient,
|
||||
lists.getListItemName()
|
||||
);
|
||||
const privileges = merge(
|
||||
{
|
||||
listItems: clusterPrivilegesListItems,
|
||||
lists: clusterPrivilegesLists,
|
||||
},
|
||||
{
|
||||
is_authenticated: request.auth.isAuthenticated ?? false,
|
||||
}
|
||||
);
|
||||
return response.ok({ body: privileges });
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
};
|
||||
|
|
|
@ -24,52 +24,59 @@ import {
|
|||
} from './utils';
|
||||
|
||||
export const readEndpointListItemRoute = (router: ListsPluginRouter): void => {
|
||||
router.get(
|
||||
{
|
||||
router.versioned
|
||||
.get({
|
||||
access: 'public',
|
||||
options: {
|
||||
tags: ['access:lists-read'],
|
||||
},
|
||||
path: ENDPOINT_LIST_ITEM_URL,
|
||||
validate: {
|
||||
query: buildRouteValidation<
|
||||
typeof readEndpointListItemRequestQuery,
|
||||
ReadEndpointListItemRequestQueryDecoded
|
||||
>(readEndpointListItemRequestQuery),
|
||||
})
|
||||
.addVersion(
|
||||
{
|
||||
validate: {
|
||||
request: {
|
||||
query: buildRouteValidation<
|
||||
typeof readEndpointListItemRequestQuery,
|
||||
ReadEndpointListItemRequestQueryDecoded
|
||||
>(readEndpointListItemRequestQuery),
|
||||
},
|
||||
},
|
||||
version: '2023-10-31',
|
||||
},
|
||||
},
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const { id, item_id: itemId } = request.query;
|
||||
const exceptionLists = await getExceptionListClient(context);
|
||||
if (id != null || itemId != null) {
|
||||
const exceptionListItem = await exceptionLists.getEndpointListItem({
|
||||
id,
|
||||
itemId,
|
||||
});
|
||||
if (exceptionListItem == null) {
|
||||
return siemResponse.error({
|
||||
body: getErrorMessageExceptionListItem({ id, itemId }),
|
||||
statusCode: 404,
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const { id, item_id: itemId } = request.query;
|
||||
const exceptionLists = await getExceptionListClient(context);
|
||||
if (id != null || itemId != null) {
|
||||
const exceptionListItem = await exceptionLists.getEndpointListItem({
|
||||
id,
|
||||
itemId,
|
||||
});
|
||||
} else {
|
||||
const [validated, errors] = validate(exceptionListItem, readEndpointListItemResponse);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
if (exceptionListItem == null) {
|
||||
return siemResponse.error({
|
||||
body: getErrorMessageExceptionListItem({ id, itemId }),
|
||||
statusCode: 404,
|
||||
});
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
const [validated, errors] = validate(exceptionListItem, readEndpointListItemResponse);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return siemResponse.error({ body: 'id or item_id required', statusCode: 400 });
|
||||
}
|
||||
} else {
|
||||
return siemResponse.error({ body: 'id or item_id required', statusCode: 400 });
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
};
|
||||
|
|
|
@ -24,53 +24,63 @@ import {
|
|||
} from './utils';
|
||||
|
||||
export const readExceptionListItemRoute = (router: ListsPluginRouter): void => {
|
||||
router.get(
|
||||
{
|
||||
router.versioned
|
||||
.get({
|
||||
access: 'public',
|
||||
options: {
|
||||
tags: ['access:lists-read'],
|
||||
},
|
||||
path: EXCEPTION_LIST_ITEM_URL,
|
||||
validate: {
|
||||
query: buildRouteValidation<
|
||||
typeof readExceptionListItemRequestQuery,
|
||||
ReadExceptionListItemRequestQueryDecoded
|
||||
>(readExceptionListItemRequestQuery),
|
||||
})
|
||||
.addVersion(
|
||||
{
|
||||
validate: {
|
||||
request: {
|
||||
query: buildRouteValidation<
|
||||
typeof readExceptionListItemRequestQuery,
|
||||
ReadExceptionListItemRequestQueryDecoded
|
||||
>(readExceptionListItemRequestQuery),
|
||||
},
|
||||
},
|
||||
version: '2023-10-31',
|
||||
},
|
||||
},
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const { id, item_id: itemId, namespace_type: namespaceType } = request.query;
|
||||
const exceptionLists = await getExceptionListClient(context);
|
||||
if (id != null || itemId != null) {
|
||||
const exceptionListItem = await exceptionLists.getExceptionListItem({
|
||||
id,
|
||||
itemId,
|
||||
namespaceType,
|
||||
});
|
||||
if (exceptionListItem == null) {
|
||||
return siemResponse.error({
|
||||
body: getErrorMessageExceptionListItem({ id, itemId }),
|
||||
statusCode: 404,
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const { id, item_id: itemId, namespace_type: namespaceType } = request.query;
|
||||
const exceptionLists = await getExceptionListClient(context);
|
||||
if (id != null || itemId != null) {
|
||||
const exceptionListItem = await exceptionLists.getExceptionListItem({
|
||||
id,
|
||||
itemId,
|
||||
namespaceType,
|
||||
});
|
||||
} else {
|
||||
const [validated, errors] = validate(exceptionListItem, readExceptionListItemResponse);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
if (exceptionListItem == null) {
|
||||
return siemResponse.error({
|
||||
body: getErrorMessageExceptionListItem({ id, itemId }),
|
||||
statusCode: 404,
|
||||
});
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
const [validated, errors] = validate(
|
||||
exceptionListItem,
|
||||
readExceptionListItemResponse
|
||||
);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return siemResponse.error({ body: 'id or item_id required', statusCode: 400 });
|
||||
}
|
||||
} else {
|
||||
return siemResponse.error({ body: 'id or item_id required', statusCode: 400 });
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
};
|
||||
|
|
|
@ -24,53 +24,60 @@ import {
|
|||
} from './utils';
|
||||
|
||||
export const readExceptionListRoute = (router: ListsPluginRouter): void => {
|
||||
router.get(
|
||||
{
|
||||
router.versioned
|
||||
.get({
|
||||
access: 'public',
|
||||
options: {
|
||||
tags: ['access:lists-read'],
|
||||
},
|
||||
path: EXCEPTION_LIST_URL,
|
||||
validate: {
|
||||
query: buildRouteValidation<
|
||||
typeof readExceptionListRequestQuery,
|
||||
ReadExceptionListRequestQueryDecoded
|
||||
>(readExceptionListRequestQuery),
|
||||
})
|
||||
.addVersion(
|
||||
{
|
||||
validate: {
|
||||
request: {
|
||||
query: buildRouteValidation<
|
||||
typeof readExceptionListRequestQuery,
|
||||
ReadExceptionListRequestQueryDecoded
|
||||
>(readExceptionListRequestQuery),
|
||||
},
|
||||
},
|
||||
version: '2023-10-31',
|
||||
},
|
||||
},
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const { id, list_id: listId, namespace_type: namespaceType } = request.query;
|
||||
const exceptionLists = await getExceptionListClient(context);
|
||||
if (id != null || listId != null) {
|
||||
const exceptionList = await exceptionLists.getExceptionList({
|
||||
id,
|
||||
listId,
|
||||
namespaceType,
|
||||
});
|
||||
if (exceptionList == null) {
|
||||
return siemResponse.error({
|
||||
body: getErrorMessageExceptionList({ id, listId }),
|
||||
statusCode: 404,
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const { id, list_id: listId, namespace_type: namespaceType } = request.query;
|
||||
const exceptionLists = await getExceptionListClient(context);
|
||||
if (id != null || listId != null) {
|
||||
const exceptionList = await exceptionLists.getExceptionList({
|
||||
id,
|
||||
listId,
|
||||
namespaceType,
|
||||
});
|
||||
} else {
|
||||
const [validated, errors] = validate(exceptionList, readExceptionListResponse);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
if (exceptionList == null) {
|
||||
return siemResponse.error({
|
||||
body: getErrorMessageExceptionList({ id, listId }),
|
||||
statusCode: 404,
|
||||
});
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
const [validated, errors] = validate(exceptionList, readExceptionListResponse);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return siemResponse.error({ body: 'id or list_id required', statusCode: 400 });
|
||||
}
|
||||
} else {
|
||||
return siemResponse.error({ body: 'id or list_id required', statusCode: 400 });
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
};
|
||||
|
|
|
@ -24,57 +24,64 @@ import {
|
|||
} from './utils';
|
||||
|
||||
export const summaryExceptionListRoute = (router: ListsPluginRouter): void => {
|
||||
router.get(
|
||||
{
|
||||
router.versioned
|
||||
.get({
|
||||
access: 'public',
|
||||
options: {
|
||||
tags: ['access:lists-summary'],
|
||||
},
|
||||
path: `${EXCEPTION_LIST_URL}/summary`,
|
||||
validate: {
|
||||
query: buildRouteValidation<
|
||||
typeof summaryExceptionListRequestQuery,
|
||||
SummaryExceptionListRequestQueryDecoded
|
||||
>(summaryExceptionListRequestQuery),
|
||||
})
|
||||
.addVersion(
|
||||
{
|
||||
validate: {
|
||||
request: {
|
||||
query: buildRouteValidation<
|
||||
typeof summaryExceptionListRequestQuery,
|
||||
SummaryExceptionListRequestQueryDecoded
|
||||
>(summaryExceptionListRequestQuery),
|
||||
},
|
||||
},
|
||||
version: '2023-10-31',
|
||||
},
|
||||
},
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const { id, list_id: listId, namespace_type: namespaceType, filter } = request.query;
|
||||
const exceptionLists = await getExceptionListClient(context);
|
||||
if (id != null || listId != null) {
|
||||
const exceptionListSummary = await exceptionLists.getExceptionListSummary({
|
||||
filter,
|
||||
id,
|
||||
listId,
|
||||
namespaceType,
|
||||
});
|
||||
if (exceptionListSummary == null) {
|
||||
return siemResponse.error({
|
||||
body: getErrorMessageExceptionList({ id, listId }),
|
||||
statusCode: 404,
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const { id, list_id: listId, namespace_type: namespaceType, filter } = request.query;
|
||||
const exceptionLists = await getExceptionListClient(context);
|
||||
if (id != null || listId != null) {
|
||||
const exceptionListSummary = await exceptionLists.getExceptionListSummary({
|
||||
filter,
|
||||
id,
|
||||
listId,
|
||||
namespaceType,
|
||||
});
|
||||
} else {
|
||||
const [validated, errors] = validate(
|
||||
exceptionListSummary,
|
||||
summaryExceptionListResponse
|
||||
);
|
||||
if (errors != null) {
|
||||
return response.ok({ body: exceptionListSummary });
|
||||
if (exceptionListSummary == null) {
|
||||
return siemResponse.error({
|
||||
body: getErrorMessageExceptionList({ id, listId }),
|
||||
statusCode: 404,
|
||||
});
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
const [validated, errors] = validate(
|
||||
exceptionListSummary,
|
||||
summaryExceptionListResponse
|
||||
);
|
||||
if (errors != null) {
|
||||
return response.ok({ body: exceptionListSummary });
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return siemResponse.error({ body: 'id or list_id required', statusCode: 400 });
|
||||
}
|
||||
} else {
|
||||
return siemResponse.error({ body: 'id or list_id required', statusCode: 400 });
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
};
|
||||
|
|
|
@ -21,76 +21,83 @@ import { buildRouteValidation, buildSiemResponse } from './utils';
|
|||
import { getExceptionListClient } from '.';
|
||||
|
||||
export const updateEndpointListItemRoute = (router: ListsPluginRouter): void => {
|
||||
router.put(
|
||||
{
|
||||
router.versioned
|
||||
.put({
|
||||
access: 'public',
|
||||
options: {
|
||||
tags: ['access:lists-all'],
|
||||
},
|
||||
path: ENDPOINT_LIST_ITEM_URL,
|
||||
validate: {
|
||||
body: buildRouteValidation<
|
||||
typeof updateEndpointListItemRequest,
|
||||
UpdateEndpointListItemRequestDecoded
|
||||
>(updateEndpointListItemRequest),
|
||||
})
|
||||
.addVersion(
|
||||
{
|
||||
validate: {
|
||||
request: {
|
||||
body: buildRouteValidation<
|
||||
typeof updateEndpointListItemRequest,
|
||||
UpdateEndpointListItemRequestDecoded
|
||||
>(updateEndpointListItemRequest),
|
||||
},
|
||||
},
|
||||
version: '2023-10-31',
|
||||
},
|
||||
},
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const {
|
||||
description,
|
||||
id,
|
||||
name,
|
||||
os_types: osTypes,
|
||||
meta,
|
||||
type,
|
||||
_version,
|
||||
comments,
|
||||
entries,
|
||||
item_id: itemId,
|
||||
tags,
|
||||
} = request.body;
|
||||
const exceptionLists = await getExceptionListClient(context);
|
||||
const exceptionListItem = await exceptionLists.updateEndpointListItem({
|
||||
_version,
|
||||
comments,
|
||||
description,
|
||||
entries,
|
||||
id,
|
||||
itemId,
|
||||
meta,
|
||||
name,
|
||||
osTypes,
|
||||
tags,
|
||||
type,
|
||||
});
|
||||
if (exceptionListItem == null) {
|
||||
if (id != null) {
|
||||
return siemResponse.error({
|
||||
body: `list item id: "${id}" not found`,
|
||||
statusCode: 404,
|
||||
});
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const {
|
||||
description,
|
||||
id,
|
||||
name,
|
||||
os_types: osTypes,
|
||||
meta,
|
||||
type,
|
||||
_version,
|
||||
comments,
|
||||
entries,
|
||||
item_id: itemId,
|
||||
tags,
|
||||
} = request.body;
|
||||
const exceptionLists = await getExceptionListClient(context);
|
||||
const exceptionListItem = await exceptionLists.updateEndpointListItem({
|
||||
_version,
|
||||
comments,
|
||||
description,
|
||||
entries,
|
||||
id,
|
||||
itemId,
|
||||
meta,
|
||||
name,
|
||||
osTypes,
|
||||
tags,
|
||||
type,
|
||||
});
|
||||
if (exceptionListItem == null) {
|
||||
if (id != null) {
|
||||
return siemResponse.error({
|
||||
body: `list item id: "${id}" not found`,
|
||||
statusCode: 404,
|
||||
});
|
||||
} else {
|
||||
return siemResponse.error({
|
||||
body: `list item item_id: "${itemId}" not found`,
|
||||
statusCode: 404,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
return siemResponse.error({
|
||||
body: `list item item_id: "${itemId}" not found`,
|
||||
statusCode: 404,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
const [validated, errors] = validate(exceptionListItem, updateEndpointListItemResponse);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
const [validated, errors] = validate(exceptionListItem, updateEndpointListItemResponse);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
};
|
||||
|
|
|
@ -22,95 +22,102 @@ import { buildRouteValidation, buildSiemResponse } from './utils';
|
|||
import { getExceptionListClient } from '.';
|
||||
|
||||
export const updateExceptionListItemRoute = (router: ListsPluginRouter): void => {
|
||||
router.put(
|
||||
{
|
||||
router.versioned
|
||||
.put({
|
||||
access: 'public',
|
||||
options: {
|
||||
tags: ['access:lists-all'],
|
||||
},
|
||||
path: EXCEPTION_LIST_ITEM_URL,
|
||||
validate: {
|
||||
body: buildRouteValidation<
|
||||
typeof updateExceptionListItemRequest,
|
||||
UpdateExceptionListItemRequestDecoded
|
||||
>(updateExceptionListItemRequest),
|
||||
})
|
||||
.addVersion(
|
||||
{
|
||||
validate: {
|
||||
request: {
|
||||
body: buildRouteValidation<
|
||||
typeof updateExceptionListItemRequest,
|
||||
UpdateExceptionListItemRequestDecoded
|
||||
>(updateExceptionListItemRequest),
|
||||
},
|
||||
},
|
||||
version: '2023-10-31',
|
||||
},
|
||||
},
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
const validationErrors = updateExceptionListItemValidate(request.body);
|
||||
if (validationErrors.length) {
|
||||
return siemResponse.error({ body: validationErrors, statusCode: 400 });
|
||||
}
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
const validationErrors = updateExceptionListItemValidate(request.body);
|
||||
if (validationErrors.length) {
|
||||
return siemResponse.error({ body: validationErrors, statusCode: 400 });
|
||||
}
|
||||
|
||||
try {
|
||||
const {
|
||||
description,
|
||||
id,
|
||||
name,
|
||||
meta,
|
||||
type,
|
||||
_version,
|
||||
comments,
|
||||
entries,
|
||||
item_id: itemId,
|
||||
namespace_type: namespaceType,
|
||||
os_types: osTypes,
|
||||
tags,
|
||||
expire_time: expireTime,
|
||||
} = request.body;
|
||||
if (id == null && itemId == null) {
|
||||
return siemResponse.error({
|
||||
body: 'either id or item_id need to be defined',
|
||||
statusCode: 404,
|
||||
});
|
||||
} else {
|
||||
const exceptionLists = await getExceptionListClient(context);
|
||||
const exceptionListItem = await exceptionLists.updateOverwriteExceptionListItem({
|
||||
try {
|
||||
const {
|
||||
description,
|
||||
id,
|
||||
name,
|
||||
meta,
|
||||
type,
|
||||
_version,
|
||||
comments,
|
||||
description,
|
||||
entries,
|
||||
expireTime,
|
||||
id,
|
||||
itemId,
|
||||
meta,
|
||||
name,
|
||||
namespaceType,
|
||||
osTypes,
|
||||
item_id: itemId,
|
||||
namespace_type: namespaceType,
|
||||
os_types: osTypes,
|
||||
tags,
|
||||
type,
|
||||
});
|
||||
if (exceptionListItem == null) {
|
||||
if (id != null) {
|
||||
return siemResponse.error({
|
||||
body: `exception list item id: "${id}" does not exist`,
|
||||
statusCode: 404,
|
||||
});
|
||||
} else {
|
||||
return siemResponse.error({
|
||||
body: `exception list item item_id: "${itemId}" does not exist`,
|
||||
statusCode: 404,
|
||||
});
|
||||
}
|
||||
expire_time: expireTime,
|
||||
} = request.body;
|
||||
if (id == null && itemId == null) {
|
||||
return siemResponse.error({
|
||||
body: 'either id or item_id need to be defined',
|
||||
statusCode: 404,
|
||||
});
|
||||
} else {
|
||||
const [validated, errors] = validate(
|
||||
exceptionListItem,
|
||||
updateExceptionListItemResponse
|
||||
);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
const exceptionLists = await getExceptionListClient(context);
|
||||
const exceptionListItem = await exceptionLists.updateOverwriteExceptionListItem({
|
||||
_version,
|
||||
comments,
|
||||
description,
|
||||
entries,
|
||||
expireTime,
|
||||
id,
|
||||
itemId,
|
||||
meta,
|
||||
name,
|
||||
namespaceType,
|
||||
osTypes,
|
||||
tags,
|
||||
type,
|
||||
});
|
||||
if (exceptionListItem == null) {
|
||||
if (id != null) {
|
||||
return siemResponse.error({
|
||||
body: `exception list item id: "${id}" does not exist`,
|
||||
statusCode: 404,
|
||||
});
|
||||
} else {
|
||||
return siemResponse.error({
|
||||
body: `exception list item item_id: "${itemId}" does not exist`,
|
||||
statusCode: 404,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
const [validated, errors] = validate(
|
||||
exceptionListItem,
|
||||
updateExceptionListItemResponse
|
||||
);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
};
|
||||
|
|
|
@ -24,76 +24,83 @@ import {
|
|||
} from './utils';
|
||||
|
||||
export const updateExceptionListRoute = (router: ListsPluginRouter): void => {
|
||||
router.put(
|
||||
{
|
||||
router.versioned
|
||||
.put({
|
||||
access: 'public',
|
||||
options: {
|
||||
tags: ['access:lists-all'],
|
||||
},
|
||||
path: EXCEPTION_LIST_URL,
|
||||
validate: {
|
||||
body: buildRouteValidation<
|
||||
typeof updateExceptionListRequest,
|
||||
UpdateExceptionListRequestDecoded
|
||||
>(updateExceptionListRequest),
|
||||
})
|
||||
.addVersion(
|
||||
{
|
||||
validate: {
|
||||
request: {
|
||||
body: buildRouteValidation<
|
||||
typeof updateExceptionListRequest,
|
||||
UpdateExceptionListRequestDecoded
|
||||
>(updateExceptionListRequest),
|
||||
},
|
||||
},
|
||||
version: '2023-10-31',
|
||||
},
|
||||
},
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const {
|
||||
_version,
|
||||
tags,
|
||||
name,
|
||||
description,
|
||||
id,
|
||||
list_id: listId,
|
||||
meta,
|
||||
namespace_type: namespaceType,
|
||||
os_types: osTypes,
|
||||
type,
|
||||
version,
|
||||
} = request.body;
|
||||
const exceptionLists = await getExceptionListClient(context);
|
||||
if (id == null && listId == null) {
|
||||
return siemResponse.error({
|
||||
body: 'either id or list_id need to be defined',
|
||||
statusCode: 404,
|
||||
});
|
||||
} else {
|
||||
const list = await exceptionLists.updateExceptionList({
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
try {
|
||||
const {
|
||||
_version,
|
||||
tags,
|
||||
name,
|
||||
description,
|
||||
id,
|
||||
listId,
|
||||
list_id: listId,
|
||||
meta,
|
||||
name,
|
||||
namespaceType,
|
||||
osTypes,
|
||||
tags,
|
||||
namespace_type: namespaceType,
|
||||
os_types: osTypes,
|
||||
type,
|
||||
version,
|
||||
});
|
||||
if (list == null) {
|
||||
} = request.body;
|
||||
const exceptionLists = await getExceptionListClient(context);
|
||||
if (id == null && listId == null) {
|
||||
return siemResponse.error({
|
||||
body: getErrorMessageExceptionList({ id, listId }),
|
||||
body: 'either id or list_id need to be defined',
|
||||
statusCode: 404,
|
||||
});
|
||||
} else {
|
||||
const [validated, errors] = validate(list, updateExceptionListResponse);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
const list = await exceptionLists.updateExceptionList({
|
||||
_version,
|
||||
description,
|
||||
id,
|
||||
listId,
|
||||
meta,
|
||||
name,
|
||||
namespaceType,
|
||||
osTypes,
|
||||
tags,
|
||||
type,
|
||||
version,
|
||||
});
|
||||
if (list == null) {
|
||||
return siemResponse.error({
|
||||
body: getErrorMessageExceptionList({ id, listId }),
|
||||
statusCode: 404,
|
||||
});
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
const [validated, errors] = validate(list, updateExceptionListResponse);
|
||||
if (errors != null) {
|
||||
return siemResponse.error({ body: errors, statusCode: 500 });
|
||||
} else {
|
||||
return response.ok({ body: validated ?? {} });
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
};
|
||||
|
|
|
@ -69,6 +69,7 @@ describe('Exceptions List Api Client', () => {
|
|||
expect(fakeHttpServices.post).toHaveBeenCalledWith(
|
||||
INTERNAL_EXCEPTIONS_LIST_ENSURE_CREATED_URL,
|
||||
{
|
||||
version: '1',
|
||||
body: JSON.stringify(getFakeListDefinition()),
|
||||
}
|
||||
);
|
||||
|
|
|
@ -62,6 +62,7 @@ export class ExceptionsListApiClient {
|
|||
const asyncFunction = async () => {
|
||||
try {
|
||||
await this.http.post<ExceptionListSchema>(INTERNAL_EXCEPTIONS_LIST_ENSURE_CREATED_URL, {
|
||||
version: '1',
|
||||
body: JSON.stringify({ ...this.listDefinition, list_id: this.listId }),
|
||||
});
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@ export default ({ getService }: FtrProviderContext): void => {
|
|||
const { body } = await supertest
|
||||
.get(`${INTERNAL_FIND_LISTS_BY_SIZE}`)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.set('elastic-api-version', '1')
|
||||
.send()
|
||||
.expect(200);
|
||||
|
||||
|
@ -65,6 +66,7 @@ export default ({ getService }: FtrProviderContext): void => {
|
|||
const { body } = await supertest
|
||||
.get(`${INTERNAL_FIND_LISTS_BY_SIZE}`)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.set('elastic-api-version', '1')
|
||||
.send()
|
||||
.expect(200);
|
||||
|
||||
|
|
|
@ -41,6 +41,7 @@ export default ({ getService }: FtrProviderContext): void => {
|
|||
const { body } = await supertest
|
||||
.post(`${INTERNAL_EXCEPTION_FILTER}`)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.set('elastic-api-version', '1')
|
||||
.send(getExceptionFilterFromExceptionItemsSchemaMock())
|
||||
.expect(200);
|
||||
|
||||
|
@ -121,6 +122,7 @@ export default ({ getService }: FtrProviderContext): void => {
|
|||
const { body } = await supertest
|
||||
.post(`${INTERNAL_EXCEPTION_FILTER}`)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.set('elastic-api-version', '1')
|
||||
.send(getExceptionFilterFromExceptionIdsSchemaMock())
|
||||
.expect(200);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue