Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@
* 2.0.
*/

import { getNewThreatIndicatorRule } from '../../../../objects/rule';
import { getEqlRule, getNewThreatIndicatorRule } from '../../../../objects/rule';

import {
SUPPRESS_FOR_DETAILS,
SUPPRESS_BY_DETAILS,
SUPPRESS_MISSING_FIELD,
DEFINITION_DETAILS,
ALERT_SUPPRESSION_INSUFFICIENT_LICENSING_ICON,
DETAILS_TITLE,
} from '../../../../screens/rule_details';

import { startBasicLicense } from '../../../../tasks/api_calls/licensing';
Expand All @@ -28,19 +29,19 @@ import { deleteAlertsAndRules } from '../../../../tasks/api_calls/common';
const SUPPRESS_BY_FIELDS = ['myhash.mysha256', 'source.ip.keyword'];

describe(
'Detection rules, Indicator Match, Alert Suppression',
'Alert Suppression license check - Rule Details',
{
tags: ['@ess'],
},
() => {
describe('Create rule form', () => {
beforeEach(() => {
deleteAlertsAndRules();
login();
visit(CREATE_RULE_URL);
startBasicLicense();
});
beforeEach(() => {
deleteAlertsAndRules();
login();
visit(CREATE_RULE_URL);
startBasicLicense();
});

describe('Indicator match', () => {
it('shows upselling message on rule details with suppression on basic license', () => {
const rule = getNewThreatIndicatorRule();

Expand Down Expand Up @@ -71,5 +72,40 @@ describe(
});
});
});

describe('EQL rule', () => {
it('shows an upselling message on rule suppression details', () => {
const rule = getEqlRule();

createRule({
...rule,
alert_suppression: {
group_by: SUPPRESS_BY_FIELDS,
duration: { value: 360, unit: 's' },
missing_fields_strategy: 'doNotSuppress',
},
}).then((createdRule) => {
visit(ruleDetailsUrl(createdRule.body.id));

cy.get(DEFINITION_DETAILS).within(() => {
getDetails(SUPPRESS_BY_DETAILS).should('have.text', SUPPRESS_BY_FIELDS.join(''));
getDetails(SUPPRESS_FOR_DETAILS).should('have.text', '360s');
getDetails(SUPPRESS_MISSING_FIELD).should(
'have.text',
'Do not suppress alerts for events with missing fields'
);

// suppression functionality should be under Tech Preview
cy.contains(DETAILS_TITLE, SUPPRESS_FOR_DETAILS).contains('Technical Preview');
});

// Platinum license is required for configuration to apply
cy.get(ALERT_SUPPRESSION_INSUFFICIENT_LICENSING_ICON).eq(2).trigger('mouseover');
cy.get(TOOLTIP).contains(
'Alert suppression is configured but will not be applied due to insufficient licensing'
);
});
});
});
}
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* 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 {
THRESHOLD_ENABLE_SUPPRESSION_CHECKBOX,
ALERT_SUPPRESSION_DURATION_VALUE_INPUT,
MACHINE_LEARNING_TYPE,
ALERT_SUPPRESSION_DURATION_UNIT_INPUT,
ALERT_SUPPRESSION_FIELDS_INPUT,
ALERT_SUPPRESSION_FIELDS,
} from '../../../../screens/create_new_rule';

import {
selectIndicatorMatchType,
selectNewTermsRuleType,
selectThresholdRuleType,
selectEsqlRuleType,
openSuppressionFieldsTooltipAndCheckLicense,
selectEqlRuleType,
} from '../../../../tasks/create_new_rule';
import { startBasicLicense } from '../../../../tasks/api_calls/licensing';
import { login } from '../../../../tasks/login';
import { visit } from '../../../../tasks/navigation';
import { CREATE_RULE_URL } from '../../../../urls/navigation';
import { TOOLTIP } from '../../../../screens/common';

import { deleteAlertsAndRules } from '../../../../tasks/api_calls/common';

describe(
'Alert Suppression basic license check - Rule Form',
{
tags: ['@ess'],
},
() => {
beforeEach(() => {
deleteAlertsAndRules();
login();
visit(CREATE_RULE_URL);
startBasicLicense();
});

it('cannot create rule with rule execution suppression on basic license for all rules with enabled suppression', () => {
// Default query rule
openSuppressionFieldsTooltipAndCheckLicense();

selectIndicatorMatchType();
openSuppressionFieldsTooltipAndCheckLicense();

selectNewTermsRuleType();
openSuppressionFieldsTooltipAndCheckLicense();

selectEsqlRuleType();
openSuppressionFieldsTooltipAndCheckLicense();

selectEqlRuleType();
cy.get(ALERT_SUPPRESSION_FIELDS_INPUT).should('be.disabled');
cy.get(ALERT_SUPPRESSION_FIELDS).trigger('mouseover');

// Platinum license is required, tooltip on disabled alert suppression checkbox should tell this
cy.get(TOOLTIP).contains('Platinum license');

// ML Rules require Platinum license
cy.get(MACHINE_LEARNING_TYPE).get('button').should('be.disabled');

selectThresholdRuleType();
cy.get(THRESHOLD_ENABLE_SUPPRESSION_CHECKBOX).should('be.disabled');
cy.get(THRESHOLD_ENABLE_SUPPRESSION_CHECKBOX).parent().trigger('mouseover');
// Platinum license is required, tooltip on disabled alert suppression checkbox should tell this
cy.get(TOOLTIP).contains('Platinum license');

cy.get(ALERT_SUPPRESSION_DURATION_VALUE_INPUT).should('be.disabled');
cy.get(ALERT_SUPPRESSION_DURATION_UNIT_INPUT).should('be.disabled');
});
}
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
* 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 {
DEFINITION_DETAILS,
SUPPRESS_FOR_DETAILS,
SUPPRESS_BY_DETAILS,
SUPPRESS_MISSING_FIELD,
DETAILS_TITLE,
} from '../../../../screens/rule_details';
import { ALERT_SUPPRESSION_FIELDS } from '../../../../screens/create_new_rule';

import { deleteAlertsAndRules } from '../../../../tasks/api_calls/common';
import {
fillAboutRuleMinimumAndContinue,
createRuleWithoutEnabling,
fillAlertSuppressionFields,
skipScheduleRuleAction,
continueFromDefineStep,
fillCustomQueryInput,
} from '../../../../tasks/create_new_rule';
import { login } from '../../../../tasks/login';
import { visit } from '../../../../tasks/navigation';
import { getDetails } from '../../../../tasks/rule_details';
import { CREATE_RULE_URL } from '../../../../urls/navigation';

describe('Custom Query Rule - Alert suppression', { tags: ['@ess', '@serverless'] }, () => {
const rule = getNewRule();

beforeEach(() => {
deleteAlertsAndRules();
login();
visit(CREATE_RULE_URL);
});

const SUPPRESS_BY_FIELDS = ['source.ip'];

it('creates rule with suppression', () => {
fillCustomQueryInput('*');
fillAlertSuppressionFields(SUPPRESS_BY_FIELDS);
// alert suppression fields input should not have Technical Preview label
cy.get(ALERT_SUPPRESSION_FIELDS).should('not.contain.text', 'Technical Preview');
continueFromDefineStep();

// ensures details preview works correctly
cy.get(DEFINITION_DETAILS).within(() => {
getDetails(SUPPRESS_BY_DETAILS).should('have.text', SUPPRESS_BY_FIELDS.join(''));
getDetails(SUPPRESS_FOR_DETAILS).should('have.text', 'One rule execution');
getDetails(SUPPRESS_MISSING_FIELD).should(
'have.text',
'Suppress and group alerts for events with missing fields'
);

// suppression functionality should be in GA
cy.contains(DETAILS_TITLE, SUPPRESS_FOR_DETAILS).should(
'not.contain.text',
'Technical Preview'
);
});

fillAboutRuleMinimumAndContinue(rule);
skipScheduleRuleAction();
createRuleWithoutEnabling();

cy.get(DEFINITION_DETAILS).within(() => {
getDetails(SUPPRESS_BY_DETAILS).should('have.text', SUPPRESS_BY_FIELDS.join(''));
getDetails(SUPPRESS_FOR_DETAILS).should('have.text', 'One rule execution');
getDetails(SUPPRESS_MISSING_FIELD).should(
'have.text',
'Suppress and group alerts for events with missing fields'
);

// suppression functionality should be in GA
cy.contains(DETAILS_TITLE, SUPPRESS_FOR_DETAILS).should(
'not.contain.text',
'Technical Preview'
);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ const SUPPRESS_BY_FIELDS = ['agent.type'];

// Skip in MKI due to flake
describe(
'Detection Rule Creation - EQL Rules - With Alert Suppression',
'Detection EQL Rules - Alert suppression',
{
tags: ['@ess', '@skipInServerlessMKI'],
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,9 @@ import {
const SUPPRESS_BY_FIELDS = ['agent.type'];

describe(
'Detection Rule Creation - EQL Rules - With Alert Suppression',
'EQL Rules - Alert suppression',
{
// skipped in MKI as it depends on feature flag alertSuppressionForEsqlRuleEnabled
// alertSuppressionForEsqlRuleEnabled feature flag is also enabled in a global config
tags: ['@ess', '@skipInServerlessMKI'],
tags: ['@ess', '@serverless'],
env: {
kbnServerArgs: [
`--xpack.securitySolution.enableExperimental=${JSON.stringify([
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/*
* 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 { getEsqlRule } from '../../../../objects/rule';
import {
DEFINITION_DETAILS,
SUPPRESS_BY_DETAILS,
SUPPRESS_FOR_DETAILS,
SUPPRESS_MISSING_FIELD,
} from '../../../../screens/rule_details';
import { getDetails } from '../../../../tasks/rule_details';
import {
selectEsqlRuleType,
fillEsqlQueryBar,
createRuleWithoutEnabling,
fillAlertSuppressionFields,
selectAlertSuppressionPerInterval,
setAlertSuppressionDuration,
selectDoNotSuppressForMissingFields,
continueFromDefineStep,
fillAboutRuleMinimumAndContinue,
skipScheduleRuleAction,
interceptEsqlQueryFieldsRequest,
} from '../../../../tasks/create_new_rule';
import { login } from '../../../../tasks/login';
import { visit } from '../../../../tasks/navigation';

import { CREATE_RULE_URL } from '../../../../urls/navigation';

// https://github.com/cypress-io/cypress/issues/22113
// issue is inside monaco editor, used in ES|QL query input
// calling it after visiting page in each tests, seems fixes the issue
// the only other alternative is patching ResizeObserver, which is something I would like to avoid
const workaroundForResizeObserver = () =>
cy.on('uncaught:exception', (err) => {
if (err.message.includes('ResizeObserver loop limit exceeded')) {
return false;
}
});

describe(
'Detection ES|QL - Alert suppression',
{
tags: ['@ess', '@serverless'],
},
() => {
const rule = getEsqlRule();

beforeEach(() => {
login();
visit(CREATE_RULE_URL);
});

it('shows custom ES|QL field in investigation fields autocomplete and saves it in rule', function () {
const CUSTOM_ESQL_FIELD = '_custom_agent_name';
const SUPPRESS_BY_FIELDS = [CUSTOM_ESQL_FIELD, 'agent.type'];

const queryWithCustomFields = [
`from auditbeat* metadata _id, _version, _index`,
`eval ${CUSTOM_ESQL_FIELD} = agent.name`,
`drop agent.*`,
].join(' | ');

workaroundForResizeObserver();

selectEsqlRuleType();

interceptEsqlQueryFieldsRequest(queryWithCustomFields, 'esqlSuppressionFieldsRequest');
fillEsqlQueryBar(queryWithCustomFields);

cy.wait('@esqlSuppressionFieldsRequest');
fillAlertSuppressionFields(SUPPRESS_BY_FIELDS);
selectAlertSuppressionPerInterval();
setAlertSuppressionDuration(2, 'h');
selectDoNotSuppressForMissingFields();
continueFromDefineStep();

// ensures details preview works correctly
cy.get(DEFINITION_DETAILS).within(() => {
getDetails(SUPPRESS_BY_DETAILS).should('have.text', SUPPRESS_BY_FIELDS.join(''));
getDetails(SUPPRESS_FOR_DETAILS).should('have.text', '2h');
getDetails(SUPPRESS_MISSING_FIELD).should(
'have.text',
'Do not suppress alerts for events with missing fields'
);
});

fillAboutRuleMinimumAndContinue(rule);
skipScheduleRuleAction();
createRuleWithoutEnabling();

// ensures rule details displayed correctly after rule created
cy.get(DEFINITION_DETAILS).within(() => {
getDetails(SUPPRESS_BY_DETAILS).should('have.text', SUPPRESS_BY_FIELDS.join(''));
getDetails(SUPPRESS_FOR_DETAILS).should('have.text', '2h');
getDetails(SUPPRESS_MISSING_FIELD).should(
'have.text',
'Do not suppress alerts for events with missing fields'
);
});
});
}
);
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import {
import { CREATE_RULE_URL } from '../../../../urls/navigation';

describe(
'Detection rules, Alert Suppression for Essentials tier',
'Alert Suppression - Essentials tier license check',
{
tags: ['@serverless'],
env: {
Expand Down
Loading