Skip to content

Commit

Permalink
[Security Solution][Expandable flyout] - replace advanced settings wi…
Browse files Browse the repository at this point in the history
…th feature flag (#184169)
  • Loading branch information
PhilippeOberti authored Jun 4, 2024
1 parent d2c30ba commit 506ff4c
Show file tree
Hide file tree
Showing 54 changed files with 462 additions and 656 deletions.
3 changes: 0 additions & 3 deletions packages/kbn-management/settings/setting_ids/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,9 +174,6 @@ export const SECURITY_SOLUTION_ENABLE_CCS_WARNING_ID = 'securitySolution:enableC
export const SECURITY_SOLUTION_SHOW_RELATED_INTEGRATIONS_ID =
'securitySolution:showRelatedIntegrations';
export const SECURITY_SOLUTION_DEFAULT_ALERT_TAGS_KEY = 'securitySolution:alertTags' as const;
/** This Kibana Advanced Setting allows users to enable/disable the Expandable Flyout */
export const SECURITY_SOLUTION_ENABLE_EXPANDABLE_FLYOUT_SETTING =
'securitySolution:enableExpandableFlyout' as const;
/** This Kibana Advanced Setting allows users to enable/disable querying cold and frozen data tiers in analyzer */
export const SECURITY_SOLUTION_EXCLUDE_COLD_AND_FROZEN_TIERS_IN_ANALYZER =
'securitySolution:excludeColdAndFrozenTiersInAnalyzer' as const;
Expand Down
1 change: 0 additions & 1 deletion packages/serverless/settings/security_project/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ export const SECURITY_PROJECT_SETTINGS = [
settings.SECURITY_SOLUTION_NEWS_FEED_URL_ID,
settings.SECURITY_SOLUTION_ENABLE_NEWS_FEED_ID,
settings.SECURITY_SOLUTION_DEFAULT_ALERT_TAGS_KEY,
settings.SECURITY_SOLUTION_ENABLE_EXPANDABLE_FLYOUT_SETTING,
settings.SECURITY_SOLUTION_ENABLE_ASSET_CRITICALITY_SETTING,
settings.SECURITY_SOLUTION_EXCLUDE_COLD_AND_FROZEN_TIERS_IN_ANALYZER,
];
Original file line number Diff line number Diff line change
Expand Up @@ -110,10 +110,6 @@ export const stackManagementSchema: MakeSchemaFrom<UsageStats> = {
type: 'boolean',
_meta: { description: 'Non-default value of setting.' },
},
'securitySolution:enableExpandableFlyout': {
type: 'boolean',
_meta: { description: 'Non-default value of setting.' },
},
'securitySolution:enableAssetCriticality': {
type: 'boolean',
_meta: { description: 'Non-default value of setting.' },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ export interface UsageStats {
'securitySolution:defaultAnomalyScore': number;
'securitySolution:refreshIntervalDefaults': string;
'securitySolution:enableNewsFeed': boolean;
'securitySolution:enableExpandableFlyout': boolean;
'securitySolution:enableAssetCriticality': boolean;
'securitySolution:excludeColdAndFrozenTiersInAnalyzer': boolean;
'securitySolution:enableCcsWarning': boolean;
Expand Down
6 changes: 0 additions & 6 deletions src/plugins/telemetry/schema/oss_plugins.json
Original file line number Diff line number Diff line change
Expand Up @@ -9630,12 +9630,6 @@
"description": "Non-default value of setting."
}
},
"securitySolution:enableExpandableFlyout": {
"type": "boolean",
"_meta": {
"description": "Non-default value of setting."
}
},
"securitySolution:enableAssetCriticality": {
"type": "boolean",
"_meta": {
Expand Down
3 changes: 0 additions & 3 deletions x-pack/plugins/security_solution/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,9 +168,6 @@ export const DEFAULT_INDEX_PATTERN = [...INCLUDE_INDEX_PATTERN, ...EXCLUDE_ELAST
/** This Kibana Advanced Setting enables the `Security news` feed widget */
export const ENABLE_NEWS_FEED_SETTING = 'securitySolution:enableNewsFeed' as const;

/** This Kibana Advanced Setting allows users to enable/disable the Expandable Flyout */
export const ENABLE_EXPANDABLE_FLYOUT_SETTING = 'securitySolution:enableExpandableFlyout' as const;

/** This Kibana Advanced Setting allows users to enable/disable querying cold and frozen data tiers in analyzer */
export const EXCLUDE_COLD_AND_FROZEN_TIERS_IN_ANALYZER =
'securitySolution:excludeColdAndFrozenTiersInAnalyzer' as const;
Expand Down
27 changes: 3 additions & 24 deletions x-pack/plugins/security_solution/common/experimental_features.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,20 +110,9 @@ export const allowedExperimentalValues = Object.freeze({
alertTypeEnabled: false,

/**
* Enables expandable flyout in create rule page, alert preview
* Disables expandable flyout
*/
expandableFlyoutInCreateRuleEnabled: true,

/**
* Enables expandable flyout for event type documents
*/
expandableEventFlyoutEnabled: true,

/**
* Enables expandable flyout in timeline
*/
expandableTimelineFlyoutEnabled: true,
/*
expandableFlyoutDisabled: false,

/**
* Enables the Assistant Model Evaluation advanced setting and API endpoint, introduced in `8.11.0`.
Expand All @@ -135,22 +124,12 @@ export const allowedExperimentalValues = Object.freeze({
*/
assistantKnowledgeBaseByDefault: false,

/**
* Enables the new user details flyout displayed on the Alerts table.
*/
newUserDetailsFlyout: true,

/**
* Enables the Managed User section inside the new user details flyout.
* To see this section you also need newUserDetailsFlyout flag enabled.
* To see this section you also need expandableFlyoutDisabled flag set to false.
*/
newUserDetailsFlyoutManagedUser: false,

/**
* Enables the new host details flyout displayed on the Alerts table.
*/
newHostDetailsFlyout: true,

/**
* Enable risk engine client and initialisation of datastream, component templates and mappings
*/
Expand Down
15 changes: 5 additions & 10 deletions x-pack/plugins/security_solution/public/cases/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import React, { useCallback, useEffect, useMemo, useRef } from 'react';
import { useDispatch } from 'react-redux';
import type { CaseViewRefreshPropInterface } from '@kbn/cases-plugin/common';
import { CaseMetricsFeature } from '@kbn/cases-plugin/common';
import { useUiSetting$ } from '@kbn/kibana-react-plugin/public';
import { useExpandableFlyoutApi } from '@kbn/expandable-flyout';
import { useIsExperimentalFeatureEnabled } from '../../common/hooks/use_experimental_features';
import { DocumentDetailsRightPanelKey } from '../../flyout/document_details/shared/constants/panel_keys';
import { useTourContext } from '../../common/components/guided_onboarding_tour';
import {
Expand All @@ -22,12 +22,7 @@ import { TimelineId } from '../../../common/types/timeline';
import { getRuleDetailsUrl, useFormatUrl } from '../../common/components/link_to';

import { useKibana, useNavigation } from '../../common/lib/kibana';
import {
APP_ID,
CASES_PATH,
ENABLE_EXPANDABLE_FLYOUT_SETTING,
SecurityPageName,
} from '../../../common/constants';
import { APP_ID, CASES_PATH, SecurityPageName } from '../../../common/constants';
import { timelineActions } from '../../timelines/store';
import { useSourcererDataView } from '../../sourcerer/containers';
import { SourcererScopeName } from '../../sourcerer/store/model';
Expand Down Expand Up @@ -63,7 +58,7 @@ const CaseContainerComponent: React.FC = () => {
SecurityPageName.rules
);
const { openFlyout } = useExpandableFlyoutApi();
const [isSecurityFlyoutEnabled] = useUiSetting$<boolean>(ENABLE_EXPANDABLE_FLYOUT_SETTING);
const expandableFlyoutDisabled = useIsExperimentalFeatureEnabled('expandableFlyoutDisabled');

const getDetectionsRuleDetailsHref = useCallback(
(ruleId) => detectionsFormatUrl(getRuleDetailsUrl(ruleId ?? '', detectionsUrlSearch)),
Expand All @@ -74,7 +69,7 @@ const CaseContainerComponent: React.FC = () => {

const showAlertDetails = useCallback(
(alertId: string, index: string) => {
if (isSecurityFlyoutEnabled) {
if (!expandableFlyoutDisabled) {
openFlyout({
right: {
id: DocumentDetailsRightPanelKey,
Expand Down Expand Up @@ -105,7 +100,7 @@ const CaseContainerComponent: React.FC = () => {
);
}
},
[dispatch, isSecurityFlyoutEnabled, openFlyout, telemetry]
[dispatch, expandableFlyoutDisabled, openFlyout, telemetry]
);

const endpointDetailsHref = (endpointId: string) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { useRouteSpy } from '../../../utils/route/use_route_spy';
import type { RouteSpyState } from '../../../utils/route/types';
import { SecurityPageName } from '@kbn/deeplinks-security';
import { createTelemetryServiceMock } from '../../../lib/telemetry/telemetry_service.mock';
import { DocumentDetailsRightPanelKey } from '../../../../flyout/document_details/shared/constants/panel_keys';

const mockDispatch = jest.fn();
jest.mock('react-redux', () => {
Expand Down Expand Up @@ -114,18 +115,7 @@ describe('RowAction', () => {
expect(wrapper.getAllByTestId('expand-event')).not.toBeNull();
});

test('Uses the old flyout when the experimental feature returns false', () => {
const wrapper = render(
<TestProviders>
<RowAction {...defaultProps} />
</TestProviders>
);
fireEvent.click(wrapper.getByTestId('expand-event'));
expect(mockDispatch).toHaveBeenCalled();
expect(mockOpenFlyout).not.toHaveBeenCalled();
});

test('Uses the new flyout when the experimental feature returns false but the page is attackDiscovery', () => {
test('should always show expandable flyout if the page is attackDiscovery', () => {
(useRouteSpy as jest.Mock).mockReturnValue([
{ ...mockRouteSpy, pageName: SecurityPageName.attackDiscovery },
]);
Expand All @@ -136,6 +126,15 @@ describe('RowAction', () => {
);
fireEvent.click(wrapper.getByTestId('expand-event'));
expect(mockDispatch).not.toHaveBeenCalled();
expect(mockOpenFlyout).toHaveBeenCalled();
expect(mockOpenFlyout).toHaveBeenCalledWith({
right: {
id: DocumentDetailsRightPanelKey,
params: {
id: '1',
indexName: undefined,
scopeId: 'table-test',
},
},
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,10 @@ import React, { useCallback, useMemo } from 'react';
import { useDispatch } from 'react-redux';
import { useExpandableFlyoutApi } from '@kbn/expandable-flyout';
import { dataTableActions, TableId } from '@kbn/securitysolution-data-table';
import { useUiSetting$ } from '@kbn/kibana-react-plugin/public';
import { useRouteSpy } from '../../../utils/route/use_route_spy';
import { useKibana } from '../../../lib/kibana';
import { timelineActions } from '../../../../timelines/store';
import {
ENABLE_EXPANDABLE_FLYOUT_SETTING,
SecurityPageName,
} from '../../../../../common/constants';
import { SecurityPageName } from '../../../../../common/constants';
import { DocumentDetailsRightPanelKey } from '../../../../flyout/document_details/shared/constants/panel_keys';
import type {
SetEventsDeleted,
Expand Down Expand Up @@ -81,10 +77,6 @@ const RowActionComponent = ({

const dispatch = useDispatch();
const [{ pageName }] = useRouteSpy();
const [isSecurityFlyoutEnabled] = useUiSetting$<boolean>(ENABLE_EXPANDABLE_FLYOUT_SETTING);
const isExpandableFlyoutInCreateRuleEnabled = useIsExperimentalFeatureEnabled(
'expandableFlyoutInCreateRuleEnabled'
);
const { activeStep, isTourShown } = useTourContext();
const shouldFocusOnOverviewTab =
(activeStep === AlertsCasesTourSteps.expandEvent ||
Expand All @@ -106,16 +98,10 @@ const RowActionComponent = ({
[columnHeaders, timelineNonEcsData]
);

let showExpandableFlyout: boolean;

// disable the old flyout on attack discovery page
if (pageName === SecurityPageName.attackDiscovery) {
showExpandableFlyout = true;
} else if (tableId === TableId.rulePreview) {
showExpandableFlyout = isSecurityFlyoutEnabled && isExpandableFlyoutInCreateRuleEnabled;
} else {
showExpandableFlyout = isSecurityFlyoutEnabled;
}
// TODO remove when https://github.com/elastic/security-team/issues/7462 is merged
const expandableFlyoutDisabled = useIsExperimentalFeatureEnabled('expandableFlyoutDisabled');
const showExpandableFlyout =
pageName === SecurityPageName.attackDiscovery ? true : !expandableFlyoutDisabled;

const handleOnEventDetailPanelOpened = useCallback(() => {
const updatedExpandedDetail: ExpandedDetailType = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,11 @@ import {
tableDefaults,
dataTableActions,
} from '@kbn/securitysolution-data-table';
import { ENABLE_EXPANDABLE_FLYOUT_SETTING } from '../../../../common/constants';
import { useIsExperimentalFeatureEnabled } from '../use_experimental_features';
import { useInitializeUrlParam } from '../../utils/global_query_string';
import { URL_PARAM_KEY } from '../use_url_state';
import type { FlyoutUrlState } from './types';
import { useShallowEqualSelector } from '../use_selector';
import { useUiSetting$ } from '../../lib/kibana';
import { getQueryStringKeyValue } from '../timeline/use_query_timeline_by_id_on_url_change';

/**
Expand All @@ -31,7 +30,7 @@ import { getQueryStringKeyValue } from '../timeline/use_query_timeline_by_id_on_

export const useInitFlyoutFromUrlParam = () => {
const { search } = useLocation();
const [isSecurityFlyoutEnabled] = useUiSetting$<boolean>(ENABLE_EXPANDABLE_FLYOUT_SETTING);
const expandableFlyoutDisabled = useIsExperimentalFeatureEnabled('expandableFlyoutDisabled');
const [urlDetails, setUrlDetails] = useState<FlyoutUrlState | null>(null);
const [hasLoadedUrlDetails, updateHasLoadedUrlDetails] = useState(false);
const dispatch = useDispatch();
Expand All @@ -45,15 +44,15 @@ export const useInitFlyoutFromUrlParam = () => {

const onInitialize = useCallback(
(initialState: FlyoutUrlState | null) => {
if (!isSecurityFlyoutEnabled && initialState != null && initialState.panelView) {
if (expandableFlyoutDisabled && initialState != null && initialState.panelView) {
setUrlDetails(initialState);
}
},
[isSecurityFlyoutEnabled]
[expandableFlyoutDisabled]
);

const loadExpandedDetailFromUrl = useCallback(() => {
if (isSecurityFlyoutEnabled) return;
if (!expandableFlyoutDisabled) return;

const { initialized, isLoading, totalCount, additionalFilters } = dataTableCurrent;
const isTableLoaded = initialized && !isLoading && totalCount > 0;
Expand All @@ -78,21 +77,21 @@ export const useInitFlyoutFromUrlParam = () => {
);
}
}
}, [dataTableCurrent, dispatch, isSecurityFlyoutEnabled, urlDetails]);
}, [dataTableCurrent, dispatch, expandableFlyoutDisabled, urlDetails]);

// The alert page creates a default dataTable slice in redux initially that is later overriden when data is retrieved
// We use the below to store the urlDetails on app load, and then set it when the table is done loading and has data
useEffect(() => {
if (!isSecurityFlyoutEnabled && !hasLoadedUrlDetails) {
if (expandableFlyoutDisabled && !hasLoadedUrlDetails) {
loadExpandedDetailFromUrl();
}
}, [hasLoadedUrlDetails, isSecurityFlyoutEnabled, loadExpandedDetailFromUrl]);
}, [hasLoadedUrlDetails, expandableFlyoutDisabled, loadExpandedDetailFromUrl]);

// We check the url for the presence of the old `evenFlyout` parameter. If it exists replace it with the new `flyout` key.
const eventFlyoutKey = getQueryStringKeyValue({ urlKey: URL_PARAM_KEY.eventFlyout, search });
let currentKey = '';
let newKey = '';
if (!isSecurityFlyoutEnabled) {
if (expandableFlyoutDisabled) {
if (eventFlyoutKey) {
currentKey = URL_PARAM_KEY.eventFlyout;
newKey = URL_PARAM_KEY.flyout;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ import {
tableDefaults,
TableId,
} from '@kbn/securitysolution-data-table';
import { useUiSetting$ } from '@kbn/kibana-react-plugin/public';
import { ALERTS_PATH, ENABLE_EXPANDABLE_FLYOUT_SETTING } from '../../../../common/constants';
import { useIsExperimentalFeatureEnabled } from '../use_experimental_features';
import { ALERTS_PATH } from '../../../../common/constants';
import { useUpdateUrlParam } from '../../utils/global_query_string';
import { useShallowEqualSelector } from '../use_selector';
import { URL_PARAM_KEY } from '../use_url_state';
Expand All @@ -28,7 +28,7 @@ import type { FlyoutUrlState } from './types';
* // TODO remove this hook entirely when we delete the old flyout code
*/
export const useSyncFlyoutUrlParam = () => {
const [isSecurityFlyoutEnabled] = useUiSetting$<boolean>(ENABLE_EXPANDABLE_FLYOUT_SETTING);
const expandableFlyoutDisabled = useIsExperimentalFeatureEnabled('expandableFlyoutDisabled');
const updateUrlParam = useUpdateUrlParam<FlyoutUrlState>(URL_PARAM_KEY.flyout);
const { pathname } = useLocation();
const dispatch = useDispatch();
Expand All @@ -40,7 +40,7 @@ export const useSyncFlyoutUrlParam = () => {
);

useEffect(() => {
if (isSecurityFlyoutEnabled) return;
if (!expandableFlyoutDisabled) return;

const isOnAlertsPage = pathname === ALERTS_PATH;
if (isOnAlertsPage && expandedDetail != null && expandedDetail?.query) {
Expand All @@ -55,5 +55,5 @@ export const useSyncFlyoutUrlParam = () => {
// Clear the reference from the url
updateUrlParam(null);
}
}, [dispatch, expandedDetail, isSecurityFlyoutEnabled, pathname, updateUrlParam]);
}, [dispatch, expandedDetail, expandableFlyoutDisabled, pathname, updateUrlParam]);
};
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ describe('AlertDetailsRedirect', () => {
"(global:(linkTo:!(timeline,socTrends),timerange:(from:'2023-04-20T12:00:00.000Z',kind:absolute,to:'2023-04-20T12:05:00.000Z')),timeline:(linkTo:!(global,socTrends),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now/d,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now/d)))",
pageFilters:
'!((exclude:!f,existsSelected:!f,fieldName:kibana.alert.workflow_status,hideActionBar:!f,selectedOptions:!(),title:Status))',
flyout: '(panelView:eventDetail,params:(eventId:test-alert-id,indexName:.someTestIndex))',
flyout:
'(preview:!(),right:(id:document-details-right,params:(id:test-alert-id,indexName:.someTestIndex,scopeId:alerts-page)))',
});

expect(historyMock.replace).toHaveBeenCalledWith({
Expand Down Expand Up @@ -98,7 +99,8 @@ describe('AlertDetailsRedirect', () => {
"(global:(linkTo:!(timeline,socTrends),timerange:(from:'2020-07-07T08:20:18.966Z',kind:absolute,to:'2020-07-08T08:25:18.966Z')),timeline:(linkTo:!(global,socTrends),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now/d,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now/d)))",
pageFilters:
'!((exclude:!f,existsSelected:!f,fieldName:kibana.alert.workflow_status,hideActionBar:!f,selectedOptions:!(),title:Status))',
flyout: '(panelView:eventDetail,params:(eventId:test-alert-id,indexName:.someTestIndex))',
flyout:
'(preview:!(),right:(id:document-details-right,params:(id:test-alert-id,indexName:.someTestIndex,scopeId:alerts-page)))',
});

expect(historyMock.replace).toHaveBeenCalledWith({
Expand Down Expand Up @@ -136,7 +138,7 @@ describe('AlertDetailsRedirect', () => {
pageFilters:
'!((exclude:!f,existsSelected:!f,fieldName:kibana.alert.workflow_status,hideActionBar:!f,selectedOptions:!(),title:Status))',
flyout:
'(panelView:eventDetail,params:(eventId:test-alert-id,indexName:.internal.alerts-security.alerts-default))',
'(preview:!(),right:(id:document-details-right,params:(id:test-alert-id,indexName:.internal.alerts-security.alerts-default,scopeId:alerts-page)))',
});

expect(historyMock.replace).toHaveBeenCalledWith({
Expand Down
Loading

0 comments on commit 506ff4c

Please sign in to comment.