mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[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:
parent
2d0f99c59c
commit
cc524d1d6d
5 changed files with 923 additions and 0 deletions
|
@ -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');
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
|
@ -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');
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
|
@ -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}`
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
|
@ -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');
|
||||
});
|
||||
});
|
||||
});
|
|
@ -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');
|
||||
});
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue