[Security Solution] Minimize the use of es_archiver on cypress tests (#85019)

* minimizes the uses of es_archiver

* refactor

* fixes merge issue

* fixes typecheck issue

* Update x-pack/plugins/security_solution/cypress/integration/timelines_export.spec.ts

Co-authored-by: Patryk Kopyciński <contact@patrykkopycinski.com>

* final refactor

* final touches

* unskips skipped tests

* removes async

* fixes typo

* removes unused lines

* fixes failing test

* fixes timelines failing tests

* fixes merge issue

Co-authored-by: Patryk Kopyciński <contact@patrykkopycinski.com>
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
MadameSheema 2020-12-10 18:31:40 +01:00 committed by GitHub
parent 36525954a1
commit 1b5d43b2e2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
31 changed files with 474 additions and 9167 deletions

View file

@ -25,7 +25,7 @@ import {
markInProgressFirstAlert,
goToInProgressAlerts,
} from '../tasks/alerts';
import { removeSignalsIndex } from '../tasks/api_calls';
import { removeSignalsIndex } from '../tasks/api_calls/rules';
import { esArchiverLoad, esArchiverUnload } from '../tasks/es_archiver';
import { loginAndWaitForPage } from '../tasks/login';

View file

@ -16,7 +16,7 @@ import {
goToOpenedAlerts,
waitForAlertsIndexToBeCreated,
} from '../tasks/alerts';
import { createCustomRule, deleteCustomRule, removeSignalsIndex } from '../tasks/api_calls';
import { createCustomRule, deleteCustomRule, removeSignalsIndex } from '../tasks/api_calls/rules';
import { goToRuleDetails } from '../tasks/alerts_detection_rules';
import { waitForAlertsToPopulate } from '../tasks/create_new_rule';
import { esArchiverLoad, esArchiverUnload } from '../tasks/es_archiver';
@ -34,9 +34,8 @@ import { refreshPage } from '../tasks/security_header';
import { DETECTIONS_URL } from '../urls/navigation';
const NUMBER_OF_AUDITBEAT_EXCEPTIONS_ALERTS = 1;
describe('Exceptions', () => {
const NUMBER_OF_AUDITBEAT_EXCEPTIONS_ALERTS = '1';
beforeEach(() => {
loginAndWaitForPageWithoutDateRange(DETECTIONS_URL);
waitForAlertsIndexToBeCreated();
@ -53,14 +52,7 @@ describe('Exceptions', () => {
refreshPage();
cy.get(ALERTS_COUNT).should('exist');
cy.get(NUMBER_OF_ALERTS)
.invoke('text')
.then((numberOfInitialAlertsText) => {
cy.wrap(parseInt(numberOfInitialAlertsText, 10)).should(
'eql',
NUMBER_OF_AUDITBEAT_EXCEPTIONS_ALERTS
);
});
cy.get(NUMBER_OF_ALERTS).should('have.text', NUMBER_OF_AUDITBEAT_EXCEPTIONS_ALERTS);
});
afterEach(() => {
@ -79,35 +71,20 @@ describe('Exceptions', () => {
refreshPage();
cy.get(ALERTS_COUNT).should('exist');
cy.get(NUMBER_OF_ALERTS)
.invoke('text')
.then((numberOfAlertsAfterCreatingExceptionText) => {
cy.wrap(parseInt(numberOfAlertsAfterCreatingExceptionText, 10)).should('eql', 0);
});
cy.get(NUMBER_OF_ALERTS).should('have.text', '0');
goToClosedAlerts();
refreshPage();
cy.get(ALERTS_COUNT).should('exist');
cy.get(NUMBER_OF_ALERTS)
.invoke('text')
.then((numberOfClosedAlertsAfterCreatingExceptionText) => {
cy.wrap(parseInt(numberOfClosedAlertsAfterCreatingExceptionText, 10)).should(
'eql',
NUMBER_OF_AUDITBEAT_EXCEPTIONS_ALERTS
);
});
cy.get(NUMBER_OF_ALERTS).should('have.text', NUMBER_OF_AUDITBEAT_EXCEPTIONS_ALERTS);
goToOpenedAlerts();
waitForTheRuleToBeExecuted();
refreshPage();
cy.get(ALERTS_COUNT).should('exist');
cy.get(NUMBER_OF_ALERTS)
.invoke('text')
.then((numberOfOpenedAlertsAfterCreatingExceptionText) => {
cy.wrap(parseInt(numberOfOpenedAlertsAfterCreatingExceptionText, 10)).should('eql', 0);
});
cy.get(NUMBER_OF_ALERTS).should('have.text', '0');
goToExceptionsTab();
removeException();
@ -118,14 +95,7 @@ describe('Exceptions', () => {
refreshPage();
cy.get(ALERTS_COUNT).should('exist');
cy.get(NUMBER_OF_ALERTS)
.invoke('text')
.then((numberOfAlertsAfterRemovingExceptionsText) => {
cy.wrap(parseInt(numberOfAlertsAfterRemovingExceptionsText, 10)).should(
'eql',
NUMBER_OF_AUDITBEAT_EXCEPTIONS_ALERTS
);
});
cy.get(NUMBER_OF_ALERTS).should('have.text', NUMBER_OF_AUDITBEAT_EXCEPTIONS_ALERTS);
});
});
@ -136,35 +106,20 @@ describe('Exceptions', () => {
esArchiverLoad('auditbeat_for_exceptions2');
cy.get(ALERTS_COUNT).should('exist');
cy.get(NUMBER_OF_ALERTS)
.invoke('text')
.then((numberOfAlertsAfterCreatingExceptionText) => {
cy.wrap(parseInt(numberOfAlertsAfterCreatingExceptionText, 10)).should('eql', 0);
});
cy.get(NUMBER_OF_ALERTS).should('have.text', '0');
goToClosedAlerts();
refreshPage();
cy.get(ALERTS_COUNT).should('exist');
cy.get(NUMBER_OF_ALERTS)
.invoke('text')
.then((numberOfClosedAlertsAfterCreatingExceptionText) => {
cy.wrap(parseInt(numberOfClosedAlertsAfterCreatingExceptionText, 10)).should(
'eql',
NUMBER_OF_AUDITBEAT_EXCEPTIONS_ALERTS
);
});
cy.get(NUMBER_OF_ALERTS).should('have.text', NUMBER_OF_AUDITBEAT_EXCEPTIONS_ALERTS);
goToOpenedAlerts();
waitForTheRuleToBeExecuted();
refreshPage();
cy.get(ALERTS_COUNT).should('exist');
cy.get(NUMBER_OF_ALERTS)
.invoke('text')
.then((numberOfOpenedAlertsAfterCreatingExceptionText) => {
cy.wrap(parseInt(numberOfOpenedAlertsAfterCreatingExceptionText, 10)).should('eql', 0);
});
cy.get(NUMBER_OF_ALERTS).should('have.text', '0');
goToExceptionsTab();
removeException();
@ -174,14 +129,7 @@ describe('Exceptions', () => {
refreshPage();
cy.get(ALERTS_COUNT).should('exist');
cy.get(NUMBER_OF_ALERTS)
.invoke('text')
.then((numberOfAlertsAfterRemovingExceptionsText) => {
cy.wrap(parseInt(numberOfAlertsAfterRemovingExceptionsText, 10)).should(
'eql',
NUMBER_OF_AUDITBEAT_EXCEPTIONS_ALERTS
);
});
cy.get(NUMBER_OF_ALERTS).should('have.text', NUMBER_OF_AUDITBEAT_EXCEPTIONS_ALERTS);
});
});
});

View file

@ -85,7 +85,8 @@ import {
waitForLoadElasticPrebuiltDetectionRulesTableToBeLoaded,
waitForRulesToBeLoaded,
} from '../tasks/alerts_detection_rules';
import { removeSignalsIndex } from '../tasks/api_calls';
import { removeSignalsIndex } from '../tasks/api_calls/rules';
import { createTimeline, deleteTimeline } from '../tasks/api_calls/timelines';
import {
createAndActivateRule,
fillAboutRule,
@ -104,23 +105,24 @@ import { loginAndWaitForPageWithoutDateRange } from '../tasks/login';
import { DETECTIONS_URL } from '../urls/navigation';
const expectedUrls = newRule.referenceUrls.join('');
const expectedFalsePositives = newRule.falsePositivesExamples.join('');
const expectedTags = newRule.tags.join('');
const expectedMitre = formatMitreAttackDescription(newRule.mitre);
const expectedNumberOfRules = 1;
const expectedEditedtags = editedRule.tags.join('');
const expectedEditedIndexPatterns =
editedRule.index && editedRule.index.length ? editedRule.index : indexPatterns;
describe('Custom detection rules creation', () => {
const expectedUrls = newRule.referenceUrls.join('');
const expectedFalsePositives = newRule.falsePositivesExamples.join('');
const expectedTags = newRule.tags.join('');
const expectedMitre = formatMitreAttackDescription(newRule.mitre);
const expectedNumberOfRules = 1;
const rule = { ...newRule };
before(() => {
esArchiverLoad('timeline');
createTimeline(newRule.timeline).then((response) => {
rule.timeline.id = response.body.data.persistTimeline.timeline.savedObjectId;
});
});
after(() => {
deleteRule();
esArchiverUnload('timeline');
deleteTimeline(rule.timeline.id!);
removeSignalsIndex();
});
@ -131,19 +133,19 @@ describe('Custom detection rules creation', () => {
goToManageAlertsDetectionRules();
waitForLoadElasticPrebuiltDetectionRulesTableToBeLoaded();
goToCreateNewRule();
fillDefineCustomRuleWithImportedQueryAndContinue(newRule);
fillAboutRuleAndContinue(newRule);
fillScheduleRuleAndContinue(newRule);
fillDefineCustomRuleWithImportedQueryAndContinue(rule);
fillAboutRuleAndContinue(rule);
fillScheduleRuleAndContinue(rule);
// expect define step to repopulate
cy.get(DEFINE_EDIT_BUTTON).click();
cy.get(CUSTOM_QUERY_INPUT).should('have.value', newRule.customQuery);
cy.get(CUSTOM_QUERY_INPUT).should('have.value', rule.customQuery);
cy.get(DEFINE_CONTINUE_BUTTON).should('exist').click({ force: true });
cy.get(DEFINE_CONTINUE_BUTTON).should('not.exist');
// expect about step to populate
cy.get(ABOUT_EDIT_BUTTON).click();
cy.get(RULE_NAME_INPUT).invoke('val').should('eql', newRule.name);
cy.get(RULE_NAME_INPUT).invoke('val').should('eql', rule.name);
cy.get(ABOUT_CONTINUE_BTN).should('exist').click({ force: true });
cy.get(ABOUT_CONTINUE_BTN).should('not.exist');
@ -163,18 +165,18 @@ describe('Custom detection rules creation', () => {
cy.get(RULES_TABLE).then(($table) => {
cy.wrap($table.find(RULES_ROW).length).should('eql', 1);
});
cy.get(RULE_NAME).should('have.text', newRule.name);
cy.get(RISK_SCORE).should('have.text', newRule.riskScore);
cy.get(SEVERITY).should('have.text', newRule.severity);
cy.get(RULE_NAME).should('have.text', rule.name);
cy.get(RISK_SCORE).should('have.text', rule.riskScore);
cy.get(SEVERITY).should('have.text', rule.severity);
cy.get(RULE_SWITCH).should('have.attr', 'aria-checked', 'true');
goToRuleDetails();
cy.get(RULE_NAME_HEADER).should('have.text', `${newRule.name}`);
cy.get(ABOUT_RULE_DESCRIPTION).should('have.text', newRule.description);
cy.get(RULE_NAME_HEADER).should('have.text', `${rule.name}`);
cy.get(ABOUT_RULE_DESCRIPTION).should('have.text', rule.description);
cy.get(ABOUT_DETAILS).within(() => {
getDetails(SEVERITY_DETAILS).should('have.text', newRule.severity);
getDetails(RISK_SCORE_DETAILS).should('have.text', newRule.riskScore);
getDetails(SEVERITY_DETAILS).should('have.text', rule.severity);
getDetails(RISK_SCORE_DETAILS).should('have.text', rule.riskScore);
getDetails(REFERENCE_URLS_DETAILS).should((details) => {
expect(removeExternalLinkText(details.text())).equal(expectedUrls);
});
@ -188,7 +190,7 @@ describe('Custom detection rules creation', () => {
cy.get(ABOUT_INVESTIGATION_NOTES).should('have.text', INVESTIGATION_NOTES_MARKDOWN);
cy.get(DEFINITION_DETAILS).within(() => {
getDetails(INDEX_PATTERNS_DETAILS).should('have.text', indexPatterns.join(''));
getDetails(CUSTOM_QUERY_DETAILS).should('have.text', newRule.customQuery);
getDetails(CUSTOM_QUERY_DETAILS).should('have.text', rule.customQuery);
getDetails(RULE_TYPE_DETAILS).should('have.text', 'Query');
getDetails(TIMELINE_TEMPLATE_DETAILS).should('have.text', 'None');
});
@ -207,11 +209,11 @@ describe('Custom detection rules creation', () => {
waitForAlertsToPopulate();
cy.get(NUMBER_OF_ALERTS).invoke('text').then(parseFloat).should('be.above', 0);
cy.get(ALERT_RULE_NAME).first().should('have.text', newRule.name);
cy.get(ALERT_RULE_NAME).first().should('have.text', rule.name);
cy.get(ALERT_RULE_VERSION).first().should('have.text', '1');
cy.get(ALERT_RULE_METHOD).first().should('have.text', 'query');
cy.get(ALERT_RULE_SEVERITY).first().should('have.text', newRule.severity.toLowerCase());
cy.get(ALERT_RULE_RISK_SCORE).first().should('have.text', newRule.riskScore);
cy.get(ALERT_RULE_SEVERITY).first().should('have.text', rule.severity.toLowerCase());
cy.get(ALERT_RULE_RISK_SCORE).first().should('have.text', rule.riskScore);
});
});
@ -291,6 +293,10 @@ describe('Custom detection rules deletion and edition', () => {
});
context('Edition', () => {
const expectedEditedtags = editedRule.tags.join('');
const expectedEditedIndexPatterns =
editedRule.index && editedRule.index.length ? editedRule.index : indexPatterns;
it('Allows a rule to be edited', () => {
editFirstRule();
waitForKibana();

View file

@ -63,6 +63,7 @@ import {
waitForLoadElasticPrebuiltDetectionRulesTableToBeLoaded,
waitForRulesToBeLoaded,
} from '../tasks/alerts_detection_rules';
import { createTimeline, deleteTimeline } from '../tasks/api_calls/timelines';
import {
createAndActivateRule,
fillAboutRuleAndContinue,
@ -72,27 +73,29 @@ import {
waitForAlertsToPopulate,
waitForTheRuleToBeExecuted,
} from '../tasks/create_new_rule';
import { esArchiverLoad, esArchiverUnload } from '../tasks/es_archiver';
import { loginAndWaitForPageWithoutDateRange } from '../tasks/login';
import { DETECTIONS_URL } from '../urls/navigation';
const expectedUrls = eqlRule.referenceUrls.join('');
const expectedFalsePositives = eqlRule.falsePositivesExamples.join('');
const expectedTags = eqlRule.tags.join('');
const expectedMitre = formatMitreAttackDescription(eqlRule.mitre);
const expectedNumberOfRules = 1;
const expectedNumberOfAlerts = 7;
const expectedNumberOfSequenceAlerts = 1;
describe('Detection rules, EQL', () => {
beforeEach(() => {
esArchiverLoad('timeline');
const expectedUrls = eqlRule.referenceUrls.join('');
const expectedFalsePositives = eqlRule.falsePositivesExamples.join('');
const expectedTags = eqlRule.tags.join('');
const expectedMitre = formatMitreAttackDescription(eqlRule.mitre);
const expectedNumberOfRules = 1;
const expectedNumberOfAlerts = 7;
const rule = { ...eqlRule };
before(() => {
createTimeline(eqlRule.timeline).then((response) => {
rule.timeline.id = response.body.data.persistTimeline.timeline.savedObjectId;
});
});
afterEach(() => {
after(() => {
deleteTimeline(rule.timeline.id!);
deleteRule();
esArchiverUnload('timeline');
});
it('Creates and activates a new EQL rule', () => {
@ -103,9 +106,9 @@ describe('Detection rules, EQL', () => {
waitForLoadElasticPrebuiltDetectionRulesTableToBeLoaded();
goToCreateNewRule();
selectEqlRuleType();
fillDefineEqlRuleAndContinue(eqlRule);
fillAboutRuleAndContinue(eqlRule);
fillScheduleRuleAndContinue(eqlRule);
fillDefineEqlRuleAndContinue(rule);
fillAboutRuleAndContinue(rule);
fillScheduleRuleAndContinue(rule);
createAndActivateRule();
cy.get(CUSTOM_RULES_BTN).should('have.text', 'Custom rules (1)');
@ -122,18 +125,18 @@ describe('Detection rules, EQL', () => {
cy.get(RULES_TABLE).then(($table) => {
cy.wrap($table.find(RULES_ROW).length).should('eql', 1);
});
cy.get(RULE_NAME).should('have.text', eqlRule.name);
cy.get(RISK_SCORE).should('have.text', eqlRule.riskScore);
cy.get(SEVERITY).should('have.text', eqlRule.severity);
cy.get(RULE_NAME).should('have.text', rule.name);
cy.get(RISK_SCORE).should('have.text', rule.riskScore);
cy.get(SEVERITY).should('have.text', rule.severity);
cy.get(RULE_SWITCH).should('have.attr', 'aria-checked', 'true');
goToRuleDetails();
cy.get(RULE_NAME_HEADER).should('have.text', `${eqlRule.name}`);
cy.get(ABOUT_RULE_DESCRIPTION).should('have.text', eqlRule.description);
cy.get(RULE_NAME_HEADER).should('have.text', `${rule.name}`);
cy.get(ABOUT_RULE_DESCRIPTION).should('have.text', rule.description);
cy.get(ABOUT_DETAILS).within(() => {
getDetails(SEVERITY_DETAILS).should('have.text', eqlRule.severity);
getDetails(RISK_SCORE_DETAILS).should('have.text', eqlRule.riskScore);
getDetails(SEVERITY_DETAILS).should('have.text', rule.severity);
getDetails(RISK_SCORE_DETAILS).should('have.text', rule.riskScore);
getDetails(REFERENCE_URLS_DETAILS).should((details) => {
expect(removeExternalLinkText(details.text())).equal(expectedUrls);
});
@ -147,18 +150,18 @@ describe('Detection rules, EQL', () => {
cy.get(ABOUT_INVESTIGATION_NOTES).should('have.text', INVESTIGATION_NOTES_MARKDOWN);
cy.get(DEFINITION_DETAILS).within(() => {
getDetails(INDEX_PATTERNS_DETAILS).should('have.text', indexPatterns.join(''));
getDetails(CUSTOM_QUERY_DETAILS).should('have.text', eqlRule.customQuery);
getDetails(CUSTOM_QUERY_DETAILS).should('have.text', rule.customQuery);
getDetails(RULE_TYPE_DETAILS).should('have.text', 'Event Correlation');
getDetails(TIMELINE_TEMPLATE_DETAILS).should('have.text', 'None');
});
cy.get(SCHEDULE_DETAILS).within(() => {
getDetails(RUNS_EVERY_DETAILS).should(
'have.text',
`${eqlRule.runsEvery.interval}${eqlRule.runsEvery.type}`
`${rule.runsEvery.interval}${rule.runsEvery.type}`
);
getDetails(ADDITIONAL_LOOK_BACK_DETAILS).should(
'have.text',
`${eqlRule.lookBack.interval}${eqlRule.lookBack.type}`
`${rule.lookBack.interval}${rule.lookBack.type}`
);
});
@ -166,11 +169,28 @@ describe('Detection rules, EQL', () => {
waitForAlertsToPopulate();
cy.get(NUMBER_OF_ALERTS).should('have.text', expectedNumberOfAlerts);
cy.get(ALERT_RULE_NAME).first().should('have.text', eqlRule.name);
cy.get(ALERT_RULE_NAME).first().should('have.text', rule.name);
cy.get(ALERT_RULE_VERSION).first().should('have.text', '1');
cy.get(ALERT_RULE_METHOD).first().should('have.text', 'eql');
cy.get(ALERT_RULE_SEVERITY).first().should('have.text', eqlRule.severity.toLowerCase());
cy.get(ALERT_RULE_RISK_SCORE).first().should('have.text', eqlRule.riskScore);
cy.get(ALERT_RULE_SEVERITY).first().should('have.text', rule.severity.toLowerCase());
cy.get(ALERT_RULE_RISK_SCORE).first().should('have.text', rule.riskScore);
});
});
describe('Detection rules, sequence EQL', () => {
const expectedNumberOfRules = 1;
const expectedNumberOfSequenceAlerts = 1;
const rule = { ...eqlSequenceRule };
before(() => {
createTimeline(eqlSequenceRule.timeline).then((response) => {
rule.timeline.id = response.body.data.persistTimeline.timeline.savedObjectId;
});
});
afterEach(() => {
deleteTimeline(eqlSequenceRule.timeline.id!);
deleteRule();
});
it('Creates and activates a new EQL rule with a sequence', () => {
@ -181,9 +201,9 @@ describe('Detection rules, EQL', () => {
waitForLoadElasticPrebuiltDetectionRulesTableToBeLoaded();
goToCreateNewRule();
selectEqlRuleType();
fillDefineEqlRuleAndContinue(eqlSequenceRule);
fillAboutRuleAndContinue(eqlSequenceRule);
fillScheduleRuleAndContinue(eqlSequenceRule);
fillDefineEqlRuleAndContinue(rule);
fillAboutRuleAndContinue(rule);
fillScheduleRuleAndContinue(rule);
createAndActivateRule();
cy.get(CUSTOM_RULES_BTN).should('have.text', 'Custom rules (1)');
@ -201,10 +221,10 @@ describe('Detection rules, EQL', () => {
waitForAlertsToPopulate();
cy.get(NUMBER_OF_ALERTS).should('have.text', expectedNumberOfSequenceAlerts);
cy.get(ALERT_RULE_NAME).first().should('have.text', eqlSequenceRule.name);
cy.get(ALERT_RULE_NAME).first().should('have.text', rule.name);
cy.get(ALERT_RULE_VERSION).first().should('have.text', '1');
cy.get(ALERT_RULE_METHOD).first().should('have.text', 'eql');
cy.get(ALERT_RULE_SEVERITY).first().should('have.text', eqlSequenceRule.severity.toLowerCase());
cy.get(ALERT_RULE_RISK_SCORE).first().should('have.text', eqlSequenceRule.riskScore);
cy.get(ALERT_RULE_SEVERITY).first().should('have.text', rule.severity.toLowerCase());
cy.get(ALERT_RULE_RISK_SCORE).first().should('have.text', rule.riskScore);
});
});

View file

@ -4,44 +4,42 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { expectedExportedRule, newRule } from '../objects/rule';
import {
goToManageAlertsDetectionRules,
waitForAlertsIndexToBeCreated,
waitForAlertsPanelToBeLoaded,
} from '../tasks/alerts';
import { exportFirstRule } from '../tasks/alerts_detection_rules';
import { removeSignalsIndex } from '../tasks/api_calls';
import { esArchiverLoad, esArchiverUnload } from '../tasks/es_archiver';
import { createCustomRule, deleteCustomRule } from '../tasks/api_calls/rules';
import { loginAndWaitForPageWithoutDateRange } from '../tasks/login';
import { DETECTIONS_URL } from '../urls/navigation';
const EXPECTED_EXPORTED_RULE_FILE_PATH = 'cypress/test_files/expected_rules_export.ndjson';
describe('Export rules', () => {
let ruleResponse: Cypress.Response;
before(() => {
esArchiverLoad('export_rule');
cy.intercept(
'POST',
'/api/detection_engine/rules/_export?exclude_export_details=false&file_name=rules_export.ndjson'
).as('export');
});
after(() => {
esArchiverUnload('export_rule');
removeSignalsIndex();
});
it('Exports a custom rule', () => {
loginAndWaitForPageWithoutDateRange(DETECTIONS_URL);
waitForAlertsPanelToBeLoaded();
waitForAlertsIndexToBeCreated();
createCustomRule(newRule).then((response) => {
ruleResponse = response;
});
});
after(() => {
deleteCustomRule();
});
it('Exports a custom rule', () => {
goToManageAlertsDetectionRules();
exportFirstRule();
cy.wait('@export').then(({ response }) => {
cy.readFile(EXPECTED_EXPORTED_RULE_FILE_PATH).then(($expectedExportedJson) => {
cy.wrap(response!.body).should('eql', $expectedExportedJson);
});
cy.wrap(response!.body).should('eql', expectedExportedRule(ruleResponse));
});
});
});

View file

@ -66,7 +66,7 @@ import {
waitForLoadElasticPrebuiltDetectionRulesTableToBeLoaded,
waitForRulesToBeLoaded,
} from '../tasks/alerts_detection_rules';
import { removeSignalsIndex } from '../tasks/api_calls';
import { removeSignalsIndex } from '../tasks/api_calls/rules';
import {
createAndActivateRule,
fillAboutRuleAndContinue,
@ -81,14 +81,14 @@ import { loginAndWaitForPageWithoutDateRange } from '../tasks/login';
import { DETECTIONS_URL } from '../urls/navigation';
const expectedUrls = newThreatIndicatorRule.referenceUrls.join('');
const expectedFalsePositives = newThreatIndicatorRule.falsePositivesExamples.join('');
const expectedTags = newThreatIndicatorRule.tags.join('');
const expectedMitre = formatMitreAttackDescription(newThreatIndicatorRule.mitre);
const expectedNumberOfRules = 1;
const expectedNumberOfAlerts = 1;
describe('Detection rules, Indicator Match', () => {
const expectedUrls = newThreatIndicatorRule.referenceUrls.join('');
const expectedFalsePositives = newThreatIndicatorRule.falsePositivesExamples.join('');
const expectedTags = newThreatIndicatorRule.tags.join('');
const expectedMitre = formatMitreAttackDescription(newThreatIndicatorRule.mitre);
const expectedNumberOfRules = 1;
const expectedNumberOfAlerts = 1;
beforeEach(() => {
esArchiverLoad('threat_indicator');
esArchiverLoad('threat_data');
@ -153,7 +153,10 @@ describe('Detection rules, Indicator Match', () => {
cy.get(ABOUT_INVESTIGATION_NOTES).should('have.text', INVESTIGATION_NOTES_MARKDOWN);
cy.get(DEFINITION_DETAILS).within(() => {
getDetails(INDEX_PATTERNS_DETAILS).should('have.text', newThreatIndicatorRule.index.join(''));
getDetails(INDEX_PATTERNS_DETAILS).should(
'have.text',
newThreatIndicatorRule.index!.join('')
);
getDetails(CUSTOM_QUERY_DETAILS).should('have.text', '*:*');
getDetails(RULE_TYPE_DETAILS).should('have.text', 'Indicator Match');
getDetails(TIMELINE_TEMPLATE_DETAILS).should('have.text', 'None');

View file

@ -5,7 +5,7 @@
*/
import { formatMitreAttackDescription } from '../helpers/rules';
import { machineLearningRule, totalNumberOfPrebuiltRulesInEsArchive } from '../objects/rule';
import { machineLearningRule } from '../objects/rule';
import {
CUSTOM_RULES_BTN,
@ -53,7 +53,6 @@ import {
waitForLoadElasticPrebuiltDetectionRulesTableToBeLoaded,
waitForRulesToBeLoaded,
} from '../tasks/alerts_detection_rules';
import { removeSignalsIndex } from '../tasks/api_calls';
import {
createAndActivateRule,
fillAboutRuleAndContinue,
@ -61,26 +60,19 @@ import {
fillScheduleRuleAndContinue,
selectMachineLearningRuleType,
} from '../tasks/create_new_rule';
import { esArchiverLoad, esArchiverUnload } from '../tasks/es_archiver';
import { loginAndWaitForPageWithoutDateRange } from '../tasks/login';
import { DETECTIONS_URL } from '../urls/navigation';
const expectedUrls = machineLearningRule.referenceUrls.join('');
const expectedFalsePositives = machineLearningRule.falsePositivesExamples.join('');
const expectedTags = machineLearningRule.tags.join('');
const expectedMitre = formatMitreAttackDescription(machineLearningRule.mitre);
const expectedNumberOfRules = totalNumberOfPrebuiltRulesInEsArchive + 1;
describe('Detection rules, machine learning', () => {
before(() => {
esArchiverLoad('prebuilt_rules_loaded');
});
const expectedUrls = machineLearningRule.referenceUrls.join('');
const expectedFalsePositives = machineLearningRule.falsePositivesExamples.join('');
const expectedTags = machineLearningRule.tags.join('');
const expectedMitre = formatMitreAttackDescription(machineLearningRule.mitre);
const expectedNumberOfRules = 1;
after(() => {
deleteRule();
esArchiverUnload('prebuilt_rules_loaded');
removeSignalsIndex();
});
it('Creates and activates a new ml rule', () => {

View file

@ -6,6 +6,7 @@
import { formatMitreAttackDescription } from '../helpers/rules';
import { indexPatterns, newOverrideRule, severitiesOverride } from '../objects/rule';
import {
NUMBER_OF_ALERTS,
ALERT_RULE_NAME,
@ -62,12 +63,14 @@ import {
} from '../tasks/alerts';
import {
changeToThreeHundredRowsPerPage,
deleteRule,
filterByCustomRules,
goToCreateNewRule,
goToRuleDetails,
waitForLoadElasticPrebuiltDetectionRulesTableToBeLoaded,
waitForRulesToBeLoaded,
} from '../tasks/alerts_detection_rules';
import { createTimeline, deleteTimeline } from '../tasks/api_calls/timelines';
import {
createAndActivateRule,
fillAboutRuleWithOverrideAndContinue,
@ -76,24 +79,27 @@ import {
waitForAlertsToPopulate,
waitForTheRuleToBeExecuted,
} from '../tasks/create_new_rule';
import { esArchiverLoad, esArchiverUnload } from '../tasks/es_archiver';
import { loginAndWaitForPageWithoutDateRange } from '../tasks/login';
import { DETECTIONS_URL } from '../urls/navigation';
const expectedUrls = newOverrideRule.referenceUrls.join('');
const expectedFalsePositives = newOverrideRule.falsePositivesExamples.join('');
const expectedTags = newOverrideRule.tags.join('');
const expectedMitre = formatMitreAttackDescription(newOverrideRule.mitre);
describe('Detection rules, override', () => {
const expectedUrls = newOverrideRule.referenceUrls.join('');
const expectedFalsePositives = newOverrideRule.falsePositivesExamples.join('');
const expectedTags = newOverrideRule.tags.join('');
const expectedMitre = formatMitreAttackDescription(newOverrideRule.mitre);
// FLAKY: https://github.com/elastic/kibana/issues/84020
describe.skip('Detection rules, override', () => {
before(() => {
esArchiverLoad('timeline');
const rule = { ...newOverrideRule };
beforeEach(() => {
createTimeline(newOverrideRule.timeline).then((response) => {
rule.timeline.id = response.body.data.persistTimeline.timeline.savedObjectId;
});
});
after(() => {
esArchiverUnload('timeline');
afterEach(() => {
deleteTimeline(rule.timeline.id!);
deleteRule();
});
it('Creates and activates a new custom rule with override option', () => {
@ -103,9 +109,9 @@ describe.skip('Detection rules, override', () => {
goToManageAlertsDetectionRules();
waitForLoadElasticPrebuiltDetectionRulesTableToBeLoaded();
goToCreateNewRule();
fillDefineCustomRuleWithImportedQueryAndContinue(newOverrideRule);
fillAboutRuleWithOverrideAndContinue(newOverrideRule);
fillScheduleRuleAndContinue(newOverrideRule);
fillDefineCustomRuleWithImportedQueryAndContinue(rule);
fillAboutRuleWithOverrideAndContinue(rule);
fillScheduleRuleAndContinue(rule);
createAndActivateRule();
cy.get(CUSTOM_RULES_BTN).should('have.text', 'Custom rules (1)');
@ -123,23 +129,23 @@ describe.skip('Detection rules, override', () => {
cy.get(RULES_TABLE).then(($table) => {
cy.wrap($table.find(RULES_ROW).length).should('eql', 1);
});
cy.get(RULE_NAME).should('have.text', newOverrideRule.name);
cy.get(RISK_SCORE).should('have.text', newOverrideRule.riskScore);
cy.get(SEVERITY).should('have.text', newOverrideRule.severity);
cy.get(RULE_NAME).should('have.text', rule.name);
cy.get(RISK_SCORE).should('have.text', rule.riskScore);
cy.get(SEVERITY).should('have.text', rule.severity);
cy.get(RULE_SWITCH).should('have.attr', 'aria-checked', 'true');
goToRuleDetails();
cy.get(RULE_NAME_HEADER).should('have.text', `${newOverrideRule.name}`);
cy.get(ABOUT_RULE_DESCRIPTION).should('have.text', newOverrideRule.description);
cy.get(RULE_NAME_HEADER).should('have.text', `${rule.name}`);
cy.get(ABOUT_RULE_DESCRIPTION).should('have.text', rule.description);
cy.get(ABOUT_DETAILS).within(() => {
getDetails(SEVERITY_DETAILS).should('have.text', newOverrideRule.severity);
getDetails(RISK_SCORE_DETAILS).should('have.text', newOverrideRule.riskScore);
getDetails(SEVERITY_DETAILS).should('have.text', rule.severity);
getDetails(RISK_SCORE_DETAILS).should('have.text', rule.riskScore);
getDetails(RISK_SCORE_OVERRIDE_DETAILS).should(
'have.text',
`${newOverrideRule.riskOverride}signal.rule.risk_score`
`${rule.riskOverride}signal.rule.risk_score`
);
getDetails(RULE_NAME_OVERRIDE_DETAILS).should('have.text', newOverrideRule.nameOverride);
getDetails(RULE_NAME_OVERRIDE_DETAILS).should('have.text', rule.nameOverride);
getDetails(REFERENCE_URLS_DETAILS).should((details) => {
expect(removeExternalLinkText(details.text())).equal(expectedUrls);
});
@ -148,11 +154,11 @@ describe.skip('Detection rules, override', () => {
expect(removeExternalLinkText(mitre.text())).equal(expectedMitre);
});
getDetails(TAGS_DETAILS).should('have.text', expectedTags);
getDetails(TIMESTAMP_OVERRIDE_DETAILS).should('have.text', newOverrideRule.timestampOverride);
getDetails(TIMESTAMP_OVERRIDE_DETAILS).should('have.text', rule.timestampOverride);
cy.contains(DETAILS_TITLE, 'Severity override')
.invoke('index', DETAILS_TITLE) // get index relative to other titles, not all siblings
.then((severityOverrideIndex) => {
newOverrideRule.severityOverride.forEach((severity, i) => {
rule.severityOverride.forEach((severity, i) => {
cy.get(DETAILS_DESCRIPTION)
.eq(severityOverrideIndex + i)
.should(
@ -166,18 +172,18 @@ describe.skip('Detection rules, override', () => {
cy.get(ABOUT_INVESTIGATION_NOTES).should('have.text', INVESTIGATION_NOTES_MARKDOWN);
cy.get(DEFINITION_DETAILS).within(() => {
getDetails(INDEX_PATTERNS_DETAILS).should('have.text', indexPatterns.join(''));
getDetails(CUSTOM_QUERY_DETAILS).should('have.text', newOverrideRule.customQuery);
getDetails(CUSTOM_QUERY_DETAILS).should('have.text', rule.customQuery);
getDetails(RULE_TYPE_DETAILS).should('have.text', 'Query');
getDetails(TIMELINE_TEMPLATE_DETAILS).should('have.text', 'None');
});
cy.get(SCHEDULE_DETAILS).within(() => {
getDetails(RUNS_EVERY_DETAILS).should(
'have.text',
`${newOverrideRule.runsEvery.interval}${newOverrideRule.runsEvery.type}`
`${rule.runsEvery.interval}${rule.runsEvery.type}`
);
getDetails(ADDITIONAL_LOOK_BACK_DETAILS).should(
'have.text',
`${newOverrideRule.lookBack.interval}${newOverrideRule.lookBack.type}`
`${rule.lookBack.interval}${rule.lookBack.type}`
);
});

View file

@ -6,6 +6,7 @@
import { formatMitreAttackDescription } from '../helpers/rules';
import { indexPatterns, newThresholdRule } from '../objects/rule';
import {
ALERT_RULE_METHOD,
ALERT_RULE_NAME,
@ -64,6 +65,7 @@ import {
waitForLoadElasticPrebuiltDetectionRulesTableToBeLoaded,
waitForRulesToBeLoaded,
} from '../tasks/alerts_detection_rules';
import { createTimeline, deleteTimeline } from '../tasks/api_calls/timelines';
import {
createAndActivateRule,
fillAboutRuleAndContinue,
@ -73,24 +75,27 @@ import {
waitForAlertsToPopulate,
waitForTheRuleToBeExecuted,
} from '../tasks/create_new_rule';
import { esArchiverLoad, esArchiverUnload } from '../tasks/es_archiver';
import { loginAndWaitForPageWithoutDateRange } from '../tasks/login';
import { DETECTIONS_URL } from '../urls/navigation';
const expectedUrls = newThresholdRule.referenceUrls.join('');
const expectedFalsePositives = newThresholdRule.falsePositivesExamples.join('');
const expectedTags = newThresholdRule.tags.join('');
const expectedMitre = formatMitreAttackDescription(newThresholdRule.mitre);
describe('Detection rules, threshold', () => {
before(() => {
esArchiverLoad('timeline');
const expectedUrls = newThresholdRule.referenceUrls.join('');
const expectedFalsePositives = newThresholdRule.falsePositivesExamples.join('');
const expectedTags = newThresholdRule.tags.join('');
const expectedMitre = formatMitreAttackDescription(newThresholdRule.mitre);
const rule = { ...newThresholdRule };
beforeEach(() => {
createTimeline(newThresholdRule.timeline).then((response) => {
rule.timeline.id = response.body.data.persistTimeline.timeline.savedObjectId;
});
});
after(() => {
afterEach(() => {
deleteTimeline(rule.timeline.id!);
deleteRule();
esArchiverUnload('timeline');
});
it('Creates and activates a new threshold rule', () => {
@ -101,9 +106,9 @@ describe('Detection rules, threshold', () => {
waitForLoadElasticPrebuiltDetectionRulesTableToBeLoaded();
goToCreateNewRule();
selectThresholdRuleType();
fillDefineThresholdRuleAndContinue(newThresholdRule);
fillAboutRuleAndContinue(newThresholdRule);
fillScheduleRuleAndContinue(newThresholdRule);
fillDefineThresholdRuleAndContinue(rule);
fillAboutRuleAndContinue(rule);
fillScheduleRuleAndContinue(rule);
createAndActivateRule();
cy.get(CUSTOM_RULES_BTN).should('have.text', 'Custom rules (1)');
@ -121,18 +126,18 @@ describe('Detection rules, threshold', () => {
cy.get(RULES_TABLE).then(($table) => {
cy.wrap($table.find(RULES_ROW).length).should('eql', 1);
});
cy.get(RULE_NAME).should('have.text', newThresholdRule.name);
cy.get(RISK_SCORE).should('have.text', newThresholdRule.riskScore);
cy.get(SEVERITY).should('have.text', newThresholdRule.severity);
cy.get(RULE_NAME).should('have.text', rule.name);
cy.get(RISK_SCORE).should('have.text', rule.riskScore);
cy.get(SEVERITY).should('have.text', rule.severity);
cy.get(RULE_SWITCH).should('have.attr', 'aria-checked', 'true');
goToRuleDetails();
cy.get(RULE_NAME_HEADER).should('have.text', `${newThresholdRule.name}`);
cy.get(ABOUT_RULE_DESCRIPTION).should('have.text', newThresholdRule.description);
cy.get(RULE_NAME_HEADER).should('have.text', `${rule.name}`);
cy.get(ABOUT_RULE_DESCRIPTION).should('have.text', rule.description);
cy.get(ABOUT_DETAILS).within(() => {
getDetails(SEVERITY_DETAILS).should('have.text', newThresholdRule.severity);
getDetails(RISK_SCORE_DETAILS).should('have.text', newThresholdRule.riskScore);
getDetails(SEVERITY_DETAILS).should('have.text', rule.severity);
getDetails(RISK_SCORE_DETAILS).should('have.text', rule.riskScore);
getDetails(REFERENCE_URLS_DETAILS).should((details) => {
expect(removeExternalLinkText(details.text())).equal(expectedUrls);
});
@ -146,22 +151,22 @@ describe('Detection rules, threshold', () => {
cy.get(ABOUT_INVESTIGATION_NOTES).should('have.text', INVESTIGATION_NOTES_MARKDOWN);
cy.get(DEFINITION_DETAILS).within(() => {
getDetails(INDEX_PATTERNS_DETAILS).should('have.text', indexPatterns.join(''));
getDetails(CUSTOM_QUERY_DETAILS).should('have.text', newThresholdRule.customQuery);
getDetails(CUSTOM_QUERY_DETAILS).should('have.text', rule.customQuery);
getDetails(RULE_TYPE_DETAILS).should('have.text', 'Threshold');
getDetails(TIMELINE_TEMPLATE_DETAILS).should('have.text', 'None');
getDetails(THRESHOLD_DETAILS).should(
'have.text',
`Results aggregated by ${newThresholdRule.thresholdField} >= ${newThresholdRule.threshold}`
`Results aggregated by ${rule.thresholdField} >= ${rule.threshold}`
);
});
cy.get(SCHEDULE_DETAILS).within(() => {
getDetails(RUNS_EVERY_DETAILS).should(
'have.text',
`${newThresholdRule.runsEvery.interval}${newThresholdRule.runsEvery.type}`
`${rule.runsEvery.interval}${rule.runsEvery.type}`
);
getDetails(ADDITIONAL_LOOK_BACK_DETAILS).should(
'have.text',
`${newThresholdRule.lookBack.interval}${newThresholdRule.lookBack.type}`
`${rule.lookBack.interval}${rule.lookBack.type}`
);
});
@ -169,12 +174,10 @@ describe('Detection rules, threshold', () => {
waitForAlertsToPopulate();
cy.get(NUMBER_OF_ALERTS).invoke('text').then(parseFloat).should('be.below', 100);
cy.get(ALERT_RULE_NAME).first().should('have.text', newThresholdRule.name);
cy.get(ALERT_RULE_NAME).first().should('have.text', rule.name);
cy.get(ALERT_RULE_VERSION).first().should('have.text', '1');
cy.get(ALERT_RULE_METHOD).first().should('have.text', 'threshold');
cy.get(ALERT_RULE_SEVERITY)
.first()
.should('have.text', newThresholdRule.severity.toLowerCase());
cy.get(ALERT_RULE_RISK_SCORE).first().should('have.text', newThresholdRule.riskScore);
cy.get(ALERT_RULE_SEVERITY).first().should('have.text', rule.severity.toLowerCase());
cy.get(ALERT_RULE_RISK_SCORE).first().should('have.text', rule.riskScore);
});
});

View file

@ -38,7 +38,8 @@ import {
import { TIMELINE_DESCRIPTION, TIMELINE_QUERY, TIMELINE_TITLE } from '../screens/timeline';
import { goToCaseDetails, goToCreateNewCase } from '../tasks/all_cases';
import { openCaseTimeline } from '../tasks/case_details';
import { createTimeline, deleteTimeline } from '../tasks/api_calls/timelines';
import { deleteCase, openCaseTimeline } from '../tasks/case_details';
import {
attachTimeline,
backToCases,
@ -46,24 +47,30 @@ import {
fillCasesMandatoryfields,
} from '../tasks/create_new_case';
import { loginAndWaitForPageWithoutDateRange } from '../tasks/login';
import { esArchiverLoad, esArchiverUnload } from '../tasks/es_archiver';
import { closeTimeline } from '../tasks/timeline';
import { CASES_URL } from '../urls/navigation';
describe('Cases', () => {
const mycase = { ...case1 };
before(() => {
esArchiverLoad('timeline');
createTimeline(case1.timeline).then((response) => {
mycase.timeline.id = response.body.data.persistTimeline.timeline.savedObjectId;
});
});
after(() => {
esArchiverUnload('timeline');
closeTimeline();
deleteTimeline(mycase.timeline.id!);
deleteCase();
});
it('Creates a new case with timeline and opens the timeline', () => {
loginAndWaitForPageWithoutDateRange(CASES_URL);
goToCreateNewCase();
fillCasesMandatoryfields(case1);
attachTimeline(case1);
fillCasesMandatoryfields(mycase);
attachTimeline(mycase);
createCase();
backToCases();
@ -74,9 +81,9 @@ describe('Cases', () => {
cy.get(ALL_CASES_OPEN_CASES_COUNT).should('have.text', 'Open (1)');
cy.get(ALL_CASES_REPORTERS_COUNT).should('have.text', 'Reporter1');
cy.get(ALL_CASES_TAGS_COUNT).should('have.text', 'Tags2');
cy.get(ALL_CASES_NAME).should('have.text', case1.name);
cy.get(ALL_CASES_REPORTER).should('have.text', case1.reporter);
case1.tags.forEach((tag, index) => {
cy.get(ALL_CASES_NAME).should('have.text', mycase.name);
cy.get(ALL_CASES_REPORTER).should('have.text', mycase.reporter);
mycase.tags.forEach((tag, index) => {
cy.get(ALL_CASES_TAGS(index)).should('have.text', tag);
});
cy.get(ALL_CASES_COMMENTS_COUNT).should('have.text', '0');
@ -87,24 +94,24 @@ describe('Cases', () => {
goToCaseDetails();
const expectedTags = case1.tags.join('');
cy.get(CASE_DETAILS_PAGE_TITLE).should('have.text', case1.name);
const expectedTags = mycase.tags.join('');
cy.get(CASE_DETAILS_PAGE_TITLE).should('have.text', mycase.name);
cy.get(CASE_DETAILS_STATUS).should('have.text', 'Open');
cy.get(CASE_DETAILS_USER_ACTION_DESCRIPTION_USERNAME).should('have.text', case1.reporter);
cy.get(CASE_DETAILS_USER_ACTION_DESCRIPTION_USERNAME).should('have.text', mycase.reporter);
cy.get(CASE_DETAILS_USER_ACTION_DESCRIPTION_EVENT).should('have.text', 'added description');
cy.get(CASE_DETAILS_DESCRIPTION).should(
'have.text',
`${case1.description} ${case1.timeline.title}`
`${mycase.description} ${mycase.timeline.title}`
);
cy.get(CASE_DETAILS_USERNAMES).eq(REPORTER).should('have.text', case1.reporter);
cy.get(CASE_DETAILS_USERNAMES).eq(PARTICIPANTS).should('have.text', case1.reporter);
cy.get(CASE_DETAILS_USERNAMES).eq(REPORTER).should('have.text', mycase.reporter);
cy.get(CASE_DETAILS_USERNAMES).eq(PARTICIPANTS).should('have.text', mycase.reporter);
cy.get(CASE_DETAILS_TAGS).should('have.text', expectedTags);
cy.get(CASE_DETAILS_PUSH_TO_EXTERNAL_SERVICE_BTN).should('have.attr', 'disabled');
openCaseTimeline();
cy.get(TIMELINE_TITLE).contains(case1.timeline.title);
cy.get(TIMELINE_DESCRIPTION).contains(case1.timeline.description);
cy.get(TIMELINE_QUERY).invoke('text').should('eq', case1.timeline.query);
cy.get(TIMELINE_TITLE).contains(mycase.timeline.title);
cy.get(TIMELINE_DESCRIPTION).contains(mycase.timeline.description);
cy.get(TIMELINE_QUERY).invoke('text').should('eq', mycase.timeline.query);
});
});

View file

@ -13,40 +13,47 @@ import {
} from '../tasks/timeline';
import { DESCRIPTION_INPUT, ADD_COMMENT_INPUT } from '../screens/create_new_case';
import { esArchiverLoad, esArchiverUnload } from '../tasks/es_archiver';
import { caseTimeline, TIMELINE_CASE_ID } from '../objects/case';
import { TIMELINE_CASE_ID } from '../objects/case';
import { caseTimeline, timeline } from '../objects/timeline';
import { createTimeline, deleteTimeline } from '../tasks/api_calls/timelines';
describe('attach timeline to case', () => {
beforeEach(() => {
loginAndWaitForTimeline(caseTimeline.id);
});
const myTimeline = { ...timeline };
context('without cases created', () => {
before(() => {
esArchiverLoad('timeline');
createTimeline(timeline).then((response) => {
myTimeline.id = response.body.data.persistTimeline.timeline.savedObjectId;
});
});
after(() => {
esArchiverUnload('timeline');
deleteTimeline(myTimeline.id!);
});
it('attach timeline to a new case', () => {
loginAndWaitForTimeline(myTimeline.id!);
attachTimelineToNewCase();
cy.location('origin').then((origin) => {
cy.get(DESCRIPTION_INPUT).should(
'have.text',
`[${caseTimeline.title}](${origin}/app/security/timelines?timeline=(id:%27${caseTimeline.id}%27,isOpen:!t))`
`[${myTimeline.title}](${origin}/app/security/timelines?timeline=(id:%27${myTimeline.id}%27,isOpen:!t))`
);
});
});
it('attach timeline to an existing case with no case', () => {
loginAndWaitForTimeline(myTimeline.id!);
attachTimelineToExistingCase();
addNewCase();
cy.location('origin').then((origin) => {
cy.get(DESCRIPTION_INPUT).should(
'have.text',
`[${caseTimeline.title}](${origin}/app/security/timelines?timeline=(id:%27${caseTimeline.id}%27,isOpen:!t))`
`[${
myTimeline.title
}](${origin}/app/security/timelines?timeline=(id:%27${myTimeline.id!}%27,isOpen:!t))`
);
});
});
@ -62,13 +69,16 @@ describe('attach timeline to case', () => {
});
it('attach timeline to an existing case', () => {
loginAndWaitForTimeline(caseTimeline.id!);
attachTimelineToExistingCase();
selectCase(TIMELINE_CASE_ID);
cy.location('origin').then((origin) => {
cy.get(ADD_COMMENT_INPUT).should(
'have.text',
`[${caseTimeline.title}](${origin}/app/security/timelines?timeline=(id:%27${caseTimeline.id}%27,isOpen:!t))`
`[${
caseTimeline.title
}](${origin}/app/security/timelines?timeline=(id:%27${caseTimeline.id!}%27,isOpen:!t))`
);
});
});

View file

@ -24,6 +24,7 @@ import {
TIMELINES_NOTES_COUNT,
TIMELINES_FAVORITE,
} from '../screens/timelines';
import { deleteTimeline } from '../tasks/api_calls/timelines';
import { loginAndWaitForPage } from '../tasks/login';
import { openTimelineUsingToggle } from '../tasks/security_main';
@ -44,8 +45,13 @@ import { openTimeline } from '../tasks/timelines';
import { OVERVIEW_URL } from '../urls/navigation';
// FLAKY: https://github.com/elastic/kibana/issues/79389
describe.skip('Timelines', () => {
describe('Timelines', () => {
let timelineId: string;
after(() => {
deleteTimeline(timelineId);
});
it('Creates a timeline', () => {
cy.intercept('PATCH', '/api/timeline').as('timeline');
@ -61,7 +67,7 @@ describe.skip('Timelines', () => {
addNameToTimeline(timeline.title);
cy.wait('@timeline').then(({ response }) => {
const timelineId = response!.body.data.persistTimeline.timeline.savedObjectId;
timelineId = response!.body.data.persistTimeline.timeline.savedObjectId;
addDescriptionToTimeline(timeline.description);
addNotesToTimeline(timeline.notes);
@ -82,7 +88,7 @@ describe.skip('Timelines', () => {
cy.get(FAVORITE_TIMELINE).should('exist');
cy.get(TIMELINE_TITLE).should('have.text', timeline.title);
cy.get(TIMELINE_DESCRIPTION).should('have.text', timeline.description);
cy.get(TIMELINE_QUERY).should('have.text', timeline.query);
cy.get(TIMELINE_QUERY).should('have.text', `${timeline.query} `);
// Comments this assertion until we agreed what to do with the filters.
// cy.get(TIMELINE_FILTER(timeline.filter)).should('exist');
// cy.get(NOTES_COUNT).should('have.text', '1');

View file

@ -24,9 +24,7 @@ import { closeTimeline, createNewTimeline } from '../tasks/timeline';
import { HOSTS_URL } from '../urls/navigation';
// FLAKY: https://github.com/elastic/kibana/issues/85098
// FLAKY: https://github.com/elastic/kibana/issues/62060
describe.skip('timeline data providers', () => {
describe('timeline data providers', () => {
before(() => {
loginAndWaitForPage(HOSTS_URL);
waitForAllHostsToBeLoaded();

View file

@ -5,44 +5,40 @@
*/
import { exportTimeline } from '../tasks/timelines';
import { esArchiverLoad, esArchiverUnload } from '../tasks/es_archiver';
import { loginAndWaitForPageWithoutDateRange } from '../tasks/login';
import { timeline as timelineTemplate } from '../objects/timeline';
import {
expectedExportedTimelineTemplate,
timeline as timelineTemplate,
} from '../objects/timeline';
import { TIMELINE_TEMPLATES_URL } from '../urls/navigation';
import { addNameToTimeline, closeTimeline, createNewTimelineTemplate } from '../tasks/timeline';
import {
createTimelineTemplate,
deleteTimeline as deleteTimelineTemplate,
} from '../tasks/api_calls/timelines';
describe('Export timelines', () => {
let templateResponse: Cypress.Response;
let templateId: string;
before(() => {
esArchiverLoad('timeline');
cy.intercept('PATCH', '/api/timeline').as('timeline');
cy.intercept('POST', '/api/timeline/_export?file_name=timelines_export.ndjson').as('export');
cy.intercept('POST', 'api/timeline/_export?file_name=timelines_export.ndjson').as('export');
createTimelineTemplate(timelineTemplate).then((response) => {
templateResponse = response;
templateId = response.body.data.persistTimeline.timeline.savedObjectId;
});
});
after(() => {
esArchiverUnload('timeline');
deleteTimelineTemplate(templateId);
});
it('Exports a custom timeline template', () => {
loginAndWaitForPageWithoutDateRange(TIMELINE_TEMPLATES_URL);
createNewTimelineTemplate();
addNameToTimeline(timelineTemplate.title);
closeTimeline();
exportTimeline(templateId!);
cy.wait('@timeline').then(({ response }) => {
const {
savedObjectId: timelineId,
templateTimelineId,
} = response!.body.data.persistTimeline.timeline;
exportTimeline(timelineId);
cy.wait('@export').then(({ response: exportResponse }) => {
cy.wrap(JSON.parse(exportResponse!.body as string).templateTimelineId).should(
'eql',
templateTimelineId
);
});
cy.wait('@export').then(({ response }) => {
cy.wrap(response!.body).should('eql', expectedExportedTimelineTemplate(templateResponse));
});
});
});

View file

@ -4,14 +4,15 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { timeline } from '../objects/timeline';
import {
ID_HEADER_FIELD,
ID_TOGGLE_FIELD,
TIMESTAMP_HEADER_FIELD,
TIMESTAMP_TOGGLE_FIELD,
} from '../screens/timeline';
import { createTimeline, deleteTimeline } from '../tasks/api_calls/timelines';
import { esArchiverLoad, esArchiverUnload } from '../tasks/es_archiver';
import { loginAndWaitForPage } from '../tasks/login';
import { openTimelineUsingToggle } from '../tasks/security_main';
import {
@ -27,13 +28,17 @@ import {
import { HOSTS_URL } from '../urls/navigation';
describe('toggle column in timeline', () => {
let timelineId: string;
before(() => {
esArchiverLoad('timeline');
loginAndWaitForPage(HOSTS_URL);
cy.intercept('POST', '/api/timeline/_export?file_name=timelines_export.ndjson').as('export');
createTimeline(timeline).then((response) => {
timelineId = response.body.data.persistTimeline.timeline.savedObjectId;
loginAndWaitForPage(HOSTS_URL);
});
});
after(() => {
esArchiverUnload('timeline');
deleteTimeline(timelineId);
});
beforeEach(() => {

View file

@ -5,36 +5,35 @@
*/
import { exportTimeline, waitForTimelinesPanelToBeLoaded } from '../tasks/timelines';
import { esArchiverLoad, esArchiverUnload } from '../tasks/es_archiver';
import { loginAndWaitForPageWithoutDateRange } from '../tasks/login';
import { TIMELINES_URL } from '../urls/navigation';
const EXPECTED_EXPORTED_TIMELINE_PATH = 'cypress/test_files/expected_timelines_export.ndjson';
import { createTimeline, deleteTimeline } from '../tasks/api_calls/timelines';
import { expectedExportedTimeline, timeline } from '../objects/timeline';
describe('Export timelines', () => {
let timelineResponse: Cypress.Response;
let timelineId: string;
before(() => {
esArchiverLoad('timeline');
cy.intercept('POST', '/api/timeline/_export?file_name=timelines_export.ndjson').as('export');
createTimeline(timeline).then((response) => {
timelineResponse = response;
timelineId = response.body.data.persistTimeline.timeline.savedObjectId;
});
});
after(() => {
esArchiverUnload('timeline');
deleteTimeline(timelineId);
});
it('Exports a custom timeline', () => {
loginAndWaitForPageWithoutDateRange(TIMELINES_URL);
waitForTimelinesPanelToBeLoaded();
exportTimeline(timelineId);
cy.readFile(EXPECTED_EXPORTED_TIMELINE_PATH).then(($expectedExportedJson) => {
const parsedJson = JSON.parse($expectedExportedJson);
const timelineId = parsedJson.savedObjectId;
exportTimeline(timelineId);
cy.wait('@export').then(({ response }) => {
cy.wrap(response!.statusCode).should('eql', 200);
cy.wrap(response!.body).should('eql', $expectedExportedJson);
});
cy.wait('@export').then(({ response }) => {
cy.wrap(response!.statusCode).should('eql', 200);
cy.wrap(response!.body).should('eql', expectedExportedTimeline(timelineResponse));
});
});
});

View file

@ -48,8 +48,7 @@ const ABSOLUTE_DATE = {
startTimeTimeline: '2019-08-02T20:03:29.186Z',
};
// SKIP: https://github.com/elastic/kibana/issues/85289
describe.skip('url state', () => {
describe('url state', () => {
it('sets the global start and end dates from the url', () => {
loginAndWaitForPageWithoutDateRange(ABSOLUTE_DATE_RANGE.url);
cy.get(DATE_PICKER_START_DATE_POPOVER_BUTTON).should(

View file

@ -4,13 +4,13 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { Timeline, TimelineWithId } from './timeline';
import { CompleteTimeline, timeline } from './timeline';
export interface TestCase {
name: string;
tags: string[];
description: string;
timeline: Timeline;
timeline: CompleteTimeline;
reporter: string;
}
@ -38,18 +38,11 @@ export interface IbmResilientConnectorOptions {
incidentTypes: string[];
}
export const caseTimeline: TimelineWithId = {
title: 'SIEM test',
description: 'description',
query: 'host.name:*',
id: '0162c130-78be-11ea-9718-118a926974a4',
};
export const case1: TestCase = {
name: 'This is the title of the case',
tags: ['Tag1', 'Tag2'],
description: 'This is the case description',
timeline: caseTimeline,
timeline,
reporter: 'elastic',
};

View file

@ -5,9 +5,9 @@
*/
/* eslint-disable @kbn/eslint/no-restricted-paths */
import { mockThreatData } from '../../public/detections/mitre/mitre_tactics_techniques';
import { rawRules } from '../../server/lib/detection_engine/rules/prepackaged_rules/index';
/* eslint-enable @kbn/eslint/no-restricted-paths */
import { mockThreatData } from '../../public/detections/mitre/mitre_tactics_techniques';
import { CompleteTimeline, timeline } from './timeline';
export const totalNumberOfPrebuiltRules = rawRules.length;
@ -40,7 +40,7 @@ export interface CustomRule {
customQuery?: string;
name: string;
description: string;
index: string[];
index?: string[];
interval?: string;
severity: string;
riskScore: string;
@ -50,9 +50,9 @@ export interface CustomRule {
falsePositivesExamples: string[];
mitre: Mitre[];
note: string;
timelineId?: string;
runsEvery: Interval;
lookBack: Interval;
timeline: CompleteTimeline;
}
export interface ThresholdRule extends CustomRule {
@ -159,7 +159,7 @@ const lookBack: Interval = {
};
export const newRule: CustomRule = {
customQuery: 'host.name:*',
customQuery: 'host.name: *',
index: indexPatterns,
name: 'New Rule Test',
description: 'The new rule description.',
@ -170,9 +170,9 @@ export const newRule: CustomRule = {
falsePositivesExamples: ['False1', 'False2'],
mitre: [mitre1, mitre2],
note: '# test markdown',
timelineId: '0162c130-78be-11ea-9718-118a926974a4',
runsEvery,
lookBack,
timeline,
};
export const existingRule: CustomRule = {
@ -195,13 +195,13 @@ export const existingRule: CustomRule = {
falsePositivesExamples: [],
mitre: [],
note: 'This is my note',
timelineId: '',
runsEvery,
lookBack,
timeline,
};
export const newOverrideRule: OverrideRule = {
customQuery: 'host.name:*',
customQuery: 'host.name: *',
index: indexPatterns,
name: 'New Rule Test',
description: 'The new rule description.',
@ -212,17 +212,17 @@ export const newOverrideRule: OverrideRule = {
falsePositivesExamples: ['False1', 'False2'],
mitre: [mitre1, mitre2],
note: '# test markdown',
timelineId: '0162c130-78be-11ea-9718-118a926974a4',
severityOverride: [severityOverride1, severityOverride2, severityOverride3, severityOverride4],
riskOverride: 'destination.port',
nameOverride: 'agent.type',
timestampOverride: '@timestamp',
runsEvery,
lookBack,
timeline,
};
export const newThresholdRule: ThresholdRule = {
customQuery: 'host.name:*',
customQuery: 'host.name: *',
index: indexPatterns,
name: 'New Rule Test',
description: 'The new rule description.',
@ -233,11 +233,11 @@ export const newThresholdRule: ThresholdRule = {
falsePositivesExamples: ['False1', 'False2'],
mitre: [mitre1, mitre2],
note: '# test markdown',
timelineId: '0162c130-78be-11ea-9718-118a926974a4',
thresholdField: 'host.name',
threshold: '10',
runsEvery,
lookBack,
timeline,
};
export const machineLearningRule: MachineLearningRule = {
@ -268,9 +268,9 @@ export const eqlRule: CustomRule = {
falsePositivesExamples: ['False1', 'False2'],
mitre: [mitre1, mitre2],
note: '# test markdown',
timelineId: '0162c130-78be-11ea-9718-118a926974a4',
runsEvery,
lookBack,
timeline,
};
export const eqlSequenceRule: CustomRule = {
@ -288,9 +288,9 @@ export const eqlSequenceRule: CustomRule = {
falsePositivesExamples: ['False1', 'False2'],
mitre: [mitre1, mitre2],
note: '# test markdown',
timelineId: '0162c130-78be-11ea-9718-118a926974a4',
runsEvery,
lookBack,
timeline,
};
export const newThreatIndicatorRule: ThreatIndicatorRule = {
@ -309,6 +309,7 @@ export const newThreatIndicatorRule: ThreatIndicatorRule = {
indicatorIndexPattern: ['threat-indicator-*'],
indicatorMapping: 'agent.id',
indicatorIndexField: 'agent.threat',
timeline,
};
export const severitiesOverride = ['Low', 'Medium', 'High', 'Critical'];
@ -319,3 +320,9 @@ export const editedRule = {
description: 'Edited Rule description',
tags: [...existingRule.tags, 'edited'],
};
export const expectedExportedRule = (ruleResponse: Cypress.Response) => {
const jsonrule = ruleResponse.body;
return `{"author":[],"actions":[],"created_at":"${jsonrule.created_at}","updated_at":"${jsonrule.updated_at}","created_by":"elastic","description":"${jsonrule.description}","enabled":false,"false_positives":[],"from":"now-17520h","id":"${jsonrule.id}","immutable":false,"index":["exceptions-*"],"interval":"10s","rule_id":"rule_testing","language":"kuery","output_index":".siem-signals-default","max_signals":100,"risk_score":${jsonrule.risk_score},"risk_score_mapping":[],"name":"${jsonrule.name}","query":"${jsonrule.query}","references":[],"severity":"${jsonrule.severity}","severity_mapping":[],"updated_by":"elastic","tags":[],"to":"now","type":"query","threat":[],"throttle":"no_actions","version":1,"exceptions_list":[]}\n{"exported_count":1,"missing_rules":[],"missing_rules_count":0}\n`;
};

View file

@ -8,6 +8,7 @@ export interface Timeline {
title: string;
description: string;
query: string;
id?: string;
}
export interface CompleteTimeline extends Timeline {
@ -21,10 +22,6 @@ export interface TimelineFilter {
value?: string;
}
export interface TimelineWithId extends Timeline {
id: string;
}
export const filter: TimelineFilter = {
field: 'host.name',
operator: 'exists',
@ -33,7 +30,27 @@ export const filter: TimelineFilter = {
export const timeline: CompleteTimeline = {
title: 'Security Timeline',
description: 'This is the best timeline',
query: 'host.name: * ',
query: 'host.name: *',
notes: 'Yes, the best timeline',
filter,
};
export const caseTimeline: Timeline = {
title: 'SIEM test',
description: 'description',
query: 'host.name: *',
id: '0162c130-78be-11ea-9718-118a926974a4',
};
export const expectedExportedTimelineTemplate = (templateResponse: Cypress.Response) => {
const timelineTemplateBody = templateResponse.body.data.persistTimeline.timeline;
return `{"savedObjectId":"${timelineTemplateBody.savedObjectId}","version":"${timelineTemplateBody.version}","columns":[{"id":"@timestamp"},{"id":"user.name"},{"id":"event.category"},{"id":"event.action"},{"id":"host.name"}],"kqlMode":"filter","kqlQuery":{"filterQuery":{"kuery":{"expression":"${timelineTemplateBody.kqlQuery.filterQuery.kuery.expression}","kind":"kuery"}}},"dateRange":{"start":"${timelineTemplateBody.dateRange.start}","end":"${timelineTemplateBody.dateRange.end}"},"description":"${timelineTemplateBody.description}","title":"${timelineTemplateBody.title}","templateTimelineVersion":1,"timelineType":"template","created":${timelineTemplateBody.created},"createdBy":"elastic","updated":${timelineTemplateBody.updated},"updatedBy":"elastic","sort":[],"eventNotes":[],"globalNotes":[],"pinnedEventIds":[]}
`;
};
export const expectedExportedTimeline = (timelineResponse: Cypress.Response) => {
const timelineBody = timelineResponse.body.data.persistTimeline.timeline;
return `{"savedObjectId":"${timelineBody.savedObjectId}","version":"${timelineBody.version}","columns":[{"id":"@timestamp"},{"id":"user.name"},{"id":"event.category"},{"id":"event.action"},{"id":"host.name"}],"kqlMode":"filter","kqlQuery":{"filterQuery":{"kuery":{"expression":"${timelineBody.kqlQuery.filterQuery.kuery.expression}","kind":"kuery"}}},"dateRange":{"start":"${timelineBody.dateRange.start}","end":"${timelineBody.dateRange.end}"},"description":"${timelineBody.description}","title":"${timelineBody.title}","created":${timelineBody.created},"createdBy":"elastic","updated":${timelineBody.updated},"updatedBy":"elastic","timelineType":"default","sort":[],"eventNotes":[],"globalNotes":[],"pinnedEventIds":[]}\n`;
};

View file

@ -21,6 +21,7 @@
// Import commands.js using ES2015 syntax:
import './commands';
import 'cypress-promise/register';
Cypress.Cookies.defaults({
preserve: 'sid',

View file

@ -4,9 +4,9 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { CustomRule } from '../objects/rule';
import { CustomRule } from '../../objects/rule';
export const createCustomRule = (rule: CustomRule) => {
export const createCustomRule = (rule: CustomRule) =>
cy.request({
method: 'POST',
url: 'api/detection_engine/rules',
@ -26,7 +26,6 @@ export const createCustomRule = (rule: CustomRule) => {
},
headers: { 'kbn-xsrf': 'cypress-creds' },
});
};
export const deleteCustomRule = () => {
cy.request({

View file

@ -0,0 +1,110 @@
/*
* 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 { CompleteTimeline } from '../../objects/timeline';
export const createTimeline = (timeline: CompleteTimeline) =>
cy.request({
method: 'POST',
url: 'api/timeline',
body: {
timeline: {
columns: [
{
id: '@timestamp',
},
{
id: 'user.name',
},
{
id: 'event.category',
},
{
id: 'event.action',
},
{
id: 'host.name',
},
],
kqlMode: 'filter',
kqlQuery: {
filterQuery: {
kuery: {
expression: timeline.query,
kind: 'kuery',
},
},
},
dateRange: {
end: '1577881376000',
start: '1514809376000',
},
description: timeline.description,
title: timeline.title,
},
},
headers: { 'kbn-xsrf': 'cypress-creds' },
});
export const createTimelineTemplate = (timeline: CompleteTimeline) =>
cy.request({
method: 'POST',
url: 'api/timeline',
body: {
timeline: {
columns: [
{
id: '@timestamp',
},
{
id: 'user.name',
},
{
id: 'event.category',
},
{
id: 'event.action',
},
{
id: 'host.name',
},
],
kqlMode: 'filter',
kqlQuery: {
filterQuery: {
kuery: {
expression: timeline.query,
kind: 'kuery',
},
},
},
dateRange: {
end: '1577881376000',
start: '1514809376000',
},
description: timeline.description,
title: timeline.title,
templateTimelineVersion: 1,
timelineType: 'template',
},
},
headers: { 'kbn-xsrf': 'cypress-creds' },
});
export const deleteTimeline = (timelineId: string) => {
cy.request({
method: 'POST',
url: 'api/solutions/security/graphql',
body: {
operationName: 'DeleteTimelineMutation',
variables: {
id: [timelineId],
},
query: 'mutation DeleteTimelineMutation($id: [ID!]!) {\n deleteTimeline(id: $id)\n}\n',
},
headers: { 'kbn-xsrf': 'delete-signals' },
});
};

View file

@ -72,9 +72,9 @@ import {
MITRE_ATTACK_ADD_TECHNIQUE_BUTTON,
} from '../screens/create_new_rule';
import { NOTIFICATION_TOASTS, TOAST_ERROR_CLASS } from '../screens/shared';
import { SERVER_SIDE_EVENT_COUNT } from '../screens/timeline';
import { TIMELINE } from '../screens/timelines';
import { refreshPage } from './security_header';
import { NUMBER_OF_ALERTS } from '../screens/alerts';
export const createAndActivateRule = () => {
cy.get(SCHEDULE_CONTINUE_BUTTON).click({ force: true });
@ -229,7 +229,7 @@ export const fillDefineCustomRuleWithImportedQueryAndContinue = (
rule: CustomRule | OverrideRule
) => {
cy.get(IMPORT_QUERY_FROM_SAVED_TIMELINE_LINK).click();
cy.get(TIMELINE(rule.timelineId!)).click();
cy.get(TIMELINE(rule.timeline.id!)).click();
cy.get(CUSTOM_QUERY_INPUT).should('have.value', rule.customQuery);
cy.get(DEFINE_CONTINUE_BUTTON).should('exist').click({ force: true });
@ -331,6 +331,22 @@ export const selectThresholdRuleType = () => {
cy.get(THRESHOLD_TYPE).click({ force: true });
};
export const waitForAlertsToPopulate = async () => {
cy.waitUntil(
() => {
refreshPage();
return cy
.get(SERVER_SIDE_EVENT_COUNT)
.invoke('text')
.then((countText) => {
const alertCount = parseInt(countText, 10) || 0;
return alertCount > 0;
});
},
{ interval: 500, timeout: 12000 }
);
};
export const waitForTheRuleToBeExecuted = () => {
cy.waitUntil(() => {
cy.get(REFRESH_BUTTON).click();
@ -340,16 +356,3 @@ export const waitForTheRuleToBeExecuted = () => {
.then((ruleStatus) => ruleStatus === 'succeeded');
});
};
export const waitForAlertsToPopulate = async () => {
cy.waitUntil(() => {
refreshPage();
return cy
.get(NUMBER_OF_ALERTS)
.invoke('text')
.then((countText) => {
const alertCount = parseInt(countText, 10) || 0;
return alertCount > 0;
});
});
};

View file

@ -1,2 +0,0 @@
{"author":[],"actions":[],"created_at":"2020-07-15T10:45:15.954Z","updated_at":"2020-07-15T10:45:16.874Z","created_by":"elastic","description":"Export rule","enabled":true,"false_positives":[],"filters":[],"from":"now-360s","id":"a4772daa-a3ef-44a3-8035-6abd1bf2893a","immutable":false,"index":["apm-*-transaction*","auditbeat-*","endgame-*","filebeat-*","logs-*","packetbeat-*","winlogbeat-*"],"interval":"5m","rule_id":"1b08a0c2-8243-463e-92c2-b464a8c97cd4","language":"kuery","license":"","output_index":".siem-signals-default","max_signals":100,"risk_score":50,"risk_score_mapping":[],"name":"Export rule","query":"host.name: *","references":[],"meta":{"from":"1m","kibana_siem_app_url":"http://localhost:5620/app/security/detections"},"severity":"low","severity_mapping":[],"updated_by":"elastic","tags":[],"to":"now","type":"query","threat":[],"throttle":"no_actions","version":1,"exceptions_list":[]}
{"exported_count":1,"missing_rules":[],"missing_rules_count":0}

View file

@ -1 +0,0 @@
{"savedObjectId":"0162c130-78be-11ea-9718-118a926974a4","version":"WzcsMV0=","columns":[{"columnHeaderType":"not-filtered","id":"@timestamp"},{"columnHeaderType":"not-filtered","id":"message"},{"columnHeaderType":"not-filtered","id":"event.category"},{"columnHeaderType":"not-filtered","id":"event.action"},{"columnHeaderType":"not-filtered","id":"host.name"},{"columnHeaderType":"not-filtered","id":"source.ip"},{"columnHeaderType":"not-filtered","id":"destination.ip"},{"columnHeaderType":"not-filtered","id":"user.name"}],"created":1586256805054,"createdBy":"elastic","dataProviders":[],"dateRange":{"end":1586256837669,"start":1546343624710},"description":"description","eventType":"all","filters":[],"kqlMode":"filter","kqlQuery":{"filterQuery":{"kuery":{"expression":"host.name:*","kind":"kuery"},"serializedQuery":"{\"bool\":{\"should\":[{\"exists\":{\"field\":\"host.name\"}}],\"minimum_should_match\":1}}"}},"savedQueryId":null,"sort":[{"columnId":"@timestamp","sortDirection":"desc"}],"title":"SIEM test","updated":1586256839298,"updatedBy":"elastic","timelineType":"default","eventNotes":[],"globalNotes":[],"pinnedEventIds":[]}

View file

@ -3114,4 +3114,4 @@
}
}
}
}
}