Skip to content

Commit

Permalink
[Security Solution] Add active maintenance window callout to the Rule…
Browse files Browse the repository at this point in the history
…s Management page (#155386)

**Addresses:** #155099
**Documentation issue:**
elastic/security-docs#3181

## Summary

Adds a Maintenance Window callout to the Rules Management page. This
callout is only displayed when a maintenance window is running.

<img width="1260" alt="Screenshot 2023-04-21 at 13 24 11"
src="https://user-images.githubusercontent.com/15949146/233624339-9c9b6e3e-9e5e-424d-9d19-9cd7d4e92259.png">


### Checklist

- [x] 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)
- [x]
[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)
issue created: elastic/security-docs#3181
- [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
- [x] Any UI touched in this PR does not create any new axe failures
(run axe in browser:
[FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/),
[Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US))
- [x] This renders correctly on smaller devices using a responsive
layout. (You can test this [in your
browser](https://www.browserstack.com/guide/responsive-testing-on-local-server))
- [x] This was checked for [cross-browser
compatibility](https://www.elastic.co/support/matrix#matrix_browsers)


### 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)

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
Co-authored-by: Georgii Gorbachev <banderror@gmail.com>
  • Loading branch information
3 people authored Apr 24, 2023
1 parent a34dd8c commit 675ed0e
Show file tree
Hide file tree
Showing 18 changed files with 359 additions and 23 deletions.
6 changes: 6 additions & 0 deletions x-pack/plugins/alerting/common/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,12 @@ export const LEGACY_BASE_ALERT_API_PATH = '/api/alerts';
export const BASE_ALERTING_API_PATH = '/api/alerting';
export const INTERNAL_BASE_ALERTING_API_PATH = '/internal/alerting';
export const INTERNAL_ALERTING_API_FIND_RULES_PATH = `${INTERNAL_BASE_ALERTING_API_PATH}/rules/_find`;

export const INTERNAL_ALERTING_API_MAINTENANCE_WINDOW_PATH =
`${INTERNAL_BASE_ALERTING_API_PATH}/rules/maintenance_window` as const;
export const INTERNAL_ALERTING_API_GET_ACTIVE_MAINTENANCE_WINDOWS_PATH =
`${INTERNAL_ALERTING_API_MAINTENANCE_WINDOW_PATH}/_active` as const;

export const ALERTS_FEATURE_ID = 'alerts';
export const MONITORING_HISTORY_LIMIT = 200;
export const ENABLE_MAINTENANCE_WINDOWS = false;
5 changes: 5 additions & 0 deletions x-pack/plugins/alerting/common/maintenance_window.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ export type MaintenanceWindow = MaintenanceWindowSOAttributes & {
id: string;
};

export type MaintenanceWindowCreateBody = Omit<
MaintenanceWindowSOProperties,
'events' | 'expirationDate' | 'enabled' | 'archived'
>;

export interface MaintenanceWindowClientContext {
getModificationMetadata: () => Promise<MaintenanceWindowModificationMetadata>;
savedObjectsClient: SavedObjectsClientContract;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@
import { IRouter } from '@kbn/core/server';
import { ILicenseState } from '../../lib';
import { verifyAccessAndContext, rewriteMaintenanceWindowRes } from '../lib';
import { AlertingRequestHandlerContext, INTERNAL_BASE_ALERTING_API_PATH } from '../../types';
import {
AlertingRequestHandlerContext,
INTERNAL_ALERTING_API_GET_ACTIVE_MAINTENANCE_WINDOWS_PATH,
} from '../../types';
import { MAINTENANCE_WINDOW_API_PRIVILEGES } from '../../../common';

export const activeMaintenanceWindowsRoute = (
Expand All @@ -17,7 +20,7 @@ export const activeMaintenanceWindowsRoute = (
) => {
router.get(
{
path: `${INTERNAL_BASE_ALERTING_API_PATH}/rules/maintenance_window/_active`,
path: INTERNAL_ALERTING_API_GET_ACTIVE_MAINTENANCE_WINDOWS_PATH,
validate: {},
options: {
tags: [`access:${MAINTENANCE_WINDOW_API_PRIVILEGES.READ_MAINTENANCE_WINDOW}`],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ import { IRouter } from '@kbn/core/server';
import { schema } from '@kbn/config-schema';
import { ILicenseState } from '../../lib';
import { verifyAccessAndContext, rewritePartialMaintenanceBodyRes } from '../lib';
import { AlertingRequestHandlerContext, INTERNAL_BASE_ALERTING_API_PATH } from '../../types';
import {
AlertingRequestHandlerContext,
INTERNAL_ALERTING_API_MAINTENANCE_WINDOW_PATH,
} from '../../types';
import { MAINTENANCE_WINDOW_API_PRIVILEGES } from '../../../common';

const paramSchema = schema.object({
Expand All @@ -26,7 +29,7 @@ export const archiveMaintenanceWindowRoute = (
) => {
router.post(
{
path: `${INTERNAL_BASE_ALERTING_API_PATH}/rules/maintenance_window/{id}/_archive`,
path: `${INTERNAL_ALERTING_API_MAINTENANCE_WINDOW_PATH}/{id}/_archive`,
validate: {
params: paramSchema,
body: bodySchema,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,18 @@ import {
RewriteRequestCase,
rewriteMaintenanceWindowRes,
} from '../lib';
import { AlertingRequestHandlerContext, INTERNAL_BASE_ALERTING_API_PATH } from '../../types';
import { MaintenanceWindowSOProperties, MAINTENANCE_WINDOW_API_PRIVILEGES } from '../../../common';
import {
AlertingRequestHandlerContext,
INTERNAL_ALERTING_API_MAINTENANCE_WINDOW_PATH,
} from '../../types';
import { MaintenanceWindowCreateBody, MAINTENANCE_WINDOW_API_PRIVILEGES } from '../../../common';

const bodySchema = schema.object({
title: schema.string(),
duration: schema.number(),
r_rule: rRuleSchema,
});

type MaintenanceWindowCreateBody = Omit<
MaintenanceWindowSOProperties,
'events' | 'expirationDate' | 'enabled' | 'archived'
>;

export const rewriteQueryReq: RewriteRequestCase<MaintenanceWindowCreateBody> = ({
r_rule: rRule,
...rest
Expand All @@ -42,7 +40,7 @@ export const createMaintenanceWindowRoute = (
) => {
router.post(
{
path: `${INTERNAL_BASE_ALERTING_API_PATH}/rules/maintenance_window`,
path: INTERNAL_ALERTING_API_MAINTENANCE_WINDOW_PATH,
validate: {
body: bodySchema,
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ import { IRouter } from '@kbn/core/server';
import { schema } from '@kbn/config-schema';
import { ILicenseState } from '../../lib';
import { verifyAccessAndContext } from '../lib';
import { AlertingRequestHandlerContext, INTERNAL_BASE_ALERTING_API_PATH } from '../../types';
import {
AlertingRequestHandlerContext,
INTERNAL_ALERTING_API_MAINTENANCE_WINDOW_PATH,
} from '../../types';
import { MAINTENANCE_WINDOW_API_PRIVILEGES } from '../../../common';

const paramSchema = schema.object({
Expand All @@ -22,7 +25,7 @@ export const deleteMaintenanceWindowRoute = (
) => {
router.delete(
{
path: `${INTERNAL_BASE_ALERTING_API_PATH}/rules/maintenance_window/{id}`,
path: `${INTERNAL_ALERTING_API_MAINTENANCE_WINDOW_PATH}/{id}`,
validate: {
params: paramSchema,
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@
import { IRouter } from '@kbn/core/server';
import { ILicenseState } from '../../lib';
import { verifyAccessAndContext, rewriteMaintenanceWindowRes } from '../lib';
import { AlertingRequestHandlerContext, INTERNAL_BASE_ALERTING_API_PATH } from '../../types';
import {
AlertingRequestHandlerContext,
INTERNAL_ALERTING_API_MAINTENANCE_WINDOW_PATH,
} from '../../types';
import { MAINTENANCE_WINDOW_API_PRIVILEGES } from '../../../common';

export const findMaintenanceWindowsRoute = (
Expand All @@ -17,7 +20,7 @@ export const findMaintenanceWindowsRoute = (
) => {
router.get(
{
path: `${INTERNAL_BASE_ALERTING_API_PATH}/rules/maintenance_window/_find`,
path: `${INTERNAL_ALERTING_API_MAINTENANCE_WINDOW_PATH}/_find`,
validate: {},
options: {
tags: [`access:${MAINTENANCE_WINDOW_API_PRIVILEGES.READ_MAINTENANCE_WINDOW}`],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ import { IRouter } from '@kbn/core/server';
import { schema } from '@kbn/config-schema';
import { ILicenseState } from '../../lib';
import { verifyAccessAndContext, rewritePartialMaintenanceBodyRes } from '../lib';
import { AlertingRequestHandlerContext, INTERNAL_BASE_ALERTING_API_PATH } from '../../types';
import {
AlertingRequestHandlerContext,
INTERNAL_ALERTING_API_MAINTENANCE_WINDOW_PATH,
} from '../../types';
import { MAINTENANCE_WINDOW_API_PRIVILEGES } from '../../../common';

const paramSchema = schema.object({
Expand All @@ -22,7 +25,7 @@ export const finishMaintenanceWindowRoute = (
) => {
router.post(
{
path: `${INTERNAL_BASE_ALERTING_API_PATH}/rules/maintenance_window/{id}/_finish`,
path: `${INTERNAL_ALERTING_API_MAINTENANCE_WINDOW_PATH}/{id}/_finish`,
validate: {
params: paramSchema,
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ import { IRouter } from '@kbn/core/server';
import { schema } from '@kbn/config-schema';
import { ILicenseState } from '../../lib';
import { verifyAccessAndContext, rewriteMaintenanceWindowRes } from '../lib';
import { AlertingRequestHandlerContext, INTERNAL_BASE_ALERTING_API_PATH } from '../../types';
import {
AlertingRequestHandlerContext,
INTERNAL_ALERTING_API_MAINTENANCE_WINDOW_PATH,
} from '../../types';
import { MAINTENANCE_WINDOW_API_PRIVILEGES } from '../../../common';

const paramSchema = schema.object({
Expand All @@ -22,7 +25,7 @@ export const getMaintenanceWindowRoute = (
) => {
router.get(
{
path: `${INTERNAL_BASE_ALERTING_API_PATH}/rules/maintenance_window/{id}`,
path: `${INTERNAL_ALERTING_API_MAINTENANCE_WINDOW_PATH}/{id}`,
validate: {
params: paramSchema,
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@ import {
RewriteRequestCase,
rewritePartialMaintenanceBodyRes,
} from '../lib';
import { AlertingRequestHandlerContext, INTERNAL_BASE_ALERTING_API_PATH } from '../../types';
import {
AlertingRequestHandlerContext,
INTERNAL_ALERTING_API_MAINTENANCE_WINDOW_PATH,
} from '../../types';
import { MaintenanceWindowSOProperties, MAINTENANCE_WINDOW_API_PRIVILEGES } from '../../../common';

const paramSchema = schema.object({
Expand Down Expand Up @@ -49,7 +52,7 @@ export const updateMaintenanceWindowRoute = (
) => {
router.post(
{
path: `${INTERNAL_BASE_ALERTING_API_PATH}/rules/maintenance_window/{id}`,
path: `${INTERNAL_ALERTING_API_MAINTENANCE_WINDOW_PATH}/{id}`,
validate: {
body: bodySchema,
params: paramSchema,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* 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 { INTERNAL_ALERTING_API_MAINTENANCE_WINDOW_PATH } from '@kbn/alerting-plugin/common';
import type { MaintenanceWindowCreateBody } from '@kbn/alerting-plugin/common';
import type { AsApiContract } from '@kbn/alerting-plugin/server/routes/lib';
import { cleanKibana } from '../../tasks/common';
import { login, visit } from '../../tasks/login';
import { DETECTIONS_RULE_MANAGEMENT_URL } from '../../urls/navigation';

describe('Maintenance window callout on Rule Management page', () => {
let maintenanceWindowId = '';

before(() => {
cleanKibana();
login();

const body: AsApiContract<MaintenanceWindowCreateBody> = {
title: 'My maintenance window',
duration: 60000, // 1 minute
r_rule: {
dtstart: new Date().toISOString(),
tzid: 'Europe/Amsterdam',
freq: 0,
count: 1,
},
};

// Create a test maintenance window
cy.request({
method: 'POST',
url: INTERNAL_ALERTING_API_MAINTENANCE_WINDOW_PATH,
headers: { 'kbn-xsrf': 'cypress-creds' },
body,
}).then((response) => {
maintenanceWindowId = response.body.id;
});
});

after(() => {
// Delete a test maintenance window
cy.request({
method: 'DELETE',
url: `${INTERNAL_ALERTING_API_MAINTENANCE_WINDOW_PATH}/${maintenanceWindowId}`,
headers: { 'kbn-xsrf': 'cypress-creds' },
});
});

it('Displays the callout when there are running maintenance windows', () => {
visit(DETECTIONS_RULE_MANAGEMENT_URL);

cy.contains('A maintenance window is currently running');
});
});
3 changes: 2 additions & 1 deletion x-pack/plugins/security_solution/cypress/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"force": true
},
"@kbn/rison",
"@kbn/datemath"
"@kbn/datemath",
"@kbn/alerting-plugin"
]
}
Original file line number Diff line number Diff line change
@@ -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 { MaintenanceWindow } from '@kbn/alerting-plugin/common/maintenance_window';
import { INTERNAL_ALERTING_API_GET_ACTIVE_MAINTENANCE_WINDOWS_PATH } from '@kbn/alerting-plugin/common';
import { KibanaServices } from '../../../../common/lib/kibana';

export const fetchActiveMaintenanceWindows = async (
signal?: AbortSignal
): Promise<MaintenanceWindow[]> =>
KibanaServices.get().http.fetch(INTERNAL_ALERTING_API_GET_ACTIVE_MAINTENANCE_WINDOWS_PATH, {
method: 'GET',
signal,
});
Loading

0 comments on commit 675ed0e

Please sign in to comment.