diff --git a/x-pack/plugins/security_solution/public/management/components/artifact_list_page/components/artifact_flyout.tsx b/x-pack/plugins/security_solution/public/management/components/artifact_list_page/components/artifact_flyout.tsx index 3fe20be2cbd64..f34bf54c1f15f 100644 --- a/x-pack/plugins/security_solution/public/management/components/artifact_list_page/components/artifact_flyout.tsx +++ b/x-pack/plugins/security_solution/public/management/components/artifact_list_page/components/artifact_flyout.tsx @@ -26,6 +26,8 @@ import { import type { EuiFlyoutSize } from '@elastic/eui/src/components/flyout/flyout'; import type { IHttpFetchError } from '@kbn/core-http-browser'; import { useIsMounted } from '@kbn/securitysolution-hook-utils'; +import { useLocation } from 'react-router-dom'; +import type { EndpointInsightRouteState } from '../../../pages/endpoint_hosts/types'; import { useUrlParams } from '../../../hooks/use_url_params'; import { useIsFlyoutOpened } from '../hooks/use_is_flyout_opened'; import { useTestIdGenerator } from '../../../hooks/use_test_id_generator'; @@ -196,7 +198,13 @@ export const ArtifactFlyout = memo( docLinks: { links: { securitySolution }, }, + application: { navigateToUrl }, } = useKibana().services; + + const location = useLocation(); + const [sourceInsight, setSourceInsight] = useState<{ id: string; back_url: string } | null>( + null + ); const getTestId = useTestIdGenerator(dataTestSubj); const toasts = useToasts(); const isFlyoutOpened = useIsFlyoutOpened(); @@ -293,7 +301,9 @@ export const ArtifactFlyout = memo( : labels.flyoutCreateSubmitSuccess(result) ); - if (isMounted()) { + if (sourceInsight?.back_url) { + navigateToUrl(sourceInsight.back_url); + } else if (isMounted()) { // Close the flyout // `undefined` will cause params to be dropped from url setUrlParams({ ...urlParams, itemId: undefined, show: undefined }, true); @@ -301,7 +311,17 @@ export const ArtifactFlyout = memo( onSuccess(); } }, - [isEditFlow, isMounted, labels, onSuccess, setUrlParams, toasts, urlParams] + [ + isEditFlow, + isMounted, + labels, + navigateToUrl, + onSuccess, + setUrlParams, + sourceInsight?.back_url, + toasts, + urlParams, + ] ); const handleSubmitClick = useCallback(() => { @@ -357,6 +377,16 @@ export const ArtifactFlyout = memo( } }, [formState, confirmModalOnSuccess]); + // If this form was opened from an endpoint insight, prepopulate the form with the insight data + useEffect(() => { + if (location.state?.insight) { + setSourceInsight({ id: 'mocked', back_url: location.state.insight.back_url }); + setFormState({ isValid: true, item: location.state.insight.item }); + + location.state.insight = undefined; + } + }, [apiClient.listId, location.state, location.state?.insight]); + // If we don't have the actual Artifact data yet for edit (in initialization phase - ex. came in with an // ID in the url that was not in the list), then retrieve it now useEffect(() => { diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/types.ts b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/types.ts index 415f05c417ca8..ec9d97b764fc4 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/types.ts +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/types.ts @@ -7,6 +7,7 @@ import type { DataViewBase } from '@kbn/es-query'; import type { GetInfoResponse } from '@kbn/fleet-plugin/common'; +import type { CreateExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types'; import type { AppLocation, EndpointPendingActions, @@ -155,3 +156,10 @@ export interface TransformStatsResponse { count: number; transforms: TransformStats[]; } + +export interface EndpointInsightRouteState { + insight?: { + back_url: string; + item: CreateExceptionListItemSchema; + }; +} diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/components/insights/workflow_insights_results.tsx b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/components/insights/workflow_insights_results.tsx index cb2f0bc0889a1..0180b3901794a 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/components/insights/workflow_insights_results.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/components/insights/workflow_insights_results.tsx @@ -22,6 +22,10 @@ import { WORKFLOW_INSIGHTS } from '../../../translations'; interface WorkflowInsightsResultsProps { results: boolean; } +import type { EndpointInsightRouteState } from '../../../../types'; +import { getEndpointDetailsPath } from '../../../../../../common/routing'; +import { useKibana } from '../../../../../../../common/lib/kibana'; +import { APP_PATH, TRUSTED_APPS_PATH } from '../../../../../../../../common/constants'; const CustomEuiCallOut = styled(EuiCallOut)` & .euiButtonIcon { @@ -32,9 +36,47 @@ const CustomEuiCallOut = styled(EuiCallOut)` export const WorkflowInsightsResults = ({ results }: WorkflowInsightsResultsProps) => { const [showEmptyResultsCallout, setShowEmptyResultsCallout] = useState(true); const hideEmptyStateCallout = () => setShowEmptyResultsCallout(false); - if (!results) { - return null; - } + const { + application: { navigateToUrl }, + } = useKibana().services; + + const openArtifactCreationPage = () => { + const url = `${APP_PATH}${TRUSTED_APPS_PATH}?show=create`; + const state: EndpointInsightRouteState = { + insight: { + back_url: `${APP_PATH}${getEndpointDetailsPath({ + name: 'endpointDetails', + selected_endpoint: '69f8c984-56bb-4f5d-b6fc-2f5673d93ec9', + })}`, + item: { + comments: [], + description: 'Test', + entries: [ + { + field: 'process.hash.*', + operator: 'included', + type: 'match', + value: 'aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d', + }, + ], + list_id: 'endpoint_trusted_apps', + name: 'Test', + namespace_type: 'agnostic', + tags: ['policy:all'], + type: 'simple', + os_types: ['windows'], + }, + }, + }; + navigateToUrl(url, { + state, + }); + }; + + const onInsightClick = (e: React.MouseEvent) => { + e.preventDefault(); + openArtifactCreationPage(); + }; return ( <> @@ -62,9 +104,8 @@ export const WorkflowInsightsResults = ({ results }: WorkflowInsightsResultsProp