Skip to content

Commit 10cfa31

Browse files
[AI4DSOC] Fix link to the new integrations page (#219030)
## Summary This PR fixes the links to the integrations page, introduced in [this PR](#215246) and [that one](#215266). At the time of the previous PRs, the new AI4DSOC integration page had not been created, so we were using the link to the normal integrations page. [This recent PR](#217905) added the new page, so we need to update those links From the landing page https://github.com/user-attachments/assets/907c12be-84dc-4bbd-a161-c8b16e2ecdba From the alert summary page https://github.com/user-attachments/assets/c25be7b3-f7ef-4e5f-8948-40def6a8d026 ## How to test This needs to be ran in Serverless: - `yarn es serverless --projectType security` - `yarn serverless-security --no-base-path` You also need to enable the AI for SOC tier, by adding the following to your `serverless.security.dev.yaml` file: ``` xpack.securitySolutionServerless.productTypes: [ { product_line: 'ai_soc', product_tier: 'search_ai_lake' }, ] ``` Use one of these Serverless users: - `platform_engineer` - `endpoint_operations_analyst` - `endpoint_policy_manager` - `admin` - `system_indices_superuser` Then: - generate data: `yarn test:generate:serverless-dev` - create 4 catch all rules, each with a name of a AI for SOC integration (`google_secops`, `microsoft_sentinel`,, `sentinel_one` and `crowdstrike`) - change [this line](https://github.com/elastic/kibana/blob/main/x-pack/solutions/security/plugins/security_solution/public/detections/hooks/alert_summary/use_fetch_integrations.ts#L73) to `installedPackages: availablePackages` to force having some packages installed - change [this line](https://github.com/elastic/kibana/blob/main/x-pack/solutions/security/plugins/security_solution/public/detections/hooks/alert_summary/use_integrations.ts#L63) to `r.name === p.name` to make sure there will be matches between integrations and rules ### Checklist - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios Relates to elastic/security-team#11955
1 parent 8eba73c commit 10cfa31

7 files changed

Lines changed: 90 additions & 40 deletions

File tree

x-pack/solutions/security/plugins/security_solution/public/detections/components/alert_summary/integrations/integration_section.test.tsx

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ import {
1414
CARD_TEST_ID,
1515
IntegrationSection,
1616
} from './integration_section';
17-
import { useAddIntegrationsUrl } from '../../../../common/hooks/use_add_integrations_url';
1817
import { useIntegrationsLastActivity } from '../../../hooks/alert_summary/use_integrations_last_activity';
1918
import { useKibana } from '@kbn/kibana-react-plugin/public';
19+
import { useNavigateToIntegrationsPage } from '../../../hooks/alert_summary/use_navigate_to_integrations_page';
2020

21-
jest.mock('../../../../common/hooks/use_add_integrations_url');
21+
jest.mock('../../../hooks/alert_summary/use_navigate_to_integrations_page');
2222
jest.mock('../../../hooks/alert_summary/use_integrations_last_activity');
2323
jest.mock('@kbn/kibana-react-plugin/public');
2424

@@ -45,7 +45,6 @@ describe('<IntegrationSection />', () => {
4545
beforeEach(() => {
4646
(useKibana as jest.Mock).mockReturnValue({
4747
services: {
48-
application: { navigateToApp: jest.fn() },
4948
http: {
5049
basePath: {
5150
prepend: jest.fn().mockReturnValue('/app/integrations/detail/splunk-0.1.0/overview'),
@@ -56,7 +55,7 @@ describe('<IntegrationSection />', () => {
5655
});
5756

5857
it('should render a card for each integration ', () => {
59-
(useAddIntegrationsUrl as jest.Mock).mockReturnValue({ onClick: jest.fn() });
58+
(useNavigateToIntegrationsPage as jest.Mock).mockReturnValue(jest.fn());
6059
(useIntegrationsLastActivity as jest.Mock).mockReturnValue({
6160
isLoading: true,
6261
lastActivities: {},
@@ -69,16 +68,14 @@ describe('<IntegrationSection />', () => {
6968
});
7069

7170
it('should navigate to the fleet page when clicking on the add integrations button', () => {
72-
const addIntegration = jest.fn();
73-
(useAddIntegrationsUrl as jest.Mock).mockReturnValue({
74-
onClick: addIntegration,
75-
});
71+
const navigateToIntegrationsPage = jest.fn();
72+
(useNavigateToIntegrationsPage as jest.Mock).mockReturnValue(navigateToIntegrationsPage);
7673
(useIntegrationsLastActivity as jest.Mock).mockReturnValue([]);
7774

7875
const { getByTestId } = render(<IntegrationSection packages={[]} />);
7976

8077
getByTestId(ADD_INTEGRATIONS_BUTTON_TEST_ID).click();
8178

82-
expect(addIntegration).toHaveBeenCalled();
79+
expect(navigateToIntegrationsPage).toHaveBeenCalled();
8380
});
8481
});

x-pack/solutions/security/plugins/security_solution/public/detections/components/alert_summary/integrations/integration_section.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import { i18n } from '@kbn/i18n';
1111
import type { PackageListItem } from '@kbn/fleet-plugin/common';
1212
import { useIntegrationsLastActivity } from '../../../hooks/alert_summary/use_integrations_last_activity';
1313
import { IntegrationCard } from './integration_card';
14-
import { useAddIntegrationsUrl } from '../../../../common/hooks/use_add_integrations_url';
14+
import { useNavigateToIntegrationsPage } from '../../../hooks/alert_summary/use_navigate_to_integrations_page';
1515

1616
const ADD_INTEGRATION = i18n.translate(
1717
'xpack.securitySolution.alertSummary.integrations.addIntegrationButtonLabel',
@@ -36,7 +36,7 @@ export interface IntegrationSectionProps {
3636
* Each integration card is also displaying the last time the sync happened (using streams).
3737
*/
3838
export const IntegrationSection = memo(({ packages }: IntegrationSectionProps) => {
39-
const { onClick: addIntegration } = useAddIntegrationsUrl(); // TODO this link might have to be revisited once the integration work is done
39+
const navigateToIntegrationsPage = useNavigateToIntegrationsPage();
4040
const { isLoading, lastActivities } = useIntegrationsLastActivity({ packages });
4141

4242
return (
@@ -59,7 +59,7 @@ export const IntegrationSection = memo(({ packages }: IntegrationSectionProps) =
5959
<EuiButtonEmpty
6060
data-test-subj={ADD_INTEGRATIONS_BUTTON_TEST_ID}
6161
iconType="plusInCircle"
62-
onClick={addIntegration}
62+
onClick={navigateToIntegrationsPage}
6363
>
6464
{ADD_INTEGRATION}
6565
</EuiButtonEmpty>

x-pack/solutions/security/plugins/security_solution/public/detections/components/alert_summary/landing_page/landing_page.test.tsx

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,11 @@ import {
1414
LANDING_PAGE_VIEW_ALL_INTEGRATIONS_BUTTON_TEST_ID,
1515
LandingPage,
1616
} from './landing_page';
17-
import { useAddIntegrationsUrl } from '../../../../common/hooks/use_add_integrations_url';
1817
import type { PackageListItem } from '@kbn/fleet-plugin/common';
1918
import { installationStatuses } from '@kbn/fleet-plugin/common/constants';
20-
import { useKibana } from '../../../../common/lib/kibana';
19+
import { useNavigateToIntegrationsPage } from '../../../hooks/alert_summary/use_navigate_to_integrations_page';
2120

22-
jest.mock('../../../../common/hooks/use_add_integrations_url');
23-
jest.mock('../../../../common/lib/kibana');
21+
jest.mock('../../../hooks/alert_summary/use_navigate_to_integrations_page');
2422

2523
const packages: PackageListItem[] = [
2624
{
@@ -47,16 +45,8 @@ const packages: PackageListItem[] = [
4745
];
4846

4947
describe('<LandingPage />', () => {
50-
beforeEach(() => {
51-
(useKibana as jest.Mock).mockReturnValue({
52-
services: { application: { navigateToApp: jest.fn() } },
53-
});
54-
});
55-
5648
it('should render all the components', () => {
57-
(useAddIntegrationsUrl as jest.Mock).mockReturnValue({
58-
onClick: jest.fn(),
59-
});
49+
(useNavigateToIntegrationsPage as jest.Mock).mockReturnValue(jest.fn());
6050

6151
const { getByTestId, queryByTestId } = render(<LandingPage packages={packages} />);
6252

@@ -75,14 +65,12 @@ describe('<LandingPage />', () => {
7565
});
7666

7767
it('should navigate to the fleet page when clicking on the more integrations button', () => {
78-
const moreIntegrations = jest.fn();
79-
(useAddIntegrationsUrl as jest.Mock).mockReturnValue({
80-
onClick: moreIntegrations,
81-
});
68+
const navigateToIntegrationsPage = jest.fn();
69+
(useNavigateToIntegrationsPage as jest.Mock).mockReturnValue(navigateToIntegrationsPage);
8270

8371
const { getByTestId } = render(<LandingPage packages={packages} />);
8472

8573
getByTestId(LANDING_PAGE_VIEW_ALL_INTEGRATIONS_BUTTON_TEST_ID).click();
86-
expect(moreIntegrations).toHaveBeenCalled();
74+
expect(navigateToIntegrationsPage).toHaveBeenCalled();
8775
});
8876
});

x-pack/solutions/security/plugins/security_solution/public/detections/components/alert_summary/landing_page/landing_page.tsx

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ import {
1919
} from '@elastic/eui';
2020
import type { PackageListItem } from '@kbn/fleet-plugin/common';
2121
import { i18n } from '@kbn/i18n';
22-
import { useAddIntegrationsUrl } from '../../../../common/hooks/use_add_integrations_url';
2322
import { IntegrationCard } from './integration_card';
2423
import imageSrc from './alert_summary.png';
24+
import { useNavigateToIntegrationsPage } from '../../../hooks/alert_summary/use_navigate_to_integrations_page';
2525

2626
const TITLE = i18n.translate('xpack.securitySolution.alertSummary.landingPage.title', {
2727
defaultMessage: 'All your alerts in one place with AI',
@@ -39,10 +39,7 @@ const VIEW_ALL_INTEGRATIONS = i18n.translate(
3939
}
4040
);
4141

42-
const PRIMARY_INTEGRATIONS = [
43-
'splunk', // doesnt yet exist
44-
'google_secops',
45-
];
42+
const PRIMARY_INTEGRATIONS = ['splunk', 'google_secops'];
4643

4744
export const LANDING_PAGE_PROMPT_TEST_ID = 'alert-summary-landing-page-prompt';
4845
export const LANDING_PAGE_IMAGE_TEST_ID = 'alert-summary-landing-page-image';
@@ -63,7 +60,7 @@ export interface LandingPageProps {
6360
*/
6461
export const LandingPage = memo(({ packages }: LandingPageProps) => {
6562
const { euiTheme } = useEuiTheme();
66-
const { onClick: moreIntegrations } = useAddIntegrationsUrl(); // TODO this link might have to be revisited once the integration work is done
63+
const navigateToIntegrationsPage = useNavigateToIntegrationsPage();
6764

6865
// We only want to show the 2 top integrations, Splunk and GoogleSecOps, in that specific order
6966
const primaryPackages = useMemo(
@@ -141,7 +138,7 @@ export const LandingPage = memo(({ packages }: LandingPageProps) => {
141138
<EuiButtonEmpty
142139
data-test-subj={LANDING_PAGE_VIEW_ALL_INTEGRATIONS_BUTTON_TEST_ID}
143140
iconType="plusInCircle"
144-
onClick={moreIntegrations}
141+
onClick={navigateToIntegrationsPage}
145142
>
146143
{VIEW_ALL_INTEGRATIONS}
147144
</EuiButtonEmpty>

x-pack/solutions/security/plugins/security_solution/public/detections/components/alert_summary/wrapper.test.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@ import {
1818
} from './wrapper';
1919
import { useKibana } from '../../../common/lib/kibana';
2020
import { TestProviders } from '../../../common/mock';
21-
import { useAddIntegrationsUrl } from '../../../common/hooks/use_add_integrations_url';
2221
import { useIntegrationsLastActivity } from '../../hooks/alert_summary/use_integrations_last_activity';
2322
import { ADD_INTEGRATIONS_BUTTON_TEST_ID } from './integrations/integration_section';
2423
import { SEARCH_BAR_TEST_ID } from './search_bar/search_bar_section';
2524
import { KPIS_SECTION } from './kpis/kpis_section';
2625
import { GROUPED_TABLE_TEST_ID } from './table/table_section';
26+
import { useNavigateToIntegrationsPage } from '../../hooks/alert_summary/use_navigate_to_integrations_page';
2727

2828
jest.mock('../../../common/components/search_bar', () => ({
2929
// The module factory of `jest.mock()` is not allowed to reference any out-of-scope variables so we can't use SEARCH_BAR_TEST_ID
@@ -33,7 +33,7 @@ jest.mock('../alerts_table/alerts_grouping', () => ({
3333
GroupedAlertsTable: () => <div />,
3434
}));
3535
jest.mock('../../../common/lib/kibana');
36-
jest.mock('../../../common/hooks/use_add_integrations_url');
36+
jest.mock('../../hooks/alert_summary/use_navigate_to_integrations_page');
3737
jest.mock('../../hooks/alert_summary/use_integrations_last_activity');
3838

3939
const packages: PackageListItem[] = [
@@ -98,7 +98,7 @@ describe('<Wrapper />', () => {
9898
});
9999

100100
it('should render the content if the dataView is created correctly', async () => {
101-
(useAddIntegrationsUrl as jest.Mock).mockReturnValue({ onClick: jest.fn() });
101+
(useNavigateToIntegrationsPage as jest.Mock).mockReturnValue(jest.fn());
102102
(useIntegrationsLastActivity as jest.Mock).mockReturnValue({
103103
isLoading: true,
104104
lastActivities: {},
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
import { renderHook } from '@testing-library/react';
9+
import {
10+
INTEGRATIONS_URL,
11+
useNavigateToIntegrationsPage,
12+
} from './use_navigate_to_integrations_page';
13+
import { useKibana, useNavigateTo } from '../../../common/lib/kibana';
14+
15+
jest.mock('../../../common/lib/kibana');
16+
17+
describe('useNavigateToIntegrationsPage', () => {
18+
it('should return function', () => {
19+
(useKibana as jest.Mock).mockReturnValue({
20+
services: {
21+
http: {
22+
basePath: {
23+
prepend: jest.fn().mockImplementation((url) => url),
24+
},
25+
},
26+
},
27+
});
28+
const navigateTo = jest.fn();
29+
(useNavigateTo as jest.Mock).mockReturnValue({ navigateTo });
30+
31+
const { result } = renderHook(() => useNavigateToIntegrationsPage());
32+
33+
expect(typeof result.current).toBe('function');
34+
result.current();
35+
expect(navigateTo).toHaveBeenCalledWith({
36+
url: INTEGRATIONS_URL,
37+
});
38+
});
39+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
import { useCallback } from 'react';
9+
import { useKibana, useNavigateTo } from '../../../common/lib/kibana';
10+
11+
export const INTEGRATIONS_URL = '/app/security/configurations/integrations/browse';
12+
13+
/**
14+
* Hook that returns a callback event to navigate to the AI4DSOC integrations page
15+
*/
16+
export const useNavigateToIntegrationsPage = (): (() => void) => {
17+
const {
18+
services: {
19+
http: {
20+
basePath: { prepend },
21+
},
22+
},
23+
} = useKibana();
24+
const { navigateTo } = useNavigateTo();
25+
26+
return useCallback(() => {
27+
navigateTo({ url: prepend(INTEGRATIONS_URL) });
28+
}, [navigateTo, prepend]);
29+
};

0 commit comments

Comments
 (0)