mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
[Security Solution] Add support for GET requests to the Detection Engine health API (#159970)
**Partially addresses:** https://github.com/elastic/kibana/issues/125642 ## Summary The PoC of the Detection Engine health API has been implemented in https://github.com/elastic/kibana/pull/157155. Now, we need to integrate it into the [support-diagnostics](https://github.com/elastic/support-diagnostics) tool. It looks like the tool requires the APIs it calls to be callable with the `GET` verb. This PR makes it possible to call 2 out of 3 health endpoints with `GET`: ```txt GET /internal/detection_engine/health/_cluster ``` ```txt GET /internal/detection_engine/health/_space ``` The `GET` routes don't accept any parameters and use the default parameters instead: - interval: `last_day` - granularity: `hour` - debug: `false` ### Checklist - [x] [Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials - [ ] [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 ### For maintainers - [x] This was checked for breaking API changes and was [labeled appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)
This commit is contained in:
parent
a653a3eca9
commit
7047f24c17
3 changed files with 170 additions and 62 deletions
|
@ -364,6 +364,7 @@ Response:
|
|||
|
||||
```txt
|
||||
POST /internal/detection_engine/health/_space
|
||||
GET /internal/detection_engine/health/_space
|
||||
```
|
||||
|
||||
Get health overview of the current Kibana space. Scope: all detection rules in the space.
|
||||
|
@ -374,12 +375,18 @@ Returns:
|
|||
- health stats history within the same interval in the form of a histogram
|
||||
(the same stats are calculated over each of the discreet sub-intervals of the whole interval)
|
||||
|
||||
Minimal required parameters: empty object.
|
||||
Minimal required parameters for the `POST` route: empty object.
|
||||
|
||||
```json
|
||||
{}
|
||||
```
|
||||
|
||||
The `GET` route don't accept any parameters and use the default parameters instead:
|
||||
|
||||
- interval: `last_day`
|
||||
- granularity: `hour`
|
||||
- debug: `false`
|
||||
|
||||
Response:
|
||||
|
||||
```json
|
||||
|
@ -721,14 +728,21 @@ Response:
|
|||
|
||||
```txt
|
||||
POST /internal/detection_engine/health/_cluster
|
||||
GET /internal/detection_engine/health/_cluster
|
||||
```
|
||||
|
||||
Minimal required parameters: empty object.
|
||||
Minimal required parameters for the `POST` route: empty object.
|
||||
|
||||
```json
|
||||
{}
|
||||
```
|
||||
|
||||
The `GET` route don't accept any parameters and use the default parameters instead:
|
||||
|
||||
- interval: `last_day`
|
||||
- granularity: `hour`
|
||||
- debug: `false`
|
||||
|
||||
Response:
|
||||
|
||||
```json
|
||||
|
|
|
@ -5,16 +5,21 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import type { KibanaResponseFactory } from '@kbn/core-http-server';
|
||||
import { transformError } from '@kbn/securitysolution-es-utils';
|
||||
import { buildRouteValidation } from '../../../../../../utils/build_validation/route_validation';
|
||||
import { buildSiemResponse } from '../../../../routes/utils';
|
||||
import type { SecuritySolutionPluginRouter } from '../../../../../../types';
|
||||
|
||||
import type { GetClusterHealthResponse } from '../../../../../../../common/detection_engine/rule_monitoring';
|
||||
import type {
|
||||
GetClusterHealthRequest,
|
||||
GetClusterHealthResponse,
|
||||
} from '../../../../../../../common/detection_engine/rule_monitoring';
|
||||
import {
|
||||
GET_CLUSTER_HEALTH_URL,
|
||||
GetClusterHealthRequestBody,
|
||||
} from '../../../../../../../common/detection_engine/rule_monitoring';
|
||||
import type { IDetectionEngineHealthClient } from '../../../logic/detection_engine_health';
|
||||
import { calculateHealthTimings } from '../health_timings';
|
||||
import { validateGetClusterHealthRequest } from './get_cluster_health_request';
|
||||
|
||||
|
@ -27,6 +32,27 @@ import { validateGetClusterHealthRequest } from './get_cluster_health_request';
|
|||
* (the same stats are calculated over each of the discreet sub-intervals of the whole interval)
|
||||
*/
|
||||
export const getClusterHealthRoute = (router: SecuritySolutionPluginRouter) => {
|
||||
router.get(
|
||||
{
|
||||
path: GET_CLUSTER_HEALTH_URL,
|
||||
validate: {},
|
||||
options: {
|
||||
tags: ['access:securitySolution'],
|
||||
},
|
||||
},
|
||||
async (context, request, response) => {
|
||||
return handleClusterHealthRequest({
|
||||
response,
|
||||
resolveParameters: () => validateGetClusterHealthRequest({}),
|
||||
resolveDependencies: async () => {
|
||||
const ctx = await context.resolve(['securitySolution']);
|
||||
const healthClient = ctx.securitySolution.getDetectionEngineHealthClient();
|
||||
return { healthClient };
|
||||
},
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
router.post(
|
||||
{
|
||||
path: GET_CLUSTER_HEALTH_URL,
|
||||
|
@ -38,36 +64,57 @@ export const getClusterHealthRoute = (router: SecuritySolutionPluginRouter) => {
|
|||
},
|
||||
},
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
|
||||
try {
|
||||
const params = validateGetClusterHealthRequest(request.body);
|
||||
|
||||
const ctx = await context.resolve(['securitySolution']);
|
||||
const healthClient = ctx.securitySolution.getDetectionEngineHealthClient();
|
||||
|
||||
const clusterHealthParameters = { interval: params.interval };
|
||||
const clusterHealth = await healthClient.calculateClusterHealth(clusterHealthParameters);
|
||||
|
||||
const responseBody: GetClusterHealthResponse = {
|
||||
// TODO: https://github.com/elastic/kibana/issues/125642 Implement the endpoint and remove the `message` property
|
||||
message: 'Not implemented',
|
||||
timings: calculateHealthTimings(params.requestReceivedAt),
|
||||
parameters: clusterHealthParameters,
|
||||
health: {
|
||||
...clusterHealth,
|
||||
debug: params.debug ? clusterHealth.debug : undefined,
|
||||
},
|
||||
};
|
||||
|
||||
return response.ok({ body: responseBody });
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
return handleClusterHealthRequest({
|
||||
response,
|
||||
resolveParameters: () => validateGetClusterHealthRequest(request.body),
|
||||
resolveDependencies: async () => {
|
||||
const ctx = await context.resolve(['securitySolution']);
|
||||
const healthClient = ctx.securitySolution.getDetectionEngineHealthClient();
|
||||
return { healthClient };
|
||||
},
|
||||
});
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
interface ClusterHealthRouteDependencies {
|
||||
healthClient: IDetectionEngineHealthClient;
|
||||
}
|
||||
|
||||
interface HandleClusterHealthRequestArgs {
|
||||
response: KibanaResponseFactory;
|
||||
resolveParameters: () => GetClusterHealthRequest;
|
||||
resolveDependencies: () => Promise<ClusterHealthRouteDependencies>;
|
||||
}
|
||||
|
||||
const handleClusterHealthRequest = async (args: HandleClusterHealthRequestArgs) => {
|
||||
const { response, resolveParameters, resolveDependencies } = args;
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
|
||||
try {
|
||||
const params = resolveParameters();
|
||||
const { healthClient } = await resolveDependencies();
|
||||
|
||||
const clusterHealthParameters = { interval: params.interval };
|
||||
const clusterHealth = await healthClient.calculateClusterHealth(clusterHealthParameters);
|
||||
|
||||
const responseBody: GetClusterHealthResponse = {
|
||||
// TODO: https://github.com/elastic/kibana/issues/125642 Implement the endpoint and remove the `message` property
|
||||
message: 'Not implemented',
|
||||
timings: calculateHealthTimings(params.requestReceivedAt),
|
||||
parameters: clusterHealthParameters,
|
||||
health: {
|
||||
...clusterHealth,
|
||||
debug: params.debug ? clusterHealth.debug : undefined,
|
||||
},
|
||||
};
|
||||
|
||||
return response.ok({ body: responseBody });
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
|
@ -5,16 +5,21 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import type { KibanaResponseFactory } from '@kbn/core-http-server';
|
||||
import { transformError } from '@kbn/securitysolution-es-utils';
|
||||
import { buildRouteValidation } from '../../../../../../utils/build_validation/route_validation';
|
||||
import { buildSiemResponse } from '../../../../routes/utils';
|
||||
import type { SecuritySolutionPluginRouter } from '../../../../../../types';
|
||||
|
||||
import type { GetSpaceHealthResponse } from '../../../../../../../common/detection_engine/rule_monitoring';
|
||||
import type {
|
||||
GetSpaceHealthRequest,
|
||||
GetSpaceHealthResponse,
|
||||
} from '../../../../../../../common/detection_engine/rule_monitoring';
|
||||
import {
|
||||
GET_SPACE_HEALTH_URL,
|
||||
GetSpaceHealthRequestBody,
|
||||
} from '../../../../../../../common/detection_engine/rule_monitoring';
|
||||
import type { IDetectionEngineHealthClient } from '../../../logic/detection_engine_health';
|
||||
import { calculateHealthTimings } from '../health_timings';
|
||||
import { validateGetSpaceHealthRequest } from './get_space_health_request';
|
||||
|
||||
|
@ -27,6 +32,27 @@ import { validateGetSpaceHealthRequest } from './get_space_health_request';
|
|||
* (the same stats are calculated over each of the discreet sub-intervals of the whole interval)
|
||||
*/
|
||||
export const getSpaceHealthRoute = (router: SecuritySolutionPluginRouter) => {
|
||||
router.get(
|
||||
{
|
||||
path: GET_SPACE_HEALTH_URL,
|
||||
validate: {},
|
||||
options: {
|
||||
tags: ['access:securitySolution'],
|
||||
},
|
||||
},
|
||||
async (context, request, response) => {
|
||||
return handleSpaceHealthRequest({
|
||||
response,
|
||||
resolveParameters: () => validateGetSpaceHealthRequest({}),
|
||||
resolveDependencies: async () => {
|
||||
const ctx = await context.resolve(['securitySolution']);
|
||||
const healthClient = ctx.securitySolution.getDetectionEngineHealthClient();
|
||||
return { healthClient };
|
||||
},
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
router.post(
|
||||
{
|
||||
path: GET_SPACE_HEALTH_URL,
|
||||
|
@ -38,34 +64,55 @@ export const getSpaceHealthRoute = (router: SecuritySolutionPluginRouter) => {
|
|||
},
|
||||
},
|
||||
async (context, request, response) => {
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
|
||||
try {
|
||||
const params = validateGetSpaceHealthRequest(request.body);
|
||||
|
||||
const ctx = await context.resolve(['securitySolution']);
|
||||
const healthClient = ctx.securitySolution.getDetectionEngineHealthClient();
|
||||
|
||||
const spaceHealthParameters = { interval: params.interval };
|
||||
const spaceHealth = await healthClient.calculateSpaceHealth(spaceHealthParameters);
|
||||
|
||||
const responseBody: GetSpaceHealthResponse = {
|
||||
timings: calculateHealthTimings(params.requestReceivedAt),
|
||||
parameters: spaceHealthParameters,
|
||||
health: {
|
||||
...spaceHealth,
|
||||
debug: params.debug ? spaceHealth.debug : undefined,
|
||||
},
|
||||
};
|
||||
|
||||
return response.ok({ body: responseBody });
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
return handleSpaceHealthRequest({
|
||||
response,
|
||||
resolveParameters: () => validateGetSpaceHealthRequest(request.body),
|
||||
resolveDependencies: async () => {
|
||||
const ctx = await context.resolve(['securitySolution']);
|
||||
const healthClient = ctx.securitySolution.getDetectionEngineHealthClient();
|
||||
return { healthClient };
|
||||
},
|
||||
});
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
interface SpaceHealthRouteDependencies {
|
||||
healthClient: IDetectionEngineHealthClient;
|
||||
}
|
||||
|
||||
interface HandleSpaceHealthRequestArgs {
|
||||
response: KibanaResponseFactory;
|
||||
resolveParameters: () => GetSpaceHealthRequest;
|
||||
resolveDependencies: () => Promise<SpaceHealthRouteDependencies>;
|
||||
}
|
||||
|
||||
const handleSpaceHealthRequest = async (args: HandleSpaceHealthRequestArgs) => {
|
||||
const { response, resolveParameters, resolveDependencies } = args;
|
||||
const siemResponse = buildSiemResponse(response);
|
||||
|
||||
try {
|
||||
const params = resolveParameters();
|
||||
const { healthClient } = await resolveDependencies();
|
||||
|
||||
const spaceHealthParameters = { interval: params.interval };
|
||||
const spaceHealth = await healthClient.calculateSpaceHealth(spaceHealthParameters);
|
||||
|
||||
const responseBody: GetSpaceHealthResponse = {
|
||||
timings: calculateHealthTimings(params.requestReceivedAt),
|
||||
parameters: spaceHealthParameters,
|
||||
health: {
|
||||
...spaceHealth,
|
||||
debug: params.debug ? spaceHealth.debug : undefined,
|
||||
},
|
||||
};
|
||||
|
||||
return response.ok({ body: responseBody });
|
||||
} catch (err) {
|
||||
const error = transformError(err);
|
||||
return siemResponse.error({
|
||||
body: error.message,
|
||||
statusCode: error.statusCode,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue