Skip to content

Commit

Permalink
## [Security Solution] Alerts Treemap and Multi-Dimensional Alert Gro…
Browse files Browse the repository at this point in the history
…uping

This PR introduces the new _Treemap_ and _Multi-Dimensional Alert Grouping_ to the Alerts page.

The initial commit was developed as an _ON week_ proof of concept (POC). It has since been updated to incorporate product and UX feedback.

### Alerts treemap

The new _Alerts_ page treemap is shown in the screenshot below:

![treemap](https://user-images.githubusercontent.com/4459398/178233664-c45be7ca-b03e-40b9-b423-aeeaa47461c0.png)

_Above: The new `treemap` in the Alerts page_

- Alerts are colored by risk score
- Clicking on a cell instantly filters the alerts page
- Treemap legend items may be added to filters and Timeline investigations
- The new treemap supports multi-dimensional grouping and filtering
  - Alerts are grouped by `kibana.alert.rule.name` and `host.name` by default

### Multi-Dimensional Alert Grouping

The table on the Alerts page, which previously supported grouping by a single field, has also been enhanced to support multi-dimensional grouping, per the screenshot below:

![alerts-table-multi-dimensional-grouping](https://user-images.githubusercontent.com/4459398/178240710-ecf66799-35a8-4874-8882-5ccfcccc86fe.png)

_Above: The table in the Alerts page, enhanced to support multi-dimensional grouping_

## Filtering the Alerts page by risk score

Every rule, including prebuilt Elastic rules and custom rules created by users, must specify a risk score at rule creation time, per the screenshot below:

![rule_risk_score_configuration](https://user-images.githubusercontent.com/4459398/156712042-19b71f53-f337-4aed-bebf-ce10ea2b9f63.png)

_Above: Every rule has a risk score specified when it's created_

The colors of the alerts displayed in the treemap are determined by the rule's risk score. This makes it easy to quickly filter the entire alerts page by clicking on the riskiest alerts.

Clicking on a cell in the treemap adds two filters, one for each group by field, per the screenshot below:

![two-filters](https://user-images.githubusercontent.com/4459398/178252768-7c66dc5e-8a3c-41d8-95e2-eeca20133127.png)

_Above: Two filters, (one for each group by field), are added to the page when a cell is clicked_

The Alerts page updates instantly when filters are added or removed. In the screenshot below, the 2nd filter was removed to filter the page to all `mimikatz process started` alerts:

![second-filter-removed](https://user-images.githubusercontent.com/4459398/178253726-66905d60-99da-4d76-9ea1-744cb53abd6f.png)

_Above: Removing the 2nd filter, a specific `host.name`, revealed all the hosts in the `mimikatz process started` alerts_

### Switching views

Users may switch between the following views:

- Table
- Trend (default)
- Treemap

per the screenshot below:

![view-selection](https://user-images.githubusercontent.com/4459398/178242001-6868c751-ffa6-486f-b81a-81a4d5912877.png)

_Above: View selection_

The default _Trend_ view is shown in the screenshot below:

![trend-view](https://user-images.githubusercontent.com/4459398/178242769-58d6c800-69db-4e14-87e4-9232f3e35427.png)

_Above: The (default) Trend view_

- The Trend chart's legend has been enhanced to display counts, per the design detailed in issue <elastic#120282>

- The Trend view only supports visualizing a single dimension. Hovering over the disabled `Group by top` select in the Trend view displays the tooltip shown in the screenshot below:

![tooltip](https://user-images.githubusercontent.com/4459398/178243356-9bfe7f54-5b31-4f61-a795-0cfa0a70285b.png)

_Above: The Trend view only supports visualizing a single dimension_

### Collapsing the panel

The panel may optionally be collapsed to save space, per the screenshot below:

![collapsed](https://user-images.githubusercontent.com/4459398/178244282-525d4c9f-a23b-4ec4-8f72-7e813e771687.png)

_Above: The panel (optionally) collapsed_

### User preferences are persisted to local storage

Previously, the _Group by_ selections on the Alerts page were always forgotten when users navigated away from the Alerts page. As a result, users had to re-select their preferred Group by fields every time they visited the page.

We now store all of the following preferences in local storage:

- View selection (Table, Trend, Treemap)
- Group by selections
- Panel collapse state

The preferences above are now restored the next time users return to the Alerts page.

### Group by field selection is synchronized between views

Group by field selection is synchronized between views. For example, if a user changes the Group by fields in the Treemap view and then switches to the Table view, the same Group by fields will be displayed in the Table view.

### Resetting Group by fields to their defaults

Users may reset the Group by fields to their defaults (`kibana.alert.rule.name` and `host.name`) for any visualization via the menu shown in the screenshot below:

![reset-group-by-fields](https://user-images.githubusercontent.com/4459398/178246997-70d89763-40d4-4c93-b0b6-b439fc3e22cd.png)

_Above: Resetting Group by fields to defaults via the menu_
  • Loading branch information
andrew-goldstein committed Jul 12, 2022
1 parent 137204e commit 1df7808
Show file tree
Hide file tree
Showing 111 changed files with 4,093 additions and 2,786 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@ export type ExperimentalFeatures = typeof allowedExperimentalValues;
* This object is then used to validate and parse the value entered.
*/
export const allowedExperimentalValues = Object.freeze({
alertsTreemapEnabled: true,
showAlertsPageTitle: true,
showChartsToggle: false,
tGridEnabled: true,
tGridEventRenderedViewEnabled: true,
excludePoliciesInFilterEnabled: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,14 @@ import {
waitForAlerts,
markAcknowledgedFirstAlert,
goToAcknowledgedAlerts,
clearGroupByTopInput,
closeAlerts,
closeFirstAlert,
goToClosedAlerts,
goToOpenedAlerts,
openAlerts,
openFirstAlert,
selectCountTable,
} from '../../tasks/alerts';
import { createCustomRuleEnabled } from '../../tasks/api_calls/rules';
import { cleanKibana, deleteAlertsAndRules } from '../../tasks/common';
Expand Down Expand Up @@ -53,6 +55,8 @@ describe('Changing alert status', () => {
cy.get(SELECTED_ALERTS).should('have.text', `Selected 3 alerts`);
closeAlerts();
waitForAlerts();
selectCountTable();
clearGroupByTopInput();
});

it('Open one alert when more than one closed alerts are selected', () => {
Expand Down Expand Up @@ -110,6 +114,8 @@ describe('Changing alert status', () => {
createCustomRuleEnabled(getNewRule());
visit(ALERTS_URL);
waitForAlertsToPopulate();
selectCountTable();
clearGroupByTopInput();
});
it('Mark one alert as acknowledged when more than one open alerts are selected', () => {
cy.get(ALERTS_COUNT)
Expand Down Expand Up @@ -148,6 +154,8 @@ describe('Changing alert status', () => {
createCustomRuleEnabled(getNewRule(), '1', '100m', 100);
visit(ALERTS_URL);
waitForAlertsToPopulate();
selectCountTable();
clearGroupByTopInput();
});
it('Closes and opens alerts', () => {
const numberOfAlertsToBeClosed = 3;
Expand Down Expand Up @@ -298,6 +306,8 @@ describe('Changing alert status', () => {
createCustomRuleEnabled(getNewRule());
visit(ALERTS_URL);
waitForAlertsToPopulate();
selectCountTable();
clearGroupByTopInput();
});
it('Mark one alert as acknowledged when more than one open alerts are selected', () => {
cy.get(ALERTS_COUNT)
Expand Down
10 changes: 8 additions & 2 deletions x-pack/plugins/security_solution/cypress/screens/alerts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
export const ADD_EXCEPTION_BTN = '[data-test-subj="add-exception-menu-item"]';

export const ALERT_COUNT_TABLE_FIRST_ROW_COUNT =
'[data-test-subj="alertsCountTable"] tr:nth-child(1) td:nth-child(3) .euiTableCellContent__text';
'[data-test-subj="alertsCountTable"] tr:nth-child(1) td:nth-child(2) .euiTableCellContent__text';

export const ALERT_CHECKBOX = '[data-test-subj~="select-event"].euiCheckbox__input';

Expand All @@ -33,6 +33,8 @@ export const ALERTS_COUNT =
export const ALERTS_TREND_SIGNAL_RULE_NAME_PANEL =
'[data-test-subj="render-content-kibana.alert.rule.name"]';

export const CHART_SELECT = '[data-test-subj="chartSelect"]';

export const CLOSE_ALERT_BTN = '[data-test-subj="close-alert-status"]';

export const CLOSE_SELECTED_ALERTS_BTN = '[data-test-subj="close-alert-status"]';
Expand All @@ -45,13 +47,15 @@ export const EMPTY_ALERT_TABLE = '[data-test-subj="tGridEmptyState"]';

export const EXPAND_ALERT_BTN = '[data-test-subj="expand-event"]';

export const GROUP_BY_TOP_INPUT = '[data-test-subj="groupByTop"] [data-test-subj="comboBoxInput"]';

export const HOST_NAME = '[data-test-subj^=formatted-field][data-test-subj$=host\\.name]';

export const ACKNOWLEDGED_ALERTS_FILTER_BTN = '[data-test-subj="acknowledgedAlerts"]';

export const LOADING_ALERTS_PANEL = '[data-test-subj="loading-alerts-panel"]';

export const MANAGE_ALERT_DETECTION_RULES_BTN = '[data-test-subj="navigation-rules"]';
export const MANAGE_ALERT_DETECTION_RULES_BTN = '[data-test-subj="manage-alert-detection-rules"]';

export const MARK_ALERT_ACKNOWLEDGED_BTN = '[data-test-subj="acknowledged-alert-status"]';

Expand All @@ -74,6 +78,8 @@ export const RULE_NAME = '[data-test-subj^=formatted-field][data-test-subj$=rule

export const SELECTED_ALERTS = '[data-test-subj="selectedShowBulkActionsButton"]';

export const SELECT_TABLE = '[data-test-subj="selectTable"]';

export const SEND_ALERT_TO_TIMELINE_BTN = '[data-test-subj="send-alert-to-timeline-button"]';

export const SEVERITY = '[data-test-subj^=formatted-field][data-test-subj$=severity]';
Expand Down
13 changes: 13 additions & 0 deletions x-pack/plugins/security_solution/cypress/tasks/alerts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,20 @@ import {
ADD_EXCEPTION_BTN,
ALERT_RISK_SCORE_HEADER,
ALERT_CHECKBOX,
CHART_SELECT,
CLOSE_ALERT_BTN,
CLOSE_SELECTED_ALERTS_BTN,
CLOSED_ALERTS_FILTER_BTN,
EXPAND_ALERT_BTN,
GROUP_BY_TOP_INPUT,
ACKNOWLEDGED_ALERTS_FILTER_BTN,
LOADING_ALERTS_PANEL,
MANAGE_ALERT_DETECTION_RULES_BTN,
MARK_ALERT_ACKNOWLEDGED_BTN,
OPEN_ALERT_BTN,
OPENED_ALERTS_FILTER_BTN,
SEND_ALERT_TO_TIMELINE_BTN,
SELECT_TABLE,
TAKE_ACTION_POPOVER_BTN,
TIMELINE_CONTEXT_MENU_BTN,
} from '../screens/alerts';
Expand Down Expand Up @@ -125,6 +128,16 @@ export const openAlerts = () => {
cy.get(OPEN_ALERT_BTN).click();
};

export const selectCountTable = () => {
cy.get(CHART_SELECT).click({ force: true });
cy.get(SELECT_TABLE).click();
};

export const clearGroupByTopInput = () => {
cy.get(GROUP_BY_TOP_INPUT).focus();
cy.get(GROUP_BY_TOP_INPUT).type('{backspace}');
};

export const goToAcknowledgedAlerts = () => {
cy.get(ACKNOWLEDGED_ALERTS_FILTER_BTN).click();
cy.get(REFRESH_BUTTON).should('not.have.attr', 'aria-label', 'Needs updating');
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

Loading

0 comments on commit 1df7808

Please sign in to comment.