-
Notifications
You must be signed in to change notification settings - Fork 8.5k
[Security Solution] New Add Data Page #108763
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
dd77671
7922134
57c8667
c29c673
b6f22aa
566b111
c6243e4
6b587c5
99dd66a
5937a32
b128771
ded53c8
6503edd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -16,6 +16,7 @@ export const APP_ICON = 'securityAnalyticsApp'; | |||||||||||||
| export const APP_ICON_SOLUTION = 'logoSecurity'; | ||||||||||||||
| export const APP_PATH = `/app/security`; | ||||||||||||||
| export const ADD_DATA_PATH = `/app/home#/tutorial_directory/security`; | ||||||||||||||
| export const ADD_INTEGRATION_PATH = `/app/integrations/browse?category=security`; | ||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This path seems to be invalid. Suggestion: instead of hardcoding the path, use Fleet's path getter method which is exported out of the public folder: import {pagePathGetters} from '../path/to/fleet/plugin/public'if wanting to land on the all integration page and search/filter by
Suggested change
If wanting to land on the all integration page showing only the
Suggested change
and finally, if wanting to show only specific types of integrations on the Security category, you can combine the above:
Suggested change
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks @paul-tavares , looks like the category version is what we want based on the decisions made in #107682
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've moved this suggestion to the new PR: #112142 (comment) |
||||||||||||||
| export const DEFAULT_BYTES_FORMAT = 'format:bytes:defaultPattern'; | ||||||||||||||
| export const DEFAULT_DATE_FORMAT = 'dateFormat'; | ||||||||||||||
| export const DEFAULT_DATE_FORMAT_TZ = 'dateFormat:tz'; | ||||||||||||||
|
|
||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -23,6 +23,10 @@ import { | |
| } from './bottom_bar'; | ||
| import { useShowTimeline } from '../../../common/utils/timeline/use_show_timeline'; | ||
| import { gutterTimeline } from '../../../common/lib/helpers'; | ||
| import { useSourcererScope } from '../../../common/containers/sourcerer'; | ||
| import { OverviewEmpty } from '../../../overview/components/overview_empty'; | ||
| import { ENDPOINT_METADATA_INDEX } from '../../../../common/constants'; | ||
| import { useFetchIndex } from '../../../common/containers/source'; | ||
|
|
||
| /* eslint-disable react/display-name */ | ||
|
|
||
|
|
@@ -73,11 +77,17 @@ export const SecuritySolutionTemplateWrapper: React.FC<SecuritySolutionPageWrapp | |
| const { show: isShowingTimelineOverlay } = useDeepEqualSelector((state) => | ||
| getTimelineShowStatus(state, TimelineId.active) | ||
| ); | ||
| const endpointMetadataIndex = useMemo<string[]>(() => { | ||
| return [ENDPOINT_METADATA_INDEX]; | ||
| }, []); | ||
| const [, { indexExists: metadataIndexExists }] = useFetchIndex(endpointMetadataIndex, true); | ||
| const { indicesExist } = useSourcererScope(); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @michaelolo24 @jonathan-buttner - to get the tests to pass, I believe this The issue is the new empty state covers the entire app, including the Endpoint management page which tracks just Endpoint metadata. I'm happy to help make the change, just wanted to point this out. I can work with you offline.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @kevinlog yea, that might be a good idea. I know @stephmilovic is making updates to a lot of the sourcerer stuff now, so might be good to sync up with her as well
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I spoke with @stephmilovic offline - a potential solution is to use the
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Great, thanks Kevin! |
||
| const securityIndicesExist = indicesExist || metadataIndexExists; | ||
|
|
||
| /* StyledKibanaPageTemplate is a styled EuiPageTemplate. Security solution currently passes the header and page content as the children of StyledKibanaPageTemplate, as opposed to using the pageHeader prop, which may account for any style discrepancies, such as the bottom border not extending the full width of the page, between EuiPageTemplate and the security solution pages. | ||
| */ | ||
|
|
||
| return ( | ||
| return securityIndicesExist ? ( | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🤔 I'm wondering if this is the right place for this change to occur, which impact all areas of security solution. For endpoint, one might (maybe?) want to start configuring policies (ex. trusted applications, event filters, etc.) before any data is available in the Endpoint metadata index. This change makes it impossible for the user to do that until at least one of the checked indexes has data in it. Do I have that right? I'm thinking that each section of security solution should problaby have its won way to determine if the onboarding page should be displayed or not. cc/ @kevinlog
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In general I agree, but for now we just need something up. This suggestion would require a lot more coordination that I"m not sure we have time for in 7.16. |
||
| <StyledKibanaPageTemplate | ||
| $isTimelineBottomBarVisible={isTimelineBottomBarVisible} | ||
| $isShowingTimelineOverlay={isShowingTimelineOverlay} | ||
|
|
@@ -98,6 +108,8 @@ export const SecuritySolutionTemplateWrapper: React.FC<SecuritySolutionPageWrapp | |
| {children} | ||
| </EuiPanel> | ||
| </StyledKibanaPageTemplate> | ||
| ) : ( | ||
| <OverviewEmpty /> | ||
| ); | ||
| } | ||
| ); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,105 +6,55 @@ | |
| */ | ||
|
|
||
| import React, { useMemo } from 'react'; | ||
| import { omit } from 'lodash/fp'; | ||
| import { createStructuredSelector } from 'reselect'; | ||
|
|
||
| import { FormattedMessage } from '@kbn/i18n/react'; | ||
| import { EuiLink } from '@elastic/eui'; | ||
| import * as i18nCommon from '../../../common/translations'; | ||
| import { EmptyPage, EmptyPageActionsProps } from '../../../common/components/empty_page'; | ||
| import { i18n } from '@kbn/i18n'; | ||
| import { useKibana } from '../../../common/lib/kibana'; | ||
| import { ADD_DATA_PATH } from '../../../../common/constants'; | ||
| import { | ||
| useEndpointSelector, | ||
| useIngestUrl, | ||
| } from '../../../management/pages/endpoint_hosts/view/hooks'; | ||
| import { useNavigateToAppEventHandler } from '../../../common/hooks/endpoint/use_navigate_to_app_event_handler'; | ||
| import { CreateStructuredSelector } from '../../../common/store'; | ||
| import { endpointPackageVersion as useEndpointPackageVersion } from '../../../management/pages/endpoint_hosts/store/selectors'; | ||
| import { ADD_INTEGRATION_PATH, ADD_DATA_PATH } from '../../../../common/constants'; | ||
| import { SOLUTION_NAME } from '../../../../public/common/translations'; | ||
| import { useUserPrivileges } from '../../../common/components/user_privileges'; | ||
|
|
||
| import { | ||
| KibanaPageTemplate, | ||
| NoDataPageActionsProps, | ||
| } from '../../../../../../../src/plugins/kibana_react/public'; | ||
|
|
||
| const OverviewEmptyComponent: React.FC = () => { | ||
| const { http, docLinks } = useKibana().services; | ||
| const basePath = http.basePath.get(); | ||
| const selector = (createStructuredSelector as CreateStructuredSelector)({ | ||
| endpointPackageVersion: useEndpointPackageVersion, | ||
| }); | ||
| const { endpointPackageVersion } = useEndpointSelector(selector); | ||
| const { url: ingestUrl } = useIngestUrl(''); | ||
|
|
||
| const endpointIntegrationUrlPath = endpointPackageVersion | ||
| ? `/endpoint-${endpointPackageVersion}/add-integration` | ||
| : ''; | ||
| const endpointIntegrationUrl = `/integrations${endpointIntegrationUrlPath}`; | ||
| const handleEndpointClick = useNavigateToAppEventHandler('fleet', { | ||
| path: endpointIntegrationUrl, | ||
| }); | ||
| const canAccessFleet = useUserPrivileges().endpointPrivileges.canAccessFleet; | ||
|
|
||
| const emptyPageActions: EmptyPageActionsProps = useMemo( | ||
| const agentAction: NoDataPageActionsProps = useMemo( | ||
| () => ({ | ||
| elasticAgent: { | ||
| label: i18nCommon.EMPTY_ACTION_ELASTIC_AGENT, | ||
| url: ingestUrl, | ||
| description: i18nCommon.EMPTY_ACTION_ELASTIC_AGENT_DESCRIPTION, | ||
| fill: false, | ||
| }, | ||
| beats: { | ||
| label: i18nCommon.EMPTY_ACTION_BEATS, | ||
| url: `${basePath}${ADD_DATA_PATH}`, | ||
| description: i18nCommon.EMPTY_ACTION_BEATS_DESCRIPTION, | ||
| fill: false, | ||
| }, | ||
| endpoint: { | ||
| label: i18nCommon.EMPTY_ACTION_ENDPOINT, | ||
| url: endpointIntegrationUrl, | ||
| description: i18nCommon.EMPTY_ACTION_ENDPOINT_DESCRIPTION, | ||
| onClick: handleEndpointClick, | ||
| fill: false, | ||
| href: `${basePath}${ADD_INTEGRATION_PATH}`, | ||
| description: i18n.translate( | ||
| 'xpack.securitySolution.pages.emptyPage.beatsCard.description', | ||
| { | ||
| defaultMessage: | ||
| 'Use Elastic Agent to collect security events and protect your endpoints from threats. Manage your agents in Fleet and add integrations with a single click.', | ||
| } | ||
| ), | ||
| }, | ||
| }), | ||
| [basePath, ingestUrl, endpointIntegrationUrl, handleEndpointClick] | ||
| [basePath] | ||
| ); | ||
|
|
||
| const emptyPageIngestDisabledActions = useMemo( | ||
| () => omit(['elasticAgent', 'endpoint'], emptyPageActions), | ||
| [emptyPageActions] | ||
| const beatsAction: NoDataPageActionsProps = useMemo( | ||
| () => ({ | ||
| beats: { | ||
| href: `${basePath}${ADD_DATA_PATH}`, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Did we want to have a description for the beats link like we do for
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is a default message for both of these links/cards. So only if you want to differentiate from that which is:
|
||
| }, | ||
| }), | ||
| [basePath] | ||
| ); | ||
|
|
||
| return canAccessFleet === true ? ( | ||
| <EmptyPage | ||
| actions={emptyPageActions} | ||
| data-test-subj="empty-page" | ||
| message={ | ||
| <> | ||
| <FormattedMessage | ||
| id="xpack.securitySolution.emptyMessage" | ||
| defaultMessage="Elastic Security integrates the free and open Elastic SIEM with Endpoint Security to prevent, detect, and respond to threats. To begin, you’ll need to add security solution related data to the Elastic Stack. For additional information, you can view our " | ||
| /> | ||
| <EuiLink href={docLinks.links.siem.gettingStarted} target="_blank"> | ||
| {i18nCommon.EMPTY_ACTION_SECONDARY} | ||
| </EuiLink> | ||
| </> | ||
| } | ||
| title={i18nCommon.EMPTY_TITLE} | ||
| /> | ||
| ) : ( | ||
| <EmptyPage | ||
| actions={emptyPageIngestDisabledActions} | ||
| return ( | ||
| <KibanaPageTemplate | ||
| data-test-subj="empty-page" | ||
| message={ | ||
| <> | ||
| <FormattedMessage | ||
| id="xpack.securitySolution.emptyMessage" | ||
| defaultMessage="Elastic Security integrates the free and open Elastic SIEM with Endpoint Security to prevent, detect, and respond to threats. To begin, you’ll need to add security solution related data to the Elastic Stack. For additional information, you can view our " | ||
| /> | ||
| <EuiLink href={docLinks.links.siem.gettingStarted} target="_blank"> | ||
| {i18nCommon.EMPTY_ACTION_SECONDARY} | ||
| </EuiLink> | ||
| </> | ||
| } | ||
| title={i18nCommon.EMPTY_TITLE} | ||
| noDataConfig={{ | ||
| solution: SOLUTION_NAME, | ||
| actions: canAccessFleet ? agentAction : beatsAction, | ||
| docsLink: docLinks.links.siem.gettingStarted, | ||
| }} | ||
| /> | ||
| ); | ||
| }; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also can we add a
data-test-subjproperty to the card so we can reference the card in the tests?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should inherit all the same props from
EuiCardwhich does support this. Have you tried adding it?