From b8b145e33bde4f18c4eeb38764b0bc62fe7c7473 Mon Sep 17 00:00:00 2001 From: Pablo Neves Machado Date: Wed, 11 May 2022 11:11:02 +0200 Subject: [PATCH] Update navigation landing pages to use appLinks config --- .../public/app/translations.ts | 6 +- .../__snapshots__/index.test.tsx.snap | 170 ++++++++++++++++++ .../index.test.tsx | 169 +---------------- .../common/hooks/use_experimental_features.ts | 24 +-- .../common/images/detection_response_page.png | Bin 0 -> 35830 bytes .../public/common/links/links.test.ts | 9 + .../public/common/links/links.ts | 17 +- .../public/common/links/types.ts | 15 +- .../security_solution/public/hosts/links.ts | 6 + .../components/landing_links_icons.test.tsx | 20 ++- .../components/landing_links_icons.tsx | 33 +--- .../components/landing_links_images.test.tsx | 18 +- .../components/landing_links_images.tsx | 34 ++-- .../public/landing_pages/constants.ts | 36 ++++ .../public/landing_pages/pages/dashboards.tsx | 35 ++-- .../landing_pages/pages/manage.test.tsx | 84 +++++---- .../public/landing_pages/pages/manage.tsx | 144 ++------------- .../landing_pages/pages/threat_hunting.tsx | 56 ++---- .../icons/blocklist.tsx | 0 .../icons/endpoint_policies.tsx | 0 .../icons/endpoints.tsx | 0 .../icons/event_filters.tsx | 0 .../icons/exception_lists.tsx | 0 .../icons/host_isolation.tsx | 0 .../icons/siem_rules.tsx | 0 .../icons/trusted_applications.tsx | 0 .../public/management/links.ts | 47 +++++ .../security_solution/public/network/links.ts | 6 + .../public/overview/links.ts | 11 ++ .../security_solution/public/users/links.ts | 5 + 30 files changed, 466 insertions(+), 479 deletions(-) create mode 100644 x-pack/plugins/security_solution/public/common/components/navigation/use_security_solution_navigation/__snapshots__/index.test.tsx.snap create mode 100644 x-pack/plugins/security_solution/public/common/images/detection_response_page.png create mode 100644 x-pack/plugins/security_solution/public/landing_pages/constants.ts rename x-pack/plugins/security_solution/public/{landing_pages => management}/icons/blocklist.tsx (100%) rename x-pack/plugins/security_solution/public/{landing_pages => management}/icons/endpoint_policies.tsx (100%) rename x-pack/plugins/security_solution/public/{landing_pages => management}/icons/endpoints.tsx (100%) rename x-pack/plugins/security_solution/public/{landing_pages => management}/icons/event_filters.tsx (100%) rename x-pack/plugins/security_solution/public/{landing_pages => management}/icons/exception_lists.tsx (100%) rename x-pack/plugins/security_solution/public/{landing_pages => management}/icons/host_isolation.tsx (100%) rename x-pack/plugins/security_solution/public/{landing_pages => management}/icons/siem_rules.tsx (100%) rename x-pack/plugins/security_solution/public/{landing_pages => management}/icons/trusted_applications.tsx (100%) diff --git a/x-pack/plugins/security_solution/public/app/translations.ts b/x-pack/plugins/security_solution/public/app/translations.ts index aa7eaa83685dba..e9a45c0397316e 100644 --- a/x-pack/plugins/security_solution/public/app/translations.ts +++ b/x-pack/plugins/security_solution/public/app/translations.ts @@ -43,7 +43,7 @@ export const USERS = i18n.translate('xpack.securitySolution.navigation.users', { }); export const RULES = i18n.translate('xpack.securitySolution.navigation.rules', { - defaultMessage: 'Rules', + defaultMessage: 'SIEM rules', }); export const EXCEPTIONS = i18n.translate('xpack.securitySolution.navigation.exceptions', { @@ -71,7 +71,7 @@ export const ENDPOINTS = i18n.translate('xpack.securitySolution.search.administr export const POLICIES = i18n.translate( 'xpack.securitySolution.navigation.administration.policies', { - defaultMessage: 'Policies', + defaultMessage: 'Endpoint policies', } ); export const TRUSTED_APPLICATIONS = i18n.translate( @@ -90,7 +90,7 @@ export const EVENT_FILTERS = i18n.translate( export const HOST_ISOLATION_EXCEPTIONS = i18n.translate( 'xpack.securitySolution.search.administration.hostIsolationExceptions', { - defaultMessage: 'Host isolation exceptions', + defaultMessage: 'Host isolation IP exceptions', } ); export const DETECT = i18n.translate('xpack.securitySolution.navigation.detect', { diff --git a/x-pack/plugins/security_solution/public/common/components/navigation/use_security_solution_navigation/__snapshots__/index.test.tsx.snap b/x-pack/plugins/security_solution/public/common/components/navigation/use_security_solution_navigation/__snapshots__/index.test.tsx.snap new file mode 100644 index 00000000000000..b80e8e290f65b2 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/navigation/use_security_solution_navigation/__snapshots__/index.test.tsx.snap @@ -0,0 +1,170 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`useSecuritySolutionNavigation should create navigation config 1`] = ` +Object { + "icon": "logoSecurity", + "items": Array [ + Object { + "id": "main", + "items": Array [ + Object { + "data-href": "securitySolutionUI/get_started?query=(language:kuery,query:'host.name:%22security-solution-es%22')&sourcerer=()&timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)))", + "data-test-subj": "navigation-get_started", + "disabled": false, + "href": "securitySolutionUI/get_started?query=(language:kuery,query:'host.name:%22security-solution-es%22')&sourcerer=()&timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)))", + "id": "get_started", + "isSelected": false, + "name": "Getting started", + "onClick": [Function], + }, + Object { + "data-href": "securitySolutionUI/overview?query=(language:kuery,query:'host.name:%22security-solution-es%22')&sourcerer=()&timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)))", + "data-test-subj": "navigation-overview", + "disabled": false, + "href": "securitySolutionUI/overview?query=(language:kuery,query:'host.name:%22security-solution-es%22')&sourcerer=()&timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)))", + "id": "overview", + "isSelected": false, + "name": "Overview", + "onClick": [Function], + }, + ], + "name": "", + }, + Object { + "id": "detect", + "items": Array [ + Object { + "data-href": "securitySolutionUI/alerts?query=(language:kuery,query:'host.name:%22security-solution-es%22')&sourcerer=()&timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)))", + "data-test-subj": "navigation-alerts", + "disabled": false, + "href": "securitySolutionUI/alerts?query=(language:kuery,query:'host.name:%22security-solution-es%22')&sourcerer=()&timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)))", + "id": "alerts", + "isSelected": false, + "name": "Alerts", + "onClick": [Function], + }, + Object { + "data-href": "securitySolutionUI/rules?query=(language:kuery,query:'host.name:%22security-solution-es%22')&sourcerer=()&timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)))", + "data-test-subj": "navigation-rules", + "disabled": false, + "href": "securitySolutionUI/rules?query=(language:kuery,query:'host.name:%22security-solution-es%22')&sourcerer=()&timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)))", + "id": "rules", + "isSelected": false, + "name": "SIEM rules", + "onClick": [Function], + }, + Object { + "data-href": "securitySolutionUI/exceptions?query=(language:kuery,query:'host.name:%22security-solution-es%22')&sourcerer=()&timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)))", + "data-test-subj": "navigation-exceptions", + "disabled": false, + "href": "securitySolutionUI/exceptions?query=(language:kuery,query:'host.name:%22security-solution-es%22')&sourcerer=()&timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)))", + "id": "exceptions", + "isSelected": false, + "name": "Exception lists", + "onClick": [Function], + }, + ], + "name": "Detect", + }, + Object { + "id": "explore", + "items": Array [ + Object { + "data-href": "securitySolutionUI/hosts?query=(language:kuery,query:'host.name:%22security-solution-es%22')&sourcerer=()&timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)))", + "data-test-subj": "navigation-hosts", + "disabled": false, + "href": "securitySolutionUI/hosts?query=(language:kuery,query:'host.name:%22security-solution-es%22')&sourcerer=()&timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)))", + "id": "hosts", + "isSelected": true, + "name": "Hosts", + "onClick": [Function], + }, + Object { + "data-href": "securitySolutionUI/network?query=(language:kuery,query:'host.name:%22security-solution-es%22')&sourcerer=()&timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)))", + "data-test-subj": "navigation-network", + "disabled": false, + "href": "securitySolutionUI/network?query=(language:kuery,query:'host.name:%22security-solution-es%22')&sourcerer=()&timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)))", + "id": "network", + "isSelected": false, + "name": "Network", + "onClick": [Function], + }, + ], + "name": "Explore", + }, + Object { + "id": "investigate", + "items": Array [ + Object { + "data-href": "securitySolutionUI/timelines?query=(language:kuery,query:'host.name:%22security-solution-es%22')&sourcerer=()&timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)))", + "data-test-subj": "navigation-timelines", + "disabled": false, + "href": "securitySolutionUI/timelines?query=(language:kuery,query:'host.name:%22security-solution-es%22')&sourcerer=()&timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)))", + "id": "timelines", + "isSelected": false, + "name": "Timelines", + "onClick": [Function], + }, + ], + "name": "Investigate", + }, + Object { + "id": "manage", + "items": Array [ + Object { + "data-href": "securitySolutionUI/endpoints", + "data-test-subj": "navigation-endpoints", + "disabled": false, + "href": "securitySolutionUI/endpoints", + "id": "endpoints", + "isSelected": false, + "name": "Endpoints", + "onClick": [Function], + }, + Object { + "data-href": "securitySolutionUI/trusted_apps", + "data-test-subj": "navigation-trusted_apps", + "disabled": false, + "href": "securitySolutionUI/trusted_apps", + "id": "trusted_apps", + "isSelected": false, + "name": "Trusted applications", + "onClick": [Function], + }, + Object { + "data-href": "securitySolutionUI/event_filters", + "data-test-subj": "navigation-event_filters", + "disabled": false, + "href": "securitySolutionUI/event_filters", + "id": "event_filters", + "isSelected": false, + "name": "Event filters", + "onClick": [Function], + }, + Object { + "data-href": "securitySolutionUI/host_isolation_exceptions", + "data-test-subj": "navigation-host_isolation_exceptions", + "disabled": false, + "href": "securitySolutionUI/host_isolation_exceptions", + "id": "host_isolation_exceptions", + "isSelected": false, + "name": "Host isolation IP exceptions", + "onClick": [Function], + }, + Object { + "data-href": "securitySolutionUI/blocklist", + "data-test-subj": "navigation-blocklist", + "disabled": false, + "href": "securitySolutionUI/blocklist", + "id": "blocklist", + "isSelected": false, + "name": "Blocklist", + "onClick": [Function], + }, + ], + "name": "Manage", + }, + ], + "name": "Security", +} +`; diff --git a/x-pack/plugins/security_solution/public/common/components/navigation/use_security_solution_navigation/index.test.tsx b/x-pack/plugins/security_solution/public/common/components/navigation/use_security_solution_navigation/index.test.tsx index 3f30facd5e41ec..dc06162cd906c3 100644 --- a/x-pack/plugins/security_solution/public/common/components/navigation/use_security_solution_navigation/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/navigation/use_security_solution_navigation/index.test.tsx @@ -108,174 +108,7 @@ describe('useSecuritySolutionNavigation', () => { { wrapper: TestProviders } ); - expect(result.current).toMatchInlineSnapshot(` - Object { - "icon": "logoSecurity", - "items": Array [ - Object { - "id": "main", - "items": Array [ - Object { - "data-href": "securitySolutionUI/get_started?query=(language:kuery,query:'host.name:%22security-solution-es%22')&sourcerer=()&timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)))", - "data-test-subj": "navigation-get_started", - "disabled": false, - "href": "securitySolutionUI/get_started?query=(language:kuery,query:'host.name:%22security-solution-es%22')&sourcerer=()&timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)))", - "id": "get_started", - "isSelected": false, - "name": "Getting started", - "onClick": [Function], - }, - Object { - "data-href": "securitySolutionUI/overview?query=(language:kuery,query:'host.name:%22security-solution-es%22')&sourcerer=()&timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)))", - "data-test-subj": "navigation-overview", - "disabled": false, - "href": "securitySolutionUI/overview?query=(language:kuery,query:'host.name:%22security-solution-es%22')&sourcerer=()&timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)))", - "id": "overview", - "isSelected": false, - "name": "Overview", - "onClick": [Function], - }, - ], - "name": "", - }, - Object { - "id": "detect", - "items": Array [ - Object { - "data-href": "securitySolutionUI/alerts?query=(language:kuery,query:'host.name:%22security-solution-es%22')&sourcerer=()&timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)))", - "data-test-subj": "navigation-alerts", - "disabled": false, - "href": "securitySolutionUI/alerts?query=(language:kuery,query:'host.name:%22security-solution-es%22')&sourcerer=()&timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)))", - "id": "alerts", - "isSelected": false, - "name": "Alerts", - "onClick": [Function], - }, - Object { - "data-href": "securitySolutionUI/rules?query=(language:kuery,query:'host.name:%22security-solution-es%22')&sourcerer=()&timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)))", - "data-test-subj": "navigation-rules", - "disabled": false, - "href": "securitySolutionUI/rules?query=(language:kuery,query:'host.name:%22security-solution-es%22')&sourcerer=()&timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)))", - "id": "rules", - "isSelected": false, - "name": "Rules", - "onClick": [Function], - }, - Object { - "data-href": "securitySolutionUI/exceptions?query=(language:kuery,query:'host.name:%22security-solution-es%22')&sourcerer=()&timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)))", - "data-test-subj": "navigation-exceptions", - "disabled": false, - "href": "securitySolutionUI/exceptions?query=(language:kuery,query:'host.name:%22security-solution-es%22')&sourcerer=()&timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)))", - "id": "exceptions", - "isSelected": false, - "name": "Exception lists", - "onClick": [Function], - }, - ], - "name": "Detect", - }, - Object { - "id": "explore", - "items": Array [ - Object { - "data-href": "securitySolutionUI/hosts?query=(language:kuery,query:'host.name:%22security-solution-es%22')&sourcerer=()&timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)))", - "data-test-subj": "navigation-hosts", - "disabled": false, - "href": "securitySolutionUI/hosts?query=(language:kuery,query:'host.name:%22security-solution-es%22')&sourcerer=()&timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)))", - "id": "hosts", - "isSelected": true, - "name": "Hosts", - "onClick": [Function], - }, - Object { - "data-href": "securitySolutionUI/network?query=(language:kuery,query:'host.name:%22security-solution-es%22')&sourcerer=()&timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)))", - "data-test-subj": "navigation-network", - "disabled": false, - "href": "securitySolutionUI/network?query=(language:kuery,query:'host.name:%22security-solution-es%22')&sourcerer=()&timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)))", - "id": "network", - "isSelected": false, - "name": "Network", - "onClick": [Function], - }, - ], - "name": "Explore", - }, - Object { - "id": "investigate", - "items": Array [ - Object { - "data-href": "securitySolutionUI/timelines?query=(language:kuery,query:'host.name:%22security-solution-es%22')&sourcerer=()&timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)))", - "data-test-subj": "navigation-timelines", - "disabled": false, - "href": "securitySolutionUI/timelines?query=(language:kuery,query:'host.name:%22security-solution-es%22')&sourcerer=()&timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)))", - "id": "timelines", - "isSelected": false, - "name": "Timelines", - "onClick": [Function], - }, - ], - "name": "Investigate", - }, - Object { - "id": "manage", - "items": Array [ - Object { - "data-href": "securitySolutionUI/endpoints", - "data-test-subj": "navigation-endpoints", - "disabled": false, - "href": "securitySolutionUI/endpoints", - "id": "endpoints", - "isSelected": false, - "name": "Endpoints", - "onClick": [Function], - }, - Object { - "data-href": "securitySolutionUI/trusted_apps", - "data-test-subj": "navigation-trusted_apps", - "disabled": false, - "href": "securitySolutionUI/trusted_apps", - "id": "trusted_apps", - "isSelected": false, - "name": "Trusted applications", - "onClick": [Function], - }, - Object { - "data-href": "securitySolutionUI/event_filters", - "data-test-subj": "navigation-event_filters", - "disabled": false, - "href": "securitySolutionUI/event_filters", - "id": "event_filters", - "isSelected": false, - "name": "Event filters", - "onClick": [Function], - }, - Object { - "data-href": "securitySolutionUI/host_isolation_exceptions", - "data-test-subj": "navigation-host_isolation_exceptions", - "disabled": false, - "href": "securitySolutionUI/host_isolation_exceptions", - "id": "host_isolation_exceptions", - "isSelected": false, - "name": "Host isolation exceptions", - "onClick": [Function], - }, - Object { - "data-href": "securitySolutionUI/blocklist", - "data-test-subj": "navigation-blocklist", - "disabled": false, - "href": "securitySolutionUI/blocklist", - "id": "blocklist", - "isSelected": false, - "name": "Blocklist", - "onClick": [Function], - }, - ], - "name": "Manage", - }, - ], - "name": "Security", - } - `); + expect(result.current).toMatchSnapshot(); }); // TODO: Steph/users remove when no longer experimental diff --git a/x-pack/plugins/security_solution/public/common/hooks/use_experimental_features.ts b/x-pack/plugins/security_solution/public/common/hooks/use_experimental_features.ts index 3132ae70381a29..1cc2506ec39968 100644 --- a/x-pack/plugins/security_solution/public/common/hooks/use_experimental_features.ts +++ b/x-pack/plugins/security_solution/public/common/hooks/use_experimental_features.ts @@ -14,14 +14,16 @@ import { const allowedExperimentalValues = getExperimentalAllowedValues(); -export const useIsExperimentalFeatureEnabled = (feature: keyof ExperimentalFeatures): boolean => - useSelector(({ app: { enableExperimental } }: State) => { - if (!enableExperimental || !(feature in enableExperimental)) { - throw new Error( - `Invalid enable value ${feature}. Allowed values are: ${allowedExperimentalValues.join( - ', ' - )}` - ); - } - return enableExperimental[feature]; - }); +export const useIsExperimentalFeatureEnabled = (feature: keyof ExperimentalFeatures): boolean => { + const enableExperimental = useEnableExperimental(); + + if (!enableExperimental || !(feature in enableExperimental)) { + throw new Error( + `Invalid enable value ${feature}. Allowed values are: ${allowedExperimentalValues.join(', ')}` + ); + } + return enableExperimental[feature]; +}; + +export const useEnableExperimental = (): ExperimentalFeatures => + useSelector(({ app: { enableExperimental } }: State) => enableExperimental); diff --git a/x-pack/plugins/security_solution/public/common/images/detection_response_page.png b/x-pack/plugins/security_solution/public/common/images/detection_response_page.png new file mode 100644 index 0000000000000000000000000000000000000000..630cd555598432dc0f50c0dd68117e6c35537bf3 GIT binary patch literal 35830 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 { id: 'hosts', path: '/hosts', title: 'Hosts', + landingImage: 'test-file-stub', + description: + 'A computer or other device that communicates with other hosts on a network. Hosts on a network include clients and servers -- that send or receive data, services or applications.', }, ]); }); @@ -383,6 +386,9 @@ describe('security app link helpers', () => { id: 'hosts', path: '/hosts', title: 'Hosts', + landingImage: 'test-file-stub', + description: + 'A computer or other device that communicates with other hosts on a network. Hosts on a network include clients and servers -- that send or receive data, services or applications.', }, { id: 'uncommon_processes', @@ -415,6 +421,9 @@ describe('security app link helpers', () => { id: 'hosts', path: '/hosts', title: 'Hosts', + landingImage: 'test-file-stub', + description: + 'A computer or other device that communicates with other hosts on a network. Hosts on a network include clients and servers -- that send or receive data, services or applications.', }); }); }); diff --git a/x-pack/plugins/security_solution/public/common/links/links.ts b/x-pack/plugins/security_solution/public/common/links/links.ts index 290a1f3fbd8208..a150ab2e7e0ceb 100644 --- a/x-pack/plugins/security_solution/public/common/links/links.ts +++ b/x-pack/plugins/security_solution/public/common/links/links.ts @@ -8,6 +8,9 @@ import { AppDeepLink, AppNavLinkStatus, Capabilities } from '@kbn/core/public'; import { get } from 'lodash'; import { SecurityPageName } from '../../../common/constants'; +import { useEnableExperimental } from '../hooks/use_experimental_features'; +import { useLicense } from '../hooks/use_license'; +import { useKibana } from '../lib/kibana'; import { appLinks, getAppLinks } from './app_links'; import { Feature, @@ -32,8 +35,6 @@ const createDeepLink = (link: LinkItem, linkProps?: UserPermissions): AppDeepLin }), } : {}), - ...(link.icon != null ? { euiIconType: link.icon } : {}), - ...(link.image != null ? { icon: link.image } : {}), ...(link.globalSearchKeywords != null ? { keywords: link.globalSearchKeywords } : {}), ...(link.globalNavEnabled != null ? { navLinkStatus: link.globalNavEnabled ? AppNavLinkStatus.visible : AppNavLinkStatus.hidden } @@ -47,8 +48,8 @@ const createNavLinkItem = (link: LinkItem, linkProps?: UserPermissions): NavLink path: link.path, title: link.title, ...(link.description != null ? { description: link.description } : {}), - ...(link.icon != null ? { icon: link.icon } : {}), - ...(link.image != null ? { image: link.image } : {}), + ...(link.landingIcon != null ? { icon: link.landingIcon } : {}), + ...(link.landingImage != null ? { image: link.landingImage } : {}), ...(link.links && link.links.length ? { links: reduceLinks({ @@ -195,3 +196,11 @@ export const getAncestorLinksInfo = (id: SecurityPageName): LinkInfo[] => { export const needsUrlState = (id: SecurityPageName): boolean => { return !getNormalizedLink(id).skipUrlState; }; + +export const useAppNavLinks = (): NavLinkItem[] => { + const license = useLicense(); + const enableExperimental = useEnableExperimental(); + const capabilities = useKibana().services.application.capabilities; + + return getNavLinkItems({ enableExperimental, license, capabilities }); +}; diff --git a/x-pack/plugins/security_solution/public/common/links/types.ts b/x-pack/plugins/security_solution/public/common/links/types.ts index eea348b3df7377..320c38d1d229b2 100644 --- a/x-pack/plugins/security_solution/public/common/links/types.ts +++ b/x-pack/plugins/security_solution/public/common/links/types.ts @@ -7,6 +7,7 @@ import { Capabilities } from '@kbn/core/types'; import { LicenseType } from '@kbn/licensing-plugin/common/types'; +import { IconType } from '@elastic/eui'; import { LicenseService } from '../../../common/license'; import { ExperimentalFeatures } from '../../../common/experimental_features'; import { CASES_FEATURE_ID, SecurityPageName, SERVER_APP_ID } from '../../../common/constants'; @@ -41,9 +42,17 @@ export interface LinkItem { globalSearchEnabled?: boolean; globalSearchKeywords?: string[]; hideWhenExperimentalKey?: keyof ExperimentalFeatures; - icon?: string; id: SecurityPageName; - image?: string; + /** + * Icon that is displayed on menu navigation landing page. + * Only required for pages that are displayed inside a landing page. + */ + landingIcon?: IconType; + /** + * Image that is displayed on menu navigation landing page. + * Only required for pages that are displayed inside a landing page. + */ + landingImage?: string; isBeta?: boolean; licenseType?: LicenseType; links?: LinkItem[]; @@ -54,7 +63,7 @@ export interface LinkItem { export interface NavLinkItem { description?: string; - icon?: string; + icon?: IconType; id: SecurityPageName; links?: NavLinkItem[]; image?: string; diff --git a/x-pack/plugins/security_solution/public/hosts/links.ts b/x-pack/plugins/security_solution/public/hosts/links.ts index 35730291d6c749..421fe9693a57a8 100644 --- a/x-pack/plugins/security_solution/public/hosts/links.ts +++ b/x-pack/plugins/security_solution/public/hosts/links.ts @@ -8,10 +8,16 @@ import { i18n } from '@kbn/i18n'; import { HOSTS_PATH, SecurityPageName } from '../../common/constants'; import { HOSTS } from '../app/translations'; import { LinkItem } from '../common/links/types'; +import hostsPageImg from '../common/images/hosts_page.png'; export const links: LinkItem = { id: SecurityPageName.hosts, title: HOSTS, + landingImage: hostsPageImg, + description: i18n.translate('xpack.securitySolution.landing.threatHunting.hostsDescription', { + defaultMessage: + 'A computer or other device that communicates with other hosts on a network. Hosts on a network include clients and servers -- that send or receive data, services or applications.', + }), path: HOSTS_PATH, globalNavEnabled: true, globalSearchKeywords: [ diff --git a/x-pack/plugins/security_solution/public/landing_pages/components/landing_links_icons.test.tsx b/x-pack/plugins/security_solution/public/landing_pages/components/landing_links_icons.test.tsx index 3553f44cc621ff..4db27261654edb 100644 --- a/x-pack/plugins/security_solution/public/landing_pages/components/landing_links_icons.test.tsx +++ b/x-pack/plugins/security_solution/public/landing_pages/components/landing_links_icons.test.tsx @@ -8,14 +8,16 @@ import { fireEvent, render } from '@testing-library/react'; import React from 'react'; import { SecurityPageName } from '../../app/types'; +import { NavLinkItem } from '../../common/links/types'; import { TestProviders } from '../../common/mock'; -import { LandingLinksIcons, NavItem } from './landing_links_icons'; +import { LandingLinksIcons } from './landing_links_icons'; -const DEFAULT_NAV_ITEM: NavItem = { +const DEFAULT_NAV_ITEM: NavLinkItem = { id: SecurityPageName.overview, - label: 'TEST LABEL', + title: 'TEST LABEL', description: 'TEST DESCRIPTION', icon: 'myTestIcon', + path: '', }; const mockNavigateTo = jest.fn(); @@ -42,28 +44,28 @@ jest.mock('../../common/components/link_to', () => { describe('LandingLinksIcons', () => { it('renders', () => { - const label = 'test label'; + const title = 'test label'; const { queryByText } = render( - + ); - expect(queryByText(label)).toBeInTheDocument(); + expect(queryByText(title)).toBeInTheDocument(); }); it('renders navigation link', () => { const id = SecurityPageName.administration; - const label = 'myTestLable'; + const title = 'myTestLable'; const { getByText } = render( - + ); - fireEvent.click(getByText(label)); + fireEvent.click(getByText(title)); expect(mockNavigateTo).toHaveBeenCalledWith({ url: '/administration' }); }); diff --git a/x-pack/plugins/security_solution/public/landing_pages/components/landing_links_icons.tsx b/x-pack/plugins/security_solution/public/landing_pages/components/landing_links_icons.tsx index 82a0d2148f6835..04a3e20b1f1789 100644 --- a/x-pack/plugins/security_solution/public/landing_pages/components/landing_links_icons.tsx +++ b/x-pack/plugins/security_solution/public/landing_pages/components/landing_links_icons.tsx @@ -4,33 +4,18 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { - EuiFlexGrid, - EuiFlexGroup, - EuiFlexItem, - EuiIcon, - EuiText, - EuiTitle, - IconType, -} from '@elastic/eui'; +import { EuiFlexGrid, EuiFlexGroup, EuiFlexItem, EuiIcon, EuiText, EuiTitle } from '@elastic/eui'; import React from 'react'; import styled from 'styled-components'; -import { SecurityPageName } from '../../app/types'; + import { SecuritySolutionLinkAnchor, withSecuritySolutionLink, } from '../../common/components/links'; +import { NavLinkItem } from '../../common/links/types'; interface LandingLinksImagesProps { - items: NavItem[]; -} - -export interface NavItem { - id: SecurityPageName; - label: string; - icon: IconType; - description: string; - path?: string; + items: NavLinkItem[]; } const Link = styled.a` @@ -50,7 +35,7 @@ const StyledEuiTitle = styled(EuiTitle)` export const LandingLinksIcons: React.FC = ({ items }) => ( - {items.map(({ label, description, path, id, icon }) => ( + {items.map(({ title, description, id, icon }) => ( = ({ items }) responsive={false} > - - - -

{label}

+ +

{title}

diff --git a/x-pack/plugins/security_solution/public/landing_pages/components/landing_links_images.test.tsx b/x-pack/plugins/security_solution/public/landing_pages/components/landing_links_images.test.tsx index 479de5e13f4326..c44374852f29bf 100644 --- a/x-pack/plugins/security_solution/public/landing_pages/components/landing_links_images.test.tsx +++ b/x-pack/plugins/security_solution/public/landing_pages/components/landing_links_images.test.tsx @@ -8,14 +8,16 @@ import { render } from '@testing-library/react'; import React from 'react'; import { SecurityPageName } from '../../app/types'; +import { NavLinkItem } from '../../common/links/types'; import { TestProviders } from '../../common/mock'; -import { LandingLinksImages, NavItem } from './landing_links_images'; +import { LandingLinksImages } from './landing_links_images'; -const DEFAULT_NAV_ITEM: NavItem = { +const DEFAULT_NAV_ITEM: NavLinkItem = { id: SecurityPageName.overview, - label: 'TEST LABEL', + title: 'TEST LABEL', description: 'TEST DESCRIPTION', image: 'TEST_IMAGE.png', + path: '', }; jest.mock('../../common/lib/kibana/kibana_react', () => { @@ -32,24 +34,24 @@ jest.mock('../../common/lib/kibana/kibana_react', () => { describe('LandingLinksImages', () => { it('renders', () => { - const label = 'test label'; + const title = 'test label'; const { queryByText } = render( - + ); - expect(queryByText(label)).toBeInTheDocument(); + expect(queryByText(title)).toBeInTheDocument(); }); it('renders image', () => { const image = 'test_image.jpeg'; - const label = 'TEST_LABEL'; + const title = 'TEST_LABEL'; const { getByTestId } = render( - + ); diff --git a/x-pack/plugins/security_solution/public/landing_pages/components/landing_links_images.tsx b/x-pack/plugins/security_solution/public/landing_pages/components/landing_links_images.tsx index b6a16da8cdc82e..22bcc0f1aa2516 100644 --- a/x-pack/plugins/security_solution/public/landing_pages/components/landing_links_images.tsx +++ b/x-pack/plugins/security_solution/public/landing_pages/components/landing_links_images.tsx @@ -7,19 +7,11 @@ import { EuiFlexGroup, EuiFlexItem, EuiImage, EuiPanel, EuiText, EuiTitle } from '@elastic/eui'; import React from 'react'; import styled from 'styled-components'; -import { SecurityPageName } from '../../app/types'; import { withSecuritySolutionLink } from '../../common/components/links'; +import { NavLinkItem } from '../../common/links/types'; interface LandingLinksImagesProps { - items: NavItem[]; -} - -export interface NavItem { - id: SecurityPageName; - label: string; - image: string; - description: string; - path?: string; + items: NavLinkItem[]; } const PrimaryEuiTitle = styled(EuiTitle)` @@ -47,24 +39,26 @@ const Content = styled(EuiFlexItem)` export const LandingLinksImages: React.FC = ({ items }) => ( - {items.map(({ label, description, path, image, id }) => ( + {items.map(({ title, description, image, id }) => ( - + {/* Empty onClick is to force hover style on `EuiPanel` */} {}}> - + {image && ( + + )} -

{label}

+

{title}

{description} diff --git a/x-pack/plugins/security_solution/public/landing_pages/constants.ts b/x-pack/plugins/security_solution/public/landing_pages/constants.ts new file mode 100644 index 00000000000000..a6b72a5e7db4f9 --- /dev/null +++ b/x-pack/plugins/security_solution/public/landing_pages/constants.ts @@ -0,0 +1,36 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { i18n } from '@kbn/i18n'; +import { SecurityPageName } from '../app/types'; + +export interface LandingNavGroup { + label: string; + itemIds: SecurityPageName[]; +} + +export const MANAGE_NAVIGATION_CATEGORIES: LandingNavGroup[] = [ + { + label: i18n.translate('xpack.securitySolution.landing.siemTitle', { + defaultMessage: 'SIEM', + }), + itemIds: [SecurityPageName.rules, SecurityPageName.exceptions], + }, + { + label: i18n.translate('xpack.securitySolution.landing.endpointsTitle', { + defaultMessage: 'ENDPOINTS', + }), + itemIds: [ + SecurityPageName.endpoints, + SecurityPageName.policies, + SecurityPageName.trustedApps, + SecurityPageName.eventFilters, + SecurityPageName.blocklist, + SecurityPageName.hostIsolationExceptions, + ], + }, +]; diff --git a/x-pack/plugins/security_solution/public/landing_pages/pages/dashboards.tsx b/x-pack/plugins/security_solution/public/landing_pages/pages/dashboards.tsx index 8c49fda169ad37..c2d5a3d8d2ee97 100644 --- a/x-pack/plugins/security_solution/public/landing_pages/pages/dashboards.tsx +++ b/x-pack/plugins/security_solution/public/landing_pages/pages/dashboards.tsx @@ -5,31 +5,24 @@ * 2.0. */ import React from 'react'; -import { i18n } from '@kbn/i18n'; import { SecurityPageName } from '../../app/types'; import { HeaderPage } from '../../common/components/header_page'; import { SecuritySolutionPageWrapper } from '../../common/components/page_wrapper'; import { SpyRoute } from '../../common/utils/route/spy_routes'; -import { LandingLinksImages, NavItem } from '../components/landing_links_images'; +import { LandingLinksImages } from '../components/landing_links_images'; import { DASHBOARDS_PAGE_TITLE } from './translations'; -import overviewPageImg from '../../common/images/overview_page.png'; -import { OVERVIEW } from '../../app/translations'; +import { useAppNavLinks } from '../../common/links'; -const items: NavItem[] = [ - { - id: SecurityPageName.overview, - label: OVERVIEW, - description: i18n.translate('xpack.securitySolution.landing.dashboards.overviewDescription', { - defaultMessage: 'What is going in your secuity environment', - }), - image: overviewPageImg, - }, -]; +export const DashboardsLandingPage = () => { + const dashboardlinks = useAppNavLinks().find( + ({ id }) => id === SecurityPageName.dashboardsLanding + ); -export const DashboardsLandingPage = () => ( - - - - - -); + return ( + + + + + + ); +}; diff --git a/x-pack/plugins/security_solution/public/landing_pages/pages/manage.test.tsx b/x-pack/plugins/security_solution/public/landing_pages/pages/manage.test.tsx index efb1bcf35c39ed..1b786912b7c6ea 100644 --- a/x-pack/plugins/security_solution/public/landing_pages/pages/manage.test.tsx +++ b/x-pack/plugins/security_solution/public/landing_pages/pages/manage.test.tsx @@ -9,43 +9,56 @@ import { render } from '@testing-library/react'; import React from 'react'; import { SecurityPageName } from '../../app/types'; import { TestProviders } from '../../common/mock'; -import { LandingCategories, NavConfigType } from './manage'; +import { LandingCategories } from './manage'; const RULES_ITEM_LABEL = 'elastic rules!'; const EXCEPTIONS_ITEM_LABEL = 'exceptional!'; +import { NavLinkItem } from '../../common/links/types'; -const testConfig: NavConfigType = { - categories: [ - { - label: 'first tests category', - itemIds: [SecurityPageName.rules], - }, - { - label: 'second tests category', - itemIds: [SecurityPageName.exceptions], - }, - ], - items: [ - { - id: SecurityPageName.rules, - label: RULES_ITEM_LABEL, - description: '', - icon: 'testIcon1', - }, - { - id: SecurityPageName.exceptions, - label: EXCEPTIONS_ITEM_LABEL, - description: '', - icon: 'testIcon2', - }, - ], -}; +const mockAppLinks: NavLinkItem[] = [ + { + id: SecurityPageName.administration, + path: '', + title: 'admin', + links: [ + { + id: SecurityPageName.rules, + title: RULES_ITEM_LABEL, + description: '', + icon: 'testIcon1', + path: '', + }, + { + id: SecurityPageName.exceptions, + title: EXCEPTIONS_ITEM_LABEL, + description: '', + icon: 'testIcon2', + path: '', + }, + ], + }, +]; + +jest.mock('../../common/links', () => ({ + useAppNavLinks: jest.fn(() => mockAppLinks), +})); describe('LandingCategories', () => { it('renders items', () => { const { queryByText } = render( - + ); @@ -57,15 +70,12 @@ describe('LandingCategories', () => { const { queryAllByTestId } = render( ); diff --git a/x-pack/plugins/security_solution/public/landing_pages/pages/manage.tsx b/x-pack/plugins/security_solution/public/landing_pages/pages/manage.tsx index da4d25f6213058..172506868cec96 100644 --- a/x-pack/plugins/security_solution/public/landing_pages/pages/manage.tsx +++ b/x-pack/plugins/security_solution/public/landing_pages/pages/manage.tsx @@ -5,140 +5,24 @@ * 2.0. */ import { EuiHorizontalRule, EuiSpacer, EuiTitle } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; import { compact } from 'lodash/fp'; import React from 'react'; import styled from 'styled-components'; -import { - BLOCKLIST, - ENDPOINTS, - EVENT_FILTERS, - EXCEPTIONS, - TRUSTED_APPLICATIONS, -} from '../../app/translations'; + import { SecurityPageName } from '../../app/types'; import { HeaderPage } from '../../common/components/header_page'; import { SecuritySolutionPageWrapper } from '../../common/components/page_wrapper'; +import { useAppNavLinks } from '../../common/links'; +import { NavLinkItem } from '../../common/links/types'; import { SpyRoute } from '../../common/utils/route/spy_routes'; -import { LandingLinksIcons, NavItem } from '../components/landing_links_icons'; -import { IconBlocklist } from '../icons/blocklist'; -import { IconEndpoints } from '../icons/endpoints'; -import { IconEndpointPolicies } from '../icons/endpoint_policies'; -import { IconEventFilters } from '../icons/event_filters'; -import { IconExceptionLists } from '../icons/exception_lists'; -import { IconHostIsolation } from '../icons/host_isolation'; -import { IconSiemRules } from '../icons/siem_rules'; -import { IconTrustedApplications } from '../icons/trusted_applications'; +import { LandingLinksIcons } from '../components/landing_links_icons'; +import { LandingNavGroup, MANAGE_NAVIGATION_CATEGORIES } from '../constants'; import { MANAGE_PAGE_TITLE } from './translations'; -// TODO -const FIX_ME_TEMPORARY_DESCRIPTION = 'Description here'; - -export interface NavConfigType { - items: NavItem[]; - categories: Array<{ label: string; itemIds: SecurityPageName[] }>; -} - -const config: NavConfigType = { - categories: [ - { - label: i18n.translate('xpack.securitySolution.landing.threatHunting.siemTitle', { - defaultMessage: 'SIEM', - }), - itemIds: [SecurityPageName.rules, SecurityPageName.exceptions], - }, - { - label: i18n.translate('xpack.securitySolution.landing.threatHunting.endpointsTitle', { - defaultMessage: 'ENDPOINTS', - }), - itemIds: [ - SecurityPageName.endpoints, - SecurityPageName.policies, - SecurityPageName.trustedApps, - SecurityPageName.eventFilters, - SecurityPageName.blocklist, - SecurityPageName.hostIsolationExceptions, - ], - }, - ], - items: [ - { - id: SecurityPageName.rules, - label: i18n.translate('xpack.securitySolution.landing.manage.rulesLabel', { - defaultMessage: 'SIEM rules', - }), - description: FIX_ME_TEMPORARY_DESCRIPTION, - icon: IconSiemRules, - }, - { - id: SecurityPageName.exceptions, - label: EXCEPTIONS, - description: FIX_ME_TEMPORARY_DESCRIPTION, - icon: IconExceptionLists, - }, - { - id: SecurityPageName.endpoints, - label: ENDPOINTS, - description: i18n.translate('xpack.securitySolution.landing.manage.endpointsDescription', { - defaultMessage: 'Hosts running endpoint security', - }), - icon: IconEndpoints, - }, - { - id: SecurityPageName.policies, - label: i18n.translate('xpack.securitySolution.landing.manage.endpointPoliceLabel', { - defaultMessage: 'Endpoint policies', - }), - description: FIX_ME_TEMPORARY_DESCRIPTION, - icon: IconEndpointPolicies, - }, - { - id: SecurityPageName.trustedApps, - label: TRUSTED_APPLICATIONS, - description: i18n.translate( - 'xpack.securitySolution.landing.manage.trustedApplicationsDescription', - { - defaultMessage: - 'Improve performance or alleviate conflicts with other applications running on your hosts', - } - ), - icon: IconTrustedApplications, - }, - { - id: SecurityPageName.eventFilters, - label: EVENT_FILTERS, - description: i18n.translate('xpack.securitySolution.landing.manage.eventFiltersDescription', { - defaultMessage: 'Exclude unwanted applications from running on your hosts', - }), - icon: IconEventFilters, - }, - { - id: SecurityPageName.blocklist, - label: BLOCKLIST, - description: FIX_ME_TEMPORARY_DESCRIPTION, - icon: IconBlocklist, - }, - { - id: SecurityPageName.hostIsolationExceptions, - label: i18n.translate('xpack.securitySolution.landing.manage.hostIsolationLabel', { - defaultMessage: 'Host isolation IP exceptions', - }), - description: i18n.translate( - 'xpack.securitySolution.landing.manage.hostIsolationDescription', - { - defaultMessage: 'Allow isolated hosts to communicate with specific IPs', - } - ), - - icon: IconHostIsolation, - }, - ], -}; - export const ManageLandingPage = () => ( - + ); @@ -148,16 +32,18 @@ const StyledEuiHorizontalRule = styled(EuiHorizontalRule)` margin-bottom: ${({ theme }) => theme.eui.paddingSizes.l}; `; -const getNavItembyId = (navConfig: NavConfigType) => (itemId: string) => - navConfig.items.find(({ id }: NavItem) => id === itemId); +const getNavItembyId = (links: NavLinkItem[]) => (itemId: string) => + links.find(({ id }: NavLinkItem) => id === itemId); + +const navItemsFromIds = (itemIds: SecurityPageName[], links: NavLinkItem[]) => + compact(itemIds.map(getNavItembyId(links))); -const navItemsFromIds = (itemIds: SecurityPageName[], navConfig: NavConfigType) => - compact(itemIds.map(getNavItembyId(navConfig))); +export const LandingCategories = React.memo(({ groups }: { groups: LandingNavGroup[] }) => { + const manageLink = useAppNavLinks().find(({ id }) => id === SecurityPageName.administration); -export const LandingCategories = React.memo(({ navConfig }: { navConfig: NavConfigType }) => { return ( <> - {navConfig.categories.map(({ label, itemIds }, index) => ( + {groups.map(({ label, itemIds }, index) => (
{index > 0 && ( <> @@ -169,7 +55,7 @@ export const LandingCategories = React.memo(({ navConfig }: { navConfig: NavConf

{label}

- +
))} diff --git a/x-pack/plugins/security_solution/public/landing_pages/pages/threat_hunting.tsx b/x-pack/plugins/security_solution/public/landing_pages/pages/threat_hunting.tsx index 2a0f4e471a75de..7d486c102a2ddf 100644 --- a/x-pack/plugins/security_solution/public/landing_pages/pages/threat_hunting.tsx +++ b/x-pack/plugins/security_solution/public/landing_pages/pages/threat_hunting.tsx @@ -5,51 +5,23 @@ * 2.0. */ import React from 'react'; -import { i18n } from '@kbn/i18n'; import { SecurityPageName } from '../../app/types'; import { HeaderPage } from '../../common/components/header_page'; import { SecuritySolutionPageWrapper } from '../../common/components/page_wrapper'; import { SpyRoute } from '../../common/utils/route/spy_routes'; -import { LandingLinksImages, NavItem } from '../components/landing_links_images'; +import { LandingLinksImages } from '../components/landing_links_images'; import { THREAT_HUNTING_PAGE_TITLE } from './translations'; -import userPageImg from '../../common/images/users_page.png'; -import hostsPageImg from '../../common/images/hosts_page.png'; -import networkPageImg from '../../common/images/network_page.png'; -import { HOSTS, NETWORK, USERS } from '../../app/translations'; +import { useAppNavLinks } from '../../common/links'; -const items: NavItem[] = [ - { - id: SecurityPageName.hosts, - label: HOSTS, - description: i18n.translate('xpack.securitySolution.landing.threatHunting.hostsDescription', { - defaultMessage: - 'Computer or other device that communicates with other hosts on a network. Hosts on a network include clients and servers -- that send or receive data, services or applications.', - }), - image: hostsPageImg, - }, - { - id: SecurityPageName.network, - label: NETWORK, - description: i18n.translate('xpack.securitySolution.landing.threatHunting.networkDescription', { - defaultMessage: - 'The action or process of interacting with others to exchange information and develop professional or social contacts.', - }), - image: networkPageImg, - }, - { - id: SecurityPageName.users, - label: USERS, - description: i18n.translate('xpack.securitySolution.landing.threatHunting.usersDescription', { - defaultMessage: 'Sudo commands dashboard from the Logs System integration.', - }), - image: userPageImg, - }, -]; - -export const ThreatHuntingLandingPage = () => ( - - - - - -); +export const ThreatHuntingLandingPage = () => { + const threatHuntinglinks = useAppNavLinks().find( + ({ id }) => id === SecurityPageName.threatHuntingLanding + ); + return ( + + + + + + ); +}; diff --git a/x-pack/plugins/security_solution/public/landing_pages/icons/blocklist.tsx b/x-pack/plugins/security_solution/public/management/icons/blocklist.tsx similarity index 100% rename from x-pack/plugins/security_solution/public/landing_pages/icons/blocklist.tsx rename to x-pack/plugins/security_solution/public/management/icons/blocklist.tsx diff --git a/x-pack/plugins/security_solution/public/landing_pages/icons/endpoint_policies.tsx b/x-pack/plugins/security_solution/public/management/icons/endpoint_policies.tsx similarity index 100% rename from x-pack/plugins/security_solution/public/landing_pages/icons/endpoint_policies.tsx rename to x-pack/plugins/security_solution/public/management/icons/endpoint_policies.tsx diff --git a/x-pack/plugins/security_solution/public/landing_pages/icons/endpoints.tsx b/x-pack/plugins/security_solution/public/management/icons/endpoints.tsx similarity index 100% rename from x-pack/plugins/security_solution/public/landing_pages/icons/endpoints.tsx rename to x-pack/plugins/security_solution/public/management/icons/endpoints.tsx diff --git a/x-pack/plugins/security_solution/public/landing_pages/icons/event_filters.tsx b/x-pack/plugins/security_solution/public/management/icons/event_filters.tsx similarity index 100% rename from x-pack/plugins/security_solution/public/landing_pages/icons/event_filters.tsx rename to x-pack/plugins/security_solution/public/management/icons/event_filters.tsx diff --git a/x-pack/plugins/security_solution/public/landing_pages/icons/exception_lists.tsx b/x-pack/plugins/security_solution/public/management/icons/exception_lists.tsx similarity index 100% rename from x-pack/plugins/security_solution/public/landing_pages/icons/exception_lists.tsx rename to x-pack/plugins/security_solution/public/management/icons/exception_lists.tsx diff --git a/x-pack/plugins/security_solution/public/landing_pages/icons/host_isolation.tsx b/x-pack/plugins/security_solution/public/management/icons/host_isolation.tsx similarity index 100% rename from x-pack/plugins/security_solution/public/landing_pages/icons/host_isolation.tsx rename to x-pack/plugins/security_solution/public/management/icons/host_isolation.tsx diff --git a/x-pack/plugins/security_solution/public/landing_pages/icons/siem_rules.tsx b/x-pack/plugins/security_solution/public/management/icons/siem_rules.tsx similarity index 100% rename from x-pack/plugins/security_solution/public/landing_pages/icons/siem_rules.tsx rename to x-pack/plugins/security_solution/public/management/icons/siem_rules.tsx diff --git a/x-pack/plugins/security_solution/public/landing_pages/icons/trusted_applications.tsx b/x-pack/plugins/security_solution/public/management/icons/trusted_applications.tsx similarity index 100% rename from x-pack/plugins/security_solution/public/landing_pages/icons/trusted_applications.tsx rename to x-pack/plugins/security_solution/public/management/icons/trusted_applications.tsx diff --git a/x-pack/plugins/security_solution/public/management/links.ts b/x-pack/plugins/security_solution/public/management/links.ts index d941d538c80f7c..98a78820c4b845 100644 --- a/x-pack/plugins/security_solution/public/management/links.ts +++ b/x-pack/plugins/security_solution/public/management/links.ts @@ -31,6 +31,16 @@ import { } from '../app/translations'; import { FEATURE, LinkItem } from '../common/links/types'; +import { IconBlocklist } from './icons/blocklist'; +import { IconEndpoints } from './icons/endpoints'; +import { IconEndpointPolicies } from './icons/endpoint_policies'; +import { IconEventFilters } from './icons/event_filters'; +import { IconExceptionLists } from './icons/exception_lists'; +import { IconHostIsolation } from './icons/host_isolation'; +import { IconSiemRules } from './icons/siem_rules'; +import { IconTrustedApplications } from './icons/trusted_applications'; +const FIX_ME_TEMPORARY_DESCRIPTION = 'Description here'; + export const links: LinkItem = { id: SecurityPageName.administration, title: MANAGE, @@ -47,6 +57,12 @@ export const links: LinkItem = { { id: SecurityPageName.rules, title: RULES, + description: i18n.translate('xpack.securitySolution.appLinks.rulesDescription', { + defaultMessage: + "Create and manage rules to check for suspicious source events, and create alerts when a rule's conditions are met.", + }), + + landingIcon: IconSiemRules, path: RULES_PATH, globalNavEnabled: false, globalSearchKeywords: [ @@ -59,6 +75,10 @@ export const links: LinkItem = { { id: SecurityPageName.exceptions, title: EXCEPTIONS, + description: i18n.translate('xpack.securitySolution.appLinks.exceptionsDescription', { + defaultMessage: 'Create and manage exceptions to prevent the creation of unwanted alerts.', + }), + landingIcon: IconExceptionLists, path: EXCEPTIONS_PATH, globalNavEnabled: false, globalSearchKeywords: [ @@ -70,6 +90,10 @@ export const links: LinkItem = { }, { id: SecurityPageName.endpoints, + description: i18n.translate('xpack.securitySolution.appLinks.endpointsDescription', { + defaultMessage: 'Hosts running endpoint security', + }), + landingIcon: IconEndpoints, globalNavEnabled: true, title: ENDPOINTS, globalNavOrder: 9006, @@ -79,6 +103,11 @@ export const links: LinkItem = { { id: SecurityPageName.policies, title: POLICIES, + description: i18n.translate('xpack.securitySolution.appLinks.policiesDescription', { + defaultMessage: + 'Use policies to customize endpoint and cloud workload protections and other configurations', + }), + landingIcon: IconEndpointPolicies, path: POLICIES_PATH, skipUrlState: true, experimentalKey: 'policyListEnabled', @@ -86,24 +115,42 @@ export const links: LinkItem = { { id: SecurityPageName.trustedApps, title: TRUSTED_APPLICATIONS, + description: i18n.translate( + 'xpack.securitySolution.appLinks.trustedApplicationsDescription', + { + defaultMessage: + 'Improve performance or alleviate conflicts with other applications running on your hosts', + } + ), + landingIcon: IconTrustedApplications, path: TRUSTED_APPS_PATH, skipUrlState: true, }, { id: SecurityPageName.eventFilters, title: EVENT_FILTERS, + description: i18n.translate('xpack.securitySolution.appLinks.eventFiltersDescription', { + defaultMessage: 'Exclude unwanted applications from running on your hosts', + }), + landingIcon: IconEventFilters, path: EVENT_FILTERS_PATH, skipUrlState: true, }, { id: SecurityPageName.hostIsolationExceptions, title: HOST_ISOLATION_EXCEPTIONS, + description: i18n.translate('xpack.securitySolution.appLinks.hostIsolationDescription', { + defaultMessage: 'Allow isolated hosts to communicate with specific IPs', + }), + landingIcon: IconHostIsolation, path: HOST_ISOLATION_EXCEPTIONS_PATH, skipUrlState: true, }, { id: SecurityPageName.blocklist, title: BLOCKLIST, + description: FIX_ME_TEMPORARY_DESCRIPTION, + landingIcon: IconBlocklist, path: BLOCKLIST_PATH, skipUrlState: true, }, diff --git a/x-pack/plugins/security_solution/public/network/links.ts b/x-pack/plugins/security_solution/public/network/links.ts index ad209a220eebcb..f52a0c6a117544 100644 --- a/x-pack/plugins/security_solution/public/network/links.ts +++ b/x-pack/plugins/security_solution/public/network/links.ts @@ -9,10 +9,16 @@ import { i18n } from '@kbn/i18n'; import { NETWORK_PATH, SecurityPageName } from '../../common/constants'; import { NETWORK } from '../app/translations'; import { LinkItem } from '../common/links/types'; +import networkPageImg from '../common/images/network_page.png'; export const links: LinkItem = { id: SecurityPageName.network, title: NETWORK, + landingImage: networkPageImg, + description: i18n.translate('xpack.securitySolution.appLinks.network.description', { + defaultMessage: + 'The action or process of interacting with others to exchange information and develop professional or social contacts.', + }), path: NETWORK_PATH, globalNavEnabled: true, globalSearchKeywords: [ diff --git a/x-pack/plugins/security_solution/public/overview/links.ts b/x-pack/plugins/security_solution/public/overview/links.ts index 89f75053b3d6f9..2cfb8df5827424 100644 --- a/x-pack/plugins/security_solution/public/overview/links.ts +++ b/x-pack/plugins/security_solution/public/overview/links.ts @@ -15,10 +15,16 @@ import { } from '../../common/constants'; import { DASHBOARDS, DETECTION_RESPONSE, GETTING_STARTED, OVERVIEW } from '../app/translations'; import { FEATURE, LinkItem } from '../common/links/types'; +import overviewPageImg from '../common/images/overview_page.png'; +import detectionResponsePageImg from '../common/images/detection_response_page.png'; export const overviewLinks: LinkItem = { id: SecurityPageName.overview, title: OVERVIEW, + landingImage: overviewPageImg, + description: i18n.translate('xpack.securitySolution.appLinks.overviewDescription', { + defaultMessage: 'What is going in your secuity environment', + }), path: OVERVIEW_PATH, globalNavEnabled: true, features: [FEATURE.general], @@ -47,6 +53,11 @@ export const gettingStartedLinks: LinkItem = { export const detectionResponseLinks: LinkItem = { id: SecurityPageName.detectionAndResponse, title: DETECTION_RESPONSE, + landingImage: detectionResponsePageImg, + description: i18n.translate('xpack.securitySolution.appLinks.detectionAndResponseDescription', { + defaultMessage: + "Monitor the impact of application and device performance from the end user's point of view.", + }), path: DETECTION_RESPONSE_PATH, globalNavEnabled: false, experimentalKey: 'detectionResponseEnabled', diff --git a/x-pack/plugins/security_solution/public/users/links.ts b/x-pack/plugins/security_solution/public/users/links.ts index bd7bef4af8e82f..c7176ec11daefd 100644 --- a/x-pack/plugins/security_solution/public/users/links.ts +++ b/x-pack/plugins/security_solution/public/users/links.ts @@ -9,10 +9,15 @@ import { i18n } from '@kbn/i18n'; import { SecurityPageName, USERS_PATH } from '../../common/constants'; import { USERS } from '../app/translations'; import { LinkItem } from '../common/links/types'; +import userPageImg from '../common/images/users_page.png'; export const links: LinkItem = { id: SecurityPageName.users, title: USERS, + landingImage: userPageImg, + description: i18n.translate('xpack.securitySolution.appLinks.users.description', { + defaultMessage: 'Sudo commands dashboard from the Logs System integration.', + }), path: USERS_PATH, globalNavEnabled: true, experimentalKey: 'usersEnabled',