mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 09:19:04 -04:00
[Security Solution] Extend Prebuilt rules install and update workflow test coverage (#161687)
## Summary - Implement test plan as described in `x-pack/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/installation_and_upgrade.md` ### For maintainers - [ ] This was checked for breaking API changes and was [labeled appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process) --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
2e15549b58
commit
887b3bde05
30 changed files with 2113 additions and 580 deletions
|
@ -236,6 +236,7 @@ enabled:
|
|||
- x-pack/test/detection_engine_api_integration/security_and_spaces/prebuilt_rules/config.ts
|
||||
- x-pack/test/detection_engine_api_integration/security_and_spaces/bundled_prebuilt_rules_package/config.ts
|
||||
- x-pack/test/detection_engine_api_integration/security_and_spaces/large_prebuilt_rules_package/config.ts
|
||||
- x-pack/test/detection_engine_api_integration/security_and_spaces/update_prebuilt_rules_package/config.ts
|
||||
- x-pack/test/encrypted_saved_objects_api_integration/config.ts
|
||||
- x-pack/test/examples/config.ts
|
||||
- x-pack/test/fleet_api_integration/config.agent.ts
|
||||
|
|
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
* 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 { APP_PATH, RULES_ADD_PATH, RULES_UPDATES } from '../../../common/constants';
|
||||
import { createRuleAssetSavedObject } from '../../helpers/rules';
|
||||
import { waitForRulesTableToBeLoaded } from '../../tasks/alerts_detection_rules';
|
||||
import { createAndInstallMockedPrebuiltRules } from '../../tasks/api_calls/prebuilt_rules';
|
||||
import { resetRulesTableState, deleteAlertsAndRules } from '../../tasks/common';
|
||||
import { esArchiverResetKibana } from '../../tasks/es_archiver';
|
||||
import { login, waitForPageWithoutDateRange } from '../../tasks/login';
|
||||
import { SECURITY_DETECTIONS_RULES_URL } from '../../urls/navigation';
|
||||
import { ROLES } from '../../../common/test';
|
||||
import {
|
||||
ADD_ELASTIC_RULES_BTN,
|
||||
getInstallSingleRuleButtonByRuleId,
|
||||
getUpgradeSingleRuleButtonByRuleId,
|
||||
INSTALL_ALL_RULES_BUTTON,
|
||||
RULES_UPDATES_TAB,
|
||||
RULE_CHECKBOX,
|
||||
UPGRADE_ALL_RULES_BUTTON,
|
||||
} from '../../screens/alerts_detection_rules';
|
||||
|
||||
const RULE_1_ID = 'rule_1';
|
||||
const RULE_2_ID = 'rule_2';
|
||||
const OUTDATED_RULE_1 = createRuleAssetSavedObject({
|
||||
name: 'Outdated rule 1',
|
||||
rule_id: RULE_1_ID,
|
||||
version: 1,
|
||||
});
|
||||
const UPDATED_RULE_1 = createRuleAssetSavedObject({
|
||||
name: 'Updated rule 1',
|
||||
rule_id: RULE_1_ID,
|
||||
version: 2,
|
||||
});
|
||||
const OUTDATED_RULE_2 = createRuleAssetSavedObject({
|
||||
name: 'Outdated rule 2',
|
||||
rule_id: RULE_2_ID,
|
||||
version: 1,
|
||||
});
|
||||
const UPDATED_RULE_2 = createRuleAssetSavedObject({
|
||||
name: 'Updated rule 2',
|
||||
rule_id: RULE_2_ID,
|
||||
version: 2,
|
||||
});
|
||||
|
||||
const loadPageAsReadOnlyUser = (url: string) => {
|
||||
login(ROLES.reader);
|
||||
waitForPageWithoutDateRange(url, ROLES.reader);
|
||||
};
|
||||
|
||||
describe('Detection rules, Prebuilt Rules Installation and Update - Authorization/RBAC', () => {
|
||||
beforeEach(() => {
|
||||
login();
|
||||
resetRulesTableState();
|
||||
deleteAlertsAndRules();
|
||||
esArchiverResetKibana();
|
||||
waitForRulesTableToBeLoaded();
|
||||
createAndInstallMockedPrebuiltRules({ rules: [OUTDATED_RULE_1, OUTDATED_RULE_2] });
|
||||
});
|
||||
|
||||
describe('User with read privileges on Security Solution', () => {
|
||||
const RULE_1 = createRuleAssetSavedObject({
|
||||
name: 'Test rule 1',
|
||||
rule_id: 'rule_1',
|
||||
});
|
||||
const RULE_2 = createRuleAssetSavedObject({
|
||||
name: 'Test rule 2',
|
||||
rule_id: 'rule_2',
|
||||
});
|
||||
beforeEach(() => {
|
||||
// Now login with read-only user in preparation for test
|
||||
createAndInstallMockedPrebuiltRules({ rules: [RULE_1, RULE_2], installToKibana: false });
|
||||
loadPageAsReadOnlyUser(SECURITY_DETECTIONS_RULES_URL);
|
||||
waitForRulesTableToBeLoaded();
|
||||
});
|
||||
|
||||
it('should not be able to install prebuilt rules', () => {
|
||||
// Check that Add Elastic Rules button is disabled
|
||||
cy.get(ADD_ELASTIC_RULES_BTN).should('be.disabled');
|
||||
|
||||
// Navigate to Add Elastic Rules page anyways via URL
|
||||
// and assert that rules cannot be selected and all
|
||||
// installation buttons are disabled
|
||||
cy.visit(`${APP_PATH}${RULES_ADD_PATH}`);
|
||||
cy.get(INSTALL_ALL_RULES_BUTTON).should('be.disabled');
|
||||
cy.get(getInstallSingleRuleButtonByRuleId(RULE_1['security-rule'].rule_id)).should(
|
||||
'not.exist'
|
||||
);
|
||||
cy.get(RULE_CHECKBOX).should('not.exist');
|
||||
});
|
||||
});
|
||||
|
||||
describe('User with read privileges on Security Solution', () => {
|
||||
beforeEach(() => {
|
||||
/* Create a second version of the rule, making it available for update */
|
||||
createAndInstallMockedPrebuiltRules({
|
||||
rules: [UPDATED_RULE_1, UPDATED_RULE_2],
|
||||
installToKibana: false,
|
||||
});
|
||||
// Now login with read-only user in preparation for test
|
||||
loadPageAsReadOnlyUser(SECURITY_DETECTIONS_RULES_URL);
|
||||
waitForRulesTableToBeLoaded();
|
||||
});
|
||||
|
||||
it('should not be able to upgrade prebuilt rules', () => {
|
||||
// Check that Rule Update tab is not shown
|
||||
cy.get(RULES_UPDATES_TAB).should('not.exist');
|
||||
|
||||
// Navigate to Rule Update tab anyways via URL
|
||||
// and assert that rules cannot be selected and all
|
||||
// upgrade buttons are disabled
|
||||
cy.visit(`${APP_PATH}${RULES_UPDATES}`);
|
||||
cy.get(UPGRADE_ALL_RULES_BUTTON).should('be.disabled');
|
||||
cy.get(getUpgradeSingleRuleButtonByRuleId(OUTDATED_RULE_1['security-rule'].rule_id)).should(
|
||||
'not.exist'
|
||||
);
|
||||
cy.get(RULE_CHECKBOX).should('not.exist');
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
* 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 { createRuleAssetSavedObject } from '../../helpers/rules';
|
||||
import { waitForRulesTableToBeLoaded } from '../../tasks/alerts_detection_rules';
|
||||
import { createAndInstallMockedPrebuiltRules } from '../../tasks/api_calls/prebuilt_rules';
|
||||
import { resetRulesTableState, deleteAlertsAndRules, reload } from '../../tasks/common';
|
||||
import { esArchiverResetKibana } from '../../tasks/es_archiver';
|
||||
import { login, visitWithoutDateRange } from '../../tasks/login';
|
||||
import { SECURITY_DETECTIONS_RULES_URL } from '../../urls/navigation';
|
||||
import {
|
||||
addElasticRulesButtonClick,
|
||||
assertRuleAvailableForInstallAndInstallOne,
|
||||
assertRuleAvailableForInstallAndInstallSelected,
|
||||
assertRuleAvailableForInstallAndInstallAllInPage,
|
||||
assertRuleAvailableForInstallAndInstallAll,
|
||||
assertRuleUpgradeAvailableAndUpgradeOne,
|
||||
assertRuleUpgradeAvailableAndUpgradeSelected,
|
||||
assertRuleUpgradeAvailableAndUpgradeAllInPage,
|
||||
assertRuleUpgradeAvailableAndUpgradeAll,
|
||||
ruleUpdatesTabClick,
|
||||
} from '../../tasks/prebuilt_rules';
|
||||
|
||||
describe('Detection rules, Prebuilt Rules Installation and Update - Error handling', () => {
|
||||
beforeEach(() => {
|
||||
login();
|
||||
resetRulesTableState();
|
||||
deleteAlertsAndRules();
|
||||
esArchiverResetKibana();
|
||||
|
||||
visitWithoutDateRange(SECURITY_DETECTIONS_RULES_URL);
|
||||
});
|
||||
|
||||
describe('Installation of prebuilt rules - Should fail gracefully with toast error message when', () => {
|
||||
const RULE_1 = createRuleAssetSavedObject({
|
||||
name: 'Test rule 1',
|
||||
rule_id: 'rule_1',
|
||||
});
|
||||
const RULE_2 = createRuleAssetSavedObject({
|
||||
name: 'Test rule 2',
|
||||
rule_id: 'rule_2',
|
||||
});
|
||||
beforeEach(() => {
|
||||
createAndInstallMockedPrebuiltRules({ rules: [RULE_1, RULE_2], installToKibana: false });
|
||||
waitForRulesTableToBeLoaded();
|
||||
});
|
||||
|
||||
it('installing prebuilt rules one by one', () => {
|
||||
addElasticRulesButtonClick();
|
||||
assertRuleAvailableForInstallAndInstallOne({ rules: [RULE_1], didRequestFail: true });
|
||||
});
|
||||
|
||||
it('installing multiple selected prebuilt rules by selecting them individually', () => {
|
||||
addElasticRulesButtonClick();
|
||||
assertRuleAvailableForInstallAndInstallSelected({
|
||||
rules: [RULE_1, RULE_2],
|
||||
didRequestFail: true,
|
||||
});
|
||||
});
|
||||
|
||||
it('installing multiple selected prebuilt rules by selecting all in page', () => {
|
||||
addElasticRulesButtonClick();
|
||||
assertRuleAvailableForInstallAndInstallAllInPage({
|
||||
rules: [RULE_1, RULE_2],
|
||||
didRequestFail: true,
|
||||
});
|
||||
});
|
||||
|
||||
it('installing all available rules at once', () => {
|
||||
addElasticRulesButtonClick();
|
||||
assertRuleAvailableForInstallAndInstallAll({ rules: [RULE_1, RULE_2], didRequestFail: true });
|
||||
});
|
||||
});
|
||||
|
||||
describe('Update of prebuilt rules - Should fail gracefully with toast error message when', () => {
|
||||
const RULE_1_ID = 'rule_1';
|
||||
const RULE_2_ID = 'rule_2';
|
||||
const OUTDATED_RULE_1 = createRuleAssetSavedObject({
|
||||
name: 'Outdated rule 1',
|
||||
rule_id: RULE_1_ID,
|
||||
version: 1,
|
||||
});
|
||||
const UPDATED_RULE_1 = createRuleAssetSavedObject({
|
||||
name: 'Updated rule 1',
|
||||
rule_id: RULE_1_ID,
|
||||
version: 2,
|
||||
});
|
||||
const OUTDATED_RULE_2 = createRuleAssetSavedObject({
|
||||
name: 'Outdated rule 2',
|
||||
rule_id: RULE_2_ID,
|
||||
version: 1,
|
||||
});
|
||||
const UPDATED_RULE_2 = createRuleAssetSavedObject({
|
||||
name: 'Updated rule 2',
|
||||
rule_id: RULE_2_ID,
|
||||
version: 2,
|
||||
});
|
||||
beforeEach(() => {
|
||||
/* Create a new rule and install it */
|
||||
createAndInstallMockedPrebuiltRules({ rules: [OUTDATED_RULE_1, OUTDATED_RULE_2] });
|
||||
/* Create a second version of the rule, making it available for update */
|
||||
createAndInstallMockedPrebuiltRules({
|
||||
rules: [UPDATED_RULE_1, UPDATED_RULE_2],
|
||||
installToKibana: false,
|
||||
});
|
||||
waitForRulesTableToBeLoaded();
|
||||
reload();
|
||||
});
|
||||
|
||||
it('upgrading prebuilt rules one by one', () => {
|
||||
ruleUpdatesTabClick();
|
||||
assertRuleUpgradeAvailableAndUpgradeOne({ rules: [OUTDATED_RULE_1], didRequestFail: true });
|
||||
});
|
||||
|
||||
it('upgrading multiple selected prebuilt rules by selecting them individually', () => {
|
||||
ruleUpdatesTabClick();
|
||||
assertRuleUpgradeAvailableAndUpgradeSelected({
|
||||
rules: [OUTDATED_RULE_1, OUTDATED_RULE_2],
|
||||
didRequestFail: true,
|
||||
});
|
||||
});
|
||||
|
||||
it('upgrading multiple selected prebuilt rules by selecting all in page', () => {
|
||||
ruleUpdatesTabClick();
|
||||
assertRuleUpgradeAvailableAndUpgradeAllInPage({
|
||||
rules: [OUTDATED_RULE_1, OUTDATED_RULE_2],
|
||||
didRequestFail: true,
|
||||
});
|
||||
});
|
||||
|
||||
it('upgrading all rules with available upgrades at once', () => {
|
||||
ruleUpdatesTabClick();
|
||||
assertRuleUpgradeAvailableAndUpgradeAll({
|
||||
rules: [OUTDATED_RULE_1, OUTDATED_RULE_2],
|
||||
didRequestFail: true,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -12,9 +12,10 @@ import {
|
|||
GO_BACK_TO_RULES_TABLE_BUTTON,
|
||||
INSTALL_ALL_RULES_BUTTON,
|
||||
INSTALL_SELECTED_RULES_BUTTON,
|
||||
RULES_MANAGEMENT_TABLE,
|
||||
RULES_ROW,
|
||||
RULES_UPDATES_TABLE,
|
||||
NO_RULES_AVAILABLE_FOR_INSTALL_MESSSAGE,
|
||||
NO_RULES_AVAILABLE_FOR_UPGRADE_MESSSAGE,
|
||||
RULES_UPDATES_TAB,
|
||||
RULE_CHECKBOX,
|
||||
SELECT_ALL_RULES_ON_PAGE_CHECKBOX,
|
||||
TOASTER,
|
||||
} from '../../screens/alerts_detection_rules';
|
||||
|
@ -29,6 +30,13 @@ import { login, visitWithoutDateRange } from '../../tasks/login';
|
|||
import { SECURITY_DETECTIONS_RULES_URL } from '../../urls/navigation';
|
||||
import {
|
||||
addElasticRulesButtonClick,
|
||||
assertRuleAvailableForInstallAndInstallOne,
|
||||
assertRuleAvailableForInstallAndInstallSelected,
|
||||
assertRuleAvailableForInstallAndInstallAllInPage,
|
||||
assertRuleAvailableForInstallAndInstallAll,
|
||||
assertRuleUpgradeAvailableAndUpgradeOne,
|
||||
assertRuleUpgradeAvailableAndUpgradeSelected,
|
||||
assertRuleUpgradeAvailableAndUpgradeAllInPage,
|
||||
assertRuleUpgradeAvailableAndUpgradeAll,
|
||||
ruleUpdatesTabClick,
|
||||
} from '../../tasks/prebuilt_rules';
|
||||
|
@ -104,7 +112,7 @@ describe('Detection rules, Prebuilt Rules Installation and Update workflow', ()
|
|||
const numberOfRulesToInstall = new Set(ruleIds).size;
|
||||
addElasticRulesButtonClick();
|
||||
|
||||
cy.get(INSTALL_ALL_RULES_BUTTON).click();
|
||||
cy.get(INSTALL_ALL_RULES_BUTTON).should('be.enabled').click();
|
||||
cy.get(TOASTER)
|
||||
.should('be.visible')
|
||||
.should('have.text', `${numberOfRulesToInstall} rules installed successfully.`);
|
||||
|
@ -144,17 +152,38 @@ describe('Detection rules, Prebuilt Rules Installation and Update workflow', ()
|
|||
beforeEach(() => {
|
||||
createAndInstallMockedPrebuiltRules({ rules: [RULE_1, RULE_2], installToKibana: false });
|
||||
waitForRulesTableToBeLoaded();
|
||||
cy.intercept('POST', '/internal/detection_engine/prebuilt_rules/installation/_perform').as(
|
||||
'installPrebuiltRules'
|
||||
);
|
||||
});
|
||||
|
||||
it('should install selected rules when user clicks on Install selected rules', () => {
|
||||
it('should install prebuilt rules one by one', () => {
|
||||
addElasticRulesButtonClick();
|
||||
cy.get(SELECT_ALL_RULES_ON_PAGE_CHECKBOX).click();
|
||||
cy.get(INSTALL_SELECTED_RULES_BUTTON).click();
|
||||
assertRuleAvailableForInstallAndInstallOne({ rules: [RULE_1] });
|
||||
});
|
||||
|
||||
it('should install multiple selected prebuilt rules by selecting them individually', () => {
|
||||
addElasticRulesButtonClick();
|
||||
assertRuleAvailableForInstallAndInstallSelected({ rules: [RULE_1, RULE_2] });
|
||||
});
|
||||
|
||||
it('should install multiple selected prebuilt rules by selecting all in page', () => {
|
||||
addElasticRulesButtonClick();
|
||||
assertRuleAvailableForInstallAndInstallAllInPage({ rules: [RULE_1, RULE_2] });
|
||||
});
|
||||
|
||||
it('should install all available rules at once', () => {
|
||||
addElasticRulesButtonClick();
|
||||
assertRuleAvailableForInstallAndInstallAll({ rules: [RULE_1, RULE_2] });
|
||||
});
|
||||
|
||||
it('should display an empty screen when all available prebuilt rules have been installed', () => {
|
||||
addElasticRulesButtonClick();
|
||||
cy.get(INSTALL_ALL_RULES_BUTTON).click();
|
||||
cy.get(TOASTER).should('be.visible').should('have.text', `2 rules installed successfully.`);
|
||||
cy.get(GO_BACK_TO_RULES_TABLE_BUTTON).click();
|
||||
cy.get(RULES_MANAGEMENT_TABLE).find(RULES_ROW).should('have.length', 2);
|
||||
cy.get(RULES_MANAGEMENT_TABLE).contains(RULE_1['security-rule'].name);
|
||||
cy.get(RULES_MANAGEMENT_TABLE).contains(RULE_2['security-rule'].name);
|
||||
cy.get(RULE_CHECKBOX).should('not.exist');
|
||||
cy.get(NO_RULES_AVAILABLE_FOR_INSTALL_MESSSAGE).should('exist');
|
||||
cy.get(GO_BACK_TO_RULES_TABLE_BUTTON).should('exist');
|
||||
});
|
||||
|
||||
it('should fail gracefully with toast error message when request to install rules fails', () => {
|
||||
|
@ -170,47 +199,70 @@ describe('Detection rules, Prebuilt Rules Installation and Update workflow', ()
|
|||
});
|
||||
});
|
||||
|
||||
describe('Update of prebuilt rules', () => {
|
||||
const RULE_ID = 'rule_id';
|
||||
const OUTDATED_RULE = createRuleAssetSavedObject({
|
||||
name: 'Outdated rule',
|
||||
rule_id: RULE_ID,
|
||||
describe('Upgrade of prebuilt rules', () => {
|
||||
const RULE_1_ID = 'rule_1';
|
||||
const RULE_2_ID = 'rule_2';
|
||||
const OUTDATED_RULE_1 = createRuleAssetSavedObject({
|
||||
name: 'Outdated rule 1',
|
||||
rule_id: RULE_1_ID,
|
||||
version: 1,
|
||||
});
|
||||
const UPDATED_RULE = createRuleAssetSavedObject({
|
||||
name: 'Updated rule',
|
||||
rule_id: RULE_ID,
|
||||
const UPDATED_RULE_1 = createRuleAssetSavedObject({
|
||||
name: 'Updated rule 1',
|
||||
rule_id: RULE_1_ID,
|
||||
version: 2,
|
||||
});
|
||||
const OUTDATED_RULE_2 = createRuleAssetSavedObject({
|
||||
name: 'Outdated rule 2',
|
||||
rule_id: RULE_2_ID,
|
||||
version: 1,
|
||||
});
|
||||
const UPDATED_RULE_2 = createRuleAssetSavedObject({
|
||||
name: 'Updated rule 2',
|
||||
rule_id: RULE_2_ID,
|
||||
version: 2,
|
||||
});
|
||||
beforeEach(() => {
|
||||
cy.intercept('POST', '/internal/detection_engine/prebuilt_rules/upgrade/_perform').as(
|
||||
'updatePrebuiltRules'
|
||||
);
|
||||
/* Create a new rule and install it */
|
||||
createAndInstallMockedPrebuiltRules({ rules: [OUTDATED_RULE] });
|
||||
createAndInstallMockedPrebuiltRules({ rules: [OUTDATED_RULE_1, OUTDATED_RULE_2] });
|
||||
/* Create a second version of the rule, making it available for update */
|
||||
createAndInstallMockedPrebuiltRules({ rules: [UPDATED_RULE], installToKibana: false });
|
||||
createAndInstallMockedPrebuiltRules({
|
||||
rules: [UPDATED_RULE_1, UPDATED_RULE_2],
|
||||
installToKibana: false,
|
||||
});
|
||||
waitForRulesTableToBeLoaded();
|
||||
reload();
|
||||
});
|
||||
|
||||
it('should update rule succesfully', () => {
|
||||
cy.intercept('POST', '/internal/detection_engine/prebuilt_rules/upgrade/_perform').as(
|
||||
'updatePrebuiltRules'
|
||||
);
|
||||
it('should upgrade prebuilt rules one by one', () => {
|
||||
ruleUpdatesTabClick();
|
||||
assertRuleUpgradeAvailableAndUpgradeAll(OUTDATED_RULE);
|
||||
cy.get(TOASTER).should('be.visible').should('have.text', `1 rule updated successfully.`);
|
||||
assertRuleUpgradeAvailableAndUpgradeOne({ rules: [OUTDATED_RULE_1] });
|
||||
});
|
||||
|
||||
it('should fail gracefully with toast error message when request to update rules fails', () => {
|
||||
/* Stub request to force rules update to fail */
|
||||
cy.intercept('POST', '/internal/detection_engine/prebuilt_rules/upgrade/_perform', {
|
||||
statusCode: 500,
|
||||
}).as('updatePrebuiltRules');
|
||||
it('should upgrade multiple selected prebuilt rules by selecting them individually', () => {
|
||||
ruleUpdatesTabClick();
|
||||
assertRuleUpgradeAvailableAndUpgradeAll(OUTDATED_RULE);
|
||||
cy.get(TOASTER).should('be.visible').should('have.text', 'Rule update failed');
|
||||
assertRuleUpgradeAvailableAndUpgradeSelected({ rules: [OUTDATED_RULE_1, OUTDATED_RULE_2] });
|
||||
});
|
||||
|
||||
/* Assert that the rule has not been updated in the UI */
|
||||
cy.get(RULES_UPDATES_TABLE).should('contain', OUTDATED_RULE['security-rule'].name);
|
||||
it('should upgrade multiple selected prebuilt rules by selecting all in page', () => {
|
||||
ruleUpdatesTabClick();
|
||||
assertRuleUpgradeAvailableAndUpgradeAllInPage({ rules: [OUTDATED_RULE_1, OUTDATED_RULE_2] });
|
||||
});
|
||||
|
||||
it('should upgrade all rules with available upgrades at once', () => {
|
||||
ruleUpdatesTabClick();
|
||||
assertRuleUpgradeAvailableAndUpgradeAll({ rules: [OUTDATED_RULE_1, OUTDATED_RULE_2] });
|
||||
cy.get(RULES_UPDATES_TAB).should('not.exist');
|
||||
});
|
||||
|
||||
it('should display an empty screen when all rules with available updates have been upgraded', () => {
|
||||
ruleUpdatesTabClick();
|
||||
assertRuleUpgradeAvailableAndUpgradeAll({ rules: [OUTDATED_RULE_1, OUTDATED_RULE_2] });
|
||||
cy.get(RULES_UPDATES_TAB).should('not.exist');
|
||||
cy.get(NO_RULES_AVAILABLE_FOR_UPGRADE_MESSSAGE).should('exist');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -12,38 +12,41 @@ import {
|
|||
installAllPrebuiltRulesRequest,
|
||||
createAndInstallMockedPrebuiltRules,
|
||||
} from '../../tasks/api_calls/prebuilt_rules';
|
||||
import { resetRulesTableState, deleteAlertsAndRules, reload } from '../../tasks/common';
|
||||
import {
|
||||
resetRulesTableState,
|
||||
deleteAlertsAndRules,
|
||||
reload,
|
||||
deletePrebuiltRulesAssets,
|
||||
} from '../../tasks/common';
|
||||
import { login, visitWithoutDateRange } from '../../tasks/login';
|
||||
import { SECURITY_DETECTIONS_RULES_URL } from '../../urls/navigation';
|
||||
|
||||
describe('Detection rules, Prebuilt Rules Installation and Update workflow', () => {
|
||||
const RULE_1 = createRuleAssetSavedObject({
|
||||
name: 'Test rule 1',
|
||||
rule_id: 'rule_1',
|
||||
});
|
||||
|
||||
describe('Detection rules, Prebuilt Rules Installation and Update Notifications', () => {
|
||||
beforeEach(() => {
|
||||
login();
|
||||
/* Make sure persisted rules table state is cleared */
|
||||
resetRulesTableState();
|
||||
deleteAlertsAndRules();
|
||||
|
||||
const RULE_1 = createRuleAssetSavedObject({
|
||||
name: 'Test rule 1',
|
||||
rule_id: 'rule_1',
|
||||
});
|
||||
createAndInstallMockedPrebuiltRules({ rules: [RULE_1], installToKibana: false });
|
||||
});
|
||||
|
||||
describe('Rules installation notification when no rules have been installed', () => {
|
||||
beforeEach(() => {
|
||||
visitWithoutDateRange(SECURITY_DETECTIONS_RULES_URL);
|
||||
});
|
||||
|
||||
it('should notify user about prebuilt rules available for installation', () => {
|
||||
cy.get(ADD_ELASTIC_RULES_BTN).should('be.visible');
|
||||
});
|
||||
deletePrebuiltRulesAssets();
|
||||
});
|
||||
|
||||
describe('No notifications', () => {
|
||||
it('should display no install or update notifications when latest rules are installed', () => {
|
||||
/* Install current available rules */
|
||||
installAllPrebuiltRulesRequest();
|
||||
it('should NOT display install or update notifications when no prebuilt assets and no rules are installed', () => {
|
||||
visitWithoutDateRange(SECURITY_DETECTIONS_RULES_URL);
|
||||
waitForRulesTableToBeLoaded();
|
||||
// TODO: test plan asserts "should NOT see a CTA to install prebuilt rules"
|
||||
// but current behavior is to always show the CTA, even with no prebuilt rule assets installed
|
||||
// Update that behaviour and then update this test.
|
||||
cy.get(RULES_UPDATES_TAB).should('not.exist');
|
||||
});
|
||||
|
||||
it('should NOT display install or update notifications when latest rules are installed', () => {
|
||||
createAndInstallMockedPrebuiltRules({ rules: [RULE_1], installToKibana: true });
|
||||
visitWithoutDateRange(SECURITY_DETECTIONS_RULES_URL);
|
||||
waitForRulesTableToBeLoaded();
|
||||
|
||||
|
@ -55,64 +58,123 @@ describe('Detection rules, Prebuilt Rules Installation and Update workflow', ()
|
|||
});
|
||||
});
|
||||
|
||||
describe('Rule installation notification when at least one rule already installed', () => {
|
||||
describe('Notifications', () => {
|
||||
beforeEach(() => {
|
||||
installAllPrebuiltRulesRequest();
|
||||
/* Create new rule assets with a different rule_id as the one that was */
|
||||
/* installed before in order to trigger the installation notification */
|
||||
const RULE_2 = createRuleAssetSavedObject({
|
||||
name: 'Test rule 2',
|
||||
rule_id: 'rule_2',
|
||||
});
|
||||
const RULE_3 = createRuleAssetSavedObject({
|
||||
name: 'Test rule 3',
|
||||
rule_id: 'rule_3',
|
||||
createAndInstallMockedPrebuiltRules({ rules: [RULE_1], installToKibana: false });
|
||||
});
|
||||
|
||||
describe('Rules installation notification when no rules have been installed', () => {
|
||||
beforeEach(() => {
|
||||
visitWithoutDateRange(SECURITY_DETECTIONS_RULES_URL);
|
||||
});
|
||||
|
||||
createAndInstallMockedPrebuiltRules({ rules: [RULE_2, RULE_3], installToKibana: false });
|
||||
visitWithoutDateRange(SECURITY_DETECTIONS_RULES_URL);
|
||||
waitForRulesTableToBeLoaded();
|
||||
});
|
||||
|
||||
it('should notify user about prebuilt rules package available for installation', () => {
|
||||
const numberOfAvailableRules = 2;
|
||||
cy.get(ADD_ELASTIC_RULES_BTN).should('be.visible');
|
||||
cy.get(ADD_ELASTIC_RULES_BTN).should(
|
||||
'have.text',
|
||||
`Add Elastic rules${numberOfAvailableRules}`
|
||||
);
|
||||
});
|
||||
|
||||
it('should notify user a rule is again available for installation if it is deleted', () => {
|
||||
/* Install available rules, assert that the notification is gone */
|
||||
/* then delete one rule and assert that the notification is back */
|
||||
installAllPrebuiltRulesRequest();
|
||||
reload();
|
||||
deleteFirstRule();
|
||||
cy.get(ADD_ELASTIC_RULES_BTN).should('be.visible');
|
||||
cy.get(ADD_ELASTIC_RULES_BTN).should('have.text', `Add Elastic rules${1}`);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Rule update notification', () => {
|
||||
beforeEach(() => {
|
||||
installAllPrebuiltRulesRequest();
|
||||
/* Create new rule asset with the same rule_id as the one that was installed */
|
||||
/* but with a higher version, in order to trigger the update notification */
|
||||
const UPDATED_RULE = createRuleAssetSavedObject({
|
||||
name: 'Test rule 1.1 (updated)',
|
||||
rule_id: 'rule_1',
|
||||
version: 2,
|
||||
it('should notify user about prebuilt rules available for installation', () => {
|
||||
cy.get(ADD_ELASTIC_RULES_BTN).should('be.visible');
|
||||
cy.get(ADD_ELASTIC_RULES_BTN).should('have.text', `Add Elastic rules${1}`);
|
||||
cy.get(RULES_UPDATES_TAB).should('not.exist');
|
||||
});
|
||||
createAndInstallMockedPrebuiltRules({ rules: [UPDATED_RULE], installToKibana: false });
|
||||
visitWithoutDateRange(SECURITY_DETECTIONS_RULES_URL);
|
||||
waitForRulesTableToBeLoaded();
|
||||
reload();
|
||||
});
|
||||
|
||||
it('should notify user about prebuilt rules package available for update', () => {
|
||||
cy.get(RULES_UPDATES_TAB).should('be.visible');
|
||||
cy.get(RULES_UPDATES_TAB).should('have.text', `Rule Updates${1}`);
|
||||
describe('Rule installation notification when at least one rule already installed', () => {
|
||||
beforeEach(() => {
|
||||
installAllPrebuiltRulesRequest().then(() => {
|
||||
/* Create new rule assets with a different rule_id as the one that was */
|
||||
/* installed before in order to trigger the installation notification */
|
||||
const RULE_2 = createRuleAssetSavedObject({
|
||||
name: 'Test rule 2',
|
||||
rule_id: 'rule_2',
|
||||
});
|
||||
const RULE_3 = createRuleAssetSavedObject({
|
||||
name: 'Test rule 3',
|
||||
rule_id: 'rule_3',
|
||||
});
|
||||
|
||||
createAndInstallMockedPrebuiltRules({ rules: [RULE_2, RULE_3], installToKibana: false });
|
||||
visitWithoutDateRange(SECURITY_DETECTIONS_RULES_URL);
|
||||
waitForRulesTableToBeLoaded();
|
||||
});
|
||||
});
|
||||
|
||||
it('should notify user about prebuilt rules available for installation', () => {
|
||||
const numberOfAvailableRules = 2;
|
||||
cy.get(ADD_ELASTIC_RULES_BTN).should('be.visible');
|
||||
cy.get(ADD_ELASTIC_RULES_BTN).should(
|
||||
'have.text',
|
||||
`Add Elastic rules${numberOfAvailableRules}`
|
||||
);
|
||||
cy.get(RULES_UPDATES_TAB).should('not.exist');
|
||||
});
|
||||
|
||||
it('should notify user a rule is again available for installation if it is deleted', () => {
|
||||
/* Install available rules, assert that the notification is gone */
|
||||
/* then delete one rule and assert that the notification is back */
|
||||
installAllPrebuiltRulesRequest().then(() => {
|
||||
reload();
|
||||
deleteFirstRule();
|
||||
cy.get(ADD_ELASTIC_RULES_BTN).should('be.visible');
|
||||
cy.get(ADD_ELASTIC_RULES_BTN).should('have.text', `Add Elastic rules${1}`);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Rule update notification', () => {
|
||||
beforeEach(() => {
|
||||
installAllPrebuiltRulesRequest().then(() => {
|
||||
/* Create new rule asset with the same rule_id as the one that was installed */
|
||||
/* but with a higher version, in order to trigger the update notification */
|
||||
const UPDATED_RULE = createRuleAssetSavedObject({
|
||||
name: 'Test rule 1.1 (updated)',
|
||||
rule_id: 'rule_1',
|
||||
version: 2,
|
||||
});
|
||||
createAndInstallMockedPrebuiltRules({ rules: [UPDATED_RULE], installToKibana: false });
|
||||
visitWithoutDateRange(SECURITY_DETECTIONS_RULES_URL);
|
||||
waitForRulesTableToBeLoaded();
|
||||
reload();
|
||||
});
|
||||
});
|
||||
|
||||
it('should notify user about prebuilt rules package available for update', () => {
|
||||
// No rules available for installation
|
||||
cy.get(ADD_ELASTIC_RULES_BTN).should('have.text', `Add Elastic rules`);
|
||||
// But 1 rule available for update
|
||||
cy.get(RULES_UPDATES_TAB).should('be.visible');
|
||||
cy.get(RULES_UPDATES_TAB).should('have.text', `Rule Updates${1}`);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Rule installation available and rule update available notifications', () => {
|
||||
beforeEach(() => {
|
||||
installAllPrebuiltRulesRequest().then(() => {
|
||||
/* Create new rule assets with a different rule_id as the one that was */
|
||||
/* installed before in order to trigger the installation notification */
|
||||
const RULE_2 = createRuleAssetSavedObject({
|
||||
name: 'Test rule 2',
|
||||
rule_id: 'rule_2',
|
||||
});
|
||||
/* Create new rule asset with the same rule_id as the one that was installed */
|
||||
/* but with a higher version, in order to trigger the update notification */
|
||||
const UPDATED_RULE = createRuleAssetSavedObject({
|
||||
name: 'Test rule 1.1 (updated)',
|
||||
rule_id: 'rule_1',
|
||||
version: 2,
|
||||
});
|
||||
createAndInstallMockedPrebuiltRules({
|
||||
rules: [RULE_2, UPDATED_RULE],
|
||||
installToKibana: false,
|
||||
});
|
||||
visitWithoutDateRange(SECURITY_DETECTIONS_RULES_URL);
|
||||
waitForRulesTableToBeLoaded();
|
||||
});
|
||||
});
|
||||
|
||||
it('should notify user about prebuilt rules available for installation and for upgrade', () => {
|
||||
// 1 rule available for installation
|
||||
cy.get(ADD_ELASTIC_RULES_BTN).should('have.text', `Add Elastic rules${1}`);
|
||||
// 1 rule available for update
|
||||
cy.get(RULES_UPDATES_TAB).should('be.visible');
|
||||
cy.get(RULES_UPDATES_TAB).should('have.text', `Rule Updates${1}`);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -107,6 +107,8 @@ export const RULES_MONITORING_TABLE = '[data-test-subj="rules-monitoring-table"]
|
|||
|
||||
export const RULES_UPDATES_TABLE = '[data-test-subj="rules-upgrades-table"]';
|
||||
|
||||
export const ADD_ELASTIC_RULES_TABLE = '[data-test-subj="add-prebuilt-rules-table"]';
|
||||
|
||||
export const RULES_ROW = '.euiTableRow';
|
||||
|
||||
export const SEVERITY = '[data-test-subj="severity"]';
|
||||
|
@ -182,3 +184,16 @@ export const RULE_EXECUTION_STATUS_BADGE = '[data-test-subj="ruleExecutionStatus
|
|||
export const EXECUTION_STATUS_FILTER_BUTTON = '[data-test-subj="executionStatusFilterButton"]';
|
||||
|
||||
export const EXECUTION_STATUS_FILTER_OPTION = '[data-test-subj="executionStatusFilterOption"]';
|
||||
|
||||
export const getInstallSingleRuleButtonByRuleId = (ruleId: string) => {
|
||||
return `[data-test-subj="installSinglePrebuiltRuleButton-${ruleId}"]`;
|
||||
};
|
||||
|
||||
export const getUpgradeSingleRuleButtonByRuleId = (ruleId: string) => {
|
||||
return `[data-test-subj="upgradeSinglePrebuiltRuleButton-${ruleId}"]`;
|
||||
};
|
||||
|
||||
export const NO_RULES_AVAILABLE_FOR_INSTALL_MESSSAGE =
|
||||
'[data-test-subj="noPrebuiltRulesAvailableForInstall"]';
|
||||
export const NO_RULES_AVAILABLE_FOR_UPGRADE_MESSSAGE =
|
||||
'[data-test-subj="noPrebuiltRulesAvailableForUpgrade"]';
|
||||
|
|
|
@ -199,6 +199,6 @@ export const createAndInstallMockedPrebuiltRules = ({
|
|||
createNewRuleAsset({ rule });
|
||||
});
|
||||
if (installToKibana) {
|
||||
installAllPrebuiltRulesRequest();
|
||||
return installAllPrebuiltRulesRequest();
|
||||
}
|
||||
};
|
||||
|
|
|
@ -8,11 +8,21 @@
|
|||
import { RULES_ADD_PATH, RULES_UPDATES } from '../../common/constants';
|
||||
import {
|
||||
ADD_ELASTIC_RULES_BTN,
|
||||
RULES_ROW,
|
||||
ADD_ELASTIC_RULES_TABLE,
|
||||
getInstallSingleRuleButtonByRuleId,
|
||||
getUpgradeSingleRuleButtonByRuleId,
|
||||
INSTALL_ALL_RULES_BUTTON,
|
||||
INSTALL_SELECTED_RULES_BUTTON,
|
||||
RULES_MANAGEMENT_TABLE,
|
||||
RULES_UPDATES_TAB,
|
||||
RULES_UPDATES_TABLE,
|
||||
RULE_CHECKBOX,
|
||||
SELECT_ALL_RULES_ON_PAGE_CHECKBOX,
|
||||
TOASTER,
|
||||
UPGRADE_ALL_RULES_BUTTON,
|
||||
UPGRADE_SELECTED_RULES_BUTTON,
|
||||
} from '../screens/alerts_detection_rules';
|
||||
import { BACK_TO_RULES_TABLE } from '../screens/rule_details';
|
||||
import type { SAMPLE_PREBUILT_RULE } from './api_calls/prebuilt_rules';
|
||||
|
||||
export const addElasticRulesButtonClick = () => {
|
||||
|
@ -25,9 +35,190 @@ export const ruleUpdatesTabClick = () => {
|
|||
cy.location('pathname').should('include', RULES_UPDATES);
|
||||
};
|
||||
|
||||
export const assertRuleUpgradeAvailableAndUpgradeAll = (rule: typeof SAMPLE_PREBUILT_RULE) => {
|
||||
cy.get(RULES_UPDATES_TABLE).find(RULES_ROW).should('have.length', 1);
|
||||
cy.get(RULES_UPDATES_TABLE).contains(rule['security-rule'].name);
|
||||
interface RuleInstallUpgradeAssertionPayload {
|
||||
rules: Array<typeof SAMPLE_PREBUILT_RULE>;
|
||||
didRequestFail?: boolean;
|
||||
}
|
||||
|
||||
export const assertRuleAvailableForInstallAndInstallOne = ({
|
||||
rules,
|
||||
didRequestFail = false,
|
||||
}: RuleInstallUpgradeAssertionPayload) => {
|
||||
interceptInstallationRequestToFail(rules, didRequestFail);
|
||||
const rule = rules[0];
|
||||
cy.get(getInstallSingleRuleButtonByRuleId(rule['security-rule'].rule_id)).click();
|
||||
cy.wait('@installPrebuiltRules');
|
||||
assertInstallationSuccessOrFailure([rule], didRequestFail);
|
||||
};
|
||||
|
||||
export const assertRuleAvailableForInstallAndInstallSelected = ({
|
||||
rules,
|
||||
didRequestFail = false,
|
||||
}: RuleInstallUpgradeAssertionPayload) => {
|
||||
interceptInstallationRequestToFail(rules, didRequestFail);
|
||||
let i = 0;
|
||||
for (const rule of rules) {
|
||||
cy.get(RULE_CHECKBOX).eq(i).click();
|
||||
cy.get(ADD_ELASTIC_RULES_TABLE).contains(rule['security-rule'].name);
|
||||
i++;
|
||||
}
|
||||
cy.get(INSTALL_SELECTED_RULES_BUTTON).click();
|
||||
cy.wait('@installPrebuiltRules');
|
||||
assertInstallationSuccessOrFailure(rules, didRequestFail);
|
||||
};
|
||||
|
||||
export const assertRuleAvailableForInstallAndInstallAllInPage = ({
|
||||
rules,
|
||||
didRequestFail = false,
|
||||
}: RuleInstallUpgradeAssertionPayload) => {
|
||||
interceptInstallationRequestToFail(rules, didRequestFail);
|
||||
for (const rule of rules) {
|
||||
cy.get(ADD_ELASTIC_RULES_TABLE).contains(rule['security-rule'].name);
|
||||
}
|
||||
cy.get(SELECT_ALL_RULES_ON_PAGE_CHECKBOX).click();
|
||||
cy.get(INSTALL_SELECTED_RULES_BUTTON).click();
|
||||
cy.wait('@installPrebuiltRules');
|
||||
assertInstallationSuccessOrFailure(rules, didRequestFail);
|
||||
};
|
||||
|
||||
export const assertRuleAvailableForInstallAndInstallAll = ({
|
||||
rules,
|
||||
didRequestFail = false,
|
||||
}: RuleInstallUpgradeAssertionPayload) => {
|
||||
interceptInstallationRequestToFail(rules, didRequestFail);
|
||||
for (const rule of rules) {
|
||||
cy.get(ADD_ELASTIC_RULES_TABLE).contains(rule['security-rule'].name);
|
||||
}
|
||||
cy.get(INSTALL_ALL_RULES_BUTTON).click();
|
||||
cy.wait('@installPrebuiltRules');
|
||||
assertInstallationSuccessOrFailure(rules, didRequestFail);
|
||||
};
|
||||
|
||||
const assertInstallationSuccessOrFailure = (
|
||||
rules: Array<typeof SAMPLE_PREBUILT_RULE>,
|
||||
didRequestFail: boolean
|
||||
) => {
|
||||
const rulesString = rules.length > 1 ? 'rules' : 'rule';
|
||||
const toastMessage = didRequestFail
|
||||
? `${rules.length} ${rulesString} failed to install.`
|
||||
: `${rules.length} ${rulesString} installed successfully.`;
|
||||
cy.get(TOASTER).should('be.visible').should('have.text', toastMessage);
|
||||
if (didRequestFail) {
|
||||
for (const rule of rules) {
|
||||
cy.get(ADD_ELASTIC_RULES_TABLE).contains(rule['security-rule'].name);
|
||||
}
|
||||
} else {
|
||||
cy.get(BACK_TO_RULES_TABLE).click();
|
||||
for (const rule of rules) {
|
||||
cy.get(RULES_MANAGEMENT_TABLE).contains(rule['security-rule'].name);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const interceptInstallationRequestToFail = (
|
||||
rules: Array<typeof SAMPLE_PREBUILT_RULE>,
|
||||
didRequestFail: boolean
|
||||
) => {
|
||||
if (didRequestFail) {
|
||||
cy.intercept('POST', '/internal/detection_engine/prebuilt_rules/installation/_perform', {
|
||||
body: {
|
||||
summary: {
|
||||
succeeded: [],
|
||||
skipped: [],
|
||||
failed: rules.length,
|
||||
},
|
||||
},
|
||||
}).as('installPrebuiltRules');
|
||||
}
|
||||
};
|
||||
|
||||
export const assertRuleUpgradeAvailableAndUpgradeOne = ({
|
||||
rules,
|
||||
didRequestFail = false,
|
||||
}: RuleInstallUpgradeAssertionPayload) => {
|
||||
interceptUpgradeRequestToFail(rules, didRequestFail);
|
||||
const rule = rules[0];
|
||||
cy.get(getUpgradeSingleRuleButtonByRuleId(rule['security-rule'].rule_id)).click();
|
||||
cy.wait('@updatePrebuiltRules');
|
||||
assertUpgradeSuccessOrFailure([rule], didRequestFail);
|
||||
};
|
||||
|
||||
export const assertRuleUpgradeAvailableAndUpgradeSelected = ({
|
||||
rules,
|
||||
didRequestFail = false,
|
||||
}: RuleInstallUpgradeAssertionPayload) => {
|
||||
interceptUpgradeRequestToFail(rules, didRequestFail);
|
||||
let i = 0;
|
||||
for (const rule of rules) {
|
||||
cy.get(RULE_CHECKBOX).eq(i).click();
|
||||
cy.get(RULES_UPDATES_TABLE).contains(rule['security-rule'].name);
|
||||
i++;
|
||||
}
|
||||
cy.get(UPGRADE_SELECTED_RULES_BUTTON).click();
|
||||
cy.wait('@updatePrebuiltRules');
|
||||
assertUpgradeSuccessOrFailure(rules, didRequestFail);
|
||||
};
|
||||
|
||||
export const assertRuleUpgradeAvailableAndUpgradeAllInPage = ({
|
||||
rules,
|
||||
didRequestFail = false,
|
||||
}: RuleInstallUpgradeAssertionPayload) => {
|
||||
interceptUpgradeRequestToFail(rules, didRequestFail);
|
||||
for (const rule of rules) {
|
||||
cy.get(RULES_UPDATES_TABLE).contains(rule['security-rule'].name);
|
||||
}
|
||||
cy.get(SELECT_ALL_RULES_ON_PAGE_CHECKBOX).click();
|
||||
cy.get(UPGRADE_SELECTED_RULES_BUTTON).click();
|
||||
cy.wait('@updatePrebuiltRules');
|
||||
assertUpgradeSuccessOrFailure(rules, didRequestFail);
|
||||
};
|
||||
|
||||
export const assertRuleUpgradeAvailableAndUpgradeAll = ({
|
||||
rules,
|
||||
didRequestFail = false,
|
||||
}: RuleInstallUpgradeAssertionPayload) => {
|
||||
interceptUpgradeRequestToFail(rules, didRequestFail);
|
||||
for (const rule of rules) {
|
||||
cy.get(RULES_UPDATES_TABLE).contains(rule['security-rule'].name);
|
||||
}
|
||||
cy.get(UPGRADE_ALL_RULES_BUTTON).click();
|
||||
cy.wait('@updatePrebuiltRules');
|
||||
assertUpgradeSuccessOrFailure(rules, didRequestFail);
|
||||
};
|
||||
|
||||
const assertUpgradeSuccessOrFailure = (
|
||||
rules: Array<typeof SAMPLE_PREBUILT_RULE>,
|
||||
didRequestFail: boolean
|
||||
) => {
|
||||
const rulesString = rules.length > 1 ? 'rules' : 'rule';
|
||||
const toastMessage = didRequestFail
|
||||
? `${rules.length} ${rulesString} failed to update.`
|
||||
: `${rules.length} ${rulesString} updated successfully.`;
|
||||
cy.get(TOASTER).should('be.visible').should('have.text', toastMessage);
|
||||
if (didRequestFail) {
|
||||
for (const rule of rules) {
|
||||
cy.get(RULES_UPDATES_TABLE).contains(rule['security-rule'].name);
|
||||
}
|
||||
} else {
|
||||
for (const rule of rules) {
|
||||
cy.get(rule['security-rule'].name).should('not.exist');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const interceptUpgradeRequestToFail = (
|
||||
rules: Array<typeof SAMPLE_PREBUILT_RULE>,
|
||||
didRequestFail: boolean
|
||||
) => {
|
||||
if (didRequestFail) {
|
||||
cy.intercept('POST', '/internal/detection_engine/prebuilt_rules/upgrade/_perform', {
|
||||
body: {
|
||||
summary: {
|
||||
succeeded: [],
|
||||
skipped: [],
|
||||
failed: rules.length,
|
||||
},
|
||||
},
|
||||
}).as('updatePrebuiltRules');
|
||||
}
|
||||
};
|
||||
|
|
|
@ -61,7 +61,7 @@ Then the package gets installed in the background from EPR
|
|||
|
||||
#### **Scenario: Package is installed via bundled Fleet package in Kibana**
|
||||
|
||||
**Automation**: 1 integration test.
|
||||
**Automation**: 2 integration tests.
|
||||
|
||||
```Gherkin
|
||||
Given the package is not installed
|
||||
|
@ -173,6 +173,8 @@ TODO: Check why for the legacy API Dmitrii has added 2 integration tests for `ru
|
|||
- `should update outdated prebuilt rules when previous historical versions available`
|
||||
- `should update outdated prebuilt rules when previous historical versions unavailable`
|
||||
|
||||
(NOTE: the second scenario tests that, if a new version of a rule is released, it can upgrade the current instance of that rule even if the historical versions of that rule are no longer in the package)
|
||||
|
||||
Notes:
|
||||
|
||||
- Legacy API:
|
||||
|
@ -220,7 +222,7 @@ Notes:
|
|||
|
||||
### Scenarios for the real package
|
||||
|
||||
#### **Scenario: User can install prebuilt rules from scratch, then install new rules and upgrade existing rules from the new pckage**
|
||||
#### **Scenario: User can install prebuilt rules from scratch, then install new rules and upgrade existing rules from the new package**
|
||||
|
||||
**Automation**: 1 integration test with real packages.
|
||||
|
||||
|
@ -250,21 +252,6 @@ Then rules returned in this response should exist as alert saved objects
|
|||
|
||||
### Rule installation and upgrade notifications on the Rule Management page
|
||||
|
||||
#### **Scenario: User is notified when no prebuilt rules are installed and there are rules available to install**
|
||||
|
||||
**Automation**: 1 e2e test with mock rules + 1 integration test with mock rules for the /status endpoint.
|
||||
|
||||
```Gherkin
|
||||
Given no prebuilt rules are installed in Kibana
|
||||
And there are X prebuilt rules available to install
|
||||
When user opens the Rule Management page
|
||||
Then user should see a CTA to install prebuilt rules
|
||||
And user should see a number of rules available to install (X)
|
||||
And user should NOT see a CTA to upgrade prebuilt rules
|
||||
And user should NOT see a number of rules available to upgrade
|
||||
And user should NOT see the Rule Updates table
|
||||
```
|
||||
|
||||
#### **Scenario: User is NOT notified when no prebuilt rules are installed and there are no prebuilt rules assets**
|
||||
|
||||
**Automation**: 1 e2e test with mock rules + 1 integration test with mock rules for the /status endpoint.
|
||||
|
@ -294,6 +281,21 @@ And user should NOT see a number of rules available to upgrade
|
|||
And user should NOT see the Rule Updates table
|
||||
```
|
||||
|
||||
#### **Scenario: User is notified when no prebuilt rules are installed and there are rules available to install**
|
||||
|
||||
**Automation**: 1 e2e test with mock rules + 1 integration test with mock rules for the /status endpoint.
|
||||
|
||||
```Gherkin
|
||||
Given no prebuilt rules are installed in Kibana
|
||||
And there are X prebuilt rules available to install
|
||||
When user opens the Rule Management page
|
||||
Then user should see a CTA to install prebuilt rules
|
||||
And user should see a number of rules available to install (X)
|
||||
And user should NOT see a CTA to upgrade prebuilt rules
|
||||
And user should NOT see a number of rules available to upgrade
|
||||
And user should NOT see the Rule Updates table
|
||||
```
|
||||
|
||||
#### **Scenario: User is notified when some prebuilt rules can be installed**
|
||||
|
||||
**Automation**: 1 e2e test with mock rules + 1 integration test with mock rules for the /status endpoint.
|
||||
|
@ -323,7 +325,6 @@ Then user should NOT see a CTA to install prebuilt rules
|
|||
And user should NOT see a number of rules available to install
|
||||
And user should see a CTA to upgrade prebuilt rules
|
||||
And user should see the number of rules available to upgrade (Z)
|
||||
And user should see the Rule Updates table
|
||||
```
|
||||
|
||||
#### **Scenario: User is notified when both rules to install and upgrade are available**
|
||||
|
@ -339,7 +340,6 @@ Then user should see a CTA to install prebuilt rules
|
|||
And user should see the number of rules available to install (Y)
|
||||
And user should see a CTA to upgrade prebuilt rules
|
||||
And user should see the number of rules available to upgrade (Z)
|
||||
And user should see the Rule Updates table
|
||||
```
|
||||
|
||||
#### **Scenario: User is notified after a prebuilt rule gets deleted**
|
||||
|
@ -533,7 +533,7 @@ Then user should NOT see the Rule Updates tab until the package installation is
|
|||
|
||||
#### **Scenario: Error is handled when any operation on prebuilt rules fails**
|
||||
|
||||
**Automation**: unit tests.
|
||||
**Automation**: e2e test with mock rules
|
||||
|
||||
```Gherkin
|
||||
When user is <operation> prebuilt rules
|
||||
|
|
|
@ -29,7 +29,7 @@ export const INSTALL_RULE_SKIPPED = (skipped: number) =>
|
|||
|
||||
export const INSTALL_RULE_FAILED = (failed: number) =>
|
||||
i18n.translate('xpack.securitySolution.detectionEngine.prebuiltRules.toast.installRuleFailed', {
|
||||
defaultMessage: '{failed, plural, one {# rule has} other {# rules have}} failed to install.',
|
||||
defaultMessage: '{failed, plural, one {# rule} other {# rules}} failed to install.',
|
||||
values: { failed },
|
||||
});
|
||||
|
||||
|
@ -55,6 +55,6 @@ export const UPGRADE_RULE_SKIPPED = (skipped: number) =>
|
|||
|
||||
export const UPGRADE_RULE_FAILED = (failed: number) =>
|
||||
i18n.translate('xpack.securitySolution.detectionEngine.prebuiltRules.toast.upgradeRuleFailed', {
|
||||
defaultMessage: '{failed, plural, one {# rule has} other {# rules have}} failed to update.',
|
||||
defaultMessage: '{failed, plural, one {# rule} other {# rules}} failed to update.',
|
||||
values: { failed },
|
||||
});
|
||||
|
|
|
@ -30,6 +30,7 @@ const AddPrebuiltRulesTableNoItemsMessageComponent = () => {
|
|||
title={<h3>{i18n.NO_RULES_AVAILABLE_FOR_INSTALL}</h3>}
|
||||
titleSize="s"
|
||||
body={i18n.NO_RULES_AVAILABLE_FOR_INSTALL_BODY}
|
||||
data-test-subj="noPrebuiltRulesAvailableForInstall"
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
|
|
|
@ -98,6 +98,7 @@ const createInstallButtonColumn = (
|
|||
size="s"
|
||||
disabled={isInstallButtonDisabled}
|
||||
onClick={() => installOneRule(ruleId)}
|
||||
data-test-subj={`installSinglePrebuiltRuleButton-${ruleId}`}
|
||||
>
|
||||
{isRuleInstalling ? <EuiLoadingSpinner size="s" /> : i18n.INSTALL_RULE_BUTTON}
|
||||
</EuiButtonEmpty>
|
||||
|
|
|
@ -29,6 +29,7 @@ const NO_ITEMS_MESSAGE = (
|
|||
title={<h3>{i18n.NO_RULES_AVAILABLE_FOR_UPGRADE}</h3>}
|
||||
titleSize="s"
|
||||
body={i18n.NO_RULES_AVAILABLE_FOR_UPGRADE_BODY}
|
||||
data-test-subj="noPrebuiltRulesAvailableForUpgrade"
|
||||
/>
|
||||
);
|
||||
|
||||
|
|
|
@ -98,6 +98,7 @@ const createUpgradeButtonColumn = (
|
|||
size="s"
|
||||
disabled={isUpgradeButtonDisabled}
|
||||
onClick={() => upgradeOneRule(ruleId)}
|
||||
data-test-subj={`upgradeSinglePrebuiltRuleButton-${ruleId}`}
|
||||
>
|
||||
{isRuleUpgrading ? <EuiLoadingSpinner size="s" /> : i18n.UPDATE_RULE_BUTTON}
|
||||
</EuiButtonEmpty>
|
||||
|
|
|
@ -11,12 +11,10 @@ import { REPO_ROOT } from '@kbn/repo-info';
|
|||
import JSON5 from 'json5';
|
||||
import expect from 'expect';
|
||||
import { PackageSpecManifest } from '@kbn/fleet-plugin/common';
|
||||
import { ALL_SAVED_OBJECT_INDICES } from '@kbn/core-saved-objects-server';
|
||||
import { FtrProviderContext } from '../../common/ftr_provider_context';
|
||||
import {
|
||||
deleteAllPrebuiltRuleAssets,
|
||||
deleteAllRules,
|
||||
getPrebuiltRulesAndTimelinesStatus,
|
||||
} from '../../utils';
|
||||
import { deleteAllPrebuiltRuleAssets, deleteAllRules } from '../../utils';
|
||||
import { getPrebuiltRulesStatus } from '../../utils/prebuilt_rules/get_prebuilt_rules_status';
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default ({ getService }: FtrProviderContext): void => {
|
||||
|
@ -52,10 +50,10 @@ export default ({ getService }: FtrProviderContext): void => {
|
|||
|
||||
it('should install prebuilt rules from the package that comes bundled with Kibana', async () => {
|
||||
// Verify that status is empty before package installation
|
||||
const statusBeforePackageInstallation = await getPrebuiltRulesAndTimelinesStatus(supertest);
|
||||
expect(statusBeforePackageInstallation.rules_installed).toBe(0);
|
||||
expect(statusBeforePackageInstallation.rules_not_installed).toBe(0);
|
||||
expect(statusBeforePackageInstallation.rules_not_updated).toBe(0);
|
||||
const statusBeforePackageInstallation = await getPrebuiltRulesStatus(supertest);
|
||||
expect(statusBeforePackageInstallation.stats.num_prebuilt_rules_installed).toBe(0);
|
||||
expect(statusBeforePackageInstallation.stats.num_prebuilt_rules_to_install).toBe(0);
|
||||
expect(statusBeforePackageInstallation.stats.num_prebuilt_rules_to_upgrade).toBe(0);
|
||||
|
||||
const EPM_URL = `/api/fleet/epm/packages/security_detection_engine/99.0.0`;
|
||||
|
||||
|
@ -69,11 +67,13 @@ export default ({ getService }: FtrProviderContext): void => {
|
|||
// As opposed to "registry"
|
||||
expect(bundledInstallResponse.body._meta.install_source).toBe('bundled');
|
||||
|
||||
await es.indices.refresh({ index: ALL_SAVED_OBJECT_INDICES });
|
||||
|
||||
// Verify that status is updated after package installation
|
||||
const statusAfterPackageInstallation = await getPrebuiltRulesAndTimelinesStatus(supertest);
|
||||
expect(statusAfterPackageInstallation.rules_installed).toBe(0);
|
||||
expect(statusAfterPackageInstallation.rules_not_installed).toBeGreaterThan(0);
|
||||
expect(statusAfterPackageInstallation.rules_not_updated).toBe(0);
|
||||
const statusAfterPackageInstallation = await getPrebuiltRulesStatus(supertest);
|
||||
expect(statusAfterPackageInstallation.stats.num_prebuilt_rules_installed).toBe(0);
|
||||
expect(statusAfterPackageInstallation.stats.num_prebuilt_rules_to_install).toBeGreaterThan(0);
|
||||
expect(statusAfterPackageInstallation.stats.num_prebuilt_rules_to_upgrade).toBe(0);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
|
|
@ -8,12 +8,9 @@ import { ALL_SAVED_OBJECT_INDICES } from '@kbn/core-saved-objects-server';
|
|||
import { DETECTION_ENGINE_RULES_URL_FIND } from '@kbn/security-solution-plugin/common/constants';
|
||||
import expect from 'expect';
|
||||
import { FtrProviderContext } from '../../common/ftr_provider_context';
|
||||
import {
|
||||
deleteAllPrebuiltRuleAssets,
|
||||
deleteAllRules,
|
||||
getPrebuiltRulesAndTimelinesStatus,
|
||||
installPrebuiltRulesAndTimelines,
|
||||
} from '../../utils';
|
||||
import { deleteAllPrebuiltRuleAssets, deleteAllRules } from '../../utils';
|
||||
import { getPrebuiltRulesStatus } from '../../utils/prebuilt_rules/get_prebuilt_rules_status';
|
||||
import { installPrebuiltRules } from '../../utils/prebuilt_rules/install_prebuilt_rules';
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default ({ getService }: FtrProviderContext): void => {
|
||||
|
@ -36,19 +33,19 @@ export default ({ getService }: FtrProviderContext): void => {
|
|||
|
||||
it('should install latest stable version and ignore prerelease packages', async () => {
|
||||
// Verify that status is empty before package installation
|
||||
const statusBeforePackageInstallation = await getPrebuiltRulesAndTimelinesStatus(supertest);
|
||||
expect(statusBeforePackageInstallation.rules_installed).toBe(0);
|
||||
expect(statusBeforePackageInstallation.rules_not_installed).toBe(0);
|
||||
expect(statusBeforePackageInstallation.rules_not_updated).toBe(0);
|
||||
const statusBeforePackageInstallation = await getPrebuiltRulesStatus(supertest);
|
||||
expect(statusBeforePackageInstallation.stats.num_prebuilt_rules_installed).toBe(0);
|
||||
expect(statusBeforePackageInstallation.stats.num_prebuilt_rules_to_install).toBe(0);
|
||||
expect(statusBeforePackageInstallation.stats.num_prebuilt_rules_to_upgrade).toBe(0);
|
||||
|
||||
await installPrebuiltRulesAndTimelines(supertest);
|
||||
await installPrebuiltRules(supertest);
|
||||
await es.indices.refresh({ index: ALL_SAVED_OBJECT_INDICES });
|
||||
|
||||
// Verify that status is updated after package installation
|
||||
const statusAfterPackageInstallation = await getPrebuiltRulesAndTimelinesStatus(supertest);
|
||||
expect(statusAfterPackageInstallation.rules_installed).toBe(1); // 1 rule in package 99.0.0
|
||||
expect(statusAfterPackageInstallation.rules_not_installed).toBe(0);
|
||||
expect(statusAfterPackageInstallation.rules_not_updated).toBe(0);
|
||||
const statusAfterPackageInstallation = await getPrebuiltRulesStatus(supertest);
|
||||
expect(statusAfterPackageInstallation.stats.num_prebuilt_rules_installed).toBe(1); // 1 rule in package 99.0.0
|
||||
expect(statusAfterPackageInstallation.stats.num_prebuilt_rules_to_install).toBe(0);
|
||||
expect(statusAfterPackageInstallation.stats.num_prebuilt_rules_to_upgrade).toBe(0);
|
||||
|
||||
// Get installed rules
|
||||
const { body: rulesResponse } = await supertest
|
||||
|
|
|
@ -21,6 +21,9 @@ import {
|
|||
createRuleAssetSavedObject,
|
||||
} from '../../utils/prebuilt_rules/create_prebuilt_rule_saved_objects';
|
||||
import { deleteAllPrebuiltRuleAssets } from '../../utils/prebuilt_rules/delete_all_prebuilt_rule_assets';
|
||||
import { getPrebuiltRulesStatus } from '../../utils/prebuilt_rules/get_prebuilt_rules_status';
|
||||
import { installPrebuiltRules } from '../../utils/prebuilt_rules/install_prebuilt_rules';
|
||||
import { upgradePrebuiltRules } from '../../utils/prebuilt_rules/upgrade_prebuilt_rules';
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default ({ getService }: FtrProviderContext): void => {
|
||||
|
@ -28,208 +31,465 @@ export default ({ getService }: FtrProviderContext): void => {
|
|||
const es = getService('es');
|
||||
const log = getService('log');
|
||||
|
||||
describe('get_prebuilt_rules_status', () => {
|
||||
beforeEach(async () => {
|
||||
await deleteAllPrebuiltRuleAssets(es);
|
||||
await deleteAllRules(supertest, log);
|
||||
});
|
||||
describe('Prebuilt Rules status', () => {
|
||||
describe('get_prebuilt_rules_status', () => {
|
||||
beforeEach(async () => {
|
||||
await deleteAllPrebuiltRuleAssets(es);
|
||||
await deleteAllRules(supertest, log);
|
||||
});
|
||||
|
||||
it('should return empty structure when no rules package installed', async () => {
|
||||
const body = await getPrebuiltRulesAndTimelinesStatus(supertest);
|
||||
it('should return empty structure when no prebuilt rule assets', async () => {
|
||||
const { stats } = await getPrebuiltRulesStatus(supertest);
|
||||
expect(stats).toMatchObject({
|
||||
num_prebuilt_rules_installed: 0,
|
||||
num_prebuilt_rules_to_install: 0,
|
||||
num_prebuilt_rules_to_upgrade: 0,
|
||||
num_prebuilt_rules_total_in_package: 0,
|
||||
});
|
||||
});
|
||||
|
||||
expect(body).toMatchObject({
|
||||
rules_custom_installed: 0,
|
||||
rules_installed: 0,
|
||||
rules_not_installed: 0,
|
||||
rules_not_updated: 0,
|
||||
it('should not update the prebuilt rule status when a custom rule is added', async () => {
|
||||
await createRule(supertest, log, getSimpleRule());
|
||||
|
||||
const { stats } = await getPrebuiltRulesStatus(supertest);
|
||||
expect(stats).toMatchObject({
|
||||
num_prebuilt_rules_installed: 0,
|
||||
num_prebuilt_rules_to_install: 0,
|
||||
num_prebuilt_rules_to_upgrade: 0,
|
||||
num_prebuilt_rules_total_in_package: 0,
|
||||
});
|
||||
});
|
||||
|
||||
describe(`rule package without historical versions`, () => {
|
||||
const getRuleAssetSavedObjects = () => [
|
||||
createRuleAssetSavedObject({ rule_id: 'rule-1', version: 1 }),
|
||||
createRuleAssetSavedObject({ rule_id: 'rule-2', version: 2 }),
|
||||
createRuleAssetSavedObject({ rule_id: 'rule-3', version: 3 }),
|
||||
createRuleAssetSavedObject({ rule_id: 'rule-4', version: 4 }),
|
||||
];
|
||||
const RULES_COUNT = 4;
|
||||
|
||||
it('should return the number of rules available to install', async () => {
|
||||
await createPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects());
|
||||
const { stats } = await getPrebuiltRulesStatus(supertest);
|
||||
expect(stats).toMatchObject({
|
||||
num_prebuilt_rules_installed: 0,
|
||||
num_prebuilt_rules_to_install: RULES_COUNT,
|
||||
num_prebuilt_rules_to_upgrade: 0,
|
||||
num_prebuilt_rules_total_in_package: RULES_COUNT,
|
||||
});
|
||||
});
|
||||
|
||||
it('should return the number of installed prebuilt rules after installing them', async () => {
|
||||
await createPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects());
|
||||
await installPrebuiltRules(supertest);
|
||||
|
||||
const { stats } = await getPrebuiltRulesStatus(supertest);
|
||||
expect(stats).toMatchObject({
|
||||
num_prebuilt_rules_installed: RULES_COUNT,
|
||||
num_prebuilt_rules_to_install: 0,
|
||||
num_prebuilt_rules_to_upgrade: 0,
|
||||
num_prebuilt_rules_total_in_package: RULES_COUNT,
|
||||
});
|
||||
});
|
||||
|
||||
it('should notify the user again that a rule is available for install after it is deleted', async () => {
|
||||
await createPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects());
|
||||
await installPrebuiltRules(supertest);
|
||||
await deleteRule(supertest, 'rule-1');
|
||||
|
||||
const { stats } = await getPrebuiltRulesStatus(supertest);
|
||||
expect(stats).toMatchObject({
|
||||
num_prebuilt_rules_installed: RULES_COUNT - 1,
|
||||
num_prebuilt_rules_to_install: 1,
|
||||
num_prebuilt_rules_to_upgrade: 0,
|
||||
num_prebuilt_rules_total_in_package: RULES_COUNT,
|
||||
});
|
||||
});
|
||||
|
||||
it('should return available rule updates', async () => {
|
||||
const ruleAssetSavedObjects = getRuleAssetSavedObjects();
|
||||
await createPrebuiltRuleAssetSavedObjects(es, ruleAssetSavedObjects);
|
||||
await installPrebuiltRules(supertest);
|
||||
|
||||
// Clear previous rule assets
|
||||
await deleteAllPrebuiltRuleAssets(es);
|
||||
// Increment the version of one of the installed rules and create the new rule assets
|
||||
ruleAssetSavedObjects[0]['security-rule'].version += 1;
|
||||
await createPrebuiltRuleAssetSavedObjects(es, ruleAssetSavedObjects);
|
||||
|
||||
const { stats } = await getPrebuiltRulesStatus(supertest);
|
||||
expect(stats).toMatchObject({
|
||||
num_prebuilt_rules_installed: RULES_COUNT,
|
||||
num_prebuilt_rules_to_install: 0,
|
||||
num_prebuilt_rules_to_upgrade: 1,
|
||||
num_prebuilt_rules_total_in_package: RULES_COUNT,
|
||||
});
|
||||
});
|
||||
|
||||
it('should not return any available update if rule has been successfully upgraded', async () => {
|
||||
const ruleAssetSavedObjects = getRuleAssetSavedObjects();
|
||||
await createPrebuiltRuleAssetSavedObjects(es, ruleAssetSavedObjects);
|
||||
await installPrebuiltRules(supertest);
|
||||
|
||||
// Clear previous rule assets
|
||||
await deleteAllPrebuiltRuleAssets(es);
|
||||
// Increment the version of one of the installed rules and create the new rule assets
|
||||
ruleAssetSavedObjects[0]['security-rule'].version += 1;
|
||||
await createPrebuiltRuleAssetSavedObjects(es, ruleAssetSavedObjects);
|
||||
// Upgrade all rules
|
||||
await upgradePrebuiltRules(supertest);
|
||||
|
||||
const { stats } = await getPrebuiltRulesStatus(supertest);
|
||||
expect(stats).toMatchObject({
|
||||
num_prebuilt_rules_installed: RULES_COUNT,
|
||||
num_prebuilt_rules_to_install: 0,
|
||||
num_prebuilt_rules_to_upgrade: 0,
|
||||
num_prebuilt_rules_total_in_package: RULES_COUNT,
|
||||
});
|
||||
});
|
||||
|
||||
it('should not return any updates if none are available', async () => {
|
||||
const ruleAssetSavedObjects = getRuleAssetSavedObjects();
|
||||
await createPrebuiltRuleAssetSavedObjects(es, ruleAssetSavedObjects);
|
||||
await installPrebuiltRules(supertest);
|
||||
|
||||
// Clear previous rule assets
|
||||
await deleteAllPrebuiltRuleAssets(es);
|
||||
// Recreate the rules without bumping any versions
|
||||
await createPrebuiltRuleAssetSavedObjects(es, ruleAssetSavedObjects);
|
||||
|
||||
const { stats } = await getPrebuiltRulesStatus(supertest);
|
||||
expect(stats).toMatchObject({
|
||||
num_prebuilt_rules_installed: RULES_COUNT,
|
||||
num_prebuilt_rules_to_install: 0,
|
||||
num_prebuilt_rules_to_upgrade: 0,
|
||||
num_prebuilt_rules_total_in_package: RULES_COUNT,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe(`rule package with historical versions`, () => {
|
||||
const getRuleAssetSavedObjects = () => [
|
||||
createRuleAssetSavedObject({ rule_id: 'rule-1', version: 1 }),
|
||||
createRuleAssetSavedObject({ rule_id: 'rule-1', version: 2 }),
|
||||
createRuleAssetSavedObject({ rule_id: 'rule-2', version: 1 }),
|
||||
createRuleAssetSavedObject({ rule_id: 'rule-2', version: 2 }),
|
||||
createRuleAssetSavedObject({ rule_id: 'rule-2', version: 3 }),
|
||||
];
|
||||
const RULES_COUNT = 2;
|
||||
|
||||
it('should return the number of rules available to install', async () => {
|
||||
await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects());
|
||||
|
||||
const { stats } = await getPrebuiltRulesStatus(supertest);
|
||||
expect(stats).toMatchObject({
|
||||
num_prebuilt_rules_installed: 0,
|
||||
num_prebuilt_rules_to_install: RULES_COUNT,
|
||||
num_prebuilt_rules_to_upgrade: 0,
|
||||
num_prebuilt_rules_total_in_package: RULES_COUNT,
|
||||
});
|
||||
});
|
||||
|
||||
it('should return the number of installed prebuilt rules after installing them', async () => {
|
||||
await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects());
|
||||
await installPrebuiltRules(supertest);
|
||||
|
||||
const { stats } = await getPrebuiltRulesStatus(supertest);
|
||||
expect(stats).toMatchObject({
|
||||
num_prebuilt_rules_installed: RULES_COUNT,
|
||||
num_prebuilt_rules_to_install: 0,
|
||||
num_prebuilt_rules_to_upgrade: 0,
|
||||
num_prebuilt_rules_total_in_package: RULES_COUNT,
|
||||
});
|
||||
});
|
||||
|
||||
it('should notify the user again that a rule is available for install after it is deleted', async () => {
|
||||
await createPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects());
|
||||
await installPrebuiltRules(supertest);
|
||||
await deleteRule(supertest, 'rule-1');
|
||||
|
||||
const { stats } = await getPrebuiltRulesStatus(supertest);
|
||||
expect(stats).toMatchObject({
|
||||
num_prebuilt_rules_installed: RULES_COUNT - 1,
|
||||
num_prebuilt_rules_to_install: 1,
|
||||
num_prebuilt_rules_to_upgrade: 0,
|
||||
num_prebuilt_rules_total_in_package: RULES_COUNT,
|
||||
});
|
||||
});
|
||||
|
||||
it('should return available rule updates when previous historical versions available', async () => {
|
||||
await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects());
|
||||
await installPrebuiltRules(supertest);
|
||||
|
||||
// Add a new version of one of the installed rules
|
||||
await createHistoricalPrebuiltRuleAssetSavedObjects(es, [
|
||||
createRuleAssetSavedObject({ rule_id: 'rule-1', version: 3 }),
|
||||
]);
|
||||
|
||||
const { stats } = await getPrebuiltRulesStatus(supertest);
|
||||
expect(stats).toMatchObject({
|
||||
num_prebuilt_rules_installed: RULES_COUNT,
|
||||
num_prebuilt_rules_to_install: 0,
|
||||
num_prebuilt_rules_to_upgrade: 1,
|
||||
num_prebuilt_rules_total_in_package: RULES_COUNT,
|
||||
});
|
||||
});
|
||||
|
||||
it('should return available rule updates when previous historical versions unavailable', async () => {
|
||||
await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects());
|
||||
await installPrebuiltRules(supertest);
|
||||
|
||||
// Delete the previous versions of rule assets
|
||||
await deleteAllPrebuiltRuleAssets(es);
|
||||
|
||||
// Add a new rule version
|
||||
await createHistoricalPrebuiltRuleAssetSavedObjects(es, [
|
||||
createRuleAssetSavedObject({ rule_id: 'rule-1', version: 3 }),
|
||||
]);
|
||||
|
||||
const { stats } = await getPrebuiltRulesStatus(supertest);
|
||||
expect(stats).toMatchObject({
|
||||
num_prebuilt_rules_installed: RULES_COUNT,
|
||||
num_prebuilt_rules_to_install: 0,
|
||||
num_prebuilt_rules_to_upgrade: 1,
|
||||
// Two prebuilt rules have been installed, but only 1 rule asset
|
||||
// is made available after deleting the previous versions
|
||||
num_prebuilt_rules_total_in_package: 1,
|
||||
});
|
||||
});
|
||||
|
||||
it('should not return available rule updates after rule has been upgraded', async () => {
|
||||
await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects());
|
||||
await installPrebuiltRules(supertest);
|
||||
|
||||
// Delete the previous versions of rule assets
|
||||
await deleteAllPrebuiltRuleAssets(es);
|
||||
|
||||
// Add a new rule version
|
||||
await createHistoricalPrebuiltRuleAssetSavedObjects(es, [
|
||||
createRuleAssetSavedObject({ rule_id: 'rule-1', version: 3 }),
|
||||
]);
|
||||
|
||||
// Upgrade the rule
|
||||
await upgradePrebuiltRules(supertest);
|
||||
|
||||
const { stats } = await getPrebuiltRulesStatus(supertest);
|
||||
expect(stats).toMatchObject({
|
||||
num_prebuilt_rules_installed: RULES_COUNT,
|
||||
num_prebuilt_rules_to_install: 0,
|
||||
num_prebuilt_rules_to_upgrade: 0,
|
||||
// Two prebuilt rules have been installed, but only 1 rule asset
|
||||
// is made available after deleting the previous versions
|
||||
num_prebuilt_rules_total_in_package: 1,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should show that one custom rule is installed when a custom rule is added', async () => {
|
||||
await createRule(supertest, log, getSimpleRule());
|
||||
|
||||
const body = await getPrebuiltRulesAndTimelinesStatus(supertest);
|
||||
expect(body).toMatchObject({
|
||||
rules_custom_installed: 1,
|
||||
rules_installed: 0,
|
||||
rules_not_installed: 0,
|
||||
rules_not_updated: 0,
|
||||
describe('get_prebuilt_rules_status - legacy', () => {
|
||||
beforeEach(async () => {
|
||||
await deleteAllPrebuiltRuleAssets(es);
|
||||
await deleteAllRules(supertest, log);
|
||||
});
|
||||
});
|
||||
|
||||
describe(`rule package without historical versions`, () => {
|
||||
const getRuleAssetSavedObjects = () => [
|
||||
createRuleAssetSavedObject({ rule_id: 'rule-1', version: 1 }),
|
||||
createRuleAssetSavedObject({ rule_id: 'rule-2', version: 2 }),
|
||||
createRuleAssetSavedObject({ rule_id: 'rule-3', version: 3 }),
|
||||
createRuleAssetSavedObject({ rule_id: 'rule-4', version: 4 }),
|
||||
];
|
||||
const RULES_COUNT = 4;
|
||||
|
||||
it('should return the number of rules available to install', async () => {
|
||||
await createPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects());
|
||||
it('should return empty structure when no rules package installed', async () => {
|
||||
const body = await getPrebuiltRulesAndTimelinesStatus(supertest);
|
||||
|
||||
expect(body).toMatchObject({
|
||||
rules_custom_installed: 0,
|
||||
rules_installed: 0,
|
||||
rules_not_installed: RULES_COUNT,
|
||||
rules_not_updated: 0,
|
||||
});
|
||||
});
|
||||
|
||||
it('should return the number of installed prebuilt rules after installing them', async () => {
|
||||
await createPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects());
|
||||
await installPrebuiltRulesAndTimelines(supertest);
|
||||
|
||||
const body = await getPrebuiltRulesAndTimelinesStatus(supertest);
|
||||
expect(body).toMatchObject({
|
||||
rules_custom_installed: 0,
|
||||
rules_installed: RULES_COUNT,
|
||||
rules_not_installed: 0,
|
||||
rules_not_updated: 0,
|
||||
});
|
||||
});
|
||||
|
||||
it('should notify the user again that a rule is available for install after it is deleted', async () => {
|
||||
await createPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects());
|
||||
await installPrebuiltRulesAndTimelines(supertest);
|
||||
await deleteRule(supertest, 'rule-1');
|
||||
it('should show that one custom rule is installed when a custom rule is added', async () => {
|
||||
await createRule(supertest, log, getSimpleRule());
|
||||
|
||||
const body = await getPrebuiltRulesAndTimelinesStatus(supertest);
|
||||
expect(body).toMatchObject({
|
||||
rules_custom_installed: 0,
|
||||
rules_installed: RULES_COUNT - 1,
|
||||
rules_not_installed: 1,
|
||||
rules_not_updated: 0,
|
||||
});
|
||||
});
|
||||
|
||||
it('should return available rule updates', async () => {
|
||||
const ruleAssetSavedObjects = getRuleAssetSavedObjects();
|
||||
await createPrebuiltRuleAssetSavedObjects(es, ruleAssetSavedObjects);
|
||||
await installPrebuiltRulesAndTimelines(supertest);
|
||||
|
||||
// Clear previous rule assets
|
||||
await deleteAllPrebuiltRuleAssets(es);
|
||||
// Increment the version of one of the installed rules and create the new rule assets
|
||||
ruleAssetSavedObjects[0]['security-rule'].version += 1;
|
||||
await createPrebuiltRuleAssetSavedObjects(es, ruleAssetSavedObjects);
|
||||
|
||||
const body = await getPrebuiltRulesAndTimelinesStatus(supertest);
|
||||
expect(body).toMatchObject({
|
||||
rules_custom_installed: 0,
|
||||
rules_installed: RULES_COUNT,
|
||||
rules_not_installed: 0,
|
||||
rules_not_updated: 1,
|
||||
});
|
||||
});
|
||||
|
||||
it('should not return any updates if none are available', async () => {
|
||||
const ruleAssetSavedObjects = getRuleAssetSavedObjects();
|
||||
await createPrebuiltRuleAssetSavedObjects(es, ruleAssetSavedObjects);
|
||||
await installPrebuiltRulesAndTimelines(supertest);
|
||||
|
||||
// Clear previous rule assets
|
||||
await deleteAllPrebuiltRuleAssets(es);
|
||||
// Recreate the rules without bumping any versions
|
||||
await createPrebuiltRuleAssetSavedObjects(es, ruleAssetSavedObjects);
|
||||
|
||||
const body = await getPrebuiltRulesAndTimelinesStatus(supertest);
|
||||
expect(body).toMatchObject({
|
||||
rules_custom_installed: 0,
|
||||
rules_installed: RULES_COUNT,
|
||||
rules_not_installed: 0,
|
||||
rules_not_updated: 0,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe(`rule package with historical versions`, () => {
|
||||
const getRuleAssetSavedObjects = () => [
|
||||
createRuleAssetSavedObject({ rule_id: 'rule-1', version: 1 }),
|
||||
createRuleAssetSavedObject({ rule_id: 'rule-1', version: 2 }),
|
||||
createRuleAssetSavedObject({ rule_id: 'rule-2', version: 1 }),
|
||||
createRuleAssetSavedObject({ rule_id: 'rule-2', version: 2 }),
|
||||
createRuleAssetSavedObject({ rule_id: 'rule-2', version: 3 }),
|
||||
];
|
||||
const RULES_COUNT = 2;
|
||||
|
||||
it('should return the number of rules available to install', async () => {
|
||||
await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects());
|
||||
const body = await getPrebuiltRulesAndTimelinesStatus(supertest);
|
||||
|
||||
expect(body).toMatchObject({
|
||||
rules_custom_installed: 0,
|
||||
rules_custom_installed: 1,
|
||||
rules_installed: 0,
|
||||
rules_not_installed: RULES_COUNT,
|
||||
rules_not_updated: 0,
|
||||
});
|
||||
});
|
||||
|
||||
it('should return the number of installed prebuilt rules after installing them', async () => {
|
||||
await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects());
|
||||
await installPrebuiltRulesAndTimelines(supertest);
|
||||
|
||||
const body = await getPrebuiltRulesAndTimelinesStatus(supertest);
|
||||
expect(body).toMatchObject({
|
||||
rules_custom_installed: 0,
|
||||
rules_installed: RULES_COUNT,
|
||||
rules_not_installed: 0,
|
||||
rules_not_updated: 0,
|
||||
});
|
||||
});
|
||||
|
||||
it('should notify the user again that a rule is available for install after it is deleted', async () => {
|
||||
await createPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects());
|
||||
await installPrebuiltRulesAndTimelines(supertest);
|
||||
await deleteRule(supertest, 'rule-1');
|
||||
describe(`rule package without historical versions`, () => {
|
||||
const getRuleAssetSavedObjects = () => [
|
||||
createRuleAssetSavedObject({ rule_id: 'rule-1', version: 1 }),
|
||||
createRuleAssetSavedObject({ rule_id: 'rule-2', version: 2 }),
|
||||
createRuleAssetSavedObject({ rule_id: 'rule-3', version: 3 }),
|
||||
createRuleAssetSavedObject({ rule_id: 'rule-4', version: 4 }),
|
||||
];
|
||||
const RULES_COUNT = 4;
|
||||
|
||||
const body = await getPrebuiltRulesAndTimelinesStatus(supertest);
|
||||
expect(body).toMatchObject({
|
||||
rules_custom_installed: 0,
|
||||
rules_installed: RULES_COUNT - 1,
|
||||
rules_not_installed: 1,
|
||||
rules_not_updated: 0,
|
||||
it('should return the number of rules available to install', async () => {
|
||||
await createPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects());
|
||||
const body = await getPrebuiltRulesAndTimelinesStatus(supertest);
|
||||
|
||||
expect(body).toMatchObject({
|
||||
rules_custom_installed: 0,
|
||||
rules_installed: 0,
|
||||
rules_not_installed: RULES_COUNT,
|
||||
rules_not_updated: 0,
|
||||
});
|
||||
});
|
||||
|
||||
it('should return the number of installed prebuilt rules after installing them', async () => {
|
||||
await createPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects());
|
||||
await installPrebuiltRulesAndTimelines(supertest);
|
||||
|
||||
const body = await getPrebuiltRulesAndTimelinesStatus(supertest);
|
||||
expect(body).toMatchObject({
|
||||
rules_custom_installed: 0,
|
||||
rules_installed: RULES_COUNT,
|
||||
rules_not_installed: 0,
|
||||
rules_not_updated: 0,
|
||||
});
|
||||
});
|
||||
|
||||
it('should notify the user again that a rule is available for install after it is deleted', async () => {
|
||||
await createPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects());
|
||||
await installPrebuiltRulesAndTimelines(supertest);
|
||||
await deleteRule(supertest, 'rule-1');
|
||||
|
||||
const body = await getPrebuiltRulesAndTimelinesStatus(supertest);
|
||||
expect(body).toMatchObject({
|
||||
rules_custom_installed: 0,
|
||||
rules_installed: RULES_COUNT - 1,
|
||||
rules_not_installed: 1,
|
||||
rules_not_updated: 0,
|
||||
});
|
||||
});
|
||||
|
||||
it('should return available rule updates', async () => {
|
||||
const ruleAssetSavedObjects = getRuleAssetSavedObjects();
|
||||
await createPrebuiltRuleAssetSavedObjects(es, ruleAssetSavedObjects);
|
||||
await installPrebuiltRulesAndTimelines(supertest);
|
||||
|
||||
// Clear previous rule assets
|
||||
await deleteAllPrebuiltRuleAssets(es);
|
||||
// Increment the version of one of the installed rules and create the new rule assets
|
||||
ruleAssetSavedObjects[0]['security-rule'].version += 1;
|
||||
await createPrebuiltRuleAssetSavedObjects(es, ruleAssetSavedObjects);
|
||||
|
||||
const body = await getPrebuiltRulesAndTimelinesStatus(supertest);
|
||||
expect(body).toMatchObject({
|
||||
rules_custom_installed: 0,
|
||||
rules_installed: RULES_COUNT,
|
||||
rules_not_installed: 0,
|
||||
rules_not_updated: 1,
|
||||
});
|
||||
});
|
||||
|
||||
it('should not return any updates if none are available', async () => {
|
||||
const ruleAssetSavedObjects = getRuleAssetSavedObjects();
|
||||
await createPrebuiltRuleAssetSavedObjects(es, ruleAssetSavedObjects);
|
||||
await installPrebuiltRulesAndTimelines(supertest);
|
||||
|
||||
// Clear previous rule assets
|
||||
await deleteAllPrebuiltRuleAssets(es);
|
||||
// Recreate the rules without bumping any versions
|
||||
await createPrebuiltRuleAssetSavedObjects(es, ruleAssetSavedObjects);
|
||||
|
||||
const body = await getPrebuiltRulesAndTimelinesStatus(supertest);
|
||||
expect(body).toMatchObject({
|
||||
rules_custom_installed: 0,
|
||||
rules_installed: RULES_COUNT,
|
||||
rules_not_installed: 0,
|
||||
rules_not_updated: 0,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should return available rule updates when previous historical versions available', async () => {
|
||||
await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects());
|
||||
await installPrebuiltRulesAndTimelines(supertest);
|
||||
describe(`rule package with historical versions`, () => {
|
||||
const getRuleAssetSavedObjects = () => [
|
||||
createRuleAssetSavedObject({ rule_id: 'rule-1', version: 1 }),
|
||||
createRuleAssetSavedObject({ rule_id: 'rule-1', version: 2 }),
|
||||
createRuleAssetSavedObject({ rule_id: 'rule-2', version: 1 }),
|
||||
createRuleAssetSavedObject({ rule_id: 'rule-2', version: 2 }),
|
||||
createRuleAssetSavedObject({ rule_id: 'rule-2', version: 3 }),
|
||||
];
|
||||
const RULES_COUNT = 2;
|
||||
|
||||
// Add a new version of one of the installed rules
|
||||
await createHistoricalPrebuiltRuleAssetSavedObjects(es, [
|
||||
createRuleAssetSavedObject({ rule_id: 'rule-1', version: 3 }),
|
||||
]);
|
||||
it('should return the number of rules available to install', async () => {
|
||||
await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects());
|
||||
const body = await getPrebuiltRulesAndTimelinesStatus(supertest);
|
||||
|
||||
const body = await getPrebuiltRulesAndTimelinesStatus(supertest);
|
||||
expect(body).toMatchObject({
|
||||
rules_custom_installed: 0,
|
||||
rules_installed: RULES_COUNT,
|
||||
rules_not_installed: 0,
|
||||
rules_not_updated: 1,
|
||||
expect(body).toMatchObject({
|
||||
rules_custom_installed: 0,
|
||||
rules_installed: 0,
|
||||
rules_not_installed: RULES_COUNT,
|
||||
rules_not_updated: 0,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should return available rule updates when previous historical versions unavailable', async () => {
|
||||
await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects());
|
||||
await installPrebuiltRulesAndTimelines(supertest);
|
||||
it('should return the number of installed prebuilt rules after installing them', async () => {
|
||||
await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects());
|
||||
await installPrebuiltRulesAndTimelines(supertest);
|
||||
|
||||
// Delete the previous versions of rule assets
|
||||
await deleteAllPrebuiltRuleAssets(es);
|
||||
const body = await getPrebuiltRulesAndTimelinesStatus(supertest);
|
||||
expect(body).toMatchObject({
|
||||
rules_custom_installed: 0,
|
||||
rules_installed: RULES_COUNT,
|
||||
rules_not_installed: 0,
|
||||
rules_not_updated: 0,
|
||||
});
|
||||
});
|
||||
|
||||
// Add a new rule version
|
||||
await createHistoricalPrebuiltRuleAssetSavedObjects(es, [
|
||||
createRuleAssetSavedObject({ rule_id: 'rule-1', version: 3 }),
|
||||
]);
|
||||
it('should notify the user again that a rule is available for install after it is deleted', async () => {
|
||||
await createPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects());
|
||||
await installPrebuiltRulesAndTimelines(supertest);
|
||||
await deleteRule(supertest, 'rule-1');
|
||||
|
||||
const body = await getPrebuiltRulesAndTimelinesStatus(supertest);
|
||||
expect(body).toMatchObject({
|
||||
rules_custom_installed: 0,
|
||||
rules_installed: RULES_COUNT,
|
||||
rules_not_installed: 0,
|
||||
rules_not_updated: 1,
|
||||
const body = await getPrebuiltRulesAndTimelinesStatus(supertest);
|
||||
expect(body).toMatchObject({
|
||||
rules_custom_installed: 0,
|
||||
rules_installed: RULES_COUNT - 1,
|
||||
rules_not_installed: 1,
|
||||
rules_not_updated: 0,
|
||||
});
|
||||
});
|
||||
|
||||
it('should return available rule updates when previous historical versions available', async () => {
|
||||
await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects());
|
||||
await installPrebuiltRulesAndTimelines(supertest);
|
||||
|
||||
// Add a new version of one of the installed rules
|
||||
await createHistoricalPrebuiltRuleAssetSavedObjects(es, [
|
||||
createRuleAssetSavedObject({ rule_id: 'rule-1', version: 3 }),
|
||||
]);
|
||||
|
||||
const body = await getPrebuiltRulesAndTimelinesStatus(supertest);
|
||||
expect(body).toMatchObject({
|
||||
rules_custom_installed: 0,
|
||||
rules_installed: RULES_COUNT,
|
||||
rules_not_installed: 0,
|
||||
rules_not_updated: 1,
|
||||
});
|
||||
});
|
||||
|
||||
it('should return available rule updates when previous historical versions unavailable', async () => {
|
||||
await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects());
|
||||
await installPrebuiltRulesAndTimelines(supertest);
|
||||
|
||||
// Delete the previous versions of rule assets
|
||||
await deleteAllPrebuiltRuleAssets(es);
|
||||
|
||||
// Add a new rule version
|
||||
await createHistoricalPrebuiltRuleAssetSavedObjects(es, [
|
||||
createRuleAssetSavedObject({ rule_id: 'rule-1', version: 3 }),
|
||||
]);
|
||||
|
||||
const body = await getPrebuiltRulesAndTimelinesStatus(supertest);
|
||||
expect(body).toMatchObject({
|
||||
rules_custom_installed: 0,
|
||||
rules_installed: RULES_COUNT,
|
||||
rules_not_installed: 0,
|
||||
rules_not_updated: 1,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -12,7 +12,7 @@ export default ({ loadTestFile }: FtrProviderContext): void => {
|
|||
describe('detection engine api security and spaces enabled - Prebuilt Rules', function () {
|
||||
loadTestFile(require.resolve('./get_prebuilt_rules_status'));
|
||||
loadTestFile(require.resolve('./get_prebuilt_timelines_status'));
|
||||
loadTestFile(require.resolve('./install_prebuilt_rules'));
|
||||
loadTestFile(require.resolve('./install_and_upgrade_prebuilt_rules'));
|
||||
loadTestFile(require.resolve('./fleet_integration'));
|
||||
});
|
||||
};
|
||||
|
|
|
@ -0,0 +1,462 @@
|
|||
/*
|
||||
* 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 expect from 'expect';
|
||||
import { DETECTION_ENGINE_RULES_URL_FIND } from '@kbn/security-solution-plugin/common/constants';
|
||||
import { FtrProviderContext } from '../../common/ftr_provider_context';
|
||||
import {
|
||||
deleteAllRules,
|
||||
deleteAllTimelines,
|
||||
deleteRule,
|
||||
getPrebuiltRulesAndTimelinesStatus,
|
||||
} from '../../utils';
|
||||
import {
|
||||
createHistoricalPrebuiltRuleAssetSavedObjects,
|
||||
createPrebuiltRuleAssetSavedObjects,
|
||||
createRuleAssetSavedObject,
|
||||
} from '../../utils/prebuilt_rules/create_prebuilt_rule_saved_objects';
|
||||
import { deleteAllPrebuiltRuleAssets } from '../../utils/prebuilt_rules/delete_all_prebuilt_rule_assets';
|
||||
import { installPrebuiltRulesAndTimelines } from '../../utils/prebuilt_rules/install_prebuilt_rules_and_timelines';
|
||||
import { installPrebuiltRules } from '../../utils/prebuilt_rules/install_prebuilt_rules';
|
||||
import { getPrebuiltRulesStatus } from '../../utils/prebuilt_rules/get_prebuilt_rules_status';
|
||||
import { upgradePrebuiltRules } from '../../utils/prebuilt_rules/upgrade_prebuilt_rules';
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default ({ getService }: FtrProviderContext): void => {
|
||||
const es = getService('es');
|
||||
const supertest = getService('supertest');
|
||||
const log = getService('log');
|
||||
|
||||
describe('install and upgrade prebuilt rules with mock rule assets', () => {
|
||||
beforeEach(async () => {
|
||||
await deleteAllRules(supertest, log);
|
||||
await deleteAllTimelines(es);
|
||||
await deleteAllPrebuiltRuleAssets(es);
|
||||
});
|
||||
|
||||
describe(`rule package without historical versions`, () => {
|
||||
const getRuleAssetSavedObjects = () => [
|
||||
createRuleAssetSavedObject({ rule_id: 'rule-1', version: 1 }),
|
||||
createRuleAssetSavedObject({ rule_id: 'rule-2', version: 2 }),
|
||||
createRuleAssetSavedObject({ rule_id: 'rule-3', version: 3 }),
|
||||
createRuleAssetSavedObject({ rule_id: 'rule-4', version: 4 }),
|
||||
];
|
||||
const RULES_COUNT = 4;
|
||||
|
||||
describe('using legacy endpoint', () => {
|
||||
it('should install prebuilt rules', async () => {
|
||||
await createPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects());
|
||||
const body = await installPrebuiltRulesAndTimelines(supertest);
|
||||
|
||||
expect(body.rules_installed).toBe(RULES_COUNT);
|
||||
expect(body.rules_updated).toBe(0);
|
||||
});
|
||||
|
||||
it('should install correct prebuilt rule versions', async () => {
|
||||
await createPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects());
|
||||
await installPrebuiltRulesAndTimelines(supertest);
|
||||
|
||||
// Get installed rules
|
||||
const { body: rulesResponse } = await supertest
|
||||
.get(DETECTION_ENGINE_RULES_URL_FIND)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.send()
|
||||
.expect(200);
|
||||
|
||||
// Check that all prebuilt rules were actually installed and their versions match the latest
|
||||
expect(rulesResponse.total).toBe(RULES_COUNT);
|
||||
expect(rulesResponse.data).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({ rule_id: 'rule-1', version: 1 }),
|
||||
expect.objectContaining({ rule_id: 'rule-2', version: 2 }),
|
||||
expect.objectContaining({ rule_id: 'rule-3', version: 3 }),
|
||||
expect.objectContaining({ rule_id: 'rule-4', version: 4 }),
|
||||
])
|
||||
);
|
||||
});
|
||||
|
||||
it('should install missing prebuilt rules', async () => {
|
||||
// Install all prebuilt detection rules
|
||||
await createPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects());
|
||||
await installPrebuiltRulesAndTimelines(supertest);
|
||||
|
||||
// Delete one of the installed rules
|
||||
await deleteRule(supertest, 'rule-1');
|
||||
|
||||
// Check that one prebuilt rule is missing
|
||||
const statusResponse = await getPrebuiltRulesAndTimelinesStatus(supertest);
|
||||
expect(statusResponse.rules_not_installed).toBe(1);
|
||||
|
||||
// Call the install prebuilt rules again and check that the missing rule was installed
|
||||
const response = await installPrebuiltRulesAndTimelines(supertest);
|
||||
expect(response.rules_installed).toBe(1);
|
||||
expect(response.rules_updated).toBe(0);
|
||||
});
|
||||
|
||||
it('should update outdated prebuilt rules', async () => {
|
||||
// Install all prebuilt detection rules
|
||||
const ruleAssetSavedObjects = getRuleAssetSavedObjects();
|
||||
await createPrebuiltRuleAssetSavedObjects(es, ruleAssetSavedObjects);
|
||||
await installPrebuiltRulesAndTimelines(supertest);
|
||||
|
||||
// Clear previous rule assets
|
||||
await deleteAllPrebuiltRuleAssets(es);
|
||||
// Increment the version of one of the installed rules and create the new rule assets
|
||||
ruleAssetSavedObjects[0]['security-rule'].version += 1;
|
||||
await createPrebuiltRuleAssetSavedObjects(es, ruleAssetSavedObjects);
|
||||
|
||||
// Check that one prebuilt rule status shows that one rule is outdated
|
||||
const statusResponse = await getPrebuiltRulesAndTimelinesStatus(supertest);
|
||||
expect(statusResponse.rules_not_updated).toBe(1);
|
||||
|
||||
// Call the install prebuilt rules again and check that the outdated rule was updated
|
||||
const response = await installPrebuiltRulesAndTimelines(supertest);
|
||||
expect(response.rules_installed).toBe(0);
|
||||
expect(response.rules_updated).toBe(1);
|
||||
});
|
||||
|
||||
it('should not install prebuilt rules if they are up to date', async () => {
|
||||
// Install all prebuilt detection rules
|
||||
await createPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects());
|
||||
await installPrebuiltRulesAndTimelines(supertest);
|
||||
|
||||
// Check that all prebuilt rules were installed
|
||||
const statusResponse = await getPrebuiltRulesAndTimelinesStatus(supertest);
|
||||
expect(statusResponse.rules_not_installed).toBe(0);
|
||||
expect(statusResponse.rules_not_updated).toBe(0);
|
||||
|
||||
// Call the install prebuilt rules again and check that no rules were installed
|
||||
const response = await installPrebuiltRulesAndTimelines(supertest);
|
||||
expect(response.rules_installed).toBe(0);
|
||||
expect(response.rules_updated).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('using current endpoint', () => {
|
||||
it('should install prebuilt rules', async () => {
|
||||
await createPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects());
|
||||
const body = await installPrebuiltRules(supertest);
|
||||
|
||||
expect(body.summary.succeeded).toBe(RULES_COUNT);
|
||||
expect(body.summary.failed).toBe(0);
|
||||
expect(body.summary.skipped).toBe(0);
|
||||
});
|
||||
|
||||
it('should install correct prebuilt rule versions', async () => {
|
||||
await createPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects());
|
||||
const body = await installPrebuiltRules(supertest);
|
||||
|
||||
// Check that all prebuilt rules were actually installed and their versions match the latest
|
||||
expect(body.results.created).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({ rule_id: 'rule-1', version: 1 }),
|
||||
expect.objectContaining({ rule_id: 'rule-2', version: 2 }),
|
||||
expect.objectContaining({ rule_id: 'rule-3', version: 3 }),
|
||||
expect.objectContaining({ rule_id: 'rule-4', version: 4 }),
|
||||
])
|
||||
);
|
||||
});
|
||||
|
||||
it('should install missing prebuilt rules', async () => {
|
||||
// Install all prebuilt detection rules
|
||||
await createPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects());
|
||||
await installPrebuiltRules(supertest);
|
||||
|
||||
// Delete one of the installed rules
|
||||
await deleteRule(supertest, 'rule-1');
|
||||
|
||||
// Check that one prebuilt rule is missing
|
||||
const statusResponse = await getPrebuiltRulesStatus(supertest);
|
||||
expect(statusResponse.stats.num_prebuilt_rules_to_install).toBe(1);
|
||||
|
||||
// Call the install prebuilt rules again and check that the missing rule was installed
|
||||
const response = await installPrebuiltRules(supertest);
|
||||
expect(response.summary.succeeded).toBe(1);
|
||||
});
|
||||
|
||||
it('should update outdated prebuilt rules', async () => {
|
||||
// Install all prebuilt detection rules
|
||||
const ruleAssetSavedObjects = getRuleAssetSavedObjects();
|
||||
await createPrebuiltRuleAssetSavedObjects(es, ruleAssetSavedObjects);
|
||||
await installPrebuiltRules(supertest);
|
||||
|
||||
// Clear previous rule assets
|
||||
await deleteAllPrebuiltRuleAssets(es);
|
||||
// Increment the version of one of the installed rules and create the new rule assets
|
||||
ruleAssetSavedObjects[0]['security-rule'].version += 1;
|
||||
await createPrebuiltRuleAssetSavedObjects(es, ruleAssetSavedObjects);
|
||||
|
||||
// Check that one prebuilt rule status shows that one rule is outdated
|
||||
const statusResponse = await getPrebuiltRulesStatus(supertest);
|
||||
expect(statusResponse.stats.num_prebuilt_rules_to_install).toBe(0);
|
||||
expect(statusResponse.stats.num_prebuilt_rules_to_upgrade).toBe(1);
|
||||
|
||||
// Call the install prebuilt rules again and check that the outdated rule was updated
|
||||
const response = await upgradePrebuiltRules(supertest);
|
||||
expect(response.summary.succeeded).toBe(1);
|
||||
expect(response.summary.skipped).toBe(0);
|
||||
});
|
||||
|
||||
it('should not install prebuilt rules if they are up to date', async () => {
|
||||
// Install all prebuilt detection rules
|
||||
await createPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects());
|
||||
await installPrebuiltRules(supertest);
|
||||
|
||||
// Check that all prebuilt rules were installed
|
||||
const statusResponse = await getPrebuiltRulesStatus(supertest);
|
||||
expect(statusResponse.stats.num_prebuilt_rules_to_install).toBe(0);
|
||||
expect(statusResponse.stats.num_prebuilt_rules_to_upgrade).toBe(0);
|
||||
|
||||
// Call the install prebuilt rules again and check that no rules were installed
|
||||
const installResponse = await installPrebuiltRules(supertest);
|
||||
expect(installResponse.summary.succeeded).toBe(0);
|
||||
expect(installResponse.summary.skipped).toBe(0);
|
||||
|
||||
// Call the upgrade prebuilt rules endpoint and check that no rules were updated
|
||||
const upgradeResponse = await upgradePrebuiltRules(supertest);
|
||||
expect(upgradeResponse.summary.succeeded).toBe(0);
|
||||
expect(upgradeResponse.summary.skipped).toBe(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe(`rule package with historical versions`, () => {
|
||||
const getRuleAssetSavedObjects = () => [
|
||||
createRuleAssetSavedObject({ rule_id: 'rule-1', version: 1 }),
|
||||
createRuleAssetSavedObject({ rule_id: 'rule-1', version: 2 }),
|
||||
createRuleAssetSavedObject({ rule_id: 'rule-2', version: 1 }),
|
||||
createRuleAssetSavedObject({ rule_id: 'rule-2', version: 2 }),
|
||||
createRuleAssetSavedObject({ rule_id: 'rule-2', version: 3 }),
|
||||
];
|
||||
const RULES_COUNT = 2;
|
||||
|
||||
describe('using legacy endpoint', () => {
|
||||
it('should install prebuilt rules', async () => {
|
||||
await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects());
|
||||
const body = await installPrebuiltRulesAndTimelines(supertest);
|
||||
|
||||
expect(body.rules_installed).toBe(RULES_COUNT);
|
||||
expect(body.rules_updated).toBe(0);
|
||||
});
|
||||
|
||||
it('should install correct prebuilt rule versions', async () => {
|
||||
await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects());
|
||||
await installPrebuiltRulesAndTimelines(supertest);
|
||||
|
||||
// Get installed rules
|
||||
const { body: rulesResponse } = await supertest
|
||||
.get(DETECTION_ENGINE_RULES_URL_FIND)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.send()
|
||||
.expect(200);
|
||||
|
||||
// Check that all prebuilt rules were actually installed and their versions match the latest
|
||||
expect(rulesResponse.total).toBe(RULES_COUNT);
|
||||
expect(rulesResponse.data).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({ rule_id: 'rule-1', version: 2 }),
|
||||
expect.objectContaining({ rule_id: 'rule-2', version: 3 }),
|
||||
])
|
||||
);
|
||||
});
|
||||
|
||||
it('should not install prebuilt rules if they are up to date', async () => {
|
||||
// Install all prebuilt detection rules
|
||||
await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects());
|
||||
await installPrebuiltRulesAndTimelines(supertest);
|
||||
|
||||
// Check that all prebuilt rules were installed
|
||||
const statusResponse = await getPrebuiltRulesAndTimelinesStatus(supertest);
|
||||
expect(statusResponse.rules_not_installed).toBe(0);
|
||||
|
||||
// Call the install prebuilt rules again and check that no rules were installed
|
||||
const response = await installPrebuiltRulesAndTimelines(supertest);
|
||||
expect(response.rules_installed).toBe(0);
|
||||
expect(response.rules_updated).toBe(0);
|
||||
});
|
||||
|
||||
it('should install missing prebuilt rules', async () => {
|
||||
// Install all prebuilt detection rules
|
||||
await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects());
|
||||
await installPrebuiltRulesAndTimelines(supertest);
|
||||
|
||||
// Delete one of the installed rules
|
||||
await deleteRule(supertest, 'rule-1');
|
||||
|
||||
// Check that one prebuilt rule is missing
|
||||
const statusResponse = await getPrebuiltRulesAndTimelinesStatus(supertest);
|
||||
expect(statusResponse.rules_not_installed).toBe(1);
|
||||
|
||||
// Call the install prebuilt rules endpoint again and check that the missing rule was installed
|
||||
const response = await installPrebuiltRulesAndTimelines(supertest);
|
||||
expect(response.rules_installed).toBe(1);
|
||||
expect(response.rules_updated).toBe(0);
|
||||
});
|
||||
|
||||
it('should update outdated prebuilt rules when previous historical versions available', async () => {
|
||||
// Install all prebuilt detection rules
|
||||
await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects());
|
||||
await installPrebuiltRulesAndTimelines(supertest);
|
||||
|
||||
// Add a new version of one of the installed rules
|
||||
await createHistoricalPrebuiltRuleAssetSavedObjects(es, [
|
||||
createRuleAssetSavedObject({ rule_id: 'rule-1', version: 3 }),
|
||||
]);
|
||||
|
||||
// Check that one prebuilt rule status shows that one rule is outdated
|
||||
const statusResponse = await getPrebuiltRulesAndTimelinesStatus(supertest);
|
||||
expect(statusResponse.rules_not_updated).toBe(1);
|
||||
|
||||
// Call the install prebuilt rules again and check that the outdated rule was updated
|
||||
const response = await installPrebuiltRulesAndTimelines(supertest);
|
||||
expect(response.rules_installed).toBe(0);
|
||||
expect(response.rules_updated).toBe(1);
|
||||
|
||||
const _statusResponse = await getPrebuiltRulesAndTimelinesStatus(supertest);
|
||||
expect(_statusResponse.rules_not_installed).toBe(0);
|
||||
expect(_statusResponse.rules_not_updated).toBe(0);
|
||||
});
|
||||
|
||||
it('should update outdated prebuilt rules when previous historical versions unavailable', async () => {
|
||||
// Install all prebuilt detection rules
|
||||
await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects());
|
||||
await installPrebuiltRulesAndTimelines(supertest);
|
||||
|
||||
// Clear previous rule assets
|
||||
await deleteAllPrebuiltRuleAssets(es);
|
||||
|
||||
// Add a new rule version
|
||||
await createHistoricalPrebuiltRuleAssetSavedObjects(es, [
|
||||
createRuleAssetSavedObject({ rule_id: 'rule-1', version: 3 }),
|
||||
]);
|
||||
|
||||
// Check that one prebuilt rule status shows that one rule is outdated
|
||||
const statusResponse = await getPrebuiltRulesAndTimelinesStatus(supertest);
|
||||
expect(statusResponse.rules_not_updated).toBe(1);
|
||||
expect(statusResponse.rules_not_installed).toBe(0);
|
||||
|
||||
// Call the install prebuilt rules again and check that the outdated rule was updated
|
||||
const response = await installPrebuiltRulesAndTimelines(supertest);
|
||||
expect(response.rules_installed).toBe(0);
|
||||
expect(response.rules_updated).toBe(1);
|
||||
|
||||
const _statusResponse = await getPrebuiltRulesAndTimelinesStatus(supertest);
|
||||
expect(_statusResponse.rules_not_updated).toBe(0);
|
||||
expect(_statusResponse.rules_not_installed).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('using current endpoint', () => {
|
||||
it('should install prebuilt rules', async () => {
|
||||
await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects());
|
||||
const body = await installPrebuiltRules(supertest);
|
||||
|
||||
expect(body.summary.succeeded).toBe(RULES_COUNT);
|
||||
});
|
||||
|
||||
it('should install correct prebuilt rule versions', async () => {
|
||||
await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects());
|
||||
const response = await installPrebuiltRules(supertest);
|
||||
|
||||
// Check that all prebuilt rules were actually installed and their versions match the latest
|
||||
expect(response.summary.succeeded).toBe(RULES_COUNT);
|
||||
expect(response.results.created).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({ rule_id: 'rule-1', version: 2 }),
|
||||
expect.objectContaining({ rule_id: 'rule-2', version: 3 }),
|
||||
])
|
||||
);
|
||||
});
|
||||
|
||||
it('should not install prebuilt rules if they are up to date', async () => {
|
||||
// Install all prebuilt detection rules
|
||||
await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects());
|
||||
await installPrebuiltRules(supertest);
|
||||
|
||||
// Check that all prebuilt rules were installed
|
||||
const statusResponse = await getPrebuiltRulesStatus(supertest);
|
||||
expect(statusResponse.stats.num_prebuilt_rules_to_install).toBe(0);
|
||||
|
||||
// Call the install prebuilt rules again and check that no rules were installed
|
||||
const response = await installPrebuiltRules(supertest);
|
||||
expect(response.summary.succeeded).toBe(0);
|
||||
expect(response.summary.total).toBe(0);
|
||||
});
|
||||
|
||||
it('should install missing prebuilt rules', async () => {
|
||||
// Install all prebuilt detection rules
|
||||
await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects());
|
||||
await installPrebuiltRules(supertest);
|
||||
|
||||
// Delete one of the installed rules
|
||||
await deleteRule(supertest, 'rule-1');
|
||||
|
||||
// Check that one prebuilt rule is missing
|
||||
const statusResponse = await getPrebuiltRulesStatus(supertest);
|
||||
expect(statusResponse.stats.num_prebuilt_rules_to_install).toBe(1);
|
||||
|
||||
// Call the install prebuilt rules endpoint again and check that the missing rule was installed
|
||||
const response = await installPrebuiltRules(supertest);
|
||||
expect(response.summary.succeeded).toBe(1);
|
||||
expect(response.summary.total).toBe(1);
|
||||
});
|
||||
|
||||
it('should update outdated prebuilt rules when previous historical versions available', async () => {
|
||||
// Install all prebuilt detection rules
|
||||
await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects());
|
||||
await installPrebuiltRules(supertest);
|
||||
|
||||
// Add a new version of one of the installed rules
|
||||
await createHistoricalPrebuiltRuleAssetSavedObjects(es, [
|
||||
createRuleAssetSavedObject({ rule_id: 'rule-1', version: 3 }),
|
||||
]);
|
||||
|
||||
// Check that the prebuilt rule status shows that one rule is outdated
|
||||
const statusResponse = await getPrebuiltRulesStatus(supertest);
|
||||
expect(statusResponse.stats.num_prebuilt_rules_to_upgrade).toBe(1);
|
||||
|
||||
// Call the upgrade prebuilt rules endpoint and check that the outdated rule was updated
|
||||
const response = await upgradePrebuiltRules(supertest);
|
||||
expect(response.summary.succeeded).toBe(1);
|
||||
expect(response.summary.total).toBe(1);
|
||||
|
||||
const status = await getPrebuiltRulesStatus(supertest);
|
||||
expect(status.stats.num_prebuilt_rules_to_install).toBe(0);
|
||||
expect(status.stats.num_prebuilt_rules_to_upgrade).toBe(0);
|
||||
});
|
||||
|
||||
it('should update outdated prebuilt rules when previous historical versions unavailable', async () => {
|
||||
// Install all prebuilt detection rules
|
||||
await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects());
|
||||
await installPrebuiltRules(supertest);
|
||||
|
||||
// Clear previous rule assets
|
||||
await deleteAllPrebuiltRuleAssets(es);
|
||||
|
||||
// Add a new rule version
|
||||
await createHistoricalPrebuiltRuleAssetSavedObjects(es, [
|
||||
createRuleAssetSavedObject({ rule_id: 'rule-1', version: 3 }),
|
||||
]);
|
||||
|
||||
// Check that the prebuilt rule status shows that one rule is outdated
|
||||
const statusResponse = await getPrebuiltRulesStatus(supertest);
|
||||
expect(statusResponse.stats.num_prebuilt_rules_to_upgrade).toBe(1);
|
||||
expect(statusResponse.stats.num_prebuilt_rules_to_install).toBe(0);
|
||||
|
||||
// Call the upgrade prebuilt rules endpoint and check that the outdated rule was updated
|
||||
const response = await upgradePrebuiltRules(supertest);
|
||||
expect(response.summary.succeeded).toBe(1);
|
||||
expect(response.summary.total).toBe(1);
|
||||
|
||||
const status = await getPrebuiltRulesStatus(supertest);
|
||||
expect(status.stats.num_prebuilt_rules_to_install).toBe(0);
|
||||
expect(status.stats.num_prebuilt_rules_to_upgrade).toBe(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
|
@ -1,250 +0,0 @@
|
|||
/*
|
||||
* 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 expect from 'expect';
|
||||
import { DETECTION_ENGINE_RULES_URL_FIND } from '@kbn/security-solution-plugin/common/constants';
|
||||
import { FtrProviderContext } from '../../common/ftr_provider_context';
|
||||
import {
|
||||
deleteAllRules,
|
||||
deleteAllTimelines,
|
||||
deleteRule,
|
||||
getPrebuiltRulesAndTimelinesStatus,
|
||||
} from '../../utils';
|
||||
import {
|
||||
createHistoricalPrebuiltRuleAssetSavedObjects,
|
||||
createPrebuiltRuleAssetSavedObjects,
|
||||
createRuleAssetSavedObject,
|
||||
} from '../../utils/prebuilt_rules/create_prebuilt_rule_saved_objects';
|
||||
import { deleteAllPrebuiltRuleAssets } from '../../utils/prebuilt_rules/delete_all_prebuilt_rule_assets';
|
||||
import { installPrebuiltRulesAndTimelines } from '../../utils/prebuilt_rules/install_prebuilt_rules_and_timelines';
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default ({ getService }: FtrProviderContext): void => {
|
||||
const es = getService('es');
|
||||
const supertest = getService('supertest');
|
||||
const log = getService('log');
|
||||
|
||||
describe('install_prebuilt_rules_from_mock_assets', () => {
|
||||
beforeEach(async () => {
|
||||
await deleteAllRules(supertest, log);
|
||||
await deleteAllTimelines(es);
|
||||
await deleteAllPrebuiltRuleAssets(es);
|
||||
});
|
||||
|
||||
describe(`rule package without historical versions`, () => {
|
||||
const getRuleAssetSavedObjects = () => [
|
||||
createRuleAssetSavedObject({ rule_id: 'rule-1', version: 1 }),
|
||||
createRuleAssetSavedObject({ rule_id: 'rule-2', version: 2 }),
|
||||
createRuleAssetSavedObject({ rule_id: 'rule-3', version: 3 }),
|
||||
createRuleAssetSavedObject({ rule_id: 'rule-4', version: 4 }),
|
||||
];
|
||||
const RULES_COUNT = 4;
|
||||
|
||||
it('should install prebuilt rules', async () => {
|
||||
await createPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects());
|
||||
const body = await installPrebuiltRulesAndTimelines(supertest);
|
||||
|
||||
expect(body.rules_installed).toBe(RULES_COUNT);
|
||||
expect(body.rules_updated).toBe(0);
|
||||
});
|
||||
|
||||
it('should install correct prebuilt rule versions', async () => {
|
||||
await createPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects());
|
||||
await installPrebuiltRulesAndTimelines(supertest);
|
||||
|
||||
// Get installed rules
|
||||
const { body: rulesResponse } = await supertest
|
||||
.get(DETECTION_ENGINE_RULES_URL_FIND)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.send()
|
||||
.expect(200);
|
||||
|
||||
// Check that all prebuilt rules were actually installed and their versions match the latest
|
||||
expect(rulesResponse.total).toBe(RULES_COUNT);
|
||||
expect(rulesResponse.data).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({ rule_id: 'rule-1', version: 1 }),
|
||||
expect.objectContaining({ rule_id: 'rule-2', version: 2 }),
|
||||
expect.objectContaining({ rule_id: 'rule-3', version: 3 }),
|
||||
expect.objectContaining({ rule_id: 'rule-4', version: 4 }),
|
||||
])
|
||||
);
|
||||
});
|
||||
|
||||
it('should not install prebuilt rules if they are up to date', async () => {
|
||||
// Install all prebuilt detection rules
|
||||
await createPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects());
|
||||
await installPrebuiltRulesAndTimelines(supertest);
|
||||
|
||||
// Check that all prebuilt rules were installed
|
||||
const statusResponse = await getPrebuiltRulesAndTimelinesStatus(supertest);
|
||||
expect(statusResponse.rules_not_installed).toBe(0);
|
||||
|
||||
// Call the install prebuilt rules again and check that no rules were installed
|
||||
const response = await installPrebuiltRulesAndTimelines(supertest);
|
||||
expect(response.rules_installed).toBe(0);
|
||||
expect(response.rules_updated).toBe(0);
|
||||
});
|
||||
|
||||
it('should install missing prebuilt rules', async () => {
|
||||
// Install all prebuilt detection rules
|
||||
await createPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects());
|
||||
await installPrebuiltRulesAndTimelines(supertest);
|
||||
|
||||
// Delete one of the installed rules
|
||||
await deleteRule(supertest, 'rule-1');
|
||||
|
||||
// Check that one prebuilt rule is missing
|
||||
const statusResponse = await getPrebuiltRulesAndTimelinesStatus(supertest);
|
||||
expect(statusResponse.rules_not_installed).toBe(1);
|
||||
|
||||
// Call the install prebuilt rules again and check that the missing rule was installed
|
||||
const response = await installPrebuiltRulesAndTimelines(supertest);
|
||||
expect(response.rules_installed).toBe(1);
|
||||
expect(response.rules_updated).toBe(0);
|
||||
});
|
||||
|
||||
it('should update outdated prebuilt rules', async () => {
|
||||
// Install all prebuilt detection rules
|
||||
const ruleAssetSavedObjects = getRuleAssetSavedObjects();
|
||||
await createPrebuiltRuleAssetSavedObjects(es, ruleAssetSavedObjects);
|
||||
await installPrebuiltRulesAndTimelines(supertest);
|
||||
|
||||
// Clear previous rule assets
|
||||
await deleteAllPrebuiltRuleAssets(es);
|
||||
// Increment the version of one of the installed rules and create the new rule assets
|
||||
ruleAssetSavedObjects[0]['security-rule'].version += 1;
|
||||
await createPrebuiltRuleAssetSavedObjects(es, ruleAssetSavedObjects);
|
||||
|
||||
// Check that one prebuilt rule status shows that one rule is outdated
|
||||
const statusResponse = await getPrebuiltRulesAndTimelinesStatus(supertest);
|
||||
expect(statusResponse.rules_not_updated).toBe(1);
|
||||
|
||||
// Call the install prebuilt rules again and check that the outdated rule was updated
|
||||
const response = await installPrebuiltRulesAndTimelines(supertest);
|
||||
expect(response.rules_installed).toBe(0);
|
||||
expect(response.rules_updated).toBe(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe(`rule package with historical versions`, () => {
|
||||
const getRuleAssetSavedObjects = () => [
|
||||
createRuleAssetSavedObject({ rule_id: 'rule-1', version: 1 }),
|
||||
createRuleAssetSavedObject({ rule_id: 'rule-1', version: 2 }),
|
||||
createRuleAssetSavedObject({ rule_id: 'rule-2', version: 1 }),
|
||||
createRuleAssetSavedObject({ rule_id: 'rule-2', version: 2 }),
|
||||
createRuleAssetSavedObject({ rule_id: 'rule-2', version: 3 }),
|
||||
];
|
||||
const RULES_COUNT = 2;
|
||||
|
||||
it('should install prebuilt rules', async () => {
|
||||
await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects());
|
||||
const body = await installPrebuiltRulesAndTimelines(supertest);
|
||||
|
||||
expect(body.rules_installed).toBe(RULES_COUNT);
|
||||
expect(body.rules_updated).toBe(0);
|
||||
});
|
||||
|
||||
it('should install correct prebuilt rule versions', async () => {
|
||||
await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects());
|
||||
await installPrebuiltRulesAndTimelines(supertest);
|
||||
|
||||
// Get installed rules
|
||||
const { body: rulesResponse } = await supertest
|
||||
.get(DETECTION_ENGINE_RULES_URL_FIND)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.send()
|
||||
.expect(200);
|
||||
|
||||
// Check that all prebuilt rules were actually installed and their versions match the latest
|
||||
expect(rulesResponse.total).toBe(RULES_COUNT);
|
||||
expect(rulesResponse.data).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({ rule_id: 'rule-1', version: 2 }),
|
||||
expect.objectContaining({ rule_id: 'rule-2', version: 3 }),
|
||||
])
|
||||
);
|
||||
});
|
||||
|
||||
it('should not install prebuilt rules if they are up to date', async () => {
|
||||
// Install all prebuilt detection rules
|
||||
await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects());
|
||||
await installPrebuiltRulesAndTimelines(supertest);
|
||||
|
||||
// Check that all prebuilt rules were installed
|
||||
const statusResponse = await getPrebuiltRulesAndTimelinesStatus(supertest);
|
||||
expect(statusResponse.rules_not_installed).toBe(0);
|
||||
|
||||
// Call the install prebuilt rules again and check that no rules were installed
|
||||
const response = await installPrebuiltRulesAndTimelines(supertest);
|
||||
expect(response.rules_installed).toBe(0);
|
||||
expect(response.rules_updated).toBe(0);
|
||||
});
|
||||
|
||||
it('should install missing prebuilt rules', async () => {
|
||||
// Install all prebuilt detection rules
|
||||
await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects());
|
||||
await installPrebuiltRulesAndTimelines(supertest);
|
||||
|
||||
// Delete one of the installed rules
|
||||
await deleteRule(supertest, 'rule-1');
|
||||
|
||||
// Check that one prebuilt rule is missing
|
||||
const statusResponse = await getPrebuiltRulesAndTimelinesStatus(supertest);
|
||||
expect(statusResponse.rules_not_installed).toBe(1);
|
||||
|
||||
// Call the install prebuilt rules again and check that the missing rule was installed
|
||||
const response = await installPrebuiltRulesAndTimelines(supertest);
|
||||
expect(response.rules_installed).toBe(1);
|
||||
expect(response.rules_updated).toBe(0);
|
||||
});
|
||||
|
||||
it('should update outdated prebuilt rules when previous historical versions available', async () => {
|
||||
// Install all prebuilt detection rules
|
||||
await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects());
|
||||
await installPrebuiltRulesAndTimelines(supertest);
|
||||
|
||||
// Add a new version of one of the installed rules
|
||||
await createHistoricalPrebuiltRuleAssetSavedObjects(es, [
|
||||
createRuleAssetSavedObject({ rule_id: 'rule-1', version: 3 }),
|
||||
]);
|
||||
|
||||
// Check that one prebuilt rule status shows that one rule is outdated
|
||||
const statusResponse = await getPrebuiltRulesAndTimelinesStatus(supertest);
|
||||
expect(statusResponse.rules_not_updated).toBe(1);
|
||||
|
||||
// Call the install prebuilt rules again and check that the outdated rule was updated
|
||||
const response = await installPrebuiltRulesAndTimelines(supertest);
|
||||
expect(response.rules_installed).toBe(0);
|
||||
expect(response.rules_updated).toBe(1);
|
||||
});
|
||||
|
||||
it('should update outdated prebuilt rules when previous historical versions unavailable', async () => {
|
||||
// Install all prebuilt detection rules
|
||||
await createHistoricalPrebuiltRuleAssetSavedObjects(es, getRuleAssetSavedObjects());
|
||||
await installPrebuiltRulesAndTimelines(supertest);
|
||||
|
||||
// Clear previous rule assets
|
||||
await deleteAllPrebuiltRuleAssets(es);
|
||||
|
||||
// Add a new rule version
|
||||
await createHistoricalPrebuiltRuleAssetSavedObjects(es, [
|
||||
createRuleAssetSavedObject({ rule_id: 'rule-1', version: 3 }),
|
||||
]);
|
||||
|
||||
// Check that one prebuilt rule status shows that one rule is outdated
|
||||
const statusResponse = await getPrebuiltRulesAndTimelinesStatus(supertest);
|
||||
expect(statusResponse.rules_not_updated).toBe(1);
|
||||
|
||||
// Call the install prebuilt rules again and check that the outdated rule was updated
|
||||
const response = await installPrebuiltRulesAndTimelines(supertest);
|
||||
expect(response.rules_installed).toBe(0);
|
||||
expect(response.rules_updated).toBe(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* 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 { FtrConfigProviderContext } from '@kbn/test';
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default async function ({ readConfigFile }: FtrConfigProviderContext) {
|
||||
const functionalConfig = await readConfigFile(require.resolve('../config.base.ts'));
|
||||
|
||||
return {
|
||||
...functionalConfig.getAll(),
|
||||
testFiles: [require.resolve('./update_prebuilt_rules_package.ts')],
|
||||
};
|
||||
}
|
|
@ -0,0 +1,274 @@
|
|||
/*
|
||||
* 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 fs from 'fs/promises';
|
||||
import path from 'path';
|
||||
import getMajorVersion from 'semver/functions/major';
|
||||
import getMinorVersion from 'semver/functions/minor';
|
||||
// @ts-expect-error we have to check types with "allowJs: false" for now, causing this import to fail
|
||||
import { REPO_ROOT } from '@kbn/repo-info';
|
||||
import JSON5 from 'json5';
|
||||
import expect from 'expect';
|
||||
import { PackageSpecManifest } from '@kbn/fleet-plugin/common';
|
||||
import { DETECTION_ENGINE_RULES_URL_FIND } from '@kbn/security-solution-plugin/common/constants';
|
||||
import { FtrProviderContext } from '../../common/ftr_provider_context';
|
||||
import {
|
||||
deleteAllPrebuiltRuleAssets,
|
||||
deleteAllRules,
|
||||
getPrebuiltRulesStatus,
|
||||
installPrebuiltRules,
|
||||
upgradePrebuiltRules,
|
||||
} from '../../utils';
|
||||
import { reviewPrebuiltRulesToInstall } from '../../utils/prebuilt_rules/review_install_prebuilt_rules';
|
||||
import { reviewPrebuiltRulesToUpgrade } from '../../utils/prebuilt_rules/review_upgrade_prebuilt_rules';
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default ({ getService }: FtrProviderContext): void => {
|
||||
const es = getService('es');
|
||||
const supertest = getService('supertest');
|
||||
const log = getService('log');
|
||||
|
||||
let currentVersion: string;
|
||||
let previousVersion: string;
|
||||
|
||||
/*
|
||||
* Recursively query the Fleet EPM API to find the latest GA patch
|
||||
* version of the previous minor version of the current package
|
||||
*/
|
||||
const getPreviousMinorGAVersion = async (
|
||||
majorVersion: number,
|
||||
minorVersion: number,
|
||||
patchVersion: number
|
||||
): Promise<string> => {
|
||||
// Failsafe check to prevent infinite recursion in case no GA
|
||||
// patch version is published for the previous minor version
|
||||
if (patchVersion > 15) {
|
||||
throw new Error('Unable to find previous minor GA version');
|
||||
}
|
||||
const EPM_URL = `/api/fleet/epm/packages/security_detection_engine/${majorVersion}.${minorVersion}.${patchVersion}`;
|
||||
|
||||
const getPackageResponse = await supertest
|
||||
.get(EPM_URL)
|
||||
.set('kbn-xsrf', 'xxxx')
|
||||
.type('application/json')
|
||||
.send({ force: true });
|
||||
|
||||
if (getPackageResponse.status !== 200 || getPackageResponse.body?.item.release !== 'ga') {
|
||||
return getPreviousMinorGAVersion(majorVersion, minorVersion, patchVersion + 1);
|
||||
}
|
||||
return getPackageResponse.body.item.version ?? '';
|
||||
};
|
||||
|
||||
describe('update_prebuilt_rules_package', () => {
|
||||
before(async () => {
|
||||
const configFilePath = path.resolve(REPO_ROOT, 'fleet_packages.json');
|
||||
const fleetPackages = await fs.readFile(configFilePath, 'utf8');
|
||||
|
||||
const parsedFleetPackages: PackageSpecManifest[] = JSON5.parse(fleetPackages);
|
||||
|
||||
const securityDetectionEnginePackage = parsedFleetPackages.find(
|
||||
(fleetPackage) => fleetPackage.name === 'security_detection_engine'
|
||||
);
|
||||
|
||||
currentVersion = securityDetectionEnginePackage?.version ?? '';
|
||||
|
||||
const majorVersion = getMajorVersion(currentVersion);
|
||||
const minorVersion = getMinorVersion(currentVersion);
|
||||
|
||||
expect(securityDetectionEnginePackage).not.toBeUndefined();
|
||||
|
||||
try {
|
||||
previousVersion = await getPreviousMinorGAVersion(majorVersion, minorVersion - 1, 0);
|
||||
} catch (error) {
|
||||
// If no previous minor GA version is found, carry out test with existing current version
|
||||
previousVersion = currentVersion;
|
||||
}
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
await deleteAllRules(supertest, log);
|
||||
await deleteAllPrebuiltRuleAssets(es);
|
||||
});
|
||||
|
||||
it('should allow user to install prebuilt rules from scratch, then install new rules and upgrade existing rules from the new package', async () => {
|
||||
// PART 1: Install prebuilt rules from the previous minor version as the current version
|
||||
|
||||
// Verify that status is empty before package installation
|
||||
const statusBeforePackageInstallation = await getPrebuiltRulesStatus(supertest);
|
||||
expect(statusBeforePackageInstallation.stats.num_prebuilt_rules_installed).toBe(0);
|
||||
expect(statusBeforePackageInstallation.stats.num_prebuilt_rules_to_install).toBe(0);
|
||||
expect(statusBeforePackageInstallation.stats.num_prebuilt_rules_to_upgrade).toBe(0);
|
||||
expect(statusBeforePackageInstallation.stats.num_prebuilt_rules_total_in_package).toBe(0);
|
||||
|
||||
const EPM_URL_FOR_PREVIOUS_VERSION = `/api/fleet/epm/packages/security_detection_engine/${previousVersion}`;
|
||||
|
||||
const installPreviousPackageResponse = await supertest
|
||||
.post(EPM_URL_FOR_PREVIOUS_VERSION)
|
||||
.set('kbn-xsrf', 'xxxx')
|
||||
.type('application/json')
|
||||
.send({ force: true })
|
||||
.expect(200);
|
||||
|
||||
expect(installPreviousPackageResponse.body._meta.install_source).toBe('registry');
|
||||
expect(installPreviousPackageResponse.body.items.length).toBeGreaterThan(0);
|
||||
|
||||
// Verify that status is updated after the installation of package "N-1"
|
||||
const statusAfterPackageInstallation = await getPrebuiltRulesStatus(supertest);
|
||||
expect(statusAfterPackageInstallation.stats.num_prebuilt_rules_installed).toBe(0);
|
||||
expect(statusAfterPackageInstallation.stats.num_prebuilt_rules_to_install).toBeGreaterThan(0);
|
||||
expect(statusAfterPackageInstallation.stats.num_prebuilt_rules_to_upgrade).toBe(0);
|
||||
expect(
|
||||
statusAfterPackageInstallation.stats.num_prebuilt_rules_total_in_package
|
||||
).toBeGreaterThan(0);
|
||||
|
||||
// Verify that _review endpoint returns the same number of rules to install as the status endpoint
|
||||
const prebuiltRulesToInstallReview = await reviewPrebuiltRulesToInstall(supertest);
|
||||
expect(prebuiltRulesToInstallReview.stats.num_rules_to_install).toBe(
|
||||
statusAfterPackageInstallation.stats.num_prebuilt_rules_to_install
|
||||
);
|
||||
|
||||
// Verify that the _perform endpoint returns the same number of installed rules as the status endpoint
|
||||
// and the _review endpoint
|
||||
const installPrebuiltRulesResponse = await installPrebuiltRules(supertest);
|
||||
expect(installPrebuiltRulesResponse.summary.succeeded).toBe(
|
||||
statusAfterPackageInstallation.stats.num_prebuilt_rules_to_install
|
||||
);
|
||||
expect(installPrebuiltRulesResponse.summary.succeeded).toBe(
|
||||
prebuiltRulesToInstallReview.stats.num_rules_to_install
|
||||
);
|
||||
|
||||
// Get installed rules
|
||||
const { body: rulesResponse } = await supertest
|
||||
.get(`${DETECTION_ENGINE_RULES_URL_FIND}?per_page=10000`)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.send()
|
||||
.expect(200);
|
||||
|
||||
// Check that all prebuilt rules were actually installed
|
||||
expect(rulesResponse.total).toBe(installPrebuiltRulesResponse.summary.succeeded);
|
||||
expect(
|
||||
installPrebuiltRulesResponse.results.created.map((rule: { rule_id: string }) => ({
|
||||
rule_id: rule.rule_id,
|
||||
}))
|
||||
).toEqual(
|
||||
expect.arrayContaining(
|
||||
rulesResponse.data.map((rule: { rule_id: string }) => ({ rule_id: rule.rule_id }))
|
||||
)
|
||||
);
|
||||
|
||||
// PART 2: Now install the lastest (current) package, defined in fleet_packages.json
|
||||
const EPM_URL_FOR_CURRENT_VERSION = `/api/fleet/epm/packages/security_detection_engine/${currentVersion}`;
|
||||
|
||||
const installLatestPackageResponse = await supertest
|
||||
.post(EPM_URL_FOR_CURRENT_VERSION)
|
||||
.set('kbn-xsrf', 'xxxx')
|
||||
.type('application/json')
|
||||
.send({ force: true })
|
||||
.expect(200);
|
||||
|
||||
expect(installLatestPackageResponse.body.items.length).toBeGreaterThanOrEqual(0);
|
||||
|
||||
// Verify status after intallation of the latest package
|
||||
const statusAfterLatestPackageInstallation = await getPrebuiltRulesStatus(supertest);
|
||||
expect(
|
||||
statusAfterLatestPackageInstallation.stats.num_prebuilt_rules_installed
|
||||
).toBeGreaterThan(0);
|
||||
expect(
|
||||
statusAfterLatestPackageInstallation.stats.num_prebuilt_rules_to_install
|
||||
).toBeGreaterThanOrEqual(0);
|
||||
expect(
|
||||
statusAfterLatestPackageInstallation.stats.num_prebuilt_rules_to_upgrade
|
||||
).toBeGreaterThanOrEqual(0);
|
||||
expect(
|
||||
statusAfterLatestPackageInstallation.stats.num_prebuilt_rules_total_in_package
|
||||
).toBeGreaterThan(0);
|
||||
|
||||
// Verify that _review endpoint returns the same number of rules to install as the status endpoint
|
||||
const prebuiltRulesToInstallReviewAfterLatestPackageInstallation =
|
||||
await reviewPrebuiltRulesToInstall(supertest);
|
||||
expect(
|
||||
prebuiltRulesToInstallReviewAfterLatestPackageInstallation.stats.num_rules_to_install
|
||||
).toBe(statusAfterLatestPackageInstallation.stats.num_prebuilt_rules_to_install);
|
||||
|
||||
// Install available rules and verify that the _perform endpoint returns the same number of
|
||||
// installed rules as the status endpoint and the _review endpoint
|
||||
const installPrebuiltRulesResponseAfterLatestPackageInstallation = await installPrebuiltRules(
|
||||
supertest
|
||||
);
|
||||
expect(installPrebuiltRulesResponseAfterLatestPackageInstallation.summary.succeeded).toBe(
|
||||
statusAfterLatestPackageInstallation.stats.num_prebuilt_rules_to_install
|
||||
);
|
||||
expect(
|
||||
installPrebuiltRulesResponseAfterLatestPackageInstallation.summary.succeeded
|
||||
).toBeGreaterThanOrEqual(
|
||||
prebuiltRulesToInstallReviewAfterLatestPackageInstallation.stats.num_rules_to_install
|
||||
);
|
||||
|
||||
// Get installed rules
|
||||
const { body: rulesResponseAfterPackageUpdate } = await supertest
|
||||
.get(`${DETECTION_ENGINE_RULES_URL_FIND}?per_page=10000`)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.send()
|
||||
.expect(200);
|
||||
|
||||
// Check that the expected new prebuilt rules from the latest package were actually installed
|
||||
expect(
|
||||
rulesResponseAfterPackageUpdate.data.map((rule: { rule_id: string }) => ({
|
||||
rule_id: rule.rule_id,
|
||||
}))
|
||||
).toEqual(
|
||||
expect.arrayContaining(
|
||||
installPrebuiltRulesResponseAfterLatestPackageInstallation.results.created.map(
|
||||
(rule: { rule_id: string }) => ({
|
||||
rule_id: rule.rule_id,
|
||||
})
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
// Verify that the upgrade _review endpoint returns the same number of rules to upgrade as the status endpoint
|
||||
const prebuiltRulesToUpgradeReviewAfterLatestPackageInstallation =
|
||||
await reviewPrebuiltRulesToUpgrade(supertest);
|
||||
expect(
|
||||
prebuiltRulesToUpgradeReviewAfterLatestPackageInstallation.stats.num_rules_to_upgrade_total
|
||||
).toBe(statusAfterLatestPackageInstallation.stats.num_prebuilt_rules_to_upgrade);
|
||||
|
||||
// Call the upgrade _perform endpoint and verify that the number of upgraded rules is the same as the one
|
||||
// returned by the _review endpoint and the status endpoint
|
||||
const upgradePrebuiltRulesResponseAfterLatestPackageInstallation = await upgradePrebuiltRules(
|
||||
supertest
|
||||
);
|
||||
expect(upgradePrebuiltRulesResponseAfterLatestPackageInstallation.summary.succeeded).toEqual(
|
||||
statusAfterLatestPackageInstallation.stats.num_prebuilt_rules_to_upgrade
|
||||
);
|
||||
expect(upgradePrebuiltRulesResponseAfterLatestPackageInstallation.summary.succeeded).toEqual(
|
||||
prebuiltRulesToUpgradeReviewAfterLatestPackageInstallation.stats.num_rules_to_upgrade_total
|
||||
);
|
||||
|
||||
// Get installed rules
|
||||
const { body: rulesResponseAfterPackageUpdateAndRuleUpgrades } = await supertest
|
||||
.get(`${DETECTION_ENGINE_RULES_URL_FIND}?per_page=10000`)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.send()
|
||||
.expect(200);
|
||||
|
||||
// Check that the expected new prebuilt rules from the latest package were actually installed
|
||||
expect(
|
||||
rulesResponseAfterPackageUpdateAndRuleUpgrades.data.map((rule: { rule_id: string }) => ({
|
||||
rule_id: rule.rule_id,
|
||||
}))
|
||||
).toEqual(
|
||||
expect.arrayContaining(
|
||||
upgradePrebuiltRulesResponseAfterLatestPackageInstallation.results.updated.map(
|
||||
(rule: { rule_id: string }) => ({
|
||||
rule_id: rule.rule_id,
|
||||
})
|
||||
)
|
||||
)
|
||||
);
|
||||
});
|
||||
});
|
||||
};
|
|
@ -101,7 +101,10 @@ export * from './wait_for_signals_to_be_present';
|
|||
export * from './prebuilt_rules/create_prebuilt_rule_saved_objects';
|
||||
export * from './prebuilt_rules/delete_all_prebuilt_rule_assets';
|
||||
export * from './prebuilt_rules/delete_prebuilt_rules_fleet_package';
|
||||
export * from './prebuilt_rules/get_prebuilt_rules_status';
|
||||
export * from './prebuilt_rules/get_prebuilt_rules_and_timelines_status';
|
||||
export * from './prebuilt_rules/install_prebuilt_rules_fleet_package';
|
||||
export * from './prebuilt_rules/install_prebuilt_rules';
|
||||
export * from './prebuilt_rules/upgrade_prebuilt_rules';
|
||||
export * from './prebuilt_rules/install_mock_prebuilt_rules';
|
||||
export * from './prebuilt_rules/install_prebuilt_rules_and_timelines';
|
||||
|
|
|
@ -12,6 +12,7 @@ import {
|
|||
import type SuperTest from 'supertest';
|
||||
|
||||
/**
|
||||
* (LEGACY)
|
||||
* Helper to retrieve the prebuilt rules status
|
||||
*
|
||||
* @param supertest The supertest deps
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import {
|
||||
GET_PREBUILT_RULES_STATUS_URL,
|
||||
GetPrebuiltRulesStatusResponseBody,
|
||||
} from '@kbn/security-solution-plugin/common/api/detection_engine/prebuilt_rules';
|
||||
import type SuperTest from 'supertest';
|
||||
|
||||
/**
|
||||
* Helper to retrieve the prebuilt rules status
|
||||
*
|
||||
* @param supertest The supertest deps
|
||||
*/
|
||||
export const getPrebuiltRulesStatus = async (
|
||||
supertest: SuperTest.SuperTest<SuperTest.Test>
|
||||
): Promise<GetPrebuiltRulesStatusResponseBody> => {
|
||||
const response = await supertest
|
||||
.get(GET_PREBUILT_RULES_STATUS_URL)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.send()
|
||||
.expect(200);
|
||||
|
||||
return response.body;
|
||||
};
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* 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 {
|
||||
PERFORM_RULE_INSTALLATION_URL,
|
||||
RuleVersionSpecifier,
|
||||
PerformRuleInstallationResponseBody,
|
||||
} from '@kbn/security-solution-plugin/common/api/detection_engine/prebuilt_rules';
|
||||
import type SuperTest from 'supertest';
|
||||
|
||||
/**
|
||||
* Installs available prebuilt rules in Kibana. Rules are
|
||||
* installed from the security-rule saved objects.
|
||||
*
|
||||
* - No rules will be installed if there are no security-rule assets (e.g., the
|
||||
* package is not installed or mocks are not created).
|
||||
*
|
||||
* - Pass in an array of rule version specifiers to install specific rules. Otherwise
|
||||
* all available rules will be installed.
|
||||
*
|
||||
* @param supertest SuperTest instance
|
||||
* @param rules Array of rule version specifiers to install (optional)
|
||||
* @returns Install prebuilt rules response
|
||||
*/
|
||||
export const installPrebuiltRules = async (
|
||||
supertest: SuperTest.SuperTest<SuperTest.Test>,
|
||||
rules?: RuleVersionSpecifier[]
|
||||
): Promise<PerformRuleInstallationResponseBody> => {
|
||||
let payload = {};
|
||||
if (rules) {
|
||||
payload = { mode: 'SPECIFIC_RULES', rules };
|
||||
} else {
|
||||
payload = { mode: 'ALL_RULES' };
|
||||
}
|
||||
const response = await supertest
|
||||
.post(PERFORM_RULE_INSTALLATION_URL)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.send(payload)
|
||||
.expect(200);
|
||||
|
||||
return response.body;
|
||||
};
|
|
@ -12,8 +12,11 @@ import {
|
|||
import type SuperTest from 'supertest';
|
||||
|
||||
/**
|
||||
* (LEGACY)
|
||||
* Installs all prebuilt rules and timelines available in Kibana. Rules are
|
||||
* installed from the security-rule saved objects.
|
||||
* This is a legacy endpoint and has been replaced by:
|
||||
* POST /internal/detection_engine/prebuilt_rules/installation/_perform
|
||||
*
|
||||
* - No rules will be installed if there are no security-rule assets (e.g., the
|
||||
* package is not installed or mocks are not created).
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* 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 { REVIEW_RULE_INSTALLATION_URL } from '@kbn/security-solution-plugin/common/api/detection_engine/prebuilt_rules/urls';
|
||||
import { ReviewRuleInstallationResponseBody } from '@kbn/security-solution-plugin/common/api/detection_engine/prebuilt_rules/review_rule_installation/review_rule_installation_route';
|
||||
import type SuperTest from 'supertest';
|
||||
|
||||
/**
|
||||
* Returns prebuilt rules that are avaialble to install
|
||||
*
|
||||
* @param supertest SuperTest instance
|
||||
* @returns Review Install prebuilt rules response
|
||||
*/
|
||||
export const reviewPrebuiltRulesToInstall = async (
|
||||
supertest: SuperTest.SuperTest<SuperTest.Test>
|
||||
): Promise<ReviewRuleInstallationResponseBody> => {
|
||||
const response = await supertest
|
||||
.post(REVIEW_RULE_INSTALLATION_URL)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.send()
|
||||
.expect(200);
|
||||
|
||||
return response.body;
|
||||
};
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* 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 { REVIEW_RULE_UPGRADE_URL } from '@kbn/security-solution-plugin/common/api/detection_engine/prebuilt_rules/urls';
|
||||
import { ReviewRuleUpgradeResponseBody } from '@kbn/security-solution-plugin/common/api/detection_engine/prebuilt_rules/review_rule_upgrade/review_rule_upgrade_route';
|
||||
import type SuperTest from 'supertest';
|
||||
|
||||
/**
|
||||
* Returns prebuilt rules that are available to Upgrade
|
||||
*
|
||||
* @param supertest SuperTest instance
|
||||
* @returns Review Upgrade prebuilt rules response
|
||||
*/
|
||||
export const reviewPrebuiltRulesToUpgrade = async (
|
||||
supertest: SuperTest.SuperTest<SuperTest.Test>
|
||||
): Promise<ReviewRuleUpgradeResponseBody> => {
|
||||
const response = await supertest
|
||||
.post(REVIEW_RULE_UPGRADE_URL)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.send()
|
||||
.expect(200);
|
||||
|
||||
return response.body;
|
||||
};
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* 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 {
|
||||
PERFORM_RULE_UPGRADE_URL,
|
||||
RuleVersionSpecifier,
|
||||
PerformRuleUpgradeResponseBody,
|
||||
} from '@kbn/security-solution-plugin/common/api/detection_engine/prebuilt_rules';
|
||||
import type SuperTest from 'supertest';
|
||||
|
||||
/**
|
||||
* Upgrades available prebuilt rules in Kibana.
|
||||
*
|
||||
* - Pass in an array of rule version specifiers to upgrade specific rules. Otherwise
|
||||
* all available rules will be upgraded.
|
||||
*
|
||||
* @param supertest SuperTest instance
|
||||
* @param rules Array of rule version specifiers to upgrade (optional)
|
||||
* @returns Upgrade prebuilt rules response
|
||||
*/
|
||||
export const upgradePrebuiltRules = async (
|
||||
supertest: SuperTest.SuperTest<SuperTest.Test>,
|
||||
rules?: RuleVersionSpecifier[]
|
||||
): Promise<PerformRuleUpgradeResponseBody> => {
|
||||
let payload = {};
|
||||
if (rules) {
|
||||
payload = { mode: 'SPECIFIC_RULES', rules, pick_version: 'TARGET' };
|
||||
} else {
|
||||
payload = { mode: 'ALL_RULES', pick_version: 'TARGET' };
|
||||
}
|
||||
const response = await supertest
|
||||
.post(PERFORM_RULE_UPGRADE_URL)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.send(payload)
|
||||
.expect(200);
|
||||
|
||||
return response.body;
|
||||
};
|
Loading…
Add table
Add a link
Reference in a new issue