forked from elastic/kibana
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Security Solution] Implement rule monitoring dashboard (elastic#159875)
**Addresses:** elastic/security-team#6032 ## Summary This PR adds a new `[Elastic Security] Detection rule monitoring` Kibana dashboard and a new `POST /internal/detection_engine/health/_setup` API endpoint. ## Dashboard The dashboard can be helpful for monitoring the health and performance of Security detection rules. Users of the dashboard must have read access to the `.kibana-event-log-*` index. The dashboard is automatically installed into the current Kibana space when a user visits a page in Security Solution - similar to how we install the Fleet package with prebuilt detection rules. <img width="1791" alt="Kibana dashboards page" src="/~https://github.com/elastic/kibana/assets/7359339/92cb3c75-39ea-4069-b70f-8f531869edf7"> <img width="1775" alt="Security dashboards page" src="/~https://github.com/elastic/kibana/assets/7359339/3b27aeb6-2222-40fd-a453-c204fcee4f31"> ![Rule monitoring dashboard itself](/~https://github.com/elastic/kibana/assets/7359339/755cc044-5613-4c78-b89f-2a9734ded76d) ## API endpoint The PR also adds a new endpoint for setting up anything related to monitoring rules and the health of the Detection Engine. If you call the endpoint, it will install the new dashboard to the Default Kibana space: ``` POST /internal/detection_engine/health/_setup ``` In order to install the dashboard to a different Kibana space, you will need to call it like that: ``` POST /s/<space-id>/internal/detection_engine/health/_setup ``` The user calling the endpoint must have access to Security Solution. No additional privileges are required, because the endpoint installs the dashboard on behalf of the internal user (`kibana_system`). ### Checklist - [ ] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](/~https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md) - [ ] [Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials - [ ] elastic/security-docs#3478 - [ ] [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
- Loading branch information
Showing
22 changed files
with
615 additions
and
29 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
29 changes: 29 additions & 0 deletions
29
...ne/rule_monitoring/logic/detection_engine_health/use_setup_detection_engine_health_api.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
/* | ||
* 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 { UseMutationOptions } from '@tanstack/react-query'; | ||
import { useMutation } from '@tanstack/react-query'; | ||
import { useEffect } from 'react'; | ||
|
||
import { SETUP_HEALTH_URL } from '../../../../../common/detection_engine/rule_monitoring'; | ||
import { api } from '../../api'; | ||
|
||
export const SETUP_DETECTION_ENGINE_HEALTH_API_MUTATION_KEY = ['POST', SETUP_HEALTH_URL]; | ||
|
||
export const useSetupDetectionEngineHealthApi = (options?: UseMutationOptions<void, Error>) => { | ||
const { mutate: setupDetectionEngineHealthApi } = useMutation( | ||
() => api.setupDetectionEngineHealthApi(), | ||
{ | ||
...options, | ||
mutationKey: SETUP_DETECTION_ENGINE_HEALTH_API_MUTATION_KEY, | ||
} | ||
); | ||
|
||
useEffect(() => { | ||
setupDetectionEngineHealthApi(); | ||
}, [setupDetectionEngineHealthApi]); | ||
}; |
47 changes: 47 additions & 0 deletions
47
.../detection_engine/rule_monitoring/api/detection_engine_health/setup/setup_health_route.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
/* | ||
* 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 { transformError } from '@kbn/securitysolution-es-utils'; | ||
import { buildSiemResponse } from '../../../../routes/utils'; | ||
import type { SecuritySolutionPluginRouter } from '../../../../../../types'; | ||
|
||
import { SETUP_HEALTH_URL } from '../../../../../../../common/detection_engine/rule_monitoring'; | ||
|
||
/** | ||
* Similar to the "setup" command of beats, this endpoint installs resources | ||
* (dashboards, data views, etc) related to rule monitoring and Detection Engine health, | ||
* and can do any other setup work. | ||
*/ | ||
export const setupHealthRoute = (router: SecuritySolutionPluginRouter) => { | ||
router.post( | ||
{ | ||
path: SETUP_HEALTH_URL, | ||
validate: {}, | ||
options: { | ||
tags: ['access:securitySolution'], | ||
}, | ||
}, | ||
async (context, request, response) => { | ||
const siemResponse = buildSiemResponse(response); | ||
|
||
try { | ||
const ctx = await context.resolve(['securitySolution']); | ||
const healthClient = ctx.securitySolution.getDetectionEngineHealthClient(); | ||
|
||
await healthClient.installAssetsForMonitoringHealth(); | ||
|
||
return response.ok({ body: {} }); | ||
} catch (err) { | ||
const error = transformError(err); | ||
return siemResponse.error({ | ||
body: error.message, | ||
statusCode: error.statusCode, | ||
}); | ||
} | ||
} | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
236 changes: 236 additions & 0 deletions
236
...ngine/rule_monitoring/logic/detection_engine_health/assets/dashboard_rule_monitoring.json
Large diffs are not rendered by default.
Oops, something went wrong.
14 changes: 14 additions & 0 deletions
14
...gine/rule_monitoring/logic/detection_engine_health/assets/data_view_kibana_event_log.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
{ | ||
"type": "index-pattern", | ||
"id": "kibana-event-log-data-view", | ||
"managed": true, | ||
"coreMigrationVersion": "8.8.0", | ||
"typeMigrationVersion": "8.0.0", | ||
"attributes": { | ||
"name": ".kibana-event-log-*", | ||
"title": ".kibana-event-log-*", | ||
"timeFieldName": "@timestamp", | ||
"allowNoIndex": true | ||
}, | ||
"references": [] | ||
} |
106 changes: 106 additions & 0 deletions
106
...ule_monitoring/logic/detection_engine_health/assets/install_assets_for_rule_monitoring.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
/* | ||
* 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 { ISavedObjectsImporter, Logger } from '@kbn/core/server'; | ||
import { SavedObjectsUtils } from '@kbn/core/server'; | ||
import { cloneDeep } from 'lodash'; | ||
import pRetry from 'p-retry'; | ||
import { Readable } from 'stream'; | ||
|
||
import sourceRuleMonitoringDashboard from './dashboard_rule_monitoring.json'; | ||
import sourceKibanaEventLogDataView from './data_view_kibana_event_log.json'; | ||
import sourceManagedTag from './tag_managed.json'; | ||
import sourceSecuritySolutionTag from './tag_security_solution.json'; | ||
|
||
const MAX_RETRIES = 2; | ||
|
||
/** | ||
* Installs managed assets for monitoring rules and health of Detection Engine. | ||
*/ | ||
export const installAssetsForRuleMonitoring = async ( | ||
savedObjectsImporter: ISavedObjectsImporter, | ||
logger: Logger, | ||
currentSpaceId: string | ||
): Promise<void> => { | ||
const operation = async (attemptCount: number) => { | ||
logger.debug(`Installing assets for rule monitoring (attempt ${attemptCount})...`); | ||
|
||
const assets = getAssetsForRuleMonitoring(currentSpaceId); | ||
|
||
// The assets are marked as "managed: true" at the saved object level, which in the future | ||
// should be reflected in the UI for the user. Ticket to track: | ||
// /~https://github.com/elastic/kibana/issues/140364 | ||
const importResult = await savedObjectsImporter.import({ | ||
readStream: Readable.from(assets), | ||
managed: true, | ||
overwrite: true, | ||
createNewCopies: false, | ||
refresh: false, | ||
namespace: spaceIdToNamespace(currentSpaceId), | ||
}); | ||
|
||
importResult.warnings.forEach((w) => { | ||
logger.warn(w.message); | ||
}); | ||
|
||
if (!importResult.success) { | ||
const errors = (importResult.errors ?? []).map( | ||
(e) => `Couldn't import "${e.type}:${e.id}": ${JSON.stringify(e.error)}` | ||
); | ||
|
||
errors.forEach((e) => { | ||
logger.error(e); | ||
}); | ||
|
||
// This will retry the operation | ||
throw new Error(errors.length > 0 ? errors[0] : `Unknown error (attempt ${attemptCount})`); | ||
} | ||
|
||
logger.debug('Assets for rule monitoring installed'); | ||
}; | ||
|
||
await pRetry(operation, { retries: MAX_RETRIES }); | ||
}; | ||
|
||
const getAssetsForRuleMonitoring = (currentSpaceId: string) => { | ||
const withSpaceId = appendSpaceId(currentSpaceId); | ||
|
||
const assetRuleMonitoringDashboard = cloneDeep(sourceRuleMonitoringDashboard); | ||
const assetKibanaEventLogDataView = cloneDeep(sourceKibanaEventLogDataView); | ||
const assetManagedTag = cloneDeep(sourceManagedTag); | ||
const assetSecuritySolutionTag = cloneDeep(sourceSecuritySolutionTag); | ||
|
||
// Update ids of the assets to include the current space id | ||
assetRuleMonitoringDashboard.id = withSpaceId('security-detection-rule-monitoring'); | ||
assetManagedTag.id = withSpaceId('fleet-managed'); | ||
assetSecuritySolutionTag.id = withSpaceId('security-solution'); | ||
|
||
// Update saved object references of the dashboard accordingly | ||
assetRuleMonitoringDashboard.references = assetRuleMonitoringDashboard.references.map( | ||
(reference) => { | ||
if (reference.id === 'fleet-managed-<spaceId>') { | ||
return { ...reference, id: assetManagedTag.id }; | ||
} | ||
if (reference.id === 'security-solution-<spaceId>') { | ||
return { ...reference, id: assetSecuritySolutionTag.id }; | ||
} | ||
|
||
return reference; | ||
} | ||
); | ||
|
||
return [ | ||
assetManagedTag, | ||
assetSecuritySolutionTag, | ||
assetKibanaEventLogDataView, | ||
assetRuleMonitoringDashboard, | ||
]; | ||
}; | ||
|
||
const appendSpaceId = (spaceId: string) => (str: string) => `${str}-${spaceId}`; | ||
|
||
const spaceIdToNamespace = SavedObjectsUtils.namespaceStringToId; |
Oops, something went wrong.