mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[Security Solution][Entity Analytics] API Versioning for new EA Routes (#167365)
## Summary * Adds API versioning to all routes involved in new Risk Engine, public and private * Adds missing PLI auth headers for some routes * Updates API invocations to specify an appropriate version header * Does NOT add header to legacy transform-based EA routes ### Checklist - [x] Verify no API calls from the UI were missed - [ ] [Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios
This commit is contained in:
parent
79c42be00c
commit
2edc13c2c1
10 changed files with 163 additions and 139 deletions
|
@ -34,6 +34,7 @@ export const fetchRiskScorePreview = async ({
|
|||
params: RiskScorePreviewRequestSchema;
|
||||
}): Promise<CalculateScoresResponse> => {
|
||||
return KibanaServices.get().http.fetch<CalculateScoresResponse>(RISK_SCORE_PREVIEW_URL, {
|
||||
version: '1',
|
||||
method: 'POST',
|
||||
body: JSON.stringify(params),
|
||||
signal,
|
||||
|
@ -49,6 +50,7 @@ export const fetchRiskEngineStatus = async ({
|
|||
signal?: AbortSignal;
|
||||
}): Promise<GetRiskEngineStatusResponse> => {
|
||||
return KibanaServices.get().http.fetch<GetRiskEngineStatusResponse>(RISK_ENGINE_STATUS_URL, {
|
||||
version: '1',
|
||||
method: 'GET',
|
||||
signal,
|
||||
});
|
||||
|
@ -59,6 +61,7 @@ export const fetchRiskEngineStatus = async ({
|
|||
*/
|
||||
export const initRiskEngine = async (): Promise<InitRiskEngineResponse> => {
|
||||
return KibanaServices.get().http.fetch<InitRiskEngineResponse>(RISK_ENGINE_INIT_URL, {
|
||||
version: '1',
|
||||
method: 'POST',
|
||||
});
|
||||
};
|
||||
|
@ -68,6 +71,7 @@ export const initRiskEngine = async (): Promise<InitRiskEngineResponse> => {
|
|||
*/
|
||||
export const enableRiskEngine = async (): Promise<EnableRiskEngineResponse> => {
|
||||
return KibanaServices.get().http.fetch<EnableRiskEngineResponse>(RISK_ENGINE_ENABLE_URL, {
|
||||
version: '1',
|
||||
method: 'POST',
|
||||
});
|
||||
};
|
||||
|
@ -77,6 +81,7 @@ export const enableRiskEngine = async (): Promise<EnableRiskEngineResponse> => {
|
|||
*/
|
||||
export const disableRiskEngine = async (): Promise<DisableRiskEngineResponse> => {
|
||||
return KibanaServices.get().http.fetch<DisableRiskEngineResponse>(RISK_ENGINE_DISABLE_URL, {
|
||||
version: '1',
|
||||
method: 'POST',
|
||||
});
|
||||
};
|
||||
|
|
|
@ -16,15 +16,15 @@ export const riskEngineDisableRoute = (
|
|||
router: SecuritySolutionPluginRouter,
|
||||
getStartServices: StartServicesAccessor<StartPlugins>
|
||||
) => {
|
||||
router.post(
|
||||
{
|
||||
router.versioned
|
||||
.post({
|
||||
access: 'internal',
|
||||
path: RISK_ENGINE_DISABLE_URL,
|
||||
validate: {},
|
||||
options: {
|
||||
tags: ['access:securitySolution', `access:${APP_ID}-entity-analytics`],
|
||||
},
|
||||
},
|
||||
async (context, request, response) => {
|
||||
})
|
||||
.addVersion({ version: '1', validate: {} }, async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
|
||||
const [_, { taskManager }] = await getStartServices();
|
||||
|
@ -52,6 +52,5 @@ export const riskEngineDisableRoute = (
|
|||
body: { message: error.message, full_error: JSON.stringify(e) },
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
};
|
||||
|
|
|
@ -16,15 +16,15 @@ export const riskEngineEnableRoute = (
|
|||
router: SecuritySolutionPluginRouter,
|
||||
getStartServices: StartServicesAccessor<StartPlugins>
|
||||
) => {
|
||||
router.post(
|
||||
{
|
||||
router.versioned
|
||||
.post({
|
||||
access: 'internal',
|
||||
path: RISK_ENGINE_ENABLE_URL,
|
||||
validate: {},
|
||||
options: {
|
||||
tags: ['access:securitySolution', `access:${APP_ID}-entity-analytics`],
|
||||
},
|
||||
},
|
||||
async (context, request, response) => {
|
||||
})
|
||||
.addVersion({ version: '1', validate: {} }, async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
const [_, { taskManager }] = await getStartServices();
|
||||
const securitySolution = await context.securitySolution;
|
||||
|
@ -51,6 +51,5 @@ export const riskEngineEnableRoute = (
|
|||
body: { message: error.message, full_error: JSON.stringify(e) },
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
};
|
||||
|
|
|
@ -17,15 +17,15 @@ export const riskEngineInitRoute = (
|
|||
router: SecuritySolutionPluginRouter,
|
||||
getStartServices: StartServicesAccessor<StartPlugins>
|
||||
) => {
|
||||
router.post(
|
||||
{
|
||||
router.versioned
|
||||
.post({
|
||||
access: 'internal',
|
||||
path: RISK_ENGINE_INIT_URL,
|
||||
validate: {},
|
||||
options: {
|
||||
tags: ['access:securitySolution', `access:${APP_ID}-entity-analytics`],
|
||||
},
|
||||
},
|
||||
async (context, request, response) => {
|
||||
})
|
||||
.addVersion({ version: '1', validate: {} }, async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
const securitySolution = await context.securitySolution;
|
||||
const [_, { taskManager }] = await getStartServices();
|
||||
|
@ -78,6 +78,5 @@ export const riskEngineInitRoute = (
|
|||
body: { message: error.message, full_error: JSON.stringify(e) },
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
};
|
||||
|
|
|
@ -12,15 +12,15 @@ import { RISK_ENGINE_STATUS_URL, APP_ID } from '../../../../common/constants';
|
|||
import type { SecuritySolutionPluginRouter } from '../../../types';
|
||||
|
||||
export const riskEngineStatusRoute = (router: SecuritySolutionPluginRouter) => {
|
||||
router.get(
|
||||
{
|
||||
router.versioned
|
||||
.get({
|
||||
access: 'internal',
|
||||
path: RISK_ENGINE_STATUS_URL,
|
||||
validate: {},
|
||||
options: {
|
||||
tags: ['access:securitySolution', `access:${APP_ID}-entity-analytics`],
|
||||
},
|
||||
},
|
||||
async (context, request, response) => {
|
||||
})
|
||||
.addVersion({ version: '1', validate: {} }, async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
|
||||
const securitySolution = await context.securitySolution;
|
||||
|
@ -46,6 +46,5 @@ export const riskEngineStatusRoute = (router: SecuritySolutionPluginRouter) => {
|
|||
body: { message: error.message, full_error: JSON.stringify(e) },
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
};
|
||||
|
|
|
@ -9,6 +9,7 @@ import type { Logger } from '@kbn/core/server';
|
|||
import { buildSiemResponse } from '@kbn/lists-plugin/server/routes/utils';
|
||||
import { transformError } from '@kbn/securitysolution-es-utils';
|
||||
import {
|
||||
APP_ID,
|
||||
DEFAULT_RISK_SCORE_PAGE_SIZE,
|
||||
RISK_SCORE_CALCULATION_URL,
|
||||
} from '../../../../common/constants';
|
||||
|
@ -19,72 +20,77 @@ import { riskScoreServiceFactory } from '../risk_score_service';
|
|||
import { getRiskInputsIndex } from '../get_risk_inputs_index';
|
||||
|
||||
export const riskScoreCalculationRoute = (router: SecuritySolutionPluginRouter, logger: Logger) => {
|
||||
router.post(
|
||||
{
|
||||
router.versioned
|
||||
.post({
|
||||
path: RISK_SCORE_CALCULATION_URL,
|
||||
validate: { body: buildRouteValidation(riskScoreCalculationRequestSchema) },
|
||||
access: 'public',
|
||||
options: {
|
||||
tags: ['access:securitySolution'],
|
||||
tags: ['access:securitySolution', `access:${APP_ID}-entity-analytics`],
|
||||
},
|
||||
},
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
const securityContext = await context.securitySolution;
|
||||
const coreContext = await context.core;
|
||||
const esClient = coreContext.elasticsearch.client.asCurrentUser;
|
||||
const soClient = coreContext.savedObjects.client;
|
||||
const spaceId = securityContext.getSpaceId();
|
||||
const riskEngineDataClient = securityContext.getRiskEngineDataClient();
|
||||
})
|
||||
.addVersion(
|
||||
{
|
||||
version: '2023-10-31',
|
||||
validate: { request: { body: buildRouteValidation(riskScoreCalculationRequestSchema) } },
|
||||
},
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
const securityContext = await context.securitySolution;
|
||||
const coreContext = await context.core;
|
||||
const esClient = coreContext.elasticsearch.client.asCurrentUser;
|
||||
const soClient = coreContext.savedObjects.client;
|
||||
const spaceId = securityContext.getSpaceId();
|
||||
const riskEngineDataClient = securityContext.getRiskEngineDataClient();
|
||||
|
||||
const riskScoreService = riskScoreServiceFactory({
|
||||
esClient,
|
||||
logger,
|
||||
riskEngineDataClient,
|
||||
spaceId,
|
||||
});
|
||||
|
||||
const {
|
||||
after_keys: userAfterKeys,
|
||||
data_view_id: dataViewId,
|
||||
debug,
|
||||
page_size: userPageSize,
|
||||
identifier_type: identifierType,
|
||||
filter,
|
||||
range,
|
||||
weights,
|
||||
} = request.body;
|
||||
|
||||
try {
|
||||
const { index, runtimeMappings } = await getRiskInputsIndex({
|
||||
dataViewId,
|
||||
const riskScoreService = riskScoreServiceFactory({
|
||||
esClient,
|
||||
logger,
|
||||
soClient,
|
||||
riskEngineDataClient,
|
||||
spaceId,
|
||||
});
|
||||
|
||||
const afterKeys = userAfterKeys ?? {};
|
||||
const pageSize = userPageSize ?? DEFAULT_RISK_SCORE_PAGE_SIZE;
|
||||
|
||||
const result = await riskScoreService.calculateAndPersistScores({
|
||||
afterKeys,
|
||||
const {
|
||||
after_keys: userAfterKeys,
|
||||
data_view_id: dataViewId,
|
||||
debug,
|
||||
pageSize,
|
||||
identifierType,
|
||||
index,
|
||||
page_size: userPageSize,
|
||||
identifier_type: identifierType,
|
||||
filter,
|
||||
range,
|
||||
runtimeMappings,
|
||||
weights,
|
||||
});
|
||||
} = request.body;
|
||||
|
||||
return response.ok({ body: result });
|
||||
} catch (e) {
|
||||
const error = transformError(e);
|
||||
try {
|
||||
const { index, runtimeMappings } = await getRiskInputsIndex({
|
||||
dataViewId,
|
||||
logger,
|
||||
soClient,
|
||||
});
|
||||
|
||||
return siemResponse.error({
|
||||
statusCode: error.statusCode,
|
||||
body: { message: error.message, full_error: JSON.stringify(e) },
|
||||
});
|
||||
const afterKeys = userAfterKeys ?? {};
|
||||
const pageSize = userPageSize ?? DEFAULT_RISK_SCORE_PAGE_SIZE;
|
||||
|
||||
const result = await riskScoreService.calculateAndPersistScores({
|
||||
afterKeys,
|
||||
debug,
|
||||
pageSize,
|
||||
identifierType,
|
||||
index,
|
||||
filter,
|
||||
range,
|
||||
runtimeMappings,
|
||||
weights,
|
||||
});
|
||||
|
||||
return response.ok({ body: result });
|
||||
} catch (e) {
|
||||
const error = transformError(e);
|
||||
|
||||
return siemResponse.error({
|
||||
statusCode: error.statusCode,
|
||||
body: { message: error.message, full_error: JSON.stringify(e) },
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
};
|
||||
|
|
|
@ -9,7 +9,11 @@ import type { Logger } from '@kbn/core/server';
|
|||
import { buildSiemResponse } from '@kbn/lists-plugin/server/routes/utils';
|
||||
import { transformError } from '@kbn/securitysolution-es-utils';
|
||||
|
||||
import { DEFAULT_RISK_SCORE_PAGE_SIZE, RISK_SCORE_PREVIEW_URL } from '../../../../common/constants';
|
||||
import {
|
||||
APP_ID,
|
||||
DEFAULT_RISK_SCORE_PAGE_SIZE,
|
||||
RISK_SCORE_PREVIEW_URL,
|
||||
} from '../../../../common/constants';
|
||||
import { riskScorePreviewRequestSchema } from '../../../../common/risk_engine/risk_score_preview/request_schema';
|
||||
import type { SecuritySolutionPluginRouter } from '../../../types';
|
||||
import { buildRouteValidation } from '../../../utils/build_validation/route_validation';
|
||||
|
@ -17,73 +21,78 @@ import { riskScoreServiceFactory } from '../risk_score_service';
|
|||
import { getRiskInputsIndex } from '../get_risk_inputs_index';
|
||||
|
||||
export const riskScorePreviewRoute = (router: SecuritySolutionPluginRouter, logger: Logger) => {
|
||||
router.post(
|
||||
{
|
||||
router.versioned
|
||||
.post({
|
||||
access: 'internal',
|
||||
path: RISK_SCORE_PREVIEW_URL,
|
||||
validate: { body: buildRouteValidation(riskScorePreviewRequestSchema) },
|
||||
options: {
|
||||
tags: ['access:securitySolution'],
|
||||
tags: ['access:securitySolution', `access:${APP_ID}-entity-analytics`],
|
||||
},
|
||||
},
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
const securityContext = await context.securitySolution;
|
||||
const coreContext = await context.core;
|
||||
const esClient = coreContext.elasticsearch.client.asCurrentUser;
|
||||
const soClient = coreContext.savedObjects.client;
|
||||
const spaceId = securityContext.getSpaceId();
|
||||
const riskEngineDataClient = securityContext.getRiskEngineDataClient();
|
||||
})
|
||||
.addVersion(
|
||||
{
|
||||
version: '1',
|
||||
validate: { request: { body: buildRouteValidation(riskScorePreviewRequestSchema) } },
|
||||
},
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
const securityContext = await context.securitySolution;
|
||||
const coreContext = await context.core;
|
||||
const esClient = coreContext.elasticsearch.client.asCurrentUser;
|
||||
const soClient = coreContext.savedObjects.client;
|
||||
const spaceId = securityContext.getSpaceId();
|
||||
const riskEngineDataClient = securityContext.getRiskEngineDataClient();
|
||||
|
||||
const riskScoreService = riskScoreServiceFactory({
|
||||
esClient,
|
||||
logger,
|
||||
riskEngineDataClient,
|
||||
spaceId,
|
||||
});
|
||||
|
||||
const {
|
||||
after_keys: userAfterKeys,
|
||||
data_view_id: dataViewId,
|
||||
debug,
|
||||
page_size: userPageSize,
|
||||
identifier_type: identifierType,
|
||||
filter,
|
||||
range: userRange,
|
||||
weights,
|
||||
} = request.body;
|
||||
|
||||
try {
|
||||
const { index, runtimeMappings } = await getRiskInputsIndex({
|
||||
dataViewId,
|
||||
const riskScoreService = riskScoreServiceFactory({
|
||||
esClient,
|
||||
logger,
|
||||
soClient,
|
||||
riskEngineDataClient,
|
||||
spaceId,
|
||||
});
|
||||
|
||||
const afterKeys = userAfterKeys ?? {};
|
||||
const range = userRange ?? { start: 'now-15d', end: 'now' };
|
||||
const pageSize = userPageSize ?? DEFAULT_RISK_SCORE_PAGE_SIZE;
|
||||
|
||||
const result = await riskScoreService.calculateScores({
|
||||
afterKeys,
|
||||
const {
|
||||
after_keys: userAfterKeys,
|
||||
data_view_id: dataViewId,
|
||||
debug,
|
||||
page_size: userPageSize,
|
||||
identifier_type: identifierType,
|
||||
filter,
|
||||
identifierType,
|
||||
index,
|
||||
pageSize,
|
||||
range,
|
||||
runtimeMappings,
|
||||
range: userRange,
|
||||
weights,
|
||||
});
|
||||
} = request.body;
|
||||
|
||||
return response.ok({ body: result });
|
||||
} catch (e) {
|
||||
const error = transformError(e);
|
||||
try {
|
||||
const { index, runtimeMappings } = await getRiskInputsIndex({
|
||||
dataViewId,
|
||||
logger,
|
||||
soClient,
|
||||
});
|
||||
|
||||
return siemResponse.error({
|
||||
statusCode: error.statusCode,
|
||||
body: { message: error.message, full_error: JSON.stringify(e) },
|
||||
});
|
||||
const afterKeys = userAfterKeys ?? {};
|
||||
const range = userRange ?? { start: 'now-15d', end: 'now' };
|
||||
const pageSize = userPageSize ?? DEFAULT_RISK_SCORE_PAGE_SIZE;
|
||||
|
||||
const result = await riskScoreService.calculateScores({
|
||||
afterKeys,
|
||||
debug,
|
||||
filter,
|
||||
identifierType,
|
||||
index,
|
||||
pageSize,
|
||||
range,
|
||||
runtimeMappings,
|
||||
weights,
|
||||
});
|
||||
|
||||
return response.ok({ body: result });
|
||||
} catch (e) {
|
||||
const error = transformError(e);
|
||||
|
||||
return siemResponse.error({
|
||||
statusCode: error.statusCode,
|
||||
body: { message: error.message, full_error: JSON.stringify(e) },
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
};
|
||||
|
|
|
@ -38,6 +38,7 @@ export default ({ getService }: FtrProviderContext): void => {
|
|||
const { body: result } = await supertest
|
||||
.post(RISK_SCORE_CALCULATION_URL)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.set('elastic-api-version', '2023-10-31')
|
||||
.send(body)
|
||||
.expect(200);
|
||||
return result;
|
||||
|
|
|
@ -36,6 +36,7 @@ export default ({ getService }: FtrProviderContext): void => {
|
|||
const defaultBody = { data_view_id: '.alerts-security.alerts-default' };
|
||||
const { body: result } = await supertest
|
||||
.post(RISK_SCORE_PREVIEW_URL)
|
||||
.set('elastic-api-version', '1')
|
||||
.set('kbn-xsrf', 'true')
|
||||
.send({ ...defaultBody, ...body })
|
||||
.expect(200);
|
||||
|
|
|
@ -427,6 +427,7 @@ export const riskEngineRouteHelpersFactory = (
|
|||
await supertest
|
||||
.post(routeWithNamespace(RISK_ENGINE_INIT_URL, namespace))
|
||||
.set('kbn-xsrf', 'true')
|
||||
.set('elastic-api-version', '1')
|
||||
.send()
|
||||
.expect(200),
|
||||
|
||||
|
@ -434,6 +435,7 @@ export const riskEngineRouteHelpersFactory = (
|
|||
await supertest
|
||||
.get(routeWithNamespace(RISK_ENGINE_STATUS_URL, namespace))
|
||||
.set('kbn-xsrf', 'true')
|
||||
.set('elastic-api-version', '1')
|
||||
.send()
|
||||
.expect(200),
|
||||
|
||||
|
@ -441,6 +443,7 @@ export const riskEngineRouteHelpersFactory = (
|
|||
await supertest
|
||||
.post(routeWithNamespace(RISK_ENGINE_ENABLE_URL, namespace))
|
||||
.set('kbn-xsrf', 'true')
|
||||
.set('elastic-api-version', '1')
|
||||
.send()
|
||||
.expect(200),
|
||||
|
||||
|
@ -448,6 +451,7 @@ export const riskEngineRouteHelpersFactory = (
|
|||
await supertest
|
||||
.post(routeWithNamespace(RISK_ENGINE_DISABLE_URL, namespace))
|
||||
.set('kbn-xsrf', 'true')
|
||||
.set('elastic-api-version', '1')
|
||||
.send()
|
||||
.expect(200),
|
||||
});
|
||||
|
@ -460,12 +464,14 @@ export const installLegacyRiskScore = async ({
|
|||
await supertest
|
||||
.post('/internal/risk_score')
|
||||
.set('kbn-xsrf', 'true')
|
||||
.set('elastic-api-version', '1')
|
||||
.send({ riskScoreEntity: 'host' })
|
||||
.expect(200);
|
||||
|
||||
await supertest
|
||||
.post('/internal/risk_score')
|
||||
.set('kbn-xsrf', 'true')
|
||||
.set('elastic-api-version', '1')
|
||||
.send({ riskScoreEntity: 'user' })
|
||||
.expect(200);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue