[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:
Juan Pablo Djeredjian 2023-07-19 17:53:15 +02:00 committed by GitHub
parent 2e15549b58
commit 887b3bde05
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
30 changed files with 2113 additions and 580 deletions

View file

@ -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

View file

@ -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');
});
});
});

View file

@ -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,
});
});
});
});

View file

@ -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');
});
});
});

View file

@ -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}`);
});
});
});
});

View file

@ -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"]';

View file

@ -199,6 +199,6 @@ export const createAndInstallMockedPrebuiltRules = ({
createNewRuleAsset({ rule });
});
if (installToKibana) {
installAllPrebuiltRulesRequest();
return installAllPrebuiltRulesRequest();
}
};

View file

@ -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');
}
};

View file

@ -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

View file

@ -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 },
});

View file

@ -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}>

View file

@ -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>

View file

@ -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"
/>
);

View file

@ -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>

View file

@ -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);
});
});
};

View file

@ -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

View file

@ -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,
});
});
});
});

View file

@ -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'));
});
};

View file

@ -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);
});
});
});
});
};

View file

@ -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);
});
});
});
};

View file

@ -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')],
};
}

View file

@ -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,
})
)
)
);
});
});
};

View file

@ -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';

View file

@ -12,6 +12,7 @@ import {
import type SuperTest from 'supertest';
/**
* (LEGACY)
* Helper to retrieve the prebuilt rules status
*
* @param supertest The supertest deps

View file

@ -0,0 +1,29 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 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;
};

View file

@ -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;
};

View file

@ -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).

View file

@ -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;
};

View file

@ -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;
};

View file

@ -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;
};