Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion x-pack/solutions/security/packages/navigation/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@ export {
SecurityGroupName,
LinkCategoryType,
SECURITY_UI_APP_ID,
ATTACKS_ALERTS_ALIGNMENT_ENABLED,
ENABLE_ALERTS_AND_ATTACKS_ALIGNMENT_SETTING,
} from './src/constants';
export * from './src/types';
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,6 @@ export enum SecurityGroupName {
alertDetections = 'securityGroup:alertDetections',
}

/** Feature flag for the alerts and attacks alignment feature */
export const ATTACKS_ALERTS_ALIGNMENT_ENABLED = 'securitySolution.attacksAlertsAlignment' as const;
/** This Kibana Advanced Setting allows users to enable/disable the Alerts and Attacks Alignment feature */
export const ENABLE_ALERTS_AND_ATTACKS_ALIGNMENT_SETTING =
'securitySolution:enableAlertsAndAttacksAlignment' as const;
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ import * as i18n from './translations';

export {
SecurityPageName,
ATTACKS_ALERTS_ALIGNMENT_ENABLED,
ENABLE_ALERTS_AND_ATTACKS_ALIGNMENT_SETTING,
} from '@kbn/security-solution-navigation';

/**
* as const
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ export const allowedExperimentalValues = Object.freeze({
/**
* Protects all the work related to the attacks and alerts alignment effort
*/
attacksAlertsAlignment: false,
enableAlertsAndAttacksAlignment: false,
/**
* Enables the QRadar rules import feature
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { firstValueFrom } from 'rxjs';
import { AIChatExperience } from '@kbn/ai-assistant-common';
import { AI_CHAT_EXPERIENCE_TYPE } from '@kbn/management-settings-ids';

import { ATTACKS_ALERTS_ALIGNMENT_ENABLED } from '../../../common/constants';
import { ENABLE_ALERTS_AND_ATTACKS_ALIGNMENT_SETTING } from '../../../common/constants';
import { aiValueLinks } from '../../reports/links';
import { configurationsLinks, getConfigurationsLinks } from '../../configurations/links';
import { links as attackDiscoveryLinks } from '../../attack_discovery/links';
Expand Down Expand Up @@ -66,7 +66,7 @@ export const getFilteredLinks = async (

return Object.freeze([
dashboardsLinks,
core.featureFlags.getBooleanValue(ATTACKS_ALERTS_ALIGNMENT_ENABLED, false)
core.uiSettings.get(ENABLE_ALERTS_AND_ATTACKS_ALIGNMENT_SETTING, false)
? alertDetectionsLinks
: alertsLink,
alertSummaryLink,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,9 @@ describe('getFilteredLinks', () => {
expect(mockGetManagementFilteredLinks).toHaveBeenCalledWith(mockCore, mockPlugins);
});

describe('`securitySolution.attacksAlertsAlignment` feature flag', () => {
it('includes correct base links in the result when feature flag is disabled', async () => {
mockCore.featureFlags.getBooleanValue.mockReturnValue(false);
describe('`securitySolution:enableAlertsAndAttacksAlignment` setting', () => {
it('includes correct base links in the result when setting is disabled', async () => {
mockCore.uiSettings.get.mockReturnValue(false);
mockGetManagementFilteredLinks.mockResolvedValue(mockManagementLinks);

const result = await getFilteredLinks(mockCore, mockPlugins);
Expand All @@ -110,8 +110,8 @@ describe('getFilteredLinks', () => {
expect(resultIds).toContain('ai_value'); // AI Value is now included statically
});

it('includes all base links in the result when feature flag is enabled', async () => {
mockCore.featureFlags.getBooleanValue.mockReturnValue(true);
it('includes all base links in the result when setting is enabled', async () => {
mockCore.uiSettings.get.mockReturnValue(true);
mockGetManagementFilteredLinks.mockResolvedValue(mockManagementLinks);

const result = await getFilteredLinks(mockCore, mockPlugins);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@ import React from 'react';
import useLocalStorage from 'react-use/lib/useLocalStorage';

import { TestProviders } from '../../common/mock';
import { ATTACK_DISCOVERY_PATH, SECURITY_FEATURE_ID } from '../../../common/constants';
import {
ATTACK_DISCOVERY_PATH,
ENABLE_ALERTS_AND_ATTACKS_ALIGNMENT_SETTING,
SECURITY_FEATURE_ID,
} from '../../../common/constants';
import { mockHistory } from '../../common/utils/route/mocks';
import { AttackDiscoveryPage } from '.';
import { mockTimelines } from '../../common/mock/mock_timelines_plugin';
Expand Down Expand Up @@ -315,9 +319,14 @@ describe('AttackDiscovery', () => {
});
});

describe('`attacksAlertsAlignmentEnabled` feature', () => {
describe('`enableAlertsAndAttacksAlignment` feature', () => {
it('renders callout about new Attacks page when feature is enabled', () => {
mockUseKibanaReturnValue.services.featureFlags.getBooleanValue.mockReturnValue(true);
mockUseKibanaReturnValue.services.uiSettings.get.mockImplementation((key) => {
if (key === ENABLE_ALERTS_AND_ATTACKS_ALIGNMENT_SETTING) {
return true;
}
return false;
});

render(
<TestProviders>
Expand All @@ -333,7 +342,12 @@ describe('AttackDiscovery', () => {
});

it('does not render callout about new Attacks page when feature is disabled', () => {
mockUseKibanaReturnValue.services.featureFlags.getBooleanValue.mockReturnValue(false);
mockUseKibanaReturnValue.services.uiSettings.get.mockImplementation((key) => {
if (key === ENABLE_ALERTS_AND_ATTACKS_ALIGNMENT_SETTING) {
return false;
}
return false;
});

render(
<TestProviders>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@ import type { Filter, Query } from '@kbn/es-query';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import useLocalStorage from 'react-use/lib/useLocalStorage';

import { ATTACKS_ALERTS_ALIGNMENT_ENABLED, SecurityPageName } from '../../../common/constants';
import {
ENABLE_ALERTS_AND_ATTACKS_ALIGNMENT_SETTING,
SecurityPageName,
} from '../../../common/constants';
import { HeaderPage } from '../../common/components/header_page';
import { useInvalidFilterQuery } from '../../common/hooks/use_invalid_filter_query';
import { useKibana } from '../../common/lib/kibana';
Expand All @@ -52,7 +55,7 @@ export const ID = 'attackDiscoveryQuery';

const AttackDiscoveryPageComponent: React.FC = () => {
const {
services: { featureFlags, uiSettings, settings },
services: { uiSettings, settings },
} = useKibana();

const { http, inferenceEnabled } = useAssistantContext();
Expand Down Expand Up @@ -224,8 +227,8 @@ const AttackDiscoveryPageComponent: React.FC = () => {

const onClose = useCallback(() => setShowFlyout(false), []);

const attacksAlertsAlignmentEnabled = featureFlags.getBooleanValue(
ATTACKS_ALERTS_ALIGNMENT_ENABLED,
const enableAlertsAndAttacksAlignment = uiSettings.get(
ENABLE_ALERTS_AND_ATTACKS_ALIGNMENT_SETTING,
false
);

Expand All @@ -251,7 +254,7 @@ const AttackDiscoveryPageComponent: React.FC = () => {

<EuiSpacer size="s" />

{attacksAlertsAlignmentEnabled && (
{enableAlertsAndAttacksAlignment && (
<>
<MovingAttacksCallout />
<EuiSpacer size="s" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,16 @@ import { useKibana } from '../../../common/lib/kibana';
jest.mock('../../../common/lib/kibana');

describe('PageTitle', () => {
const mockGetBooleanValue = jest.fn();
const mockGetSetting = jest.fn();

beforeEach(() => {
jest.clearAllMocks();
(useKibana as jest.Mock).mockReturnValue({
services: {
featureFlags: { getBooleanValue: mockGetBooleanValue },
uiSettings: { get: mockGetSetting },
},
});
mockGetBooleanValue.mockReturnValue(false);
mockGetSetting.mockReturnValue(false);
});

it('renders the expected title', () => {
Expand All @@ -36,16 +36,16 @@ describe('PageTitle', () => {
});

describe('Attacks page announcement', () => {
it('renders the Attacks page announcement when `attacksAlertsAlignmentEnabled` feature flag is enabled', () => {
mockGetBooleanValue.mockReturnValue(true);
it('renders the Attacks page announcement when `enableAlertsAndAttacksAlignment` setting is enabled', () => {
mockGetSetting.mockReturnValue(true);

render(<PageTitle />);

expect(screen.getByTestId('attackDiscoveryAnnouncementBadge')).toBeInTheDocument();
});

it('does not render the Attacks page announcement when `attacksAlertsAlignmentEnabled` feature flag is disabled', () => {
mockGetBooleanValue.mockReturnValue(false);
it('does not render the Attacks page announcement when `enableAlertsAndAttacksAlignment` setting is disabled', () => {
mockGetSetting.mockReturnValue(false);

render(<PageTitle />);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,19 @@ import { EuiBetaBadge, EuiFlexGroup, EuiFlexItem, EuiTitle, useEuiTheme } from '
import { css } from '@emotion/react';
import React from 'react';

import { ATTACKS_ALERTS_ALIGNMENT_ENABLED } from '@kbn/security-solution-navigation';
import { ENABLE_ALERTS_AND_ATTACKS_ALIGNMENT_SETTING } from '@kbn/security-solution-navigation';
import { useKibana } from '../../../common/lib/kibana';
import * as i18n from './translations';
import { IconAnnouncementBadge } from './announcement_badge';

const PageTitleComponent: React.FC = () => {
const { euiTheme } = useEuiTheme();
const {
services: { featureFlags },
services: { uiSettings },
} = useKibana();

const attacksAlertsAlignmentEnabled = featureFlags.getBooleanValue(
ATTACKS_ALERTS_ALIGNMENT_ENABLED,
const enableAlertsAndAttacksAlignment = uiSettings.get(
ENABLE_ALERTS_AND_ATTACKS_ALIGNMENT_SETTING,
false
);

Expand All @@ -33,7 +33,7 @@ const PageTitleComponent: React.FC = () => {
</EuiTitle>
</EuiFlexItem>

{attacksAlertsAlignmentEnabled && (
{enableAlertsAndAttacksAlignment && (
<EuiFlexItem
css={css`
margin: ${euiTheme.size.s} 0 0 ${euiTheme.size.m};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { LinkCategoryType, type SeparatorLinkCategory } from '@kbn/security-solu
import { SecurityPageName } from '../../../../../common';

export const getNavCategories = (
attacksAlertsAlignmentEnabled?: boolean
enableAlertsAndAttacksAlignment?: boolean
): SeparatorLinkCategory[] => {
return [
{
Expand All @@ -20,7 +20,9 @@ export const getNavCategories = (
type: LinkCategoryType.separator,
linkIds: [
SecurityPageName.rulesLanding,
attacksAlertsAlignmentEnabled ? SecurityPageName.alertDetections : SecurityPageName.alerts,
enableAlertsAndAttacksAlignment
? SecurityPageName.alertDetections
: SecurityPageName.alerts,
SecurityPageName.attackDiscovery,
SecurityPageName.cloudSecurityPostureFindings,
SecurityPageName.case,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -242,4 +242,26 @@ describe('SecuritySideNav', () => {
);
});
});

describe('enableAlertsAndAttacksAlignment setting', () => {
it('should call getNavCategories with true when setting is enabled', () => {
useKibana().services.uiSettings.get = jest.fn().mockReturnValue(true);
renderNav();
expect(mockSolutionSideNav).toHaveBeenCalledWith(
expect.objectContaining({
categories: getNavCategories(true),
})
);
});

it('should call getNavCategories with false when setting is disabled', () => {
useKibana().services.uiSettings.get = jest.fn().mockReturnValue(false);
renderNav();
expect(mockSolutionSideNav).toHaveBeenCalledWith(
expect.objectContaining({
categories: getNavCategories(false),
})
);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
type SolutionSideNavItem,
} from '@kbn/security-solution-side-nav';
import useObservable from 'react-use/lib/useObservable';
import { ATTACKS_ALERTS_ALIGNMENT_ENABLED } from '../../../../../common/constants';
import { ENABLE_ALERTS_AND_ATTACKS_ALIGNMENT_SETTING } from '../../../../../common/constants';
import { SecurityPageName } from '../../../../app/types';
import type { NavigationLink } from '../../../links';
import { useRouteSpy } from '../../../utils/route/use_route_spy';
Expand Down Expand Up @@ -135,19 +135,19 @@ const usePanelBottomOffset = (): string | undefined => {
* It takes the links to render from the generic application `links` configs.
*/
export const SecuritySideNav: React.FC = () => {
const { featureFlags } = useKibana().services;
const { uiSettings } = useKibana().services;
const items = useSolutionSideNavItems();
const selectedId = useSelectedId();
const panelTopOffset = usePanelTopOffset();
const panelBottomOffset = usePanelBottomOffset();

const categories = useMemo(() => {
const attacksAlertsAlignmentEnabled = featureFlags.getBooleanValue(
ATTACKS_ALERTS_ALIGNMENT_ENABLED,
const enableAlertsAndAttacksAlignment = uiSettings.get(
ENABLE_ALERTS_AND_ATTACKS_ALIGNMENT_SETTING,
false
);
return getNavCategories(attacksAlertsAlignmentEnabled);
}, [featureFlags]);
return getNavCategories(enableAlertsAndAttacksAlignment);
}, [uiSettings]);

if (!items) {
return <EuiLoadingSpinner size="m" data-test-subj="sideNavLoader" />;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
addListener as originalAddListener,
removeListener as originalRemoveListener,
} from '@reduxjs/toolkit';
import { ATTACKS_ALERTS_ALIGNMENT_ENABLED } from '../../../common/constants';
import { ENABLE_ALERTS_AND_ATTACKS_ALIGNMENT_SETTING } from '../../../common/constants';
import type { RootState } from '../redux/reducer';
import { useKibana } from '../../common/lib/kibana';
import { createDataViewSelectedListener } from '../redux/listeners/data_view_selected';
Expand Down Expand Up @@ -44,8 +44,8 @@ export const useInitDataViewManager = () => {
const dispatch = useDispatch();
const services = useKibana().services;
const newDataViewPickerEnabled = useIsExperimentalFeatureEnabled('newDataViewPickerEnabled');
const attacksAlertsAlignmentEnabled = services.featureFlags.getBooleanValue(
ATTACKS_ALERTS_ALIGNMENT_ENABLED,
const enableAlertsAndAttacksAlignment = services.uiSettings.get(
ENABLE_ALERTS_AND_ATTACKS_ALIGNMENT_SETTING,
false
);

Expand Down Expand Up @@ -103,7 +103,7 @@ export const useInitDataViewManager = () => {
storage: services.storage,
logger: createInitListenerLogger,
},
attacksAlertsAlignmentEnabled
enableAlertsAndAttacksAlignment
);

logger.debug('Registering data view manager listeners');
Expand Down Expand Up @@ -144,7 +144,7 @@ export const useInitDataViewManager = () => {
});
};
}, [
attacksAlertsAlignmentEnabled,
enableAlertsAndAttacksAlignment,
dispatch,
logger,
newDataViewPickerEnabled,
Expand Down
Loading
Loading