mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
# Backport This will backport the following commits from `main` to `8.18`: - [[Security Solution] Adds prebuilt rule import/export cypress tests (#212172)](https://github.com/elastic/kibana/pull/212172) <!--- Backport version: 9.6.6 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sorenlouv/backport) <!--BACKPORT [{"author":{"name":"Davis Plumlee","email":"56367316+dplumlee@users.noreply.github.com"},"sourceCommit":{"committedDate":"2025-02-24T21:17:44Z","message":"[Security Solution] Adds prebuilt rule import/export cypress tests (#212172)\n\n**Partially addresses:** https://github.com/elastic/kibana/issues/202079\n\n## Summary\n\nAdds cypress tests in accordance to\nhttps://github.com/elastic/kibana/pull/204889\n\nFollow-up to: https://github.com/elastic/kibana/pull/206893\n\nAdds tests for rule import and export related to the prebuilt rule\ncustomization epic.\n### Checklist\n\nCheck the PR satisfies following conditions. \n\nReviewers should verify this PR satisfies this list as well.\n\n- [x] [Unit or functional\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\nwere updated or added to match the most common scenarios\n- [x] [Flaky Test\nRunner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was\nused on any tests changed\n- [x] 🟢 ESS x50:\nhttps://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/7923\n- [x] 🟢 Serverless x50:\nhttps://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/7924","sha":"427d2d992988a125f00075ae959c33f6d2bc7a6e","branchLabelMapping":{"^v9.1.0$":"main","^v8.19.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["test","release_note:skip","v9.0.0","Team:Detections and Resp","Team: SecuritySolution","Team:Detection Rule Management","Feature:Prebuilt Detection Rules","backport:version","v8.18.0","v9.1.0","v8.19.0"],"title":"[Security Solution] Adds prebuilt rule import/export cypress tests","number":212172,"url":"https://github.com/elastic/kibana/pull/212172","mergeCommit":{"message":"[Security Solution] Adds prebuilt rule import/export cypress tests (#212172)\n\n**Partially addresses:** https://github.com/elastic/kibana/issues/202079\n\n## Summary\n\nAdds cypress tests in accordance to\nhttps://github.com/elastic/kibana/pull/204889\n\nFollow-up to: https://github.com/elastic/kibana/pull/206893\n\nAdds tests for rule import and export related to the prebuilt rule\ncustomization epic.\n### Checklist\n\nCheck the PR satisfies following conditions. \n\nReviewers should verify this PR satisfies this list as well.\n\n- [x] [Unit or functional\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\nwere updated or added to match the most common scenarios\n- [x] [Flaky Test\nRunner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was\nused on any tests changed\n- [x] 🟢 ESS x50:\nhttps://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/7923\n- [x] 🟢 Serverless x50:\nhttps://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/7924","sha":"427d2d992988a125f00075ae959c33f6d2bc7a6e"}},"sourceBranch":"main","suggestedTargetBranches":["9.0","8.18","8.x"],"targetPullRequestStates":[{"branch":"9.0","label":"v9.0.0","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"8.18","label":"v8.18.0","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v9.1.0","branchLabelMappingKey":"^v9.1.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/212172","number":212172,"mergeCommit":{"message":"[Security Solution] Adds prebuilt rule import/export cypress tests (#212172)\n\n**Partially addresses:** https://github.com/elastic/kibana/issues/202079\n\n## Summary\n\nAdds cypress tests in accordance to\nhttps://github.com/elastic/kibana/pull/204889\n\nFollow-up to: https://github.com/elastic/kibana/pull/206893\n\nAdds tests for rule import and export related to the prebuilt rule\ncustomization epic.\n### Checklist\n\nCheck the PR satisfies following conditions. \n\nReviewers should verify this PR satisfies this list as well.\n\n- [x] [Unit or functional\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\nwere updated or added to match the most common scenarios\n- [x] [Flaky Test\nRunner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was\nused on any tests changed\n- [x] 🟢 ESS x50:\nhttps://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/7923\n- [x] 🟢 Serverless x50:\nhttps://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/7924","sha":"427d2d992988a125f00075ae959c33f6d2bc7a6e"}},{"branch":"8.x","label":"v8.19.0","branchLabelMappingKey":"^v8.19.0$","isSourceBranch":false,"state":"NOT_CREATED"}]}] BACKPORT--> Co-authored-by: Davis Plumlee <56367316+dplumlee@users.noreply.github.com>
This commit is contained in:
parent
ffddd1d4af
commit
72aa9f258f
8 changed files with 414 additions and 25 deletions
|
@ -0,0 +1,230 @@
|
|||
/*
|
||||
* 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 { bulkExportRules } from '../../../../tasks/rules_bulk_actions';
|
||||
import { exportRuleFromDetailsPage } from '../../../../tasks/rule_details';
|
||||
import {
|
||||
expectedExportedRule,
|
||||
expectedExportedRules,
|
||||
getIndexPatterns,
|
||||
getNewRule,
|
||||
} from '../../../../objects/rule';
|
||||
import {
|
||||
exportRule,
|
||||
filterByCustomRules,
|
||||
filterByElasticRules,
|
||||
selectAllRules,
|
||||
selectRulesByName,
|
||||
} from '../../../../tasks/alerts_detection_rules';
|
||||
import { RULE_NAME, TOASTER_BODY } from '../../../../screens/alerts_detection_rules';
|
||||
import { createRuleAssetSavedObject } from '../../../../helpers/rules';
|
||||
import { deleteAlertsAndRules } from '../../../../tasks/api_calls/common';
|
||||
import { createAndInstallMockedPrebuiltRules } from '../../../../tasks/api_calls/prebuilt_rules';
|
||||
import { createRule, findRuleByRuleId, patchRule } from '../../../../tasks/api_calls/rules';
|
||||
|
||||
import { login } from '../../../../tasks/login';
|
||||
|
||||
import { visitRulesManagementTable } from '../../../../tasks/rules_management';
|
||||
|
||||
const PREBUILT_RULE_ID = 'rule_1';
|
||||
|
||||
describe(
|
||||
'Detection rules, Prebuilt Rules Export workflow - With Rule Customization',
|
||||
{
|
||||
tags: ['@ess', '@serverless', '@skipInServerlessMKI'],
|
||||
env: {
|
||||
ftrConfig: {
|
||||
kbnServerArgs: [
|
||||
`--xpack.securitySolution.enableExperimental=${JSON.stringify([
|
||||
'prebuiltRulesCustomizationEnabled',
|
||||
])}`,
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
() => {
|
||||
describe('Rule export workflow with single rules', () => {
|
||||
const PREBUILT_RULE = createRuleAssetSavedObject({
|
||||
name: 'Non-customized prebuilt rule',
|
||||
rule_id: PREBUILT_RULE_ID,
|
||||
version: 1,
|
||||
index: getIndexPatterns(),
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
login();
|
||||
deleteAlertsAndRules();
|
||||
cy.intercept('POST', '/api/detection_engine/rules/_bulk_action').as('bulk_action');
|
||||
/* Create a new rule and install it */
|
||||
createAndInstallMockedPrebuiltRules([PREBUILT_RULE]);
|
||||
createRule(
|
||||
getNewRule({ name: 'Custom rule to export', rule_id: 'custom_rule_id', enabled: false })
|
||||
).as('customRuleResponse');
|
||||
visitRulesManagementTable();
|
||||
});
|
||||
|
||||
it('can export non-customized prebuilt rules from the rule management table individually', function () {
|
||||
findRuleByRuleId(PREBUILT_RULE_ID).as('prebuiltRuleResponse');
|
||||
exportRule('Non-customized prebuilt rule');
|
||||
cy.wait('@bulk_action').then(({ response }) => {
|
||||
cy.wrap(response?.body).should('eql', expectedExportedRule(this.prebuiltRuleResponse));
|
||||
cy.get(TOASTER_BODY).should('have.text', 'Successfully exported 1 of 1 rule.');
|
||||
});
|
||||
});
|
||||
|
||||
it('can export customized prebuilt rules from the rule management table individually', function () {
|
||||
patchRule(PREBUILT_RULE_ID, { name: 'Customized prebuilt rule' }).as(
|
||||
'prebuiltRuleResponse'
|
||||
); // We want to make this a customized prebuilt rule
|
||||
exportRule('Customized prebuilt rule');
|
||||
cy.wait('@bulk_action').then(({ response }) => {
|
||||
cy.wrap(response?.body).should('eql', expectedExportedRule(this.prebuiltRuleResponse));
|
||||
cy.get(TOASTER_BODY).should('have.text', 'Successfully exported 1 of 1 rule.');
|
||||
});
|
||||
});
|
||||
|
||||
it('can export custom rules from the rule management table individually', function () {
|
||||
exportRule('Custom rule to export');
|
||||
cy.wait('@bulk_action').then(({ response }) => {
|
||||
cy.wrap(response?.body).should('eql', expectedExportedRule(this.customRuleResponse));
|
||||
cy.get(TOASTER_BODY).should('have.text', 'Successfully exported 1 of 1 rule.');
|
||||
});
|
||||
});
|
||||
|
||||
it('can export a non-customized prebuilt rule from the rule details page', function () {
|
||||
findRuleByRuleId(PREBUILT_RULE_ID).as('prebuiltRuleResponse');
|
||||
cy.get(RULE_NAME).contains('Non-customized prebuilt rule').click();
|
||||
exportRuleFromDetailsPage();
|
||||
cy.wait('@bulk_action').then(({ response }) => {
|
||||
cy.wrap(response?.body).should('eql', expectedExportedRule(this.prebuiltRuleResponse));
|
||||
cy.get(TOASTER_BODY).should('have.text', 'Successfully exported 1 of 1 rule.');
|
||||
});
|
||||
});
|
||||
|
||||
it('can export a customized prebuilt rule from the rule details page', function () {
|
||||
patchRule(PREBUILT_RULE_ID, { name: 'Customized prebuilt rule' }).as(
|
||||
'prebuiltRuleResponse'
|
||||
); // We want to make this a customized prebuilt rule
|
||||
cy.get(RULE_NAME).contains('Customized prebuilt rule').click();
|
||||
exportRuleFromDetailsPage();
|
||||
cy.wait('@bulk_action').then(({ response }) => {
|
||||
cy.wrap(response?.body).should('eql', expectedExportedRule(this.prebuiltRuleResponse));
|
||||
cy.get(TOASTER_BODY).should('have.text', 'Successfully exported 1 of 1 rule.');
|
||||
});
|
||||
});
|
||||
|
||||
it('can export a custom rule from the rule details page', function () {
|
||||
cy.get(RULE_NAME).contains('Custom rule to export').click();
|
||||
exportRuleFromDetailsPage();
|
||||
cy.wait('@bulk_action').then(({ response }) => {
|
||||
cy.wrap(response?.body).should('eql', expectedExportedRule(this.customRuleResponse));
|
||||
cy.get(TOASTER_BODY).should('have.text', 'Successfully exported 1 of 1 rule.');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Rule export workflow with multiple rules', () => {
|
||||
const PREBUILT_RULE_1 = createRuleAssetSavedObject({
|
||||
name: 'Non-customized prebuilt rule',
|
||||
rule_id: PREBUILT_RULE_ID,
|
||||
version: 1,
|
||||
index: getIndexPatterns(),
|
||||
});
|
||||
|
||||
const PREBUILT_RULE_2 = createRuleAssetSavedObject({
|
||||
name: 'Non-customized prebuilt rule',
|
||||
rule_id: 'rule_2',
|
||||
version: 1,
|
||||
index: getIndexPatterns(),
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
login();
|
||||
deleteAlertsAndRules();
|
||||
cy.intercept('POST', '/api/detection_engine/rules/_bulk_action').as('bulk_action');
|
||||
/* Create a new rule and install it */
|
||||
createAndInstallMockedPrebuiltRules([PREBUILT_RULE_1, PREBUILT_RULE_2]);
|
||||
|
||||
findRuleByRuleId(PREBUILT_RULE_ID).as('nonCustomizedPrebuiltRuleResponse');
|
||||
// We want to make this a customized prebuilt rule
|
||||
patchRule('rule_2', { name: 'Customized prebuilt rule' }).as(
|
||||
'customizedPrebuiltRuleResponse'
|
||||
);
|
||||
createRule(getNewRule({ name: 'Custom rule to export', enabled: false })).as(
|
||||
'customRuleResponse'
|
||||
);
|
||||
visitRulesManagementTable();
|
||||
});
|
||||
|
||||
it('can export a non-customized prebuilt rule from the rule management table using the bulk actions menu', function () {
|
||||
selectRulesByName(['Non-customized prebuilt rule']);
|
||||
bulkExportRules();
|
||||
cy.wait('@bulk_action').then(({ response }) => {
|
||||
cy.wrap(response?.body).should(
|
||||
'eql',
|
||||
expectedExportedRule(this.nonCustomizedPrebuiltRuleResponse)
|
||||
);
|
||||
cy.get(TOASTER_BODY).should('have.text', 'Successfully exported 1 of 1 rule.');
|
||||
});
|
||||
});
|
||||
|
||||
it('can export a customized prebuilt rule from the rule management table using the bulk actions menu', function () {
|
||||
selectRulesByName(['Customized prebuilt rule']);
|
||||
bulkExportRules();
|
||||
cy.wait('@bulk_action').then(({ response }) => {
|
||||
cy.wrap(response?.body).should(
|
||||
'eql',
|
||||
expectedExportedRule(this.customizedPrebuiltRuleResponse)
|
||||
);
|
||||
cy.get(TOASTER_BODY).should('have.text', 'Successfully exported 1 of 1 rule.');
|
||||
});
|
||||
});
|
||||
|
||||
it('can export a custom rule from the rule management table using the bulk actions menu', function () {
|
||||
filterByCustomRules();
|
||||
selectAllRules();
|
||||
bulkExportRules();
|
||||
cy.wait('@bulk_action').then(({ response }) => {
|
||||
cy.wrap(response?.body).should('eql', expectedExportedRule(this.customRuleResponse));
|
||||
cy.get(TOASTER_BODY).should('have.text', 'Successfully exported 1 of 1 rule.');
|
||||
});
|
||||
});
|
||||
|
||||
it('can export all rule types from the rule management table using the bulk actions menu', function () {
|
||||
selectAllRules();
|
||||
bulkExportRules();
|
||||
cy.wait('@bulk_action').then(({ response }) => {
|
||||
cy.wrap(response?.body).should(
|
||||
'eql',
|
||||
expectedExportedRules([
|
||||
this.nonCustomizedPrebuiltRuleResponse,
|
||||
this.customizedPrebuiltRuleResponse,
|
||||
this.customRuleResponse,
|
||||
])
|
||||
);
|
||||
cy.get(TOASTER_BODY).should('have.text', 'Successfully exported 3 of 3 rules.');
|
||||
});
|
||||
});
|
||||
|
||||
it('can export customized and non-customized prebuilt rules from the rule management table using the bulk actions menu', function () {
|
||||
filterByElasticRules();
|
||||
selectAllRules();
|
||||
bulkExportRules();
|
||||
cy.wait('@bulk_action').then(({ response }) => {
|
||||
cy.wrap(response?.body).should(
|
||||
'eql',
|
||||
expectedExportedRules([
|
||||
this.nonCustomizedPrebuiltRuleResponse,
|
||||
this.customizedPrebuiltRuleResponse,
|
||||
])
|
||||
);
|
||||
cy.get(TOASTER_BODY).should('have.text', 'Successfully exported 2 of 2 rules.');
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* 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 {
|
||||
expectToContainModifiedBadge,
|
||||
expectToNotContainModifiedBadge,
|
||||
importRulesWithOverwriteAll,
|
||||
} from '../../../../tasks/alerts_detection_rules';
|
||||
import { TOASTER } from '../../../../screens/alerts_detection_rules';
|
||||
import { createRuleAssetSavedObject } from '../../../../helpers/rules';
|
||||
import { deleteAlertsAndRules } from '../../../../tasks/api_calls/common';
|
||||
import { createAndInstallMockedPrebuiltRules } from '../../../../tasks/api_calls/prebuilt_rules';
|
||||
|
||||
import { login } from '../../../../tasks/login';
|
||||
|
||||
import { visitRulesManagementTable } from '../../../../tasks/rules_management';
|
||||
|
||||
const RULES_TO_IMPORT_FILENAME = 'cypress/fixtures/8_18_prebuilt_rules.ndjson';
|
||||
|
||||
describe(
|
||||
'Detection rules, Prebuilt Rules Import workflow - With Rule Customization',
|
||||
{
|
||||
tags: ['@ess', '@serverless', '@skipInServerlessMKI'],
|
||||
env: {
|
||||
ftrConfig: {
|
||||
kbnServerArgs: [
|
||||
`--xpack.securitySolution.enableExperimental=${JSON.stringify([
|
||||
'prebuiltRulesCustomizationEnabled',
|
||||
])}`,
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
() => {
|
||||
describe('when file is unmodified prebuilt rule with matching rule_id', () => {
|
||||
const PREBUILT_RULE_1 = createRuleAssetSavedObject({
|
||||
name: 'rule 1',
|
||||
rule_id: 'rule_1',
|
||||
version: 2,
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
login();
|
||||
deleteAlertsAndRules();
|
||||
cy.intercept('POST', '/api/detection_engine/rules/_import*').as('import');
|
||||
/* Create a new rule and install it */
|
||||
createAndInstallMockedPrebuiltRules([PREBUILT_RULE_1]);
|
||||
visitRulesManagementTable();
|
||||
});
|
||||
|
||||
it('can import the rule file', () => {
|
||||
importRulesWithOverwriteAll(RULES_TO_IMPORT_FILENAME);
|
||||
|
||||
cy.wait('@import').then(({ response }) => {
|
||||
cy.wrap(response?.statusCode).should('eql', 200);
|
||||
cy.get(TOASTER).should('have.text', 'Successfully imported 1 rule');
|
||||
|
||||
expectToNotContainModifiedBadge('rule 1');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when file is modified prebuilt rule with matching rule_id', () => {
|
||||
const PREBUILT_RULE_1 = createRuleAssetSavedObject({
|
||||
name: 'original rule 1',
|
||||
rule_id: 'rule_1',
|
||||
version: 2,
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
login();
|
||||
deleteAlertsAndRules();
|
||||
cy.intercept('POST', '/api/detection_engine/rules/_import*').as('import');
|
||||
/* Create a new rule and install it */
|
||||
createAndInstallMockedPrebuiltRules([PREBUILT_RULE_1]);
|
||||
visitRulesManagementTable();
|
||||
});
|
||||
|
||||
it('can import the rule file', () => {
|
||||
importRulesWithOverwriteAll(RULES_TO_IMPORT_FILENAME);
|
||||
|
||||
cy.wait('@import').then(({ response }) => {
|
||||
cy.wrap(response?.statusCode).should('eql', 200);
|
||||
cy.get(TOASTER).should('have.text', 'Successfully imported 1 rule');
|
||||
|
||||
expectToContainModifiedBadge('rule 1');
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
|
@ -0,0 +1,2 @@
|
|||
{"id":"8ddab7fb-e049-4502-908f-bd040274c1b6","updated_at":"2025-01-16T05:03:09.376Z","updated_by":"system_indices_superuser","created_at":"2025-01-16T05:03:09.376Z","created_by":"system_indices_superuser","name":"rule 1","tags":[],"interval":"5m","enabled":false,"revision":0,"description":"some description","risk_score":55,"severity":"high","license":"Elastic License v2","output_index":"","author":[],"false_positives":[],"from":"now-6m","rule_id":"rule_1","max_signals":100,"risk_score_mapping":[],"severity_mapping":[],"threat":[],"to":"now","references":[],"version":2,"exceptions_list":[],"immutable":true,"rule_source":{"type":"external","is_customized":false},"related_integrations":[],"required_fields":[],"setup":"","type":"query","language":"kuery","query":"user.name: root or user.name: admin","actions":[]}
|
||||
{"exported_count":1,"exported_rules_count":1,"missing_rules":[],"missing_rules_count":0,"exported_exception_list_count":0,"exported_exception_list_item_count":0,"missing_exception_list_item_count":0,"missing_exception_list_items":[],"missing_exception_lists":[],"missing_exception_lists_count":0,"exported_action_connector_count":0,"missing_action_connection_count":0,"missing_action_connections":[],"excluded_action_connection_count":0,"excluded_action_connections":[]}
|
|
@ -523,7 +523,63 @@ export const getEditedRule = (): QueryRuleCreateProps =>
|
|||
tags: [...(getExistingRule().tags || []), 'edited'],
|
||||
});
|
||||
|
||||
export const expectedExportedRules = (responses: Array<Cypress.Response<RuleResponse>>): string => {
|
||||
const rules = responses
|
||||
.map((response) => JSON.stringify(getFormattedRuleResponse(response)))
|
||||
.join('\n');
|
||||
|
||||
// NOTE: Order of the properties in this object matters for the tests to work.
|
||||
const details = {
|
||||
exported_count: responses.length,
|
||||
exported_rules_count: responses.length,
|
||||
missing_rules: [],
|
||||
missing_rules_count: 0,
|
||||
exported_exception_list_count: 0,
|
||||
exported_exception_list_item_count: 0,
|
||||
missing_exception_list_item_count: 0,
|
||||
missing_exception_list_items: [],
|
||||
missing_exception_lists: [],
|
||||
missing_exception_lists_count: 0,
|
||||
exported_action_connector_count: 0,
|
||||
missing_action_connection_count: 0,
|
||||
missing_action_connections: [],
|
||||
excluded_action_connection_count: 0,
|
||||
excluded_action_connections: [],
|
||||
};
|
||||
|
||||
return `${rules}\n${JSON.stringify(details)}\n`;
|
||||
};
|
||||
|
||||
export const expectedExportedRule = (ruleResponse: Cypress.Response<RuleResponse>): string => {
|
||||
const rule = getFormattedRuleResponse(ruleResponse);
|
||||
|
||||
// NOTE: Order of the properties in this object matters for the tests to work.
|
||||
const details = {
|
||||
exported_count: 1,
|
||||
exported_rules_count: 1,
|
||||
missing_rules: [],
|
||||
missing_rules_count: 0,
|
||||
exported_exception_list_count: 0,
|
||||
exported_exception_list_item_count: 0,
|
||||
missing_exception_list_item_count: 0,
|
||||
missing_exception_list_items: [],
|
||||
missing_exception_lists: [],
|
||||
missing_exception_lists_count: 0,
|
||||
exported_action_connector_count: 0,
|
||||
missing_action_connection_count: 0,
|
||||
missing_action_connections: [],
|
||||
excluded_action_connection_count: 0,
|
||||
excluded_action_connections: [],
|
||||
};
|
||||
|
||||
return `${JSON.stringify(rule)}\n${JSON.stringify(details)}\n`;
|
||||
};
|
||||
|
||||
// TODO: Follow up https://github.com/elastic/kibana/pull/137628 and add an explicit type to this object
|
||||
// without using Partial
|
||||
const getFormattedRuleResponse = (
|
||||
ruleResponse: Cypress.Response<RuleResponse>
|
||||
): Partial<RuleResponse> => {
|
||||
const {
|
||||
id,
|
||||
updated_at: updatedAt,
|
||||
|
@ -555,6 +611,8 @@ export const expectedExportedRule = (ruleResponse: Cypress.Response<RuleResponse
|
|||
related_integrations: relatedIntegrations,
|
||||
setup,
|
||||
investigation_fields: investigationFields,
|
||||
license,
|
||||
revision,
|
||||
} = ruleResponse.body;
|
||||
|
||||
let query: string | undefined;
|
||||
|
@ -563,9 +621,7 @@ export const expectedExportedRule = (ruleResponse: Cypress.Response<RuleResponse
|
|||
}
|
||||
|
||||
// NOTE: Order of the properties in this object matters for the tests to work.
|
||||
// TODO: Follow up https://github.com/elastic/kibana/pull/137628 and add an explicit type to this object
|
||||
// without using Partial
|
||||
const rule: Partial<RuleResponse> = {
|
||||
return {
|
||||
id,
|
||||
updated_at: updatedAt,
|
||||
updated_by: updatedBy,
|
||||
|
@ -575,11 +631,12 @@ export const expectedExportedRule = (ruleResponse: Cypress.Response<RuleResponse
|
|||
tags,
|
||||
interval,
|
||||
enabled,
|
||||
revision: 0,
|
||||
revision,
|
||||
description,
|
||||
risk_score: riskScore,
|
||||
severity,
|
||||
note,
|
||||
license,
|
||||
output_index: '',
|
||||
investigation_fields: investigationFields,
|
||||
author,
|
||||
|
@ -605,28 +662,8 @@ export const expectedExportedRule = (ruleResponse: Cypress.Response<RuleResponse
|
|||
query,
|
||||
actions: [],
|
||||
};
|
||||
|
||||
// NOTE: Order of the properties in this object matters for the tests to work.
|
||||
const details = {
|
||||
exported_count: 1,
|
||||
exported_rules_count: 1,
|
||||
missing_rules: [],
|
||||
missing_rules_count: 0,
|
||||
exported_exception_list_count: 0,
|
||||
exported_exception_list_item_count: 0,
|
||||
missing_exception_list_item_count: 0,
|
||||
missing_exception_list_items: [],
|
||||
missing_exception_lists: [],
|
||||
missing_exception_lists_count: 0,
|
||||
exported_action_connector_count: 0,
|
||||
missing_action_connection_count: 0,
|
||||
missing_action_connections: [],
|
||||
excluded_action_connection_count: 0,
|
||||
excluded_action_connections: [],
|
||||
};
|
||||
|
||||
return `${JSON.stringify(rule)}\n${JSON.stringify(details)}\n`;
|
||||
};
|
||||
|
||||
export const getEndpointRule = (): QueryRuleCreateProps => ({
|
||||
type: 'query',
|
||||
query: 'event.kind:alert and event.module:(endpoint and not endgame)',
|
||||
|
|
|
@ -110,6 +110,8 @@ export const ADD_ELASTIC_RULES_TABLE = '[data-test-subj="add-prebuilt-rules-tabl
|
|||
|
||||
export const RULES_ROW = '.euiTableRow';
|
||||
|
||||
export const RULE_ROW_MODIFIED_BADGE = '[data-test-subj="rulesTableModifiedColumnBadge"]';
|
||||
|
||||
export const SEVERITY = '[data-test-subj="severity"]';
|
||||
|
||||
export const SELECT_ALL_RULES_BTN = '[data-test-subj="selectAllRules"]';
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
export const POPOVER_ACTIONS_TRIGGER_BUTTON =
|
||||
'[data-test-subj="rules-details-popover-button-icon"]';
|
||||
|
||||
export const EXPORT_RULE_ACTION_BUTTON = '[data-test-subj="rules-details-export-rule"]';
|
||||
|
||||
export const ABOUT_INVESTIGATION_NOTES = '[data-test-subj="stepAboutDetailsNoteContent"]';
|
||||
|
||||
export const ABOUT_RULE_DESCRIPTION = '[data-test-subj=stepAboutRuleDetailsToggleDescriptionText]';
|
||||
|
|
|
@ -56,6 +56,20 @@ export const patchRule = (
|
|||
);
|
||||
};
|
||||
|
||||
export const findRuleByRuleId = (
|
||||
ruleId: string
|
||||
): Cypress.Chainable<Cypress.Response<RuleResponse>> => {
|
||||
return cy.currentSpace().then((spaceId) =>
|
||||
rootRequest<RuleResponse>({
|
||||
method: 'GET',
|
||||
url: `${
|
||||
spaceId ? getSpaceUrl(spaceId, DETECTION_ENGINE_RULES_URL) : DETECTION_ENGINE_RULES_URL
|
||||
}?rule_id=${ruleId}`,
|
||||
failOnStatusCode: false,
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Snoozes a rule via API
|
||||
*
|
||||
|
|
|
@ -46,6 +46,8 @@ import {
|
|||
RULE_GAPS_STATUS_FILTER,
|
||||
RULE_GAPS_DATE_FILTER_OPTION,
|
||||
RULE_GAPS_DATE_PICKER_APPLY_REFRESH,
|
||||
POPOVER_ACTIONS_TRIGGER_BUTTON,
|
||||
EXPORT_RULE_ACTION_BUTTON,
|
||||
} from '../screens/rule_details';
|
||||
import { RuleDetailsTabs, ruleDetailsUrl } from '../urls/rule_details';
|
||||
import {
|
||||
|
@ -216,6 +218,11 @@ export const filterByRunType = (ruleType: string) => {
|
|||
cy.get(EXECUTION_RUN_TYPE_FILTER_ITEM).contains(ruleType).click();
|
||||
};
|
||||
|
||||
export const exportRuleFromDetailsPage = () => {
|
||||
cy.get(POPOVER_ACTIONS_TRIGGER_BUTTON).click();
|
||||
cy.get(EXPORT_RULE_ACTION_BUTTON).click();
|
||||
};
|
||||
|
||||
export const getBackfillsTableRows = () => {
|
||||
return cy.get(RULE_BACKFILLS_TABLE).find('tbody tr');
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue