diff --git a/x-pack/plugins/security_solution/common/constants.ts b/x-pack/plugins/security_solution/common/constants.ts index 7358fbb33b4b2..6357dfd766a4c 100644 --- a/x-pack/plugins/security_solution/common/constants.ts +++ b/x-pack/plugins/security_solution/common/constants.ts @@ -22,6 +22,7 @@ export const APP_ICON = 'securityAnalyticsApp' as const; export const APP_ICON_SOLUTION = 'logoSecurity' as const; export const APP_PATH = `/app/security` as const; export const ADD_DATA_PATH = `/app/integrations/browse/security`; +export const ADD_THREAT_INTELLIGENCE_DATA_PATH = `/app/integrations/browse/threat_intel`; export const DEFAULT_BYTES_FORMAT = 'format:bytes:defaultPattern' as const; export const DEFAULT_DATE_FORMAT = 'dateFormat' as const; export const DEFAULT_DATE_FORMAT_TZ = 'dateFormat:tz' as const; @@ -152,6 +153,7 @@ export const USERS_PATH = '/users' as const; export const KUBERNETES_PATH = '/kubernetes' as const; export const NETWORK_PATH = '/network' as const; export const MANAGEMENT_PATH = '/administration' as const; +export const THREAT_INTELLIGENCE_PATH = '/threat_intelligence' as const; export const ENDPOINTS_PATH = `${MANAGEMENT_PATH}/endpoints` as const; export const POLICIES_PATH = `${MANAGEMENT_PATH}/policy` as const; export const TRUSTED_APPS_PATH = `${MANAGEMENT_PATH}/trusted_apps` as const; diff --git a/x-pack/plugins/security_solution/public/app/home/global_header/index.test.tsx b/x-pack/plugins/security_solution/public/app/home/global_header/index.test.tsx index 87b0b5a7da6ed..bd5049909c95d 100644 --- a/x-pack/plugins/security_solution/public/app/home/global_header/index.test.tsx +++ b/x-pack/plugins/security_solution/public/app/home/global_header/index.test.tsx @@ -9,7 +9,12 @@ import { render } from '@testing-library/react'; import { useLocation } from 'react-router-dom'; import { useVariationMock } from '../../../common/components/utils.mocks'; import { GlobalHeader } from '.'; -import { ADD_DATA_PATH, SecurityPageName } from '../../../../common/constants'; +import { + ADD_DATA_PATH, + ADD_THREAT_INTELLIGENCE_DATA_PATH, + SecurityPageName, + THREAT_INTELLIGENCE_PATH, +} from '../../../../common/constants'; import { createSecuritySolutionStorageMock, mockGlobalState, @@ -98,6 +103,17 @@ describe('global header', () => { expect(link?.getAttribute('href')).toBe(ADD_DATA_PATH); }); + it('points to the threat_intel Add data URL for threat_intelligence url', () => { + (useLocation as jest.Mock).mockReturnValue({ pathname: THREAT_INTELLIGENCE_PATH }); + const { queryByTestId } = render( + + + + ); + const link = queryByTestId('add-data'); + expect(link?.getAttribute('href')).toBe(ADD_THREAT_INTELLIGENCE_DATA_PATH); + }); + it('points to the resolved Add data URL by useVariation', () => { (useLocation as jest.Mock).mockReturnValue([ { pageName: SecurityPageName.overview, detailName: undefined }, diff --git a/x-pack/plugins/security_solution/public/app/home/global_header/index.tsx b/x-pack/plugins/security_solution/public/app/home/global_header/index.tsx index 3b405df246601..37efdce430317 100644 --- a/x-pack/plugins/security_solution/public/app/home/global_header/index.tsx +++ b/x-pack/plugins/security_solution/public/app/home/global_header/index.tsx @@ -20,8 +20,8 @@ import { toMountPoint } from '@kbn/kibana-react-plugin/public'; import { useVariation } from '../../../common/components/utils'; import { MlPopover } from '../../../common/components/ml_popover/ml_popover'; import { useKibana } from '../../../common/lib/kibana'; -import { ADD_DATA_PATH } from '../../../../common/constants'; -import { isDetectionsPath } from '../../../helpers'; +import { ADD_DATA_PATH, ADD_THREAT_INTELLIGENCE_DATA_PATH } from '../../../../common/constants'; +import { isDetectionsPath, isThreatIntelligencePath } from '../../../helpers'; import { Sourcerer } from '../../../common/components/sourcerer'; import { TimelineId } from '../../../../common/types/timeline'; import { timelineDefaults } from '../../../timelines/store/timeline/defaults'; @@ -58,7 +58,10 @@ export const GlobalHeader = React.memo( const sourcererScope = getScopeFromPath(pathname); const showSourcerer = showSourcererByPath(pathname); - const [addIntegrationsUrl, setAddIntegrationsUrl] = useState(ADD_DATA_PATH); + const integrationsUrl = isThreatIntelligencePath(pathname) + ? ADD_THREAT_INTELLIGENCE_DATA_PATH + : ADD_DATA_PATH; + const [addIntegrationsUrl, setAddIntegrationsUrl] = useState(integrationsUrl); useVariation( cloudExperiments, 'security-solutions.add-integrations-url', diff --git a/x-pack/plugins/security_solution/public/helpers.tsx b/x-pack/plugins/security_solution/public/helpers.tsx index 4520f70e3ab76..df0a660f4def4 100644 --- a/x-pack/plugins/security_solution/public/helpers.tsx +++ b/x-pack/plugins/security_solution/public/helpers.tsx @@ -5,8 +5,8 @@ * 2.0. */ -import { ALERT_RULE_UUID, ALERT_RULE_NAME, ALERT_RULE_PARAMETERS } from '@kbn/rule-data-utils'; -import { has, get, isEmpty } from 'lodash/fp'; +import { ALERT_RULE_NAME, ALERT_RULE_PARAMETERS, ALERT_RULE_UUID } from '@kbn/rule-data-utils'; +import { get, has, isEmpty } from 'lodash/fp'; import React from 'react'; import type { RouteProps } from 'react-router-dom'; import { matchPath, Redirect } from 'react-router-dom'; @@ -15,12 +15,13 @@ import type { Capabilities, CoreStart } from '@kbn/core/public'; import { ALERTS_PATH, APP_UI_ID, + CASES_FEATURE_ID, + CASES_PATH, EXCEPTIONS_PATH, + LANDING_PATH, RULES_PATH, SERVER_APP_ID, - CASES_FEATURE_ID, - LANDING_PATH, - CASES_PATH, + THREAT_INTELLIGENCE_PATH, } from '../common/constants'; import type { Ecs } from '../common/ecs'; import type { @@ -164,6 +165,13 @@ export const isDetectionsPath = (pathname: string): boolean => { }); }; +export const isThreatIntelligencePath = (pathname: string): boolean => { + return !!matchPath(pathname, { + path: `(${THREAT_INTELLIGENCE_PATH})`, + strict: false, + }); +}; + export const getSubPluginRoutesByCapabilities = ( subPlugins: StartedSubPlugins, capabilities: Capabilities diff --git a/x-pack/plugins/threat_intelligence/cypress/e2e/indicators.cy.ts b/x-pack/plugins/threat_intelligence/cypress/e2e/indicators.cy.ts index c5d67894aa0ff..17c4d79e60dcc 100644 --- a/x-pack/plugins/threat_intelligence/cypress/e2e/indicators.cy.ts +++ b/x-pack/plugins/threat_intelligence/cypress/e2e/indicators.cy.ts @@ -6,30 +6,31 @@ */ import { + ADD_INTEGRATIONS_BUTTON, + BREADCRUMBS, DEFAULT_LAYOUT_TITLE, - FLYOUT_JSON, - FLYOUT_TABLE, - FLYOUT_TABS, - FLYOUT_TITLE, - INDICATORS_TABLE, - TOGGLE_FLYOUT_BUTTON, - FILTERS_GLOBAL_CONTAINER, - TIME_RANGE_PICKER, - QUERY_INPUT, - TABLE_CONTROLS, - INDICATOR_TYPE_CELL, EMPTY_STATE, - FIELD_SELECTOR, - BREADCRUMBS, - LEADING_BREADCRUMB, ENDING_BREADCRUMB, FIELD_BROWSER, FIELD_BROWSER_MODAL, - FIELD_SELECTOR_TOGGLE_BUTTON, + FIELD_SELECTOR, FIELD_SELECTOR_INPUT, FIELD_SELECTOR_LIST, + FIELD_SELECTOR_TOGGLE_BUTTON, + FILTERS_GLOBAL_CONTAINER, + FLYOUT_JSON, + FLYOUT_TABLE, + FLYOUT_TABS, + FLYOUT_TITLE, + INDICATOR_TYPE_CELL, + INDICATORS_TABLE, INSPECTOR_BUTTON, INSPECTOR_PANEL, + LEADING_BREADCRUMB, + QUERY_INPUT, + TABLE_CONTROLS, + TIME_RANGE_PICKER, + TOGGLE_FLYOUT_BUTTON, } from '../screens/indicators'; import { login } from '../tasks/login'; import { esArchiverLoad, esArchiverUnload } from '../tasks/es_archiver'; @@ -189,4 +190,20 @@ describe('Indicators', () => { }); }); }); + + describe('Add integrations', () => { + before(() => { + cy.visit(THREAT_INTELLIGENCE); + + selectRange(); + }); + + describe('when the global header add integrations button is clicked', () => { + it('should navigate to the Integrations page with Threat Intelligence category selected', () => { + cy.get(ADD_INTEGRATIONS_BUTTON).click(); + + cy.url().should('include', 'threat_intel'); + }); + }); + }); }); diff --git a/x-pack/plugins/threat_intelligence/cypress/screens/indicators.ts b/x-pack/plugins/threat_intelligence/cypress/screens/indicators.ts index 0464e57c6749b..9e32e8843c4c3 100644 --- a/x-pack/plugins/threat_intelligence/cypress/screens/indicators.ts +++ b/x-pack/plugins/threat_intelligence/cypress/screens/indicators.ts @@ -117,3 +117,5 @@ export const INDICATOR_FLYOUT_INVESTIGATE_IN_TIMELINE_BUTTON = export const INSPECTOR_BUTTON = '[data-test-subj="tiIndicatorsGridInspect"]'; export const INSPECTOR_PANEL = '[data-test-subj="inspectorPanel"]'; + +export const ADD_INTEGRATIONS_BUTTON = '[data-test-subj="add-data"]';