Skip to content

Commit

Permalink
[Security Solution] Top-level Cases feature under the Security (#112980)
Browse files Browse the repository at this point in the history
* add the new top cases feature in security

* fix api intyegration and cypress

* fix api integration

* fix cypress roles test

* missing api integration

* review Joe

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
  • Loading branch information
XavierM and kibanamachine authored Oct 1, 2021
1 parent 01e6ff3 commit 3b958e7
Show file tree
Hide file tree
Showing 20 changed files with 91 additions and 68 deletions.
1 change: 1 addition & 0 deletions x-pack/plugins/security_solution/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { ENABLE_CASE_CONNECTOR } from '../../cases/common';
import { metadataTransformPattern } from './endpoint/constants';

export const APP_ID = 'securitySolution';
export const CASES_FEATURE_ID = 'securitySolutionCases';
export const SERVER_APP_ID = 'siem';
export const APP_NAME = 'Security';
export const APP_ICON = 'securityAnalyticsApp';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ const secAll: Role = {
{
feature: {
siem: ['all'],
securitySolutionCases: ['all'],
actions: ['all'],
actionsSimulators: ['all'],
},
Expand Down Expand Up @@ -110,7 +111,8 @@ const secReadCasesAll: Role = {
kibana: [
{
feature: {
siem: ['minimal_read', 'cases_all'],
siem: ['read'],
securitySolutionCases: ['all'],
actions: ['all'],
actionsSimulators: ['all'],
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { getDeepLinks, PREMIUM_DEEP_LINK_IDS } from '.';
import { AppDeepLink, Capabilities } from '../../../../../../src/core/public';
import { SecurityPageName } from '../types';
import { mockGlobalState } from '../../common/mock';
import { CASES_FEATURE_ID } from '../../../common/constants';

const findDeepLink = (id: string, deepLinks: AppDeepLink[]): AppDeepLink | null =>
deepLinks.reduce((deepLinkFound: AppDeepLink | null, deepLink) => {
Expand Down Expand Up @@ -58,7 +59,7 @@ describe('deepLinks', () => {
it('should return case links for basic license with only read_cases capabilities', () => {
const basicLicense = 'basic';
const basicLinks = getDeepLinks(mockGlobalState.app.enableExperimental, basicLicense, {
siem: { read_cases: true, crud_cases: false },
[CASES_FEATURE_ID]: { read_cases: true, crud_cases: false },
} as unknown as Capabilities);

expect(findDeepLink(SecurityPageName.case, basicLinks)).toBeTruthy();
Expand All @@ -67,15 +68,15 @@ describe('deepLinks', () => {
it('should return case links with NO deepLinks for basic license with only read_cases capabilities', () => {
const basicLicense = 'basic';
const basicLinks = getDeepLinks(mockGlobalState.app.enableExperimental, basicLicense, {
siem: { read_cases: true, crud_cases: false },
[CASES_FEATURE_ID]: { read_cases: true, crud_cases: false },
} as unknown as Capabilities);
expect(findDeepLink(SecurityPageName.case, basicLinks)?.deepLinks?.length === 0).toBeTruthy();
});

it('should return case links with deepLinks for basic license with crud_cases capabilities', () => {
const basicLicense = 'basic';
const basicLinks = getDeepLinks(mockGlobalState.app.enableExperimental, basicLicense, {
siem: { read_cases: true, crud_cases: true },
[CASES_FEATURE_ID]: { read_cases: true, crud_cases: true },
} as unknown as Capabilities);

expect(
Expand All @@ -86,7 +87,7 @@ describe('deepLinks', () => {
it('should return NO case links for basic license with NO read_cases capabilities', () => {
const basicLicense = 'basic';
const basicLinks = getDeepLinks(mockGlobalState.app.enableExperimental, basicLicense, {
siem: { read_cases: false, crud_cases: false },
[CASES_FEATURE_ID]: { read_cases: false, crud_cases: false },
} as unknown as Capabilities);

expect(findDeepLink(SecurityPageName.case, basicLinks)).toBeFalsy();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import {
TRUSTED_APPS_PATH,
EVENT_FILTERS_PATH,
UEBA_PATH,
CASES_FEATURE_ID,
HOST_ISOLATION_EXCEPTIONS_PATH,
} from '../../../common/constants';
import { ExperimentalFeatures } from '../../../common/experimental_features';
Expand Down Expand Up @@ -362,7 +363,7 @@ export function getDeepLinks(
return false;
}
if (deepLink.id === SecurityPageName.case) {
return capabilities == null || capabilities.siem.read_cases === true;
return capabilities == null || capabilities[CASES_FEATURE_ID].read_cases === true;
}
if (deepLink.id === SecurityPageName.ueba) {
return enableExperimental.uebaEnabled;
Expand All @@ -373,7 +374,7 @@ export function getDeepLinks(
if (
deepLink.id === SecurityPageName.case &&
capabilities != null &&
capabilities.siem.crud_cases === false
capabilities[CASES_FEATURE_ID].crud_cases === false
) {
return {
...deepLink,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,12 @@ import { i18n } from '@kbn/i18n';

import { camelCase, isArray, isObject } from 'lodash';
import { set } from '@elastic/safer-lodash-set';
import { APP_ID, DEFAULT_DATE_FORMAT, DEFAULT_DATE_FORMAT_TZ } from '../../../../common/constants';
import {
APP_ID,
CASES_FEATURE_ID,
DEFAULT_DATE_FORMAT,
DEFAULT_DATE_FORMAT_TZ,
} from '../../../../common/constants';
import { errorToToaster, useStateToaster } from '../../components/toasters';
import { AuthenticatedUser } from '../../../../../security/common/model';
import { NavigateToAppOptions } from '../../../../../../../src/core/public';
Expand Down Expand Up @@ -151,13 +156,9 @@ export const useGetUserCasesPermissions = () => {
const uiCapabilities = useKibana().services.application.capabilities;

useEffect(() => {
const capabilitiesCanUserCRUD: boolean =
typeof uiCapabilities.siem.crud_cases === 'boolean' ? uiCapabilities.siem.crud_cases : false;
const capabilitiesCanUserRead: boolean =
typeof uiCapabilities.siem.read_cases === 'boolean' ? uiCapabilities.siem.read_cases : false;
setCasesPermissions({
crud: capabilitiesCanUserCRUD,
read: capabilitiesCanUserRead,
crud: !!uiCapabilities[CASES_FEATURE_ID].crud_cases,
read: !!uiCapabilities[CASES_FEATURE_ID].read_cases,
});
}, [uiCapabilities]);

Expand Down
92 changes: 45 additions & 47 deletions x-pack/plugins/security_solution/server/features.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,49 +9,48 @@ import { i18n } from '@kbn/i18n';

import { KibanaFeatureConfig, SubFeatureConfig } from '../../features/common';
import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/server';
import { APP_ID, SERVER_APP_ID } from '../common/constants';
import { APP_ID, CASES_FEATURE_ID, SERVER_APP_ID } from '../common/constants';
import { savedObjectTypes } from './saved_objects';

const CASES_SUB_FEATURE: SubFeatureConfig = {
name: 'Cases',
privilegeGroups: [
{
groupType: 'mutually_exclusive',
privileges: [
{
id: 'cases_all',
includeIn: 'all',
name: 'All',
savedObject: {
all: [],
read: [],
},
// using variables with underscores here otherwise when we retrieve them from the kibana
// capabilities in a hook I get type errors regarding boolean | ReadOnly<{[x: string]: boolean}>
ui: ['crud_cases', 'read_cases'], // uiCapabilities.siem.crud_cases
cases: {
all: [APP_ID],
},
},
{
id: 'cases_read',
includeIn: 'read',
name: 'Read',
savedObject: {
all: [],
read: [],
},
// using variables with underscores here otherwise when we retrieve them from the kibana
// capabilities in a hook I get type errors regarding boolean | ReadOnly<{[x: string]: boolean}>
ui: ['read_cases'], // uiCapabilities.siem.read_cases
cases: {
read: [APP_ID],
},
},
],
export const getCasesKibanaFeature = (): KibanaFeatureConfig => ({
id: CASES_FEATURE_ID,
name: i18n.translate('xpack.securitySolution.featureRegistry.linkSecuritySolutionCaseTitle', {
defaultMessage: 'Cases',
}),
order: 1100,
category: DEFAULT_APP_CATEGORIES.security,
app: [CASES_FEATURE_ID, 'kibana'],
catalogue: [APP_ID],
cases: [APP_ID],
privileges: {
all: {
app: [CASES_FEATURE_ID, 'kibana'],
catalogue: [APP_ID],
cases: {
all: [APP_ID],
},
api: [],
savedObject: {
all: [],
read: [],
},
ui: ['crud_cases', 'read_cases'], // uiCapabilities[CASES_FEATURE_ID].crud_cases or read_cases
},
],
};
read: {
app: [CASES_FEATURE_ID, 'kibana'],
catalogue: [APP_ID],
cases: {
read: [APP_ID],
},
api: [],
savedObject: {
all: [],
read: [],
},
ui: ['read_cases'], // uiCapabilities[CASES_FEATURE_ID].read_cases
},
},
});

export const getAlertsSubFeature = (ruleTypes: string[]): SubFeatureConfig => ({
name: i18n.translate('xpack.securitySolution.featureRegistry.manageAlertsName', {
Expand Down Expand Up @@ -108,18 +107,17 @@ export const getKibanaPrivilegesFeaturePrivileges = (ruleTypes: string[]): Kiban
order: 1100,
category: DEFAULT_APP_CATEGORIES.security,
app: [APP_ID, 'kibana'],
catalogue: ['securitySolution'],
catalogue: [APP_ID],
management: {
insightsAndAlerting: ['triggersActions'],
},
alerting: ruleTypes,
cases: [APP_ID],
subFeatures: [{ ...CASES_SUB_FEATURE } /* , { ...getAlertsSubFeature(ruleTypes) } */],
subFeatures: [],
privileges: {
all: {
app: [APP_ID, 'kibana'],
catalogue: ['securitySolution'],
api: ['securitySolution', 'lists-all', 'lists-read', 'rac'],
catalogue: [APP_ID],
api: [APP_ID, 'lists-all', 'lists-read', 'rac'],
savedObject: {
all: ['alert', 'exception-list', 'exception-list-agnostic', ...savedObjectTypes],
read: [],
Expand All @@ -136,8 +134,8 @@ export const getKibanaPrivilegesFeaturePrivileges = (ruleTypes: string[]): Kiban
},
read: {
app: [APP_ID, 'kibana'],
catalogue: ['securitySolution'],
api: ['securitySolution', 'lists-read', 'rac'],
catalogue: [APP_ID],
api: [APP_ID, 'lists-read', 'rac'],
savedObject: {
all: [],
read: ['exception-list', 'exception-list-agnostic', ...savedObjectTypes],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"feature": {
"ml": ["all"],
"siem": ["all", "read_alerts", "crud_alerts"],
"securitySolutionCases": ["all"],
"actions": ["read"],
"builtInAlerts": ["all"],
"dev_tools": ["all"]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"feature": {
"ml": ["read"],
"siem": ["all", "read_alerts", "crud_alerts"],
"securitySolutionCases": ["all"],
"actions": ["read"],
"builtInAlerts": ["all"]
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"feature": {
"ml": ["all"],
"siem": ["all", "read_alerts", "crud_alerts"],
"securitySolutionCases": ["all"],
"actions": ["all"],
"builtInAlerts": ["all"]
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"feature": {
"ml": ["read"],
"siem": ["read", "read_alerts"],
"securitySolutionCases": ["read"],
"actions": ["read"],
"builtInAlerts": ["read"]
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"feature": {
"ml": ["read"],
"siem": ["all", "read_alerts", "crud_alerts"],
"securitySolutionCases": ["all"],
"actions": ["read"],
"builtInAlerts": ["all"]
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"feature": {
"ml": ["read"],
"siem": ["all", "read_alerts", "crud_alerts"],
"securitySolutionCases": ["all"],
"actions": ["all"],
"builtInAlerts": ["all"]
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"feature": {
"ml": ["read"],
"siem": ["read", "read_alerts"],
"securitySolutionCases": ["read"],
"actions": ["read"],
"builtInAlerts": ["read"]
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"feature": {
"ml": ["read"],
"siem": ["read", "read_alerts"],
"securitySolutionCases": ["read"],
"actions": ["read"],
"builtInAlerts": ["read"]
},
Expand Down
3 changes: 2 additions & 1 deletion x-pack/plugins/security_solution/server/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ import aadFieldConversion from './lib/detection_engine/routes/index/signal_aad_m
import { alertsFieldMap } from './lib/detection_engine/rule_types/field_maps/alerts';
import { rulesFieldMap } from './lib/detection_engine/rule_types/field_maps/rules';
import { RuleExecutionLogClient } from './lib/detection_engine/rule_execution_log/rule_execution_log_client';
import { getKibanaPrivilegesFeaturePrivileges } from './features';
import { getKibanaPrivilegesFeaturePrivileges, getCasesKibanaFeature } from './features';
import { EndpointMetadataService } from './endpoint/services/metadata';
import { CreateRuleOptions } from './lib/detection_engine/rule_types/types';
import { ctiFieldMap } from './lib/detection_engine/rule_types/field_maps/cti';
Expand Down Expand Up @@ -305,6 +305,7 @@ export class Plugin implements IPlugin<PluginSetup, PluginStart, SetupPlugins, S
];

plugins.features.registerKibanaFeature(getKibanaPrivilegesFeaturePrivileges(ruleTypes));
plugins.features.registerKibanaFeature(getCasesKibanaFeature());

// Continue to register legacy rules against alerting client exposed through rule-registry
if (this.setupPlugins.alerting != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ export default function ({ getService }: FtrProviderContext) {
'osquery',
'uptime',
'siem',
'securitySolutionCases',
'fleet',
].sort()
);
Expand Down
3 changes: 2 additions & 1 deletion x-pack/test/api_integration/apis/security/privileges.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,9 @@ export default function ({ getService }: FtrProviderContext) {
actions: ['all', 'read'],
stackAlerts: ['all', 'read'],
ml: ['all', 'read'],
siem: ['all', 'read', 'minimal_all', 'minimal_read', 'cases_all', 'cases_read'],
siem: ['all', 'read'],
uptime: ['all', 'read'],
securitySolutionCases: ['all', 'read'],
infrastructure: ['all', 'read'],
logs: ['all', 'read'],
apm: ['all', 'read', 'minimal_all', 'minimal_read', 'alerts_all', 'alerts_read'],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export default function ({ getService }: FtrProviderContext) {
osquery: ['all', 'read'],
ml: ['all', 'read'],
siem: ['all', 'read'],
securitySolutionCases: ['all', 'read'],
fleet: ['all', 'read'],
stackAlerts: ['all', 'read'],
actions: ['all', 'read'],
Expand Down
Loading

0 comments on commit 3b958e7

Please sign in to comment.