Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
891ed01
change alerts_summary capabilities
tomsonpl Mar 19, 2025
762b8df
Merge branch 'main' into ai-soc-alerts-capabilities
tomsonpl Mar 31, 2025
330698a
hide rules and alerts behind detections capability
tomsonpl Apr 1, 2025
517be02
Merge branch 'main' into ai-soc-alerts-capabilities
tomsonpl Apr 1, 2025
16dd9c9
fix tests
tomsonpl Apr 1, 2025
3f4a1d9
Merge remote-tracking branch 'origin/ai-soc-alerts-capabilities' into…
tomsonpl Apr 1, 2025
d8198a6
Merge branch 'main' into ai-soc-alerts-capabilities
tomsonpl Apr 1, 2025
d9e455e
Merge branch 'main' into ai-soc-alerts-capabilities
tomsonpl Apr 2, 2025
aa07440
renderSpyRoute conditionally
tomsonpl Apr 2, 2025
03aae6a
Merge remote-tracking branch 'origin/ai-soc-alerts-capabilities' into…
tomsonpl Apr 2, 2025
5d2d066
add omitSpyRoutes conditionally
tomsonpl Apr 2, 2025
009d0b9
Merge branch 'main' into ai-soc-alerts-capabilities
tomsonpl Apr 2, 2025
df33a7b
bring back permissions
tomsonpl Apr 2, 2025
e6bd02e
Merge remote-tracking branch 'origin/ai-soc-alerts-capabilities' into…
tomsonpl Apr 2, 2025
721a915
fix snapshot
tomsonpl Apr 3, 2025
4018e97
bring back missing privileges
tomsonpl Apr 3, 2025
fa805ff
add external_detections
tomsonpl Apr 3, 2025
26ebfc8
Merge branch 'main' into ai-soc-alerts-capabilities
tomsonpl Apr 3, 2025
4902e2b
Revert "fix snapshot"
tomsonpl Apr 3, 2025
a6d5384
Merge remote-tracking branch 'origin/ai-soc-alerts-capabilities' into…
tomsonpl Apr 3, 2025
9c67d36
skip test
tomsonpl Apr 4, 2025
c3ea565
Merge branch 'main' into ai-soc-alerts-capabilities
tomsonpl Apr 4, 2025
1a39746
fix test
tomsonpl Apr 4, 2025
fffd446
Merge remote-tracking branch 'origin/ai-soc-alerts-capabilities' into…
tomsonpl Apr 4, 2025
29b44c8
move features and add test
tomsonpl Apr 4, 2025
f04f375
fix snapshots
tomsonpl Apr 4, 2025
523baa0
Merge branch 'main' into ai-soc-alerts-capabilities
tomsonpl Apr 5, 2025
bcd6ff6
Merge branch 'main' into ai-soc-alerts-capabilities
tomsonpl Apr 7, 2025
bcc2632
move back lists api privileges to kibana features
tomsonpl Apr 7, 2025
c40981a
initial e2e tests, reorder navigation items
tomsonpl Apr 7, 2025
15daf93
Merge remote-tracking branch 'origin/ai-soc-alerts-capabilities' into…
tomsonpl Apr 7, 2025
0c48020
fix
tomsonpl Apr 7, 2025
cb5f3ff
bring back alerting privileges
tomsonpl Apr 8, 2025
24fe483
revert order change
tomsonpl Apr 8, 2025
35c1a03
Merge branch 'main' into ai-soc-alerts-capabilities
tomsonpl Apr 8, 2025
cea2117
fix snapshot
tomsonpl Apr 8, 2025
e9c9770
test access with v1 and v2 roles
tomsonpl Apr 8, 2025
32d9466
fix
tomsonpl Apr 8, 2025
0097540
Update x-pack/solutions/security/plugins/security_solution/public/com…
tomsonpl Apr 9, 2025
a0bdf5c
Merge branch 'main' into ai-soc-alerts-capabilities
tomsonpl Apr 9, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,15 @@
export enum ProductFeatureSecurityKey {
/** Enables Advanced Insights (Entity Risk, GenAI) */
advancedInsights = 'advanced_insights',
/** Enables Alerts Summary page for AI SOC */
alertsSummary = 'alerts_summary',

/** Enables Configurations page for AI SOC */
configurations = 'configurations',

/** Elastic endpoint detections, includes alerts, rules, investigations */
detections = 'detections',

/** Enables external detections for AI SOC, includes alerts_summary, basic_rules*/
externalDetections = 'external_detections',
/**
* Enables Investigation guide in Timeline
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import type { DefaultSecurityProductFeaturesConfig } from './types';
* - `subFeatureIds`: the ids of the sub-features that will be added into the Security subFeatures entry.
* - `subFeaturesPrivileges`: the privileges that will be added into the existing Security subFeature with the privilege `id` specified.
*/

export const securityDefaultProductFeaturesConfig: DefaultSecurityProductFeaturesConfig = {
[ProductFeatureSecurityKey.advancedInsights]: {
privileges: {
Expand All @@ -32,25 +33,45 @@ export const securityDefaultProductFeaturesConfig: DefaultSecurityProductFeature
},
},
},
[ProductFeatureSecurityKey.investigationGuide]: {

[ProductFeatureSecurityKey.externalDetections]: {
privileges: {
all: {
ui: ['investigation-guide'],
ui: ['external_detections'],
api: [],
},
read: {
ui: ['investigation-guide'],
ui: ['external_detections'],
api: [],
},
},
},
[ProductFeatureSecurityKey.detections]: {
privileges: {
all: {
ui: ['detections'],
api: [
'cloud-security-posture-all',
'cloud-security-posture-read',
'cloud-defend-all',
'cloud-defend-read',
'bulkGetUserProfiles',
],
},
read: {
ui: ['detections'],
api: ['cloud-security-posture-read', 'cloud-defend-read', 'bulkGetUserProfiles'],
},
},
},
[ProductFeatureSecurityKey.alertsSummary]: {

[ProductFeatureSecurityKey.investigationGuide]: {
privileges: {
all: {
ui: ['alerts_summary'],
api: [`${APP_ID}-alert-summary`],
ui: ['investigation-guide'],
},
read: {
ui: ['alerts_summary_read'],
api: [`${APP_ID}-alert-summary`],
ui: ['investigation-guide'],
},
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,18 +76,7 @@ export const getSecurityV2BaseKibanaFeature = ({
all: {
app: [APP_ID, CLOUD_POSTURE_APP_ID, 'kibana'],
catalogue: [APP_ID],
api: [
APP_ID,
'lists-all',
'lists-read',
'lists-summary',
'rac',
'cloud-security-posture-all',
'cloud-security-posture-read',
'cloud-defend-all',
'cloud-defend-read',
'bulkGetUserProfiles',
],
api: [APP_ID, 'rac', 'lists-all', 'lists-read', 'lists-summary'],
savedObject: {
all: ['alert', ...savedObjects],
read: [],
Expand All @@ -104,14 +93,7 @@ export const getSecurityV2BaseKibanaFeature = ({
read: {
app: [APP_ID, CLOUD_POSTURE_APP_ID, 'kibana'],
catalogue: [APP_ID],
api: [
APP_ID,
'lists-read',
'rac',
'cloud-security-posture-read',
'cloud-defend-read',
'bulkGetUserProfiles',
],
api: [APP_ID, 'rac', 'lists-read'],
savedObject: {
all: [],
read: [...savedObjects],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,13 @@ import { generateHistoryMock } from '../../utils/route/mocks';
import type { LinkInfo } from '../../links';
import { useLinkInfo } from '../../links';
import { useUpsellingPage } from '../../hooks/use_upselling';
import { SpyRoute } from '../../utils/route/spy_routes';

jest.mock('../../links');
jest.mock('../../hooks/use_upselling');
jest.mock('../../utils/route/spy_routes', () => ({
SpyRoute: jest.fn(() => null),
}));

const defaultLinkInfo: LinkInfo = {
id: SecurityPageName.exploreLanding,
Expand Down Expand Up @@ -147,4 +151,18 @@ describe('SecurityRoutePageWrapper', () => {

expect(getByTestId(TEST_COMPONENT_SUBJ)).toBeInTheDocument();
});
it('should not render SpyRoute when omitSpyRoute is set to true', () => {
(useLinkInfo as jest.Mock).mockReturnValue(defaultLinkInfo);
(useUpsellingPage as jest.Mock).mockReturnValue(undefined);

render(
<SecurityRoutePageWrapper pageName={SecurityPageName.exploreLanding} omitSpyRoute>
<TestComponent />
</SecurityRoutePageWrapper>,
{ wrapper: Wrapper }
);

// SpyRoute was mocked, so if omitSpyRoute worked, it should not have been called
expect(SpyRoute).not.toHaveBeenCalled();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ interface SecurityRoutePageWrapperProps {
* Used primarily in the AI for SOC tier, to allow redirecting to the home page instead of showing the NoPrivileges page.
*/
redirectIfUnauthorized?: boolean;
// Used to disable the SpyRoute for the page, if e.g. the page's children have their own SpyRoute specified.
omitSpyRoute?: boolean;
}

/**
Expand All @@ -46,6 +48,7 @@ export const SecurityRoutePageWrapper: FC<PropsWithChildren<SecurityRoutePageWra
pageName,
redirectIfUnauthorized,
redirectOnMissing,
omitSpyRoute,
}) => {
const link = useLinkInfo(pageName);

Expand Down Expand Up @@ -91,7 +94,7 @@ export const SecurityRoutePageWrapper: FC<PropsWithChildren<SecurityRoutePageWra
return (
<TrackApplicationView viewId={pageName}>
{children}
<SpyRoute pageName={pageName} />
{!omitSpyRoute && <SpyRoute pageName={pageName} />}
Comment thread
semd marked this conversation as resolved.
</TrackApplicationView>
);
};
Expand All @@ -105,14 +108,20 @@ export const withSecurityRoutePageWrapper = <T extends {}>(
{
redirectOnMissing,
redirectIfUnauthorized,
}: { redirectOnMissing?: boolean; redirectIfUnauthorized?: boolean } = {}
omitSpyRoute,
}: {
redirectOnMissing?: boolean;
redirectIfUnauthorized?: boolean;
omitSpyRoute?: boolean;
} = {}
) => {
return function WithSecurityRoutePageWrapper(props: T) {
return (
<SecurityRoutePageWrapper
pageName={pageName}
redirectOnMissing={redirectOnMissing}
redirectIfUnauthorized={redirectIfUnauthorized}
omitSpyRoute={omitSpyRoute}
>
<Component {...props} />
</SecurityRoutePageWrapper>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ describe('use show timeline', () => {
siemV2: {
show: true,
crud: true,
detections: true,
},
},
upselling: mockUpselling,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { ALERT_SUMMARY, ALERTS } from '../app/translations';
import type { LinkItem } from '../common/links/types';

export const alertsLink: LinkItem = {
capabilities: [`${SECURITY_FEATURE_ID}.show`],
capabilities: [[`${SECURITY_FEATURE_ID}.show`, `${SECURITY_FEATURE_ID}.detections`]],
globalNavPosition: 3,
globalSearchKeywords: [
i18n.translate('xpack.securitySolution.appLinks.alerts', {
Expand All @@ -29,7 +29,7 @@ export const alertsLink: LinkItem = {
};

export const alertSummaryLink: LinkItem = {
capabilities: [[`${SECURITY_FEATURE_ID}.show`, `${SECURITY_FEATURE_ID}.alerts_summary`]],
capabilities: [[`${SECURITY_FEATURE_ID}.show`, `${SECURITY_FEATURE_ID}.external_detections`]],
globalNavPosition: 3,
globalSearchKeywords: [
i18n.translate('xpack.securitySolution.appLinks.alertSummary', {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,15 @@ import React from 'react';
import type { RouteComponentProps, RouteProps } from 'react-router-dom';
import { Redirect } from 'react-router-dom';
import { AlertSummaryContainer } from './pages/alert_summary';
import { ALERT_SUMMARY_PATH, ALERTS_PATH, DETECTIONS_PATH } from '../../common/constants';
import {
ALERT_SUMMARY_PATH,
ALERTS_PATH,
DETECTIONS_PATH,
SecurityPageName,
} from '../../common/constants';
import { PluginTemplateWrapper } from '../common/components/plugin_template_wrapper';
import { Alerts } from './pages/alerts';
import { withSecurityRoutePageWrapper } from '../common/components/security_route_page_wrapper';

const AlertsRoutes = () => (
<PluginTemplateWrapper>
Expand All @@ -29,14 +35,20 @@ const DetectionsRedirects = ({ location }: RouteComponentProps) =>
export const routes: RouteProps[] = [
{
path: DETECTIONS_PATH,
render: DetectionsRedirects,
render: withSecurityRoutePageWrapper(DetectionsRedirects, SecurityPageName.detections, {
redirectOnMissing: true,
}),
},
{
path: ALERTS_PATH,
component: AlertsRoutes,
component: withSecurityRoutePageWrapper(AlertsRoutes, SecurityPageName.alerts, {
redirectOnMissing: true,
}),
},
{
path: ALERT_SUMMARY_PATH,
component: AlertSummaryContainer,
component: withSecurityRoutePageWrapper(AlertSummaryContainer, SecurityPageName.alertSummary, {
redirectOnMissing: true,
}),
},
];
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export const links: LinkItem = {
hideTimeline: true,
skipUrlState: true,
globalNavPosition: 2,
capabilities: [`${SECURITY_FEATURE_ID}.show`],
capabilities: [[`${SECURITY_FEATURE_ID}.show`, `${SECURITY_FEATURE_ID}.detections`]],
links: [
{
id: SecurityPageName.rules,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ import type { SecuritySubPluginRoutes } from '../app/types';
import { RulesLandingPage } from './landing';
import { CoverageOverviewPage } from '../detection_engine/rule_management_ui/pages/coverage_overview';
import { RuleDetailTabs } from '../detection_engine/rule_details_ui/pages/rule_details/use_rule_details_tabs';
import {
SecurityRoutePageWrapper,
withSecurityRoutePageWrapper,
} from '../common/components/security_route_page_wrapper';

const RulesSubRoutes = [
{
Expand Down Expand Up @@ -64,7 +68,7 @@ const RulesContainerComponent: React.FC = () => {

return (
<PluginTemplateWrapper>
<TrackApplicationView viewId={SecurityPageName.rules}>
<SecurityRoutePageWrapper pageName={SecurityPageName.rules} redirectOnMissing omitSpyRoute>
<Routes>
<Route // Redirect to first tab if none specified
path="/rules/id/:detailName"
Expand Down Expand Up @@ -99,7 +103,7 @@ const RulesContainerComponent: React.FC = () => {
<Route component={NotFoundPage} />
<SpyRoute pageName={SecurityPageName.rules} />
</Routes>
</TrackApplicationView>
</SecurityRoutePageWrapper>
</PluginTemplateWrapper>
);
};
Expand All @@ -117,14 +121,22 @@ const CoverageOverviewRoutes = () => (
export const routes: SecuritySubPluginRoutes = [
{
path: RULES_LANDING_PATH,
component: RulesLandingPage,
component: withSecurityRoutePageWrapper(RulesLandingPage, SecurityPageName.rulesLanding, {
redirectOnMissing: true,
}),
},
{
path: RULES_PATH,
component: Rules,
},
{
path: COVERAGE_OVERVIEW_PATH,
component: CoverageOverviewRoutes,
component: withSecurityRoutePageWrapper(
CoverageOverviewRoutes,
SecurityPageName.coverageOverview,
{
redirectOnMissing: true,
}
),
},
];
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {

// List of product features that are disabled in different offering (eg. Serverless).
const DISABLED_PRODUCT_FEATURES: ProductFeatureKeyType[] = [
ProductFeatureSecurityKey.alertsSummary,
ProductFeatureSecurityKey.externalDetections,
ProductFeatureSecurityKey.configurations,
];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,23 @@ export const PLI_PRODUCT_FEATURES: PliProductFeatures = {
search_ai_lake: [
ProductFeatureKey.attackDiscovery,
ProductFeatureKey.assistant,
ProductFeatureKey.alertsSummary,
ProductFeatureKey.configurations,
ProductFeatureKey.externalDetections,
],
essentials: [ProductFeatureKey.attackDiscovery, ProductFeatureKey.assistant],
complete: [ProductFeatureKey.attackDiscovery, ProductFeatureKey.assistant],
},
[ProductLine.security]: {
search_ai_lake: [],
essentials: [
ProductFeatureKey.detections,
ProductFeatureKey.timeline,
ProductFeatureKey.notes,
ProductFeatureKey.endpointHostManagement,
ProductFeatureKey.endpointPolicyManagement,
],
complete: [
ProductFeatureKey.detections,
ProductFeatureKey.timeline,
ProductFeatureKey.notes,
ProductFeatureKey.endpointHostManagement,
Expand Down
Loading