mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 09:19:04 -04:00
[Security Solution][Detection Engine] adds rule actions PLI (#168510)
## Summary - implements the first phase of [rule external actions Serverless PLI](https://docs.google.com/spreadsheets/d/1BR9kjzSR0F6o6huxbJidk5ro4CVYfhmLog9ArEbxA8g/edit#gid=301346322). Phase 1 is defined by support of PLI capabilities in actions plugins and described [here](https://github.com/elastic/kibana/issues/163751). It allows only hiding actions that are not in tier. Upselling messages, will be introduced in phase 2, according to response ops ticket ### Essentials Tier Serverless config: ```yaml xpack.securitySolutionServerless.productTypes: [ { product_line: 'security', product_tier: 'essentials' }, { product_line: 'endpoint', product_tier: 'complete' }, ] ``` For Essentials, only 3 rule actions available: - email - index - slack <img width="2525" alt="Screenshot 2023-10-11 at 11 13 57" src="2a10d077
-3090-494d-953f-2880c2afdccf"> ### Complete Tier Serverless config: ```yaml xpack.securitySolutionServerless.productTypes: [ { product_line: 'security', product_tier: 'complete' }, { product_line: 'endpoint', product_tier: 'complete' }, ] ``` <img width="2530" alt="Screenshot 2023-10-11 at 11 17 10" src="1e5912a5
-a358-409b-8fd6-e526e047fe54"> ### Checklist Delete any items that are not applicable to this PR. - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
3f6872d77b
commit
94284a105a
11 changed files with 213 additions and 3 deletions
|
@ -48,6 +48,11 @@ export enum AppFeatureSecurityKey {
|
|||
* Enables managing endpoint exceptions on rules and alerts
|
||||
*/
|
||||
endpointExceptions = 'endpointExceptions',
|
||||
|
||||
/**
|
||||
* enables all rule actions
|
||||
*/
|
||||
externalRuleActions = 'external_rule_actions',
|
||||
}
|
||||
|
||||
export enum AppFeatureCasesKey {
|
||||
|
|
|
@ -106,4 +106,6 @@ export const securityDefaultAppFeaturesConfig: DefaultSecurityAppFeaturesConfig
|
|||
},
|
||||
|
||||
[AppFeatureSecurityKey.osqueryAutomatedResponseActions]: {},
|
||||
|
||||
[AppFeatureSecurityKey.externalRuleActions]: {},
|
||||
};
|
||||
|
|
|
@ -22,6 +22,7 @@ export const PLI_APP_FEATURES: PliAppFeatures = {
|
|||
AppFeatureKey.investigationGuide,
|
||||
AppFeatureKey.threatIntelligence,
|
||||
AppFeatureKey.casesConnectors,
|
||||
AppFeatureKey.externalRuleActions,
|
||||
],
|
||||
},
|
||||
endpoint: {
|
||||
|
|
|
@ -19,7 +19,8 @@
|
|||
"serverless",
|
||||
"taskManager",
|
||||
"cloud",
|
||||
"fleet"
|
||||
"fleet",
|
||||
"actions"
|
||||
],
|
||||
"optionalPlugins": [
|
||||
"securitySolutionEss"
|
||||
|
|
|
@ -32,6 +32,7 @@ import {
|
|||
endpointMeteringService,
|
||||
setEndpointPackagePolicyServerlessFlag,
|
||||
} from './endpoint/services';
|
||||
import { enableRuleActions } from './rules/enable_rule_actions';
|
||||
|
||||
export class SecuritySolutionServerlessPlugin
|
||||
implements
|
||||
|
@ -54,6 +55,7 @@ export class SecuritySolutionServerlessPlugin
|
|||
|
||||
public setup(coreSetup: CoreSetup, pluginsSetup: SecuritySolutionServerlessPluginSetupDeps) {
|
||||
this.config = createConfig(this.initializerContext, pluginsSetup.securitySolution);
|
||||
const enabledAppFeatures = getProductAppFeatures(this.config.productTypes);
|
||||
|
||||
// securitySolutionEss plugin should always be disabled when securitySolutionServerless is enabled.
|
||||
// This check is an additional layer of security to prevent double registrations when
|
||||
|
@ -63,12 +65,14 @@ export class SecuritySolutionServerlessPlugin
|
|||
const productTypesStr = JSON.stringify(this.config.productTypes, null, 2);
|
||||
this.logger.info(`Security Solution running with product types:\n${productTypesStr}`);
|
||||
const appFeaturesConfigurator = getProductAppFeaturesConfigurator(
|
||||
getProductAppFeatures(this.config.productTypes),
|
||||
enabledAppFeatures,
|
||||
this.config
|
||||
);
|
||||
pluginsSetup.securitySolution.setAppFeaturesConfigurator(appFeaturesConfigurator);
|
||||
}
|
||||
|
||||
enableRuleActions({ actions: pluginsSetup.actions, appFeatureKeys: enabledAppFeatures });
|
||||
|
||||
this.cloudSecurityUsageReportingTask = new SecurityUsageReportingTask({
|
||||
core: coreSetup,
|
||||
logFactory: this.initializerContext.logger,
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* 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 { AppFeatureSecurityKey } from '@kbn/security-solution-features/keys';
|
||||
import {
|
||||
IndexConnectorTypeId,
|
||||
SlackWebhookConnectorTypeId,
|
||||
EmailConnectorTypeId,
|
||||
} from '@kbn/stack-connectors-plugin/server/connector_types';
|
||||
import { EnabledActionTypes } from '@kbn/actions-plugin/server/config';
|
||||
import type { AppFeatureKeys } from '@kbn/security-solution-features/src/types';
|
||||
|
||||
import type { PluginSetupContract as ActionsPluginSetupContract } from '@kbn/actions-plugin/server';
|
||||
|
||||
const INTERNAL_RULE_ACTIONS = [
|
||||
IndexConnectorTypeId,
|
||||
SlackWebhookConnectorTypeId,
|
||||
EmailConnectorTypeId,
|
||||
];
|
||||
|
||||
/**
|
||||
* enable rule actions based on AppFeature Config
|
||||
*/
|
||||
export const enableRuleActions = ({
|
||||
actions,
|
||||
appFeatureKeys,
|
||||
}: {
|
||||
actions: ActionsPluginSetupContract;
|
||||
appFeatureKeys: AppFeatureKeys;
|
||||
}) => {
|
||||
if (appFeatureKeys.includes(AppFeatureSecurityKey.externalRuleActions)) {
|
||||
// enables all rule actions
|
||||
actions.setEnabledConnectorTypes([EnabledActionTypes.Any]);
|
||||
} else {
|
||||
actions.setEnabledConnectorTypes(INTERNAL_RULE_ACTIONS);
|
||||
}
|
||||
};
|
|
@ -18,6 +18,7 @@ import type {
|
|||
import type { CloudSetup } from '@kbn/cloud-plugin/server';
|
||||
import type { SecuritySolutionEssPluginSetup } from '@kbn/security-solution-ess/server';
|
||||
import type { FleetStartContract } from '@kbn/fleet-plugin/server';
|
||||
import type { PluginSetupContract as ActionsPluginSetupContract } from '@kbn/actions-plugin/server';
|
||||
|
||||
import type { ServerlessPluginSetup } from '@kbn/serverless/server';
|
||||
import type { ProductTier } from '../common/product';
|
||||
|
@ -37,6 +38,7 @@ export interface SecuritySolutionServerlessPluginSetupDeps {
|
|||
features: PluginSetupContract;
|
||||
taskManager: TaskManagerSetupContract;
|
||||
cloud: CloudSetup;
|
||||
actions: ActionsPluginSetupContract;
|
||||
}
|
||||
|
||||
export interface SecuritySolutionServerlessPluginStartDeps {
|
||||
|
|
|
@ -44,6 +44,8 @@
|
|||
"@kbn/usage-collection-plugin",
|
||||
"@kbn/cloud-defend-plugin",
|
||||
"@kbn/core-logging-server-mocks",
|
||||
"@kbn/shared-ux-chrome-navigation"
|
||||
"@kbn/shared-ux-chrome-navigation",
|
||||
"@kbn/stack-connectors-plugin",
|
||||
"@kbn/actions-plugin"
|
||||
]
|
||||
}
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { getNewRule } from '../../../objects/rule';
|
||||
|
||||
import {
|
||||
INDEX_SELECTOR,
|
||||
SLACK_ACTION_BTN,
|
||||
WEBHOOK_ACTION_BTN,
|
||||
EMAIL_ACTION_BTN,
|
||||
ACTION_BTN,
|
||||
} from '../../../screens/common/rule_actions';
|
||||
|
||||
import { createRule } from '../../../tasks/api_calls/rules';
|
||||
|
||||
import { RULES_MANAGEMENT_URL } from '../../../urls/rules_management';
|
||||
import { cleanKibana, deleteAlertsAndRules } from '../../../tasks/common';
|
||||
import { goToActionsStepTab } from '../../../tasks/create_new_rule';
|
||||
import { login } from '../../../tasks/login';
|
||||
|
||||
import { editFirstRule } from '../../../tasks/alerts_detection_rules';
|
||||
|
||||
import { visit } from '../../../tasks/navigation';
|
||||
|
||||
const rule = getNewRule();
|
||||
|
||||
describe(
|
||||
'Rule actions PLI complete product tier',
|
||||
{
|
||||
tags: ['@serverless'],
|
||||
|
||||
env: {
|
||||
ftrConfig: {
|
||||
productTypes: [
|
||||
{ product_line: 'security', product_tier: 'complete' },
|
||||
{ product_line: 'endpoint', product_tier: 'complete' },
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
() => {
|
||||
before(() => {
|
||||
cleanKibana();
|
||||
login();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
deleteAlertsAndRules();
|
||||
createRule(rule);
|
||||
login();
|
||||
});
|
||||
|
||||
it('more than 3 rule actions should be available', () => {
|
||||
visit(RULES_MANAGEMENT_URL);
|
||||
editFirstRule();
|
||||
|
||||
goToActionsStepTab();
|
||||
|
||||
// all actions available
|
||||
cy.get(ACTION_BTN).should('have.length.greaterThan', 4);
|
||||
|
||||
cy.get(INDEX_SELECTOR).should('be.visible');
|
||||
cy.get(SLACK_ACTION_BTN).should('be.visible');
|
||||
cy.get(EMAIL_ACTION_BTN).should('be.visible');
|
||||
cy.get(WEBHOOK_ACTION_BTN).should('be.visible');
|
||||
});
|
||||
}
|
||||
);
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { getNewRule } from '../../../objects/rule';
|
||||
|
||||
import {
|
||||
INDEX_SELECTOR,
|
||||
SLACK_ACTION_BTN,
|
||||
WEBHOOK_ACTION_BTN,
|
||||
EMAIL_ACTION_BTN,
|
||||
ACTION_BTN,
|
||||
} from '../../../screens/common/rule_actions';
|
||||
|
||||
import { createRule } from '../../../tasks/api_calls/rules';
|
||||
|
||||
import { RULES_MANAGEMENT_URL } from '../../../urls/rules_management';
|
||||
import { cleanKibana, deleteAlertsAndRules } from '../../../tasks/common';
|
||||
import { goToActionsStepTab } from '../../../tasks/create_new_rule';
|
||||
import { login } from '../../../tasks/login';
|
||||
|
||||
import { editFirstRule } from '../../../tasks/alerts_detection_rules';
|
||||
|
||||
import { visit } from '../../../tasks/navigation';
|
||||
|
||||
const rule = getNewRule();
|
||||
|
||||
describe(
|
||||
'Rule actions PLI essentials product tier',
|
||||
{
|
||||
tags: ['@serverless'],
|
||||
|
||||
env: {
|
||||
ftrConfig: {
|
||||
productTypes: [
|
||||
{ product_line: 'security', product_tier: 'essentials' },
|
||||
{ product_line: 'endpoint', product_tier: 'essentials' },
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
() => {
|
||||
before(() => {
|
||||
cleanKibana();
|
||||
login();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
deleteAlertsAndRules();
|
||||
createRule(rule);
|
||||
login();
|
||||
});
|
||||
|
||||
it('only 3 rule actions should be available', () => {
|
||||
visit(RULES_MANAGEMENT_URL);
|
||||
editFirstRule();
|
||||
|
||||
goToActionsStepTab();
|
||||
|
||||
// only 3 basic actions available
|
||||
cy.get(ACTION_BTN).should('have.length', 3);
|
||||
|
||||
cy.get(INDEX_SELECTOR).should('be.visible');
|
||||
cy.get(SLACK_ACTION_BTN).should('be.visible');
|
||||
cy.get(EMAIL_ACTION_BTN).should('be.visible');
|
||||
|
||||
// webhook is not available
|
||||
cy.get(WEBHOOK_ACTION_BTN).should('not.exist');
|
||||
});
|
||||
}
|
||||
);
|
|
@ -7,6 +7,13 @@
|
|||
|
||||
export const EMAIL_ACTION_BTN = '[data-test-subj=".email-siem-ActionTypeSelectOption"]';
|
||||
|
||||
export const WEBHOOK_ACTION_BTN = '[data-test-subj=".webhook-siem-ActionTypeSelectOption"]';
|
||||
|
||||
/**
|
||||
* all rule actions buttons, elements which data-test-subj attribute ends with '-siem-ActionTypeSelectOption'
|
||||
*/
|
||||
export const ACTION_BTN = '[data-test-subj$="-siem-ActionTypeSelectOption"]';
|
||||
|
||||
export const CREATE_ACTION_CONNECTOR_BTN = '[data-test-subj="createActionConnectorButton-0"]';
|
||||
|
||||
export const SAVE_ACTION_CONNECTOR_BTN = '[data-test-subj="saveActionButtonModal"]';
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue