[Security Solution] Move risk score API schemas to /common/api (#163032)

Closes https://github.com/elastic/security-team/issues/7101
This commit is contained in:
Marshall Main 2023-08-07 07:33:08 -07:00 committed by GitHub
parent 1047eef005
commit 30ca22c254
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 147 additions and 88 deletions

1
.github/CODEOWNERS vendored
View file

@ -1098,6 +1098,7 @@ x-pack/plugins/cloud_integrations/cloud_full_story/server/config.ts @elastic/kib
/x-pack/plugins/security_solution/server/lib/timeline @elastic/security-threat-hunting-investigations
## Security Solution sub teams - Threat Hunting Explore
/x-pack/plugins/security_solution/common/api/risk_score @elastic/security-threat-hunting-explore
/x-pack/plugins/security_solution/common/search_strategy/security_solution/hosts @elastic/security-threat-hunting-explore
/x-pack/plugins/security_solution/common/search_strategy/security_solution/matrix_histogram @elastic/security-threat-hunting-explore
/x-pack/plugins/security_solution/common/search_strategy/security_solution/network @elastic/security-threat-hunting-explore

View file

@ -0,0 +1,18 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import type { TypeOf } from '@kbn/config-schema';
import { schema } from '@kbn/config-schema';
export const createEsIndexRequestBody = schema.object({
index: schema.string({ minLength: 1 }),
mappings: schema.maybe(
schema.oneOf([schema.string(), schema.recordOf(schema.string({ minLength: 1 }), schema.any())])
),
});
export type CreateEsIndexRequestBody = TypeOf<typeof createEsIndexRequestBody>;

View file

@ -5,23 +5,23 @@
* 2.0.
*/
import { createPrebuiltSavedObjectsSchema } from './schema';
import { createPrebuiltSavedObjectsRequestBody } from './create_prebuilt_saved_objects_route';
describe('createPrebuiltSavedObjectsSchema', () => {
describe('createPrebuiltSavedObjectsRequestBody', () => {
it('should throw error', () => {
expect(() =>
createPrebuiltSavedObjectsSchema.params.validate({ template_name: '123' })
createPrebuiltSavedObjectsRequestBody.params.validate({ template_name: '123' })
).toThrow();
});
it.each([['hostRiskScoreDashboards', 'userRiskScoreDashboards']])(
'should allow template %p',
async (template) => {
expect(createPrebuiltSavedObjectsSchema.params.validate({ template_name: template })).toEqual(
{
template_name: template,
}
);
expect(
createPrebuiltSavedObjectsRequestBody.params.validate({ template_name: template })
).toEqual({
template_name: template,
});
}
);
});

View file

@ -0,0 +1,17 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { schema } from '@kbn/config-schema';
export const createPrebuiltSavedObjectsRequestBody = {
params: schema.object({
template_name: schema.oneOf([
schema.literal('hostRiskScoreDashboards'),
schema.literal('userRiskScoreDashboards'),
]),
}),
};

View file

@ -0,0 +1,25 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import type { TypeOf } from '@kbn/config-schema';
import { schema } from '@kbn/config-schema';
export const createStoredScriptRequestBody = schema.object({
id: schema.string({ minLength: 1 }),
script: schema.object({
lang: schema.oneOf([
schema.string(),
schema.literal('painless'),
schema.literal('expression'),
schema.literal('mustache'),
schema.literal('java'),
]),
options: schema.maybe(schema.recordOf(schema.string(), schema.string())),
source: schema.string(),
}),
});
export type CreateStoredScriptRequestBody = TypeOf<typeof createStoredScriptRequestBody>;

View file

@ -0,0 +1,12 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { schema } from '@kbn/config-schema';
export const deleteIndicesRequestBody = schema.object({
indices: schema.arrayOf(schema.string()),
});

View file

@ -7,16 +7,7 @@
import { schema } from '@kbn/config-schema';
export const createPrebuiltSavedObjectsSchema = {
params: schema.object({
template_name: schema.oneOf([
schema.literal('hostRiskScoreDashboards'),
schema.literal('userRiskScoreDashboards'),
]),
}),
};
export const deletePrebuiltSavedObjectsSchema = {
export const deletePrebuiltSavedObjectsRequestBody = {
params: schema.object({
template_name: schema.oneOf([
schema.literal('hostRiskScoreDashboards'),

View file

@ -0,0 +1,15 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import type { TypeOf } from '@kbn/config-schema';
import { schema } from '@kbn/config-schema';
export const deleteStoredScriptRequestBody = schema.object({
id: schema.string({ minLength: 1 }),
});
export type DeleteStoredScriptRequestBody = TypeOf<typeof deleteStoredScriptRequestBody>;

View file

@ -0,0 +1,16 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
export * from './create_index/create_index_route';
export * from './create_prebuilt_saved_objects/create_prebuilt_saved_objects_route';
export * from './create_stored_script/create_stored_script_route';
export * from './delete_indices/delete_indices_route';
export * from './delete_prebuilt_saved_objects/delete_prebuilt_saved_objects_route';
export * from './delete_stored_script/delete_stored_script_route';
export * from './index_status/index_status_route';
export * from './install_modules/install_modules_route';
export * from './read_prebuilt_dev_tool_content/read_prebuilt_dev_tool_content_route';

View file

@ -7,7 +7,7 @@
import * as t from 'io-ts';
export const indexStatusSchema = t.type({
export const indexStatusRequestQuery = t.type({
indexName: t.string,
entity: t.string,
});

View file

@ -6,9 +6,9 @@
*/
import { schema } from '@kbn/config-schema';
import { RiskScoreEntity } from '../../../../common/search_strategy';
import { RiskScoreEntity } from '../../../search_strategy';
export const onboardingRiskScoreSchema = {
export const onboardingRiskScoreRequestBody = {
body: schema.object({
riskScoreEntity: schema.oneOf([
schema.literal(RiskScoreEntity.host),

View file

@ -7,7 +7,7 @@
import { schema } from '@kbn/config-schema';
export const ReadConsoleRequestSchema = {
export const readConsoleRequestBody = {
params: schema.object({
console_id: schema.oneOf([
schema.literal('enable_host_risk_score'),

View file

@ -11,14 +11,14 @@ import { APP_ID, RISK_SCORE_INDEX_STATUS_API_URL } from '../../../../common/cons
import type { SecuritySolutionPluginRouter } from '../../../types';
import { buildRouteValidation } from '../../../utils/build_validation/route_validation';
import { buildSiemResponse } from '../../detection_engine/routes/utils';
import { indexStatusSchema } from './schema';
import { indexStatusRequestQuery } from '../../../../common/api/risk_score';
export const getRiskScoreIndexStatusRoute = (router: SecuritySolutionPluginRouter) => {
router.get(
{
path: RISK_SCORE_INDEX_STATUS_API_URL,
validate: {
query: buildRouteValidation(indexStatusSchema),
query: buildRouteValidation(indexStatusRequestQuery),
},
options: {
tags: ['access:securitySolution', `access:${APP_ID}-entity-analytics`],

View file

@ -11,13 +11,14 @@ import type { Logger } from '@kbn/core/server';
import { transformError } from '@kbn/securitysolution-es-utils';
import { RISK_SCORE_CREATE_INDEX } from '../../../../common/constants';
import type { SecuritySolutionPluginRouter } from '../../../types';
import { createEsIndexBodySchema, createIndex } from './lib/create_index';
import { createIndex } from './lib/create_index';
import { createEsIndexRequestBody } from '../../../../common/api/risk_score';
export const createEsIndexRoute = (router: SecuritySolutionPluginRouter, logger: Logger) => {
router.put(
{
path: RISK_SCORE_CREATE_INDEX,
validate: { body: createEsIndexBodySchema },
validate: { body: createEsIndexRequestBody },
options: {
tags: ['access:securitySolution'],
},

View file

@ -4,23 +4,19 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { schema } from '@kbn/config-schema';
import { transformError } from '@kbn/securitysolution-es-utils';
import { buildSiemResponse } from '@kbn/lists-plugin/server/routes/utils';
import { RISK_SCORE_DELETE_INDICES } from '../../../../common/constants';
import type { SecuritySolutionPluginRouter } from '../../../types';
import { deleteEsIndices } from './lib/delete_indices';
const bodySchema = schema.object({
indices: schema.arrayOf(schema.string()),
});
import { deleteIndicesRequestBody } from '../../../../common/api/risk_score';
export const deleteEsIndicesRoute = (router: SecuritySolutionPluginRouter) => {
router.post(
{
path: RISK_SCORE_DELETE_INDICES,
validate: { body: bodySchema },
validate: { body: deleteIndicesRequestBody },
options: {
tags: ['access:securitySolution'],
},

View file

@ -4,19 +4,9 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import type { TypeOf } from '@kbn/config-schema';
import { schema } from '@kbn/config-schema';
import type { ElasticsearchClient, Logger } from '@kbn/core/server';
import { transformError } from '@kbn/securitysolution-es-utils';
export const createEsIndexBodySchema = schema.object({
index: schema.string({ minLength: 1 }),
mappings: schema.maybe(
schema.oneOf([schema.string(), schema.recordOf(schema.string({ minLength: 1 }), schema.any())])
),
});
type CreateEsIndexBodySchema = TypeOf<typeof createEsIndexBodySchema>;
import type { CreateEsIndexRequestBody } from '../../../../../common/api/risk_score';
export const createIndex = async ({
esClient,
@ -25,7 +15,7 @@ export const createIndex = async ({
}: {
esClient: ElasticsearchClient;
logger: Logger;
options: CreateEsIndexBodySchema;
options: CreateEsIndexRequestBody;
}) => {
try {
await esClient.indices.create({

View file

@ -16,7 +16,7 @@ import type { SetupPlugins } from '../../../../plugin';
import { buildSiemResponse } from '../../../detection_engine/routes/utils';
import { installRiskScoreModule } from '../helpers/install_risk_score_module';
import { onboardingRiskScoreSchema } from '../schema';
import { onboardingRiskScoreRequestBody } from '../../../../../common/api/risk_score';
export const installRiskScoresRoute = (
router: SecuritySolutionPluginRouter,
@ -26,7 +26,7 @@ export const installRiskScoresRoute = (
router.post(
{
path: INTERNAL_RISK_SCORE_URL,
validate: onboardingRiskScoreSchema,
validate: onboardingRiskScoreRequestBody,
options: {
tags: ['access:securitySolution', `access:${APP_ID}-entity-analytics`],
},

View file

@ -14,7 +14,7 @@ import { DEV_TOOL_PREBUILT_CONTENT } from '../../../../../common/constants';
import type { SecuritySolutionPluginRouter } from '../../../../types';
import { consoleMappings } from '../console_mappings';
import { ReadConsoleRequestSchema } from '../schema';
import { readConsoleRequestBody } from '../../../../../common/api/risk_score';
import { RiskScoreEntity } from '../../../../../common/search_strategy';
import { getView } from '../utils';
@ -48,7 +48,7 @@ export const readPrebuiltDevToolContentRoute = (router: SecuritySolutionPluginRo
router.get(
{
path: DEV_TOOL_PREBUILT_CONTENT,
validate: ReadConsoleRequestSchema,
validate: readConsoleRequestBody,
options: {
tags: ['access:securitySolution'],
},

View file

@ -5,17 +5,17 @@
* 2.0.
*/
import { ReadConsoleRequestSchema } from './schema';
import { readConsoleRequestBody } from '../../../../common/api/risk_score';
describe('ReadConsoleRequestSchema', () => {
it('should throw error', () => {
expect(() => ReadConsoleRequestSchema.params.validate({ console_id: '123' })).toThrow();
expect(() => readConsoleRequestBody.params.validate({ console_id: '123' })).toThrow();
});
it.each([['enable_host_risk_score', 'enable_user_risk_score']])(
'should allow console_id %p',
async (template) => {
expect(ReadConsoleRequestSchema.params.validate({ console_id: template })).toEqual({
expect(readConsoleRequestBody.params.validate({ console_id: template })).toEqual({
console_id: template,
});
}

View file

@ -16,7 +16,7 @@ import { buildSiemResponse } from '../../../detection_engine/routes/utils';
import { buildFrameworkRequest } from '../../../timeline/utils/common';
import { bulkCreateSavedObjects } from '../helpers/bulk_create_saved_objects';
import { createPrebuiltSavedObjectsSchema } from '../schema';
import { createPrebuiltSavedObjectsRequestBody } from '../../../../../common/api/risk_score';
export const createPrebuiltSavedObjectsRoute = (
router: SecuritySolutionPluginRouter,
@ -26,7 +26,7 @@ export const createPrebuiltSavedObjectsRoute = (
router.post(
{
path: PREBUILT_SAVED_OBJECTS_BULK_CREATE,
validate: createPrebuiltSavedObjectsSchema,
validate: createPrebuiltSavedObjectsRequestBody,
options: {
tags: ['access:securitySolution'],
},

View file

@ -16,7 +16,7 @@ import { buildSiemResponse } from '../../../detection_engine/routes/utils';
import { buildFrameworkRequest } from '../../../timeline/utils/common';
import { bulkDeleteSavedObjects } from '../helpers/bulk_delete_saved_objects';
import { deletePrebuiltSavedObjectsSchema } from '../schema';
import { deletePrebuiltSavedObjectsRequestBody } from '../../../../../common/api/risk_score';
export const deletePrebuiltSavedObjectsRoute = (
router: SecuritySolutionPluginRouter,
@ -25,7 +25,7 @@ export const deletePrebuiltSavedObjectsRoute = (
router.post(
{
path: PREBUILT_SAVED_OBJECTS_BULK_DELETE,
validate: deletePrebuiltSavedObjectsSchema,
validate: deletePrebuiltSavedObjectsRequestBody,
options: {
tags: ['access:securitySolution'],
},

View file

@ -8,15 +8,16 @@
import type { Logger } from '@kbn/core/server';
import { buildSiemResponse } from '@kbn/lists-plugin/server/routes/utils';
import { transformError } from '@kbn/securitysolution-es-utils';
import { createStoredScriptRequestBody } from '../../../../common/api/risk_score';
import { RISK_SCORE_CREATE_STORED_SCRIPT } from '../../../../common/constants';
import type { SecuritySolutionPluginRouter } from '../../../types';
import { createStoredScriptBodySchema, createStoredScript } from './lib/create_script';
import { createStoredScript } from './lib/create_script';
export const createStoredScriptRoute = (router: SecuritySolutionPluginRouter, logger: Logger) => {
router.put(
{
path: RISK_SCORE_CREATE_STORED_SCRIPT,
validate: { body: createStoredScriptBodySchema },
validate: { body: createStoredScriptRequestBody },
options: {
tags: ['access:securitySolution'],
},

View file

@ -9,13 +9,14 @@ import { transformError } from '@kbn/securitysolution-es-utils';
import { buildSiemResponse } from '@kbn/lists-plugin/server/routes/utils';
import { RISK_SCORE_DELETE_STORED_SCRIPT } from '../../../../common/constants';
import type { SecuritySolutionPluginRouter } from '../../../types';
import { deleteStoredScriptBodySchema, deleteStoredScript } from './lib/delete_script';
import { deleteStoredScript } from './lib/delete_script';
import { deleteStoredScriptRequestBody } from '../../../../common/api/risk_score';
export const deleteStoredScriptRoute = (router: SecuritySolutionPluginRouter) => {
router.delete(
{
path: RISK_SCORE_DELETE_STORED_SCRIPT,
validate: { body: deleteStoredScriptBodySchema },
validate: { body: deleteStoredScriptRequestBody },
options: {
tags: ['access:securitySolution'],
},

View file

@ -4,27 +4,9 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import type { TypeOf } from '@kbn/config-schema';
import { schema } from '@kbn/config-schema';
import type { ElasticsearchClient, Logger } from '@kbn/core/server';
import { transformError } from '@kbn/securitysolution-es-utils';
export const createStoredScriptBodySchema = schema.object({
id: schema.string({ minLength: 1 }),
script: schema.object({
lang: schema.oneOf([
schema.string(),
schema.literal('painless'),
schema.literal('expression'),
schema.literal('mustache'),
schema.literal('java'),
]),
options: schema.maybe(schema.recordOf(schema.string(), schema.string())),
source: schema.string(),
}),
});
type CreateStoredScriptBodySchema = TypeOf<typeof createStoredScriptBodySchema>;
import type { CreateStoredScriptRequestBody } from '../../../../../common/api/risk_score';
export const createStoredScript = async ({
esClient,
@ -33,7 +15,7 @@ export const createStoredScript = async ({
}: {
esClient: ElasticsearchClient;
logger: Logger;
options: CreateStoredScriptBodySchema;
options: CreateStoredScriptRequestBody;
}) => {
try {
await esClient.putScript(options);

View file

@ -4,22 +4,15 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import type { TypeOf } from '@kbn/config-schema';
import { schema } from '@kbn/config-schema';
import type { IScopedClusterClient } from '@kbn/core-elasticsearch-server';
export const deleteStoredScriptBodySchema = schema.object({
id: schema.string({ minLength: 1 }),
});
type DeleteStoredScriptBodySchema = TypeOf<typeof deleteStoredScriptBodySchema>;
import type { DeleteStoredScriptRequestBody } from '../../../../../common/api/risk_score';
export const deleteStoredScript = async ({
client,
options,
}: {
client: IScopedClusterClient;
options: DeleteStoredScriptBodySchema;
options: DeleteStoredScriptRequestBody;
}) => {
await client.asCurrentUser.deleteScript(options);
};