[Detection Engine] Add back cypress tests that were removed (#172532)

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Yara Tercero 2023-12-05 00:25:16 -08:00 committed by GitHub
parent 2d0f99c59c
commit cc524d1d6d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 923 additions and 0 deletions

View file

@ -0,0 +1,200 @@
/*
* 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 { ROLES } from '@kbn/security-solution-plugin/common/test';
import { ALERTS_URL } from '../../../../../urls/navigation';
import { RULES_MANAGEMENT_URL } from '../../../../../urls/rules_management';
import { ruleDetailsUrl } from '../../../../../urls/rule_details';
import { getNewRule } from '../../../../../objects/rule';
import { PAGE_TITLE } from '../../../../../screens/common/page';
import { login } from '../../../../../tasks/login';
import { visit } from '../../../../../tasks/navigation';
import { createRule, deleteCustomRule } from '../../../../../tasks/api_calls/rules';
import {
getCallOut,
NEED_ADMIN_FOR_UPDATE_CALLOUT,
waitForCallOutToBeShown,
} from '../../../../../tasks/common/callouts';
const loadPageAsPlatformEngineerUser = (url: string) => {
login(ROLES.soc_manager);
visit(url);
waitForPageTitleToBeShown();
};
const waitForPageTitleToBeShown = () => {
cy.get(PAGE_TITLE).should('be.visible');
};
describe(
'Detections > Need Admin Callouts indicating an admin is needed to migrate the alert data set',
{ tags: ['@ess', '@skipInServerless'] },
() => {
before(() => {
// First, we have to open the app on behalf of a privileged user in order to initialize it.
// Otherwise the app will be disabled and show a "welcome"-like page.
login();
visit(ALERTS_URL);
waitForPageTitleToBeShown();
});
context(
'The users index_mapping_outdated is "true" and their admin callouts should show up',
() => {
beforeEach(() => {
// Index mapping outdated is forced to return true as being outdated so that we get the
// need admin callouts being shown.
cy.intercept('GET', '/api/detection_engine/index', (req) => {
req.reply((res) => {
res.send(200, {
index_mapping_outdated: true,
name: '.alerts-security.alerts-default',
});
});
});
});
context('On Detections home page', () => {
beforeEach(() => {
loadPageAsPlatformEngineerUser(ALERTS_URL);
});
it('We show the need admin primary callout', () => {
waitForCallOutToBeShown(NEED_ADMIN_FOR_UPDATE_CALLOUT, 'primary');
});
});
context('On Rules Management page', () => {
beforeEach(() => {
loadPageAsPlatformEngineerUser(RULES_MANAGEMENT_URL);
});
it('We show 1 primary callout of need admin', () => {
waitForCallOutToBeShown(NEED_ADMIN_FOR_UPDATE_CALLOUT, 'primary');
});
});
context('On Rule Details page', () => {
beforeEach(() => {
createRule(getNewRule({ rule_id: 'rule_testing' })).then((rule) =>
loadPageAsPlatformEngineerUser(ruleDetailsUrl(rule.body.id))
);
});
afterEach(() => {
deleteCustomRule();
});
it('We show 1 primary callout', () => {
waitForCallOutToBeShown(NEED_ADMIN_FOR_UPDATE_CALLOUT, 'primary');
});
});
}
);
context(
'The users index_mapping_outdated is "false" and their admin callouts should not show up ',
() => {
beforeEach(() => {
// Index mapping outdated is forced to return true as being outdated so that we get the
// need admin callouts being shown.
cy.intercept('GET', '/api/detection_engine/index', {
index_mapping_outdated: false,
name: '.alerts-security.alerts-default',
});
});
context('On Detections home page', () => {
beforeEach(() => {
loadPageAsPlatformEngineerUser(ALERTS_URL);
});
it('We show the need admin primary callout', () => {
getCallOut(NEED_ADMIN_FOR_UPDATE_CALLOUT).should('not.exist');
});
});
context('On Rules Management page', () => {
beforeEach(() => {
loadPageAsPlatformEngineerUser(RULES_MANAGEMENT_URL);
});
it('We show 1 primary callout of need admin', () => {
getCallOut(NEED_ADMIN_FOR_UPDATE_CALLOUT).should('not.exist');
});
});
context('On Rule Details page', () => {
beforeEach(() => {
createRule(getNewRule({ rule_id: 'rule_testing' })).then((rule) =>
loadPageAsPlatformEngineerUser(ruleDetailsUrl(rule.body.id))
);
});
afterEach(() => {
deleteCustomRule();
});
it('We show 1 primary callout', () => {
getCallOut(NEED_ADMIN_FOR_UPDATE_CALLOUT).should('not.exist');
});
});
}
);
context(
'The users index_mapping_outdated is "null" and their admin callouts should not show up ',
() => {
beforeEach(() => {
// Index mapping outdated is forced to return true as being outdated so that we get the
// need admin callouts being shown.
cy.intercept('GET', '/api/detection_engine/index', {
index_mapping_outdated: null,
name: '.alerts-security.alerts-default',
});
});
context('On Detections home page', () => {
beforeEach(() => {
loadPageAsPlatformEngineerUser(ALERTS_URL);
});
it('We show the need admin primary callout', () => {
getCallOut(NEED_ADMIN_FOR_UPDATE_CALLOUT).should('not.exist');
});
});
context('On Rules Management page', () => {
beforeEach(() => {
loadPageAsPlatformEngineerUser(RULES_MANAGEMENT_URL);
});
it('We show 1 primary callout of need admin', () => {
getCallOut(NEED_ADMIN_FOR_UPDATE_CALLOUT).should('not.exist');
});
});
context('On Rule Details page', () => {
beforeEach(() => {
createRule(getNewRule({ rule_id: 'rule_testing' })).then((rule) =>
loadPageAsPlatformEngineerUser(ruleDetailsUrl(rule.body.id))
);
});
afterEach(() => {
deleteCustomRule();
});
it('We show 1 primary callout', () => {
getCallOut(NEED_ADMIN_FOR_UPDATE_CALLOUT).should('not.exist');
});
});
}
);
}
);

View file

@ -0,0 +1,148 @@
/*
* 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 { ROLES } from '@kbn/security-solution-plugin/common/test';
import { ALERTS_URL } from '../../../../../urls/navigation';
import { RULES_MANAGEMENT_URL } from '../../../../../urls/rules_management';
import { getNewRule } from '../../../../../objects/rule';
import { PAGE_TITLE } from '../../../../../screens/common/page';
import { login } from '../../../../../tasks/login';
import { visit } from '../../../../../tasks/navigation';
import { createRule, deleteCustomRule } from '../../../../../tasks/api_calls/rules';
import {
getCallOut,
waitForCallOutToBeShown,
dismissCallOut,
MISSING_PRIVILEGES_CALLOUT,
} from '../../../../../tasks/common/callouts';
import { ruleDetailsUrl } from '../../../../../urls/rule_details';
const loadPageAsReadOnlyUser = (url: string) => {
login(ROLES.t1_analyst);
visit(url);
waitForPageTitleToBeShown();
};
const loadPageAsPlatformEngineer = (url: string) => {
login(ROLES.platform_engineer);
visit(url);
waitForPageTitleToBeShown();
};
const reloadPage = () => {
cy.reload();
waitForPageTitleToBeShown();
};
const waitForPageTitleToBeShown = () => {
cy.get(PAGE_TITLE).should('be.visible');
};
describe(
'Detections > Callouts',
{ tags: ['@ess', '@serverless', '@brokenInServerlessQA'] },
() => {
before(() => {
// First, we have to open the app on behalf of a privileged user in order to initialize it.
// Otherwise the app will be disabled and show a "welcome"-like page.
login();
visit(ALERTS_URL);
waitForPageTitleToBeShown();
});
context('indicating read-only access to resources', () => {
context('On Detections home page', () => {
beforeEach(() => {
loadPageAsReadOnlyUser(ALERTS_URL);
});
it('We show one primary callout', () => {
waitForCallOutToBeShown(MISSING_PRIVILEGES_CALLOUT, 'primary');
});
context('When a user clicks Dismiss on the callout', () => {
it('We hide it and persist the dismissal', () => {
waitForCallOutToBeShown(MISSING_PRIVILEGES_CALLOUT, 'primary');
dismissCallOut(MISSING_PRIVILEGES_CALLOUT);
reloadPage();
getCallOut(MISSING_PRIVILEGES_CALLOUT).should('not.exist');
});
});
});
// FYI: Rules Management check moved to ../detection_rules/all_rules_read_only.spec.ts
context('On Rule Details page', () => {
beforeEach(() => {
createRule(getNewRule()).then((rule) =>
loadPageAsReadOnlyUser(ruleDetailsUrl(rule.body.id))
);
});
afterEach(() => {
deleteCustomRule();
});
it('We show one primary callout', () => {
waitForCallOutToBeShown(MISSING_PRIVILEGES_CALLOUT, 'primary');
});
context('When a user clicks Dismiss on the callouts', () => {
it('We hide them and persist the dismissal', () => {
waitForCallOutToBeShown(MISSING_PRIVILEGES_CALLOUT, 'primary');
dismissCallOut(MISSING_PRIVILEGES_CALLOUT);
reloadPage();
getCallOut(MISSING_PRIVILEGES_CALLOUT).should('not.exist');
});
});
});
});
context('indicating read-write access to resources', () => {
context('On Detections home page', () => {
beforeEach(() => {
loadPageAsPlatformEngineer(ALERTS_URL);
});
it('We show no callout', () => {
getCallOut(MISSING_PRIVILEGES_CALLOUT).should('not.exist');
});
});
context('On Rules Management page', () => {
beforeEach(() => {
login(ROLES.platform_engineer);
loadPageAsPlatformEngineer(RULES_MANAGEMENT_URL);
});
it('We show no callout', () => {
getCallOut(MISSING_PRIVILEGES_CALLOUT).should('not.exist');
});
});
context('On Rule Details page', () => {
beforeEach(() => {
createRule(getNewRule()).then((rule) =>
loadPageAsPlatformEngineer(ruleDetailsUrl(rule.body.id))
);
});
afterEach(() => {
deleteCustomRule();
});
it('We show no callouts', () => {
getCallOut(MISSING_PRIVILEGES_CALLOUT).should('not.exist');
});
});
});
}
);

View file

@ -0,0 +1,203 @@
/*
* 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 { disableExpandableFlyout } from '../../../../../tasks/api_calls/kibana_advanced_settings';
import { getNewThreatIndicatorRule, indicatorRuleMatchingDoc } from '../../../../../objects/rule';
import { login } from '../../../../../tasks/login';
import {
JSON_TEXT,
TABLE_CELL,
TABLE_ROWS,
THREAT_DETAILS_VIEW,
ENRICHMENT_COUNT_NOTIFICATION,
INDICATOR_MATCH_ENRICHMENT_SECTION,
INVESTIGATION_TIME_ENRICHMENT_SECTION,
THREAT_DETAILS_ACCORDION,
} from '../../../../../screens/alerts_details';
import { TIMELINE_FIELD } from '../../../../../screens/rule_details';
import {
expandFirstAlert,
setEnrichmentDates,
viewThreatIntelTab,
} from '../../../../../tasks/alerts';
import { createRule } from '../../../../../tasks/api_calls/rules';
import { openJsonView, openThreatIndicatorDetails } from '../../../../../tasks/alerts_details';
import { addsFieldsToTimeline, visitRuleDetailsPage } from '../../../../../tasks/rule_details';
// TODO: https://github.com/elastic/kibana/issues/161539
describe(
'Threat Match Enrichment',
{ tags: ['@ess', '@serverless', '@brokenInServerless'] },
() => {
before(() => {
// illegal_argument_exception: unknown setting [index.lifecycle.rollover_alias]
cy.task('esArchiverLoad', { archiveName: 'threat_indicator' });
cy.task('esArchiverLoad', { archiveName: 'suspicious_source_event' });
login();
disableExpandableFlyout();
});
after(() => {
cy.task('esArchiverUnload', 'threat_indicator');
cy.task('esArchiverUnload', 'suspicious_source_event');
});
beforeEach(() => {
login();
createRule({ ...getNewThreatIndicatorRule(), rule_id: 'rule_testing', enabled: true }).then(
(rule) => visitRuleDetailsPage(rule.body.id)
);
});
// TODO: https://github.com/elastic/kibana/issues/161539
// Skipped: https://github.com/elastic/kibana/issues/162818
it.skip('Displays enrichment matched.* fields on the timeline', () => {
const expectedFields = {
'threat.enrichments.matched.atomic': indicatorRuleMatchingDoc.atomic,
'threat.enrichments.matched.type': indicatorRuleMatchingDoc.matchedType,
'threat.enrichments.matched.field':
getNewThreatIndicatorRule().threat_mapping[0].entries[0].field,
'threat.enrichments.matched.id': indicatorRuleMatchingDoc.matchedId,
'threat.enrichments.matched.index': indicatorRuleMatchingDoc.matchedIndex,
};
const fields = Object.keys(expectedFields) as Array<keyof typeof expectedFields>;
addsFieldsToTimeline('threat.enrichments.matched', fields);
fields.forEach((field) => {
cy.get(TIMELINE_FIELD(field)).should('have.text', expectedFields[field]);
});
});
it('Displays persisted enrichments on the JSON view', () => {
const expectedEnrichment = [
{
'indicator.file.hash.md5': ['9b6c3518a91d23ed77504b5416bfb5b3'],
'matched.index': ['logs-ti_abusech.malware'],
'indicator.file.type': ['elf'],
'indicator.file.hash.tlsh': [
'6D7312E017B517CC1371A8353BED205E9128223972AE35302E97528DF957703BAB2DBE',
],
'feed.name': ['AbuseCH malware'],
'indicator.file.hash.ssdeep': [
'1536:87vbq1lGAXSEYQjbChaAU2yU23M51DjZgSQAvcYkFtZTjzBht5:8D+CAXFYQChaAUk5ljnQssL',
],
'indicator.file.hash.sha256': [
'a04ac6d98ad989312783d4fe3456c53730b212c79a426fb215708b6c6daa3de3',
],
'indicator.first_seen': ['2021-03-10T08:02:14.000Z'],
'matched.field': ['myhash.mysha256'],
'indicator.type': ['file'],
'matched.type': ['indicator_match_rule'],
'matched.id': ['84cf452c1e0375c3d4412cb550bd1783358468a3b3b777da4829d72c7d6fb74f'],
'matched.atomic': ['a04ac6d98ad989312783d4fe3456c53730b212c79a426fb215708b6c6daa3de3'],
'indicator.file.size': [80280],
},
];
expandFirstAlert();
openJsonView();
cy.get(JSON_TEXT).then((x) => {
const parsed = JSON.parse(x.text());
expect(parsed.fields['threat.enrichments']).to.deep.equal(expectedEnrichment);
});
});
it('Displays threat indicator details on the threat intel tab', () => {
const expectedThreatIndicatorData = [
{ field: 'feed.name', value: 'AbuseCH malware' },
{ field: 'indicator.file.hash.md5', value: '9b6c3518a91d23ed77504b5416bfb5b3' },
{
field: 'indicator.file.hash.sha256',
value: 'a04ac6d98ad989312783d4fe3456c53730b212c79a426fb215708b6c6daa3de3',
},
{
field: 'indicator.file.hash.ssdeep',
value: '1536:87vbq1lGAXSEYQjbChaAU2yU23M51DjZgSQAvcYkFtZTjzBht5:8D+CAXFYQChaAUk5ljnQssL',
},
{
field: 'indicator.file.hash.tlsh',
value: '6D7312E017B517CC1371A8353BED205E9128223972AE35302E97528DF957703BAB2DBE',
},
{ field: 'indicator.file.size', value: '80280' },
{ field: 'indicator.file.type', value: 'elf' },
{ field: 'indicator.first_seen', value: '2021-03-10T08:02:14.000Z' },
{ field: 'indicator.type', value: 'file' },
{
field: 'matched.atomic',
value: 'a04ac6d98ad989312783d4fe3456c53730b212c79a426fb215708b6c6daa3de3',
},
{ field: 'matched.field', value: 'myhash.mysha256' },
{
field: 'matched.id',
value: '84cf452c1e0375c3d4412cb550bd1783358468a3b3b777da4829d72c7d6fb74f',
},
{ field: 'matched.index', value: 'logs-ti_abusech.malware' },
{ field: 'matched.type', value: 'indicator_match_rule' },
];
expandFirstAlert();
openThreatIndicatorDetails();
cy.get(ENRICHMENT_COUNT_NOTIFICATION).should('have.text', '1');
cy.get(THREAT_DETAILS_VIEW).within(() => {
cy.get(TABLE_ROWS).should('have.length', expectedThreatIndicatorData.length);
expectedThreatIndicatorData.forEach((row, index) => {
cy.get(TABLE_ROWS)
.eq(index)
.within(() => {
cy.get(TABLE_CELL).eq(0).should('have.text', row.field);
cy.get(TABLE_CELL).eq(1).should('have.text', row.value);
});
});
});
});
describe('with additional indicators', () => {
before(() => {
cy.task('esArchiverLoad', { archiveName: 'threat_indicator2' });
});
after(() => {
cy.task('esArchiverUnload', 'threat_indicator2');
});
it('Displays matched fields from both indicator match rules and investigation time enrichments on Threat Intel tab', () => {
const indicatorMatchRuleEnrichment = {
field: 'myhash.mysha256',
value: 'a04ac6d98ad989312783d4fe3456c53730b212c79a426fb215708b6c6daa3de3',
feedName: 'AbuseCH malware',
};
const investigationTimeEnrichment = {
field: 'source.ip',
value: '192.168.1.1',
feedName: 'feed_name',
};
expandFirstAlert();
viewThreatIntelTab();
setEnrichmentDates('08/05/2018 10:00 AM');
cy.get(`${INDICATOR_MATCH_ENRICHMENT_SECTION} ${THREAT_DETAILS_ACCORDION}`)
.should('exist')
.should(
'have.text',
`${indicatorMatchRuleEnrichment.field} ${indicatorMatchRuleEnrichment.value} from ${indicatorMatchRuleEnrichment.feedName}`
);
cy.get(`${INVESTIGATION_TIME_ENRICHMENT_SECTION} ${THREAT_DETAILS_ACCORDION}`)
.should('exist')
.should(
'have.text',
`${investigationTimeEnrichment.field} ${investigationTimeEnrichment.value} from ${investigationTimeEnrichment.feedName}`
);
});
});
}
);

View file

@ -0,0 +1,267 @@
/*
* 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 { ROLES } from '@kbn/security-solution-plugin/common/test';
import { getNewRule } from '../../../../../objects/rule';
import {
ALERTS_COUNT,
CLOSE_SELECTED_ALERTS_BTN,
MARK_ALERT_ACKNOWLEDGED_BTN,
SELECTED_ALERTS,
TAKE_ACTION_POPOVER_BTN,
TIMELINE_CONTEXT_MENU_BTN,
} from '../../../../../screens/alerts';
import {
selectNumberOfAlerts,
waitForAlerts,
markAcknowledgedFirstAlert,
markAlertsAcknowledged,
goToAcknowledgedAlerts,
closeFirstAlert,
closeAlerts,
goToClosedAlerts,
goToOpenedAlerts,
openAlerts,
openFirstAlert,
} from '../../../../../tasks/alerts';
import { createRule } from '../../../../../tasks/api_calls/rules';
import { deleteAlertsAndRules } from '../../../../../tasks/api_calls/common';
import { waitForAlertsToPopulate } from '../../../../../tasks/create_new_rule';
import { login } from '../../../../../tasks/login';
import { visit } from '../../../../../tasks/navigation';
import { ALERTS_URL } from '../../../../../urls/navigation';
// FLAKY: https://github.com/elastic/kibana/issues/169091
describe.skip('Changing alert status', { tags: ['@ess', '@serverless'] }, () => {
before(() => {
cy.task('esArchiverLoad', { archiveName: 'auditbeat_multiple' });
});
after(() => {
cy.task('esArchiverUnload', 'auditbeat_multiple');
});
context('Opening alerts', { tags: ['@ess', '@serverless'] }, () => {
beforeEach(() => {
login();
deleteAlertsAndRules();
createRule(getNewRule());
visit(ALERTS_URL);
waitForAlertsToPopulate();
selectNumberOfAlerts(3);
cy.get(SELECTED_ALERTS).should('have.text', `Selected 3 alerts`);
closeAlerts();
waitForAlerts();
});
it('can mark a closed alert as open', () => {
waitForAlertsToPopulate();
cy.get(ALERTS_COUNT)
.invoke('text')
.then((numberOfOpenedAlertsText) => {
const numberOfOpenedAlerts = parseInt(numberOfOpenedAlertsText, 10);
goToClosedAlerts();
waitForAlerts();
cy.get(ALERTS_COUNT)
.invoke('text')
.then((alertNumberString) => {
const numberOfAlerts = alertNumberString.split(' ')[0];
const numberOfAlertsToBeOpened = 1;
openFirstAlert();
waitForAlerts();
const expectedNumberOfAlerts = +numberOfAlerts - numberOfAlertsToBeOpened;
cy.get(ALERTS_COUNT).contains(expectedNumberOfAlerts);
goToOpenedAlerts();
waitForAlerts();
cy.get(ALERTS_COUNT).contains(`${numberOfOpenedAlerts + numberOfAlertsToBeOpened}`);
});
});
});
it('can bulk open alerts', () => {
waitForAlertsToPopulate();
cy.get(ALERTS_COUNT)
.invoke('text')
.then((numberOfOpenedAlertsText) => {
const numberOfOpenedAlerts = parseInt(numberOfOpenedAlertsText, 10);
goToClosedAlerts();
waitForAlerts();
cy.get(ALERTS_COUNT)
.invoke('text')
.then((alertNumberString) => {
const numberOfAlerts = alertNumberString.split(' ')[0];
const numberOfAlertsToBeOpened = 2;
const numberOfAlertsToBeSelected = 2;
selectNumberOfAlerts(numberOfAlertsToBeSelected);
cy.get(SELECTED_ALERTS).should(
'have.text',
`Selected ${numberOfAlertsToBeSelected} alerts`
);
openAlerts();
waitForAlerts();
const expectedNumberOfAlerts = +numberOfAlerts - numberOfAlertsToBeOpened;
cy.get(ALERTS_COUNT).contains(expectedNumberOfAlerts);
goToOpenedAlerts();
waitForAlerts();
cy.get(ALERTS_COUNT).contains(`${numberOfOpenedAlerts + numberOfAlertsToBeOpened}`);
});
});
});
});
context('Marking alerts as acknowledged', { tags: ['@ess', '@serverless'] }, () => {
beforeEach(() => {
login();
deleteAlertsAndRules();
createRule(getNewRule());
visit(ALERTS_URL);
waitForAlertsToPopulate();
});
it('can mark alert as acknowledged', () => {
cy.get(ALERTS_COUNT)
.invoke('text')
.then((alertNumberString) => {
const numberOfAlerts = alertNumberString.split(' ')[0];
const numberOfAlertsToBeMarkedAcknowledged = 1;
markAcknowledgedFirstAlert();
waitForAlerts();
const expectedNumberOfAlerts = +numberOfAlerts - numberOfAlertsToBeMarkedAcknowledged;
cy.get(ALERTS_COUNT).contains(expectedNumberOfAlerts);
goToAcknowledgedAlerts();
waitForAlerts();
cy.get(ALERTS_COUNT).contains(`${numberOfAlertsToBeMarkedAcknowledged}`);
});
});
it('can bulk mark alerts as acknowledged', () => {
cy.get(ALERTS_COUNT)
.invoke('text')
.then((alertNumberString) => {
const numberOfAlerts = alertNumberString.split(' ')[0];
const numberOfAlertsToBeMarkedAcknowledged = 2;
const numberOfAlertsToBeSelected = 2;
selectNumberOfAlerts(numberOfAlertsToBeSelected);
markAlertsAcknowledged();
waitForAlerts();
const expectedNumberOfAlerts = +numberOfAlerts - numberOfAlertsToBeMarkedAcknowledged;
cy.get(ALERTS_COUNT).contains(expectedNumberOfAlerts);
goToAcknowledgedAlerts();
waitForAlerts();
cy.get(ALERTS_COUNT).contains(numberOfAlertsToBeMarkedAcknowledged);
});
});
});
context('Closing alerts', { tags: ['@ess', '@serverless'] }, () => {
beforeEach(() => {
login();
deleteAlertsAndRules();
createRule(getNewRule({ rule_id: '1', max_signals: 100 }));
visit(ALERTS_URL);
waitForAlertsToPopulate();
});
it('can close an alert', () => {
const numberOfAlertsToBeClosed = 1;
cy.get(ALERTS_COUNT)
.invoke('text')
.then((alertNumberString) => {
const numberOfAlerts = alertNumberString.split(' ')[0];
cy.get(ALERTS_COUNT).should('have.text', `${numberOfAlerts} alerts`);
selectNumberOfAlerts(numberOfAlertsToBeClosed);
cy.get(SELECTED_ALERTS).should('have.text', `Selected ${numberOfAlertsToBeClosed} alert`);
closeFirstAlert();
waitForAlerts();
const expectedNumberOfAlertsAfterClosing = +numberOfAlerts - numberOfAlertsToBeClosed;
cy.get(ALERTS_COUNT).contains(expectedNumberOfAlertsAfterClosing);
goToClosedAlerts();
waitForAlerts();
cy.get(ALERTS_COUNT).contains(numberOfAlertsToBeClosed);
});
});
it('can bulk close alerts', () => {
const numberOfAlertsToBeClosed = 2;
cy.get(ALERTS_COUNT)
.invoke('text')
.then((alertNumberString) => {
const numberOfAlerts = alertNumberString.split(' ')[0];
cy.get(ALERTS_COUNT).should('have.text', `${numberOfAlerts} alerts`);
selectNumberOfAlerts(numberOfAlertsToBeClosed);
cy.get(SELECTED_ALERTS).should(
'have.text',
`Selected ${numberOfAlertsToBeClosed} alerts`
);
closeAlerts();
waitForAlerts();
const expectedNumberOfAlertsAfterClosing = +numberOfAlerts - numberOfAlertsToBeClosed;
cy.get(ALERTS_COUNT).contains(expectedNumberOfAlertsAfterClosing);
goToClosedAlerts();
waitForAlerts();
cy.get(ALERTS_COUNT).contains(numberOfAlertsToBeClosed);
});
});
});
// This test is unable to be run in serverless as `reader` is not available and viewer is currently reserved
// https://github.com/elastic/kibana/pull/169723#issuecomment-1793191007
// https://github.com/elastic/kibana/issues/170583
context('User is readonly', { tags: ['@ess', '@brokenInServerless'] }, () => {
beforeEach(() => {
login();
visit(ALERTS_URL);
deleteAlertsAndRules();
createRule(getNewRule());
login(ROLES.reader);
visit(ALERTS_URL);
waitForAlertsToPopulate();
});
it('should not allow users to change a single alert status', () => {
// This is due to the reader role which makes everything in security 'read only'
cy.get(TIMELINE_CONTEXT_MENU_BTN).should('not.exist');
});
it('should not allow users to bulk change the alert status', () => {
selectNumberOfAlerts(2);
cy.get(TAKE_ACTION_POPOVER_BTN).first().click();
cy.get(TAKE_ACTION_POPOVER_BTN).should('be.visible');
cy.get(CLOSE_SELECTED_ALERTS_BTN).should('not.exist');
cy.get(MARK_ALERT_ACKNOWLEDGED_BTN).should('not.exist');
});
});
});

View file

@ -0,0 +1,105 @@
/*
* 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 { getNewRule } from '../../../../../objects/rule';
import {
clickAlertTag,
openAlertTaggingBulkActionMenu,
selectNumberOfAlerts,
updateAlertTags,
} from '../../../../../tasks/alerts';
import { createRule } from '../../../../../tasks/api_calls/rules';
import { deleteAlertsAndRules } from '../../../../../tasks/api_calls/common';
import { login } from '../../../../../tasks/login';
import { visitWithTimeRange } from '../../../../../tasks/navigation';
import { ALERTS_URL } from '../../../../../urls/navigation';
import { waitForAlertsToPopulate } from '../../../../../tasks/create_new_rule';
import {
ALERTS_TABLE_ROW_LOADER,
MIXED_ALERT_TAG,
SELECTED_ALERT_TAG,
UNSELECTED_ALERT_TAG,
} from '../../../../../screens/alerts';
describe('Alert tagging', { tags: ['@ess', '@serverless'] }, () => {
before(() => {
cy.task('esArchiverLoad', { archiveName: 'endpoint' });
cy.task('esArchiverLoad', { archiveName: 'auditbeat_multiple' });
});
after(() => {
cy.task('esArchiverUnload', 'endpoint');
cy.task('esArchiverUnload', 'auditbeat_multiple');
});
beforeEach(() => {
login();
deleteAlertsAndRules();
createRule(getNewRule({ rule_id: 'new custom rule' }));
visitWithTimeRange(ALERTS_URL);
waitForAlertsToPopulate();
});
it('Add and remove a tag using the alert bulk action menu', () => {
// Add a tag to one alert
selectNumberOfAlerts(1);
openAlertTaggingBulkActionMenu();
clickAlertTag('Duplicate');
updateAlertTags();
cy.get(ALERTS_TABLE_ROW_LOADER).should('not.exist');
selectNumberOfAlerts(1);
openAlertTaggingBulkActionMenu();
cy.get(SELECTED_ALERT_TAG).contains('Duplicate');
// Remove tag from that alert
clickAlertTag('Duplicate');
updateAlertTags();
cy.get(ALERTS_TABLE_ROW_LOADER).should('not.exist');
selectNumberOfAlerts(1);
openAlertTaggingBulkActionMenu();
cy.get(UNSELECTED_ALERT_TAG).first().contains('Duplicate');
});
it('Add a tag using the alert bulk action menu with mixed state', () => {
// Add tag to one alert first
selectNumberOfAlerts(1);
openAlertTaggingBulkActionMenu();
clickAlertTag('Duplicate');
updateAlertTags();
cy.get(ALERTS_TABLE_ROW_LOADER).should('not.exist');
// Then add tags to both alerts
selectNumberOfAlerts(5);
openAlertTaggingBulkActionMenu();
cy.get(MIXED_ALERT_TAG).contains('Duplicate');
clickAlertTag('Duplicate');
updateAlertTags();
cy.get(ALERTS_TABLE_ROW_LOADER).should('not.exist');
selectNumberOfAlerts(5);
openAlertTaggingBulkActionMenu();
cy.get(SELECTED_ALERT_TAG).contains('Duplicate');
});
it('Remove a tag using the alert bulk action menu with mixed state', () => {
// Add tag to one alert first
selectNumberOfAlerts(1);
openAlertTaggingBulkActionMenu();
clickAlertTag('Duplicate');
updateAlertTags();
cy.get(ALERTS_TABLE_ROW_LOADER).should('not.exist');
waitForAlertsToPopulate();
// Then remove tags from both alerts
selectNumberOfAlerts(2);
openAlertTaggingBulkActionMenu();
cy.get(MIXED_ALERT_TAG).contains('Duplicate');
clickAlertTag('Duplicate');
clickAlertTag('Duplicate'); // Clicking twice will return to unselected state
updateAlertTags();
cy.get(ALERTS_TABLE_ROW_LOADER).should('not.exist');
selectNumberOfAlerts(2);
openAlertTaggingBulkActionMenu();
cy.get(UNSELECTED_ALERT_TAG).first().contains('Duplicate');
});
});