mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[SIEM] Adds 'Create new rule' Cypress test (#59790)
* adds 'Creates and activates new rule' * loads data using es_archive * refactor test
This commit is contained in:
parent
29eda20237
commit
0f71886f83
18 changed files with 481 additions and 12 deletions
|
@ -4,10 +4,46 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { ELASTIC_RULES_BTN, RULES_TABLE, RULES_ROW } from '../screens/signal_detection_rules';
|
||||
import { newRule } from '../objects/rule';
|
||||
|
||||
import {
|
||||
ABOUT_DESCRIPTION,
|
||||
ABOUT_EXPECTED_URLS,
|
||||
ABOUT_FALSE_POSITIVES,
|
||||
ABOUT_MITRE,
|
||||
ABOUT_RISK,
|
||||
ABOUT_RULE_DESCRIPTION,
|
||||
ABOUT_SEVERITY,
|
||||
ABOUT_TAGS,
|
||||
ABOUT_TIMELINE,
|
||||
DEFINITION_CUSTOM_QUERY,
|
||||
DEFINITION_DESCRIPTION,
|
||||
DEFINITION_INDEX_PATTERNS,
|
||||
RULE_NAME_HEADER,
|
||||
SCHEDULE_DESCRIPTION,
|
||||
SCHEDULE_LOOPBACK,
|
||||
SCHEDULE_RUNS,
|
||||
} from '../screens/rule_details';
|
||||
import {
|
||||
CUSTOM_RULES_BTN,
|
||||
ELASTIC_RULES_BTN,
|
||||
RISK_SCORE,
|
||||
RULE_NAME,
|
||||
RULES_TABLE,
|
||||
RULES_ROW,
|
||||
SEVERITY,
|
||||
} from '../screens/signal_detection_rules';
|
||||
|
||||
import {
|
||||
createAndActivateRule,
|
||||
fillAboutRuleAndContinue,
|
||||
fillDefineRuleAndContinue,
|
||||
} from '../tasks/create_new_rule';
|
||||
import {
|
||||
changeToThreeHundredRowsPerPage,
|
||||
filterByCustomRules,
|
||||
goToCreateNewRule,
|
||||
goToRuleDetails,
|
||||
loadPrebuiltDetectionRules,
|
||||
waitForLoadElasticPrebuiltDetectionRulesTableToBeLoaded,
|
||||
waitForPrebuiltDetectionRulesToBeLoaded,
|
||||
|
@ -18,19 +54,26 @@ import {
|
|||
waitForSignalsIndexToBeCreated,
|
||||
waitForSignalsPanelToBeLoaded,
|
||||
} from '../tasks/detections';
|
||||
import { esArchiverLoadEmptyKibana, esArchiverUnloadEmptyKibana } from '../tasks/es_archiver';
|
||||
import { loginAndWaitForPageWithoutDateRange } from '../tasks/login';
|
||||
|
||||
import { DETECTIONS } from '../urls/navigation';
|
||||
|
||||
describe('Signal detection rules', () => {
|
||||
before(() => {
|
||||
esArchiverLoadEmptyKibana();
|
||||
loginAndWaitForPageWithoutDateRange(DETECTIONS);
|
||||
});
|
||||
it('Loads prebuilt rules', () => {
|
||||
waitForSignalsPanelToBeLoaded();
|
||||
waitForSignalsIndexToBeCreated();
|
||||
goToManageSignalDetectionRules();
|
||||
waitForLoadElasticPrebuiltDetectionRulesTableToBeLoaded();
|
||||
});
|
||||
|
||||
after(() => {
|
||||
esArchiverUnloadEmptyKibana();
|
||||
});
|
||||
|
||||
it('Loads prebuilt rules', () => {
|
||||
loadPrebuiltDetectionRules();
|
||||
waitForPrebuiltDetectionRulesToBeLoaded();
|
||||
|
||||
|
@ -47,4 +90,128 @@ describe('Signal detection rules', () => {
|
|||
cy.wrap($table.find(RULES_ROW).length).should('eql', expectedNumberOfRules);
|
||||
});
|
||||
});
|
||||
|
||||
it('Creates and activates new rule', () => {
|
||||
goToCreateNewRule();
|
||||
fillDefineRuleAndContinue(newRule);
|
||||
fillAboutRuleAndContinue(newRule);
|
||||
createAndActivateRule();
|
||||
|
||||
cy.get(CUSTOM_RULES_BTN)
|
||||
.invoke('text')
|
||||
.should('eql', 'Custom rules (1)');
|
||||
|
||||
changeToThreeHundredRowsPerPage();
|
||||
waitForRulesToBeLoaded();
|
||||
|
||||
const expectedNumberOfRules = 93;
|
||||
cy.get(RULES_TABLE).then($table => {
|
||||
cy.wrap($table.find(RULES_ROW).length).should('eql', expectedNumberOfRules);
|
||||
});
|
||||
|
||||
filterByCustomRules();
|
||||
|
||||
cy.get(RULES_TABLE).then($table => {
|
||||
cy.wrap($table.find(RULES_ROW).length).should('eql', 1);
|
||||
});
|
||||
cy.get(RULE_NAME)
|
||||
.invoke('text')
|
||||
.should('eql', newRule.name);
|
||||
cy.get(RISK_SCORE)
|
||||
.invoke('text')
|
||||
.should('eql', newRule.riskScore);
|
||||
cy.get(SEVERITY)
|
||||
.invoke('text')
|
||||
.should('eql', newRule.severity);
|
||||
cy.get('[data-test-subj="rule-switch"]').should('have.attr', 'aria-checked', 'true');
|
||||
|
||||
goToRuleDetails();
|
||||
|
||||
cy.get(RULE_NAME_HEADER)
|
||||
.invoke('text')
|
||||
.should('eql', `${newRule.name} Beta`);
|
||||
|
||||
const expectedIndexPatterns = [
|
||||
'apm-*-transaction*',
|
||||
'auditbeat-*',
|
||||
'endgame-*',
|
||||
'filebeat-*',
|
||||
'packetbeat-*',
|
||||
'winlogbeat-*',
|
||||
];
|
||||
cy.get(DEFINITION_INDEX_PATTERNS).then(patterns => {
|
||||
cy.wrap(patterns).each((pattern, index) => {
|
||||
cy.wrap(pattern)
|
||||
.invoke('text')
|
||||
.should('eql', expectedIndexPatterns[index]);
|
||||
});
|
||||
});
|
||||
cy.get(DEFINITION_DESCRIPTION)
|
||||
.eq(DEFINITION_CUSTOM_QUERY)
|
||||
.invoke('text')
|
||||
.should('eql', `${newRule.customQuery} `);
|
||||
cy.get(ABOUT_DESCRIPTION)
|
||||
.eq(ABOUT_RULE_DESCRIPTION)
|
||||
.invoke('text')
|
||||
.should('eql', newRule.description);
|
||||
cy.get(ABOUT_DESCRIPTION)
|
||||
.eq(ABOUT_SEVERITY)
|
||||
.invoke('text')
|
||||
.should('eql', newRule.severity);
|
||||
cy.get(ABOUT_DESCRIPTION)
|
||||
.eq(ABOUT_RISK)
|
||||
.invoke('text')
|
||||
.should('eql', newRule.riskScore);
|
||||
cy.get(ABOUT_DESCRIPTION)
|
||||
.eq(ABOUT_TIMELINE)
|
||||
.invoke('text')
|
||||
.should('eql', 'Default blank timeline');
|
||||
|
||||
let expectedUrls = '';
|
||||
newRule.referenceUrls.forEach(url => {
|
||||
expectedUrls = expectedUrls + url;
|
||||
});
|
||||
cy.get(ABOUT_DESCRIPTION)
|
||||
.eq(ABOUT_EXPECTED_URLS)
|
||||
.invoke('text')
|
||||
.should('eql', expectedUrls);
|
||||
|
||||
let expectedFalsePositives = '';
|
||||
newRule.falsePositivesExamples.forEach(falsePositive => {
|
||||
expectedFalsePositives = expectedFalsePositives + falsePositive;
|
||||
});
|
||||
cy.get(ABOUT_DESCRIPTION)
|
||||
.eq(ABOUT_FALSE_POSITIVES)
|
||||
.invoke('text')
|
||||
.should('eql', expectedFalsePositives);
|
||||
|
||||
let expectedMitre = '';
|
||||
newRule.mitre.forEach(mitre => {
|
||||
expectedMitre = expectedMitre + mitre.tactic;
|
||||
mitre.techniques.forEach(technique => {
|
||||
expectedMitre = expectedMitre + technique;
|
||||
});
|
||||
});
|
||||
cy.get(ABOUT_DESCRIPTION)
|
||||
.eq(ABOUT_MITRE)
|
||||
.invoke('text')
|
||||
.should('eql', expectedMitre);
|
||||
|
||||
let expectedTags = '';
|
||||
newRule.tags.forEach(tag => {
|
||||
expectedTags = expectedTags + tag;
|
||||
});
|
||||
cy.get(ABOUT_DESCRIPTION)
|
||||
.eq(ABOUT_TAGS)
|
||||
.invoke('text')
|
||||
.should('eql', expectedTags);
|
||||
cy.get(SCHEDULE_DESCRIPTION)
|
||||
.eq(SCHEDULE_RUNS)
|
||||
.invoke('text')
|
||||
.should('eql', '5m');
|
||||
cy.get(SCHEDULE_DESCRIPTION)
|
||||
.eq(SCHEDULE_LOOPBACK)
|
||||
.invoke('text')
|
||||
.should('eql', '1m');
|
||||
});
|
||||
});
|
||||
|
|
45
x-pack/legacy/plugins/siem/cypress/objects/rule.ts
Normal file
45
x-pack/legacy/plugins/siem/cypress/objects/rule.ts
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
interface Mitre {
|
||||
tactic: string;
|
||||
techniques: string[];
|
||||
}
|
||||
|
||||
export interface Rule {
|
||||
customQuery: string;
|
||||
name: string;
|
||||
description: string;
|
||||
severity: string;
|
||||
riskScore: string;
|
||||
tags: string[];
|
||||
timelineTemplate?: string;
|
||||
referenceUrls: string[];
|
||||
falsePositivesExamples: string[];
|
||||
mitre: Mitre[];
|
||||
}
|
||||
|
||||
const mitre1: Mitre = {
|
||||
tactic: 'Discovery (TA0007)',
|
||||
techniques: ['Cloud Service Discovery (T1526)', 'File and Directory Discovery (T1083)'],
|
||||
};
|
||||
|
||||
const mitre2: Mitre = {
|
||||
tactic: 'Execution (TA0002)',
|
||||
techniques: ['CMSTP (T1191)'],
|
||||
};
|
||||
|
||||
export const newRule: Rule = {
|
||||
customQuery: 'hosts.name: *',
|
||||
name: 'New Rule Test',
|
||||
description: 'The new rule description.',
|
||||
severity: 'High',
|
||||
riskScore: '17',
|
||||
tags: ['test', 'newRule'],
|
||||
referenceUrls: ['https://www.google.com/', 'https://elastic.co/'],
|
||||
falsePositivesExamples: ['False1', 'False2'],
|
||||
mitre: [mitre1, mitre2],
|
||||
};
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
export const ABOUT_CONTINUE_BTN = '[data-test-subj="about-continue"]';
|
||||
|
||||
export const ADD_FALSE_POSITIVE_BTN =
|
||||
'[data-test-subj="detectionEngineStepAboutRuleFalsePositives"] .euiButtonEmpty__text';
|
||||
|
||||
export const ADD_REFERENCE_URL_BTN =
|
||||
'[data-test-subj="detectionEngineStepAboutRuleReferenceUrls"] .euiButtonEmpty__text';
|
||||
|
||||
export const MITRE_BTN = '[data-test-subj="addMitre"]';
|
||||
|
||||
export const ADVANCED_SETTINGS_BTN = '[data-test-subj="advancedSettings"] .euiAccordion__button';
|
||||
|
||||
export const CREATE_AND_ACTIVATE_BTN = '[data-test-subj="create-activate"]';
|
||||
|
||||
export const CUSTOM_QUERY_INPUT = '[data-test-subj="queryInput"]';
|
||||
|
||||
export const DEFINE_CONTINUE_BUTTON = '[data-test-subj="continue"]';
|
||||
|
||||
export const FALSE_POSITIVES_INPUT =
|
||||
'[data-test-subj="detectionEngineStepAboutRuleFalsePositives"] input';
|
||||
|
||||
export const MITRE_TACTIC = '.euiContextMenuItem__text';
|
||||
|
||||
export const MITRE_TACTIC_DROPDOWN = '[data-test-subj="mitreTactic"]';
|
||||
|
||||
export const MITRE_TECHNIQUES_INPUT =
|
||||
'[data-test-subj="mitreTechniques"] [data-test-subj="comboBoxSearchInput"]';
|
||||
|
||||
export const REFERENCE_URLS_INPUT =
|
||||
'[data-test-subj="detectionEngineStepAboutRuleReferenceUrls"] input';
|
||||
|
||||
export const RISK_INPUT = '.euiRangeInput';
|
||||
|
||||
export const RULE_DESCRIPTION_INPUT =
|
||||
'[data-test-subj="detectionEngineStepAboutRuleDescription"] [data-test-subj="input"]';
|
||||
|
||||
export const RULE_NAME_INPUT =
|
||||
'[data-test-subj="detectionEngineStepAboutRuleName"] [data-test-subj="input"]';
|
||||
|
||||
export const SEVERITY_DROPDOWN = '[data-test-subj="select"]';
|
||||
|
||||
export const TAGS_INPUT =
|
||||
'[data-test-subj="detectionEngineStepAboutRuleTags"] [data-test-subj="comboBoxSearchInput"]';
|
39
x-pack/legacy/plugins/siem/cypress/screens/rule_details.ts
Normal file
39
x-pack/legacy/plugins/siem/cypress/screens/rule_details.ts
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
export const ABOUT_DESCRIPTION = '[data-test-subj="aboutRule"] .euiDescriptionList__description';
|
||||
|
||||
export const ABOUT_EXPECTED_URLS = 4;
|
||||
|
||||
export const ABOUT_FALSE_POSITIVES = 5;
|
||||
|
||||
export const ABOUT_MITRE = 6;
|
||||
|
||||
export const ABOUT_RULE_DESCRIPTION = 0;
|
||||
|
||||
export const ABOUT_RISK = 2;
|
||||
|
||||
export const ABOUT_SEVERITY = 1;
|
||||
|
||||
export const ABOUT_TAGS = 7;
|
||||
|
||||
export const ABOUT_TIMELINE = 3;
|
||||
|
||||
export const DEFINITION_CUSTOM_QUERY = 1;
|
||||
|
||||
export const DEFINITION_DESCRIPTION =
|
||||
'[data-test-subj="definition"] .euiDescriptionList__description';
|
||||
|
||||
export const DEFINITION_INDEX_PATTERNS =
|
||||
'[data-test-subj="definition"] .euiDescriptionList__description .euiBadge__text';
|
||||
|
||||
export const RULE_NAME_HEADER = '[data-test-subj="header-page-title"]';
|
||||
|
||||
export const SCHEDULE_DESCRIPTION = '[data-test-subj="schedule"] .euiDescriptionList__description';
|
||||
|
||||
export const SCHEDULE_RUNS = 0;
|
||||
|
||||
export const SCHEDULE_LOOPBACK = 1;
|
|
@ -4,6 +4,10 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
export const CREATE_NEW_RULE_BTN = '[data-test-subj="create-new-rule"]';
|
||||
|
||||
export const CUSTOM_RULES_BTN = '[data-test-subj="show-custom-rules-filter-button"]';
|
||||
|
||||
export const ELASTIC_RULES_BTN = '[data-test-subj="show-elastic-rules-filter-button"]';
|
||||
|
||||
export const LOAD_PREBUILT_RULES_BTN = '[data-test-subj="load-prebuilt-rules"]';
|
||||
|
@ -15,8 +19,14 @@ export const LOADING_SPINNER = '[data-test-subj="loading-spinner"]';
|
|||
|
||||
export const PAGINATION_POPOVER_BTN = '[data-test-subj="tablePaginationPopoverButton"]';
|
||||
|
||||
export const RISK_SCORE = '[data-test-subj="riskScore"]';
|
||||
|
||||
export const RULE_NAME = '[data-test-subj="ruleName"]';
|
||||
|
||||
export const RULES_TABLE = '[data-test-subj="rules-table"]';
|
||||
|
||||
export const RULES_ROW = '.euiTableRow';
|
||||
|
||||
export const SEVERITY = '[data-test-subj="severity"]';
|
||||
|
||||
export const THREE_HUNDRED_ROWS = '[data-test-subj="tablePagination-300-rows"]';
|
||||
|
|
92
x-pack/legacy/plugins/siem/cypress/tasks/create_new_rule.ts
Normal file
92
x-pack/legacy/plugins/siem/cypress/tasks/create_new_rule.ts
Normal file
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
import { Rule } from '../objects/rule';
|
||||
import {
|
||||
ABOUT_CONTINUE_BTN,
|
||||
ADD_FALSE_POSITIVE_BTN,
|
||||
ADD_REFERENCE_URL_BTN,
|
||||
ADVANCED_SETTINGS_BTN,
|
||||
CREATE_AND_ACTIVATE_BTN,
|
||||
CUSTOM_QUERY_INPUT,
|
||||
DEFINE_CONTINUE_BUTTON,
|
||||
FALSE_POSITIVES_INPUT,
|
||||
MITRE_BTN,
|
||||
MITRE_TACTIC,
|
||||
MITRE_TACTIC_DROPDOWN,
|
||||
MITRE_TECHNIQUES_INPUT,
|
||||
RISK_INPUT,
|
||||
REFERENCE_URLS_INPUT,
|
||||
RULE_DESCRIPTION_INPUT,
|
||||
RULE_NAME_INPUT,
|
||||
SEVERITY_DROPDOWN,
|
||||
TAGS_INPUT,
|
||||
} from '../screens/create_new_rule';
|
||||
|
||||
export const createAndActivateRule = () => {
|
||||
cy.get(CREATE_AND_ACTIVATE_BTN).click({ force: true });
|
||||
cy.get(CREATE_AND_ACTIVATE_BTN).should('not.exist');
|
||||
};
|
||||
|
||||
export const fillAboutRuleAndContinue = (rule: Rule) => {
|
||||
cy.get(RULE_NAME_INPUT).type(rule.name, { force: true });
|
||||
cy.get(RULE_DESCRIPTION_INPUT).type(rule.description, { force: true });
|
||||
|
||||
cy.get(SEVERITY_DROPDOWN).click({ force: true });
|
||||
cy.get(`#${rule.severity.toLowerCase()}`).click();
|
||||
|
||||
cy.get(RISK_INPUT)
|
||||
.clear({ force: true })
|
||||
.type(`${rule.riskScore}`, { force: true });
|
||||
|
||||
rule.tags.forEach(tag => {
|
||||
cy.get(TAGS_INPUT).type(`${tag}{enter}`, { force: true });
|
||||
});
|
||||
|
||||
cy.get(ADVANCED_SETTINGS_BTN).click({ force: true });
|
||||
|
||||
rule.referenceUrls.forEach((url, index) => {
|
||||
cy.get(REFERENCE_URLS_INPUT)
|
||||
.eq(index)
|
||||
.type(url, { force: true });
|
||||
cy.get(ADD_REFERENCE_URL_BTN).click({ force: true });
|
||||
});
|
||||
|
||||
rule.falsePositivesExamples.forEach((falsePositive, index) => {
|
||||
cy.get(FALSE_POSITIVES_INPUT)
|
||||
.eq(index)
|
||||
.type(falsePositive, { force: true });
|
||||
cy.get(ADD_FALSE_POSITIVE_BTN).click({ force: true });
|
||||
});
|
||||
|
||||
rule.mitre.forEach((mitre, index) => {
|
||||
cy.get(MITRE_TACTIC_DROPDOWN)
|
||||
.eq(index)
|
||||
.click({ force: true });
|
||||
cy.contains(MITRE_TACTIC, mitre.tactic).click();
|
||||
|
||||
mitre.techniques.forEach(technique => {
|
||||
cy.get(MITRE_TECHNIQUES_INPUT)
|
||||
.eq(index)
|
||||
.type(`${technique}{enter}`, { force: true });
|
||||
});
|
||||
|
||||
cy.get(MITRE_BTN).click({ force: true });
|
||||
});
|
||||
|
||||
cy.get(ABOUT_CONTINUE_BTN)
|
||||
.should('exist')
|
||||
.click({ force: true });
|
||||
};
|
||||
|
||||
export const fillDefineRuleAndContinue = (rule: Rule) => {
|
||||
cy.get(CUSTOM_QUERY_INPUT).type(rule.customQuery);
|
||||
cy.get(CUSTOM_QUERY_INPUT).should('have.attr', 'value', rule.customQuery);
|
||||
cy.get(DEFINE_CONTINUE_BUTTON)
|
||||
.should('exist')
|
||||
.click({ force: true });
|
||||
|
||||
cy.get(CUSTOM_QUERY_INPUT).should('not.exist');
|
||||
};
|
29
x-pack/legacy/plugins/siem/cypress/tasks/es_archiver.ts
Normal file
29
x-pack/legacy/plugins/siem/cypress/tasks/es_archiver.ts
Normal file
|
@ -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;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
export const esArchiverLoadEmptyKibana = () => {
|
||||
cy.exec(
|
||||
`node ../../../../scripts/es_archiver empty_kibana load empty--dir ../../../test/siem_cypress/es_archives --config ../../../../test/functional/config.js --es-url ${Cypress.env(
|
||||
'ELASTICSEARCH_URL'
|
||||
)} --kibana-url ${Cypress.config().baseUrl}`
|
||||
);
|
||||
};
|
||||
|
||||
export const esArchiverUnloadEmptyKibana = () => {
|
||||
cy.exec(
|
||||
`node ../../../../scripts/es_archiver empty_kibana unload empty--dir ../../../test/siem_cypress/es_archives --config ../../../../test/functional/config.js --es-url ${Cypress.env(
|
||||
'ELASTICSEARCH_URL'
|
||||
)} --kibana-url ${Cypress.config().baseUrl}`
|
||||
);
|
||||
};
|
||||
|
||||
export const esArchiverResetKibana = () => {
|
||||
cy.exec(
|
||||
`node ../../../../scripts/es_archiver empty-kibana-index --config ../../../../test/functional/config.js --es-url ${Cypress.env(
|
||||
'ELASTICSEARCH_URL'
|
||||
)} --kibana-url ${Cypress.config().baseUrl}`
|
||||
);
|
||||
};
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
import {
|
||||
CREATE_NEW_RULE_BTN,
|
||||
LOAD_PREBUILT_RULES_BTN,
|
||||
LOADING_INITIAL_PREBUILT_RULES_TABLE,
|
||||
LOADING_SPINNER,
|
||||
|
@ -18,6 +19,22 @@ export const changeToThreeHundredRowsPerPage = () => {
|
|||
cy.get(THREE_HUNDRED_ROWS).click();
|
||||
};
|
||||
|
||||
export const filterByCustomRules = () => {
|
||||
cy.get('[data-test-subj="show-custom-rules-filter-button"]').click({ force: true });
|
||||
cy.get('[data-test-subj="loading-spinner"]').should('exist');
|
||||
cy.get('[data-test-subj="loading-spinner"]').should('not.exist');
|
||||
};
|
||||
|
||||
export const goToCreateNewRule = () => {
|
||||
cy.get(CREATE_NEW_RULE_BTN).click({ force: true });
|
||||
};
|
||||
|
||||
export const goToRuleDetails = () => {
|
||||
cy.get('[data-test-subj="ruleName"]').click({ force: true });
|
||||
cy.get('.euiLoadingSpinner').should('exist');
|
||||
cy.get('.euiLoadingSpinner').should('not.exist');
|
||||
};
|
||||
|
||||
export const loadPrebuiltDetectionRules = () => {
|
||||
cy.get(LOAD_PREBUILT_RULES_BTN)
|
||||
.should('exist')
|
||||
|
|
|
@ -11,6 +11,7 @@ import {
|
|||
EuiLink,
|
||||
EuiBasicTableColumn,
|
||||
EuiTableActionsColumnType,
|
||||
EuiText,
|
||||
EuiHealth,
|
||||
} from '@elastic/eui';
|
||||
import * as H from 'history';
|
||||
|
@ -99,7 +100,9 @@ export const getColumns = ({
|
|||
field: 'name',
|
||||
name: i18n.COLUMN_RULE,
|
||||
render: (value: Rule['name'], item: Rule) => (
|
||||
<EuiLink href={getRuleDetailsUrl(item.id)}>{value}</EuiLink>
|
||||
<EuiLink data-test-subj="ruleName" href={getRuleDetailsUrl(item.id)}>
|
||||
{value}
|
||||
</EuiLink>
|
||||
),
|
||||
truncateText: true,
|
||||
width: '24%',
|
||||
|
@ -107,6 +110,11 @@ export const getColumns = ({
|
|||
{
|
||||
field: 'risk_score',
|
||||
name: i18n.COLUMN_RISK_SCORE,
|
||||
render: (value: Rule['risk_score']) => (
|
||||
<EuiText data-test-subj="riskScore" size="s">
|
||||
{value}
|
||||
</EuiText>
|
||||
),
|
||||
truncateText: true,
|
||||
width: '14%',
|
||||
},
|
||||
|
@ -150,7 +158,7 @@ export const getColumns = ({
|
|||
field: 'tags',
|
||||
name: i18n.COLUMN_TAGS,
|
||||
render: (value: Rule['tags']) => (
|
||||
<TruncatableText>
|
||||
<TruncatableText data-test-subj="tags">
|
||||
{value.map((tag, i) => (
|
||||
<EuiBadge color="hollow" key={`${tag}-${i}`}>
|
||||
{tag}
|
||||
|
@ -167,6 +175,7 @@ export const getColumns = ({
|
|||
name: i18n.COLUMN_ACTIVATE,
|
||||
render: (value: Rule['enabled'], item: Rule) => (
|
||||
<RuleSwitch
|
||||
data-test-subj="enabled"
|
||||
dispatch={dispatch}
|
||||
id={item.id}
|
||||
enabled={item.enabled}
|
||||
|
|
|
@ -69,7 +69,7 @@ const StepRuleDescriptionComponent: React.FC<StepRuleDescriptionProps> = ({
|
|||
|
||||
return (
|
||||
<EuiFlexGroup>
|
||||
<EuiFlexItem key={`description-step-rule`}>
|
||||
<EuiFlexItem data-test-subj="definition" key={`description-step-rule`}>
|
||||
<EuiDescriptionList listItems={listItems} />
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
|
|
@ -129,6 +129,7 @@ export const AddMitreThreat = ({ dataTestSubj, field, idAria, isDisabled }: AddI
|
|||
onChange={updateTactic.bind(null, index)}
|
||||
fullWidth={false}
|
||||
valueOfSelected={camelCase(tacticName)}
|
||||
data-test-subj="mitreTactic"
|
||||
/>
|
||||
);
|
||||
|
||||
|
@ -144,6 +145,7 @@ export const AddMitreThreat = ({ dataTestSubj, field, idAria, isDisabled }: AddI
|
|||
<EuiFlexGroup gutterSize="s" alignItems="center">
|
||||
<EuiFlexItem grow>
|
||||
<EuiComboBox
|
||||
data-test-subj="mitreTechniques"
|
||||
placeholder={item.tactic.name === 'none' ? '' : i18n.TECHNIQUES_PLACEHOLDER}
|
||||
options={options}
|
||||
selectedOptions={selectedOptions}
|
||||
|
@ -208,7 +210,7 @@ export const AddMitreThreat = ({ dataTestSubj, field, idAria, isDisabled }: AddI
|
|||
{values.length - 1 !== index && <EuiSpacer size="s" />}
|
||||
</div>
|
||||
))}
|
||||
<MyAddItemButton onClick={addItem} isDisabled={isDisabled}>
|
||||
<MyAddItemButton data-test-subj="addMitre" onClick={addItem} isDisabled={isDisabled}>
|
||||
{i18n.ADD_MITRE_ATTACK}
|
||||
</MyAddItemButton>
|
||||
</MitreContainer>
|
||||
|
|
|
@ -15,6 +15,7 @@ interface Props {
|
|||
|
||||
const SeverityBadgeComponent: React.FC<Props> = ({ value }) => (
|
||||
<EuiHealth
|
||||
data-test-subj="severity"
|
||||
color={
|
||||
value === 'low'
|
||||
? euiLightVars.euiColorVis0
|
||||
|
|
|
@ -126,7 +126,7 @@ const StepAboutRuleComponent: FC<StepAboutRuleProps> = ({
|
|||
) : (
|
||||
<>
|
||||
<StepContentWrapper addPadding={!isUpdateView}>
|
||||
<Form form={form} data-test-subj="stepAboutRule">
|
||||
<Form form={form}>
|
||||
<CommonUseField
|
||||
path="name"
|
||||
componentProps={{
|
||||
|
@ -198,6 +198,7 @@ const StepAboutRuleComponent: FC<StepAboutRuleProps> = ({
|
|||
</TagContainer>
|
||||
<EuiSpacer size="m" />
|
||||
<AdvancedSettingsAccordion
|
||||
data-test-subj="advancedSettings"
|
||||
id="advancedSettingsAccordion"
|
||||
buttonContent={AdvancedSettingsAccordionButton}
|
||||
>
|
||||
|
@ -269,7 +270,12 @@ const StepAboutRuleComponent: FC<StepAboutRuleProps> = ({
|
|||
responsive={false}
|
||||
>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButton fill onClick={onSubmit} isDisabled={isLoading}>
|
||||
<EuiButton
|
||||
data-test-subj="about-continue"
|
||||
fill
|
||||
onClick={onSubmit}
|
||||
isDisabled={isLoading}
|
||||
>
|
||||
{RuleI18n.CONTINUE}
|
||||
</EuiButton>
|
||||
</EuiFlexItem>
|
||||
|
|
|
@ -238,7 +238,7 @@ const StepDefineRuleComponent: FC<StepDefineRuleProps> = ({
|
|||
responsive={false}
|
||||
>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButton fill onClick={onSubmit} isDisabled={isLoading}>
|
||||
<EuiButton fill onClick={onSubmit} isDisabled={isLoading} data-test-subj="continue">
|
||||
{RuleI18n.CONTINUE}
|
||||
</EuiButton>
|
||||
</EuiFlexItem>
|
||||
|
|
|
@ -133,6 +133,7 @@ const StepScheduleRuleComponent: FC<StepScheduleRuleProps> = ({
|
|||
isDisabled={isLoading}
|
||||
isLoading={isLoading}
|
||||
onClick={onSubmit.bind(null, true)}
|
||||
data-test-subj="create-activate"
|
||||
>
|
||||
{I18n.COMPLETE_WITH_ACTIVATING}
|
||||
</EuiButton>
|
||||
|
|
|
@ -309,7 +309,7 @@ const RuleDetailsPageComponent: FC<PropsFromRedux> = ({
|
|||
</StepPanel>
|
||||
</EuiFlexItem>
|
||||
|
||||
<EuiFlexItem component="section" grow={2}>
|
||||
<EuiFlexItem data-test-subj="aboutRule" component="section" grow={2}>
|
||||
<StepPanel loading={isLoading} title={ruleI18n.ABOUT}>
|
||||
{aboutRuleData != null && (
|
||||
<StepAboutRule
|
||||
|
@ -322,7 +322,7 @@ const RuleDetailsPageComponent: FC<PropsFromRedux> = ({
|
|||
</StepPanel>
|
||||
</EuiFlexItem>
|
||||
|
||||
<EuiFlexItem component="section" grow={1}>
|
||||
<EuiFlexItem data-test-subj="schedule" component="section" grow={1}>
|
||||
<StepPanel loading={isLoading} title={ruleI18n.SCHEDULE}>
|
||||
{scheduleRuleData != null && (
|
||||
<StepScheduleRule
|
||||
|
|
|
@ -147,6 +147,7 @@ const RulesPageComponent: React.FC = () => {
|
|||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButton
|
||||
data-test-subj="create-new-rule"
|
||||
fill
|
||||
href={getCreateRuleUrl()}
|
||||
iconType="plusInCircle"
|
||||
|
|
|
@ -27,6 +27,7 @@ export async function SiemCypressTestRunner({ getService }: FtrProviderContext)
|
|||
env: {
|
||||
FORCE_COLOR: '1',
|
||||
CYPRESS_baseUrl: Url.format(config.get('servers.kibana')),
|
||||
CYPRESS_ELASTICSEARCH_URL: Url.format(config.get('servers.elasticsearch')),
|
||||
CYPRESS_ELASTICSEARCH_USERNAME: config.get('servers.elasticsearch.username'),
|
||||
CYPRESS_ELASTICSEARCH_PASSWORD: config.get('servers.elasticsearch.password'),
|
||||
...process.env,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue