-
Notifications
You must be signed in to change notification settings - Fork 8.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Refactor user flyout components to be reused by hosts
- Loading branch information
Showing
53 changed files
with
1,990 additions
and
565 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
49 changes: 49 additions & 0 deletions
49
x-pack/plugins/security_solution/public/flyout/entity_details/host_details_left/index.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
/* | ||
* 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 React, { useMemo } from 'react'; | ||
import type { FlyoutPanelProps } from '@kbn/expandable-flyout'; | ||
import { getRiskInputTab } from '../../../entity_analytics/components/entity_details_flyout'; | ||
import { EntityDetailsLeftPanelTab, LeftPanelHeader } from '../shared/left_panel/left_panel_header'; | ||
import { LeftPanelContent } from '../shared/left_panel/left_panel_content'; | ||
|
||
interface RiskInputsParam { | ||
alertIds: string[]; | ||
} | ||
|
||
export interface HostDetailsPanelProps extends Record<string, unknown> { | ||
riskInputs: RiskInputsParam; | ||
} | ||
export interface HostDetailsExpandableFlyoutProps extends FlyoutPanelProps { | ||
key: 'host_details'; | ||
params: HostDetailsPanelProps; | ||
} | ||
export const HostDetailsPanelKey: HostDetailsExpandableFlyoutProps['key'] = 'host_details'; | ||
|
||
export const HostDetailsPanel = ({ riskInputs }: HostDetailsPanelProps) => { | ||
// Temporary implementation while Host details left panel don't have Asset tabs | ||
const [tabs, selectedTabId, setSelectedTabId] = useMemo(() => { | ||
return [ | ||
riskInputs.alertIds.length > 0 ? [getRiskInputTab(riskInputs.alertIds)] : [], | ||
EntityDetailsLeftPanelTab.RISK_INPUTS, | ||
() => {}, | ||
]; | ||
}, [riskInputs.alertIds]); | ||
|
||
return ( | ||
<> | ||
<LeftPanelHeader | ||
selectedTabId={selectedTabId} | ||
setSelectedTabId={setSelectedTabId} | ||
tabs={tabs} | ||
/> | ||
<LeftPanelContent selectedTabId={selectedTabId} tabs={tabs} /> | ||
</> | ||
); | ||
}; | ||
|
||
HostDetailsPanel.displayName = 'HostDetailsPanel'; |
147 changes: 147 additions & 0 deletions
147
x-pack/plugins/security_solution/public/flyout/entity_details/host_right/content.stories.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
/* | ||
* 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 React from 'react'; | ||
import { storiesOf } from '@storybook/react'; | ||
import { EuiFlyout } from '@elastic/eui'; | ||
import type { ExpandableFlyoutContextValue } from '@kbn/expandable-flyout/src/context'; | ||
import { ExpandableFlyoutContext } from '@kbn/expandable-flyout/src/context'; | ||
import { StorybookProviders } from '../../../common/mock/storybook_providers'; | ||
import { | ||
mockManagedUserData, | ||
mockObservedUser, | ||
mockRiskScoreState, | ||
} from '../../../timelines/components/side_panel/new_user_detail/__mocks__'; | ||
import { UserPanelContent } from './content'; | ||
|
||
const flyoutContextValue = { | ||
openLeftPanel: () => window.alert('openLeftPanel called'), | ||
panels: {}, | ||
} as unknown as ExpandableFlyoutContextValue; | ||
|
||
const riskScoreData = { ...mockRiskScoreState, data: [] }; | ||
|
||
storiesOf('Components/UserPanelContent', module) | ||
.addDecorator((storyFn) => ( | ||
<StorybookProviders> | ||
<ExpandableFlyoutContext.Provider value={flyoutContextValue}> | ||
<EuiFlyout size="m" onClose={() => {}}> | ||
{storyFn()} | ||
</EuiFlyout> | ||
</ExpandableFlyoutContext.Provider> | ||
</StorybookProviders> | ||
)) | ||
.add('default', () => ( | ||
<UserPanelContent | ||
managedUser={mockManagedUserData} | ||
observedUser={mockObservedUser} | ||
riskScoreState={riskScoreData} | ||
contextID={'test-user-details'} | ||
scopeId={'test-scopeId'} | ||
isDraggable={false} | ||
/> | ||
)) | ||
.add('integration disabled', () => ( | ||
<UserPanelContent | ||
managedUser={{ | ||
data: undefined, | ||
isLoading: false, | ||
isIntegrationEnabled: false, | ||
}} | ||
observedUser={mockObservedUser} | ||
riskScoreState={riskScoreData} | ||
contextID={'test-user-details'} | ||
scopeId={'test-scopeId'} | ||
isDraggable={false} | ||
/> | ||
)) | ||
.add('no managed data', () => ( | ||
<UserPanelContent | ||
managedUser={{ | ||
data: undefined, | ||
isLoading: false, | ||
isIntegrationEnabled: true, | ||
}} | ||
observedUser={mockObservedUser} | ||
riskScoreState={riskScoreData} | ||
contextID={'test-user-details'} | ||
scopeId={'test-scopeId'} | ||
isDraggable={false} | ||
/> | ||
)) | ||
.add('no observed data', () => ( | ||
<UserPanelContent | ||
managedUser={mockManagedUserData} | ||
observedUser={{ | ||
details: { | ||
user: { | ||
id: [], | ||
domain: [], | ||
}, | ||
host: { | ||
ip: [], | ||
os: { | ||
name: [], | ||
family: [], | ||
}, | ||
}, | ||
}, | ||
isLoading: false, | ||
firstSeen: { | ||
isLoading: false, | ||
date: undefined, | ||
}, | ||
lastSeen: { | ||
isLoading: false, | ||
date: undefined, | ||
}, | ||
anomalies: { isLoading: false, anomalies: null, jobNameById: {} }, | ||
}} | ||
riskScoreState={riskScoreData} | ||
contextID={'test-user-details'} | ||
scopeId={'test-scopeId'} | ||
isDraggable={false} | ||
/> | ||
)) | ||
.add('loading', () => ( | ||
<UserPanelContent | ||
managedUser={{ | ||
data: undefined, | ||
isLoading: true, | ||
isIntegrationEnabled: true, | ||
}} | ||
observedUser={{ | ||
details: { | ||
user: { | ||
id: [], | ||
domain: [], | ||
}, | ||
host: { | ||
ip: [], | ||
os: { | ||
name: [], | ||
family: [], | ||
}, | ||
}, | ||
}, | ||
isLoading: true, | ||
firstSeen: { | ||
isLoading: true, | ||
date: undefined, | ||
}, | ||
lastSeen: { | ||
isLoading: true, | ||
date: undefined, | ||
}, | ||
anomalies: { isLoading: true, anomalies: null, jobNameById: {} }, | ||
}} | ||
riskScoreState={riskScoreData} | ||
contextID={'test-user-details'} | ||
scopeId={'test-scopeId'} | ||
isDraggable={false} | ||
/> | ||
)); |
54 changes: 54 additions & 0 deletions
54
x-pack/plugins/security_solution/public/flyout/entity_details/host_right/content.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
/* | ||
* 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 { EuiHorizontalRule } from '@elastic/eui'; | ||
|
||
import React from 'react'; | ||
import type { RiskScoreState } from '../../../entity_analytics/api/hooks/use_risk_score'; | ||
import type { HostItem, RiskScoreEntity } from '../../../../common/search_strategy'; | ||
import { FlyoutBody } from '../../shared/components/flyout_body'; | ||
import { ObservedEntity } from '../shared/observed_entity'; | ||
import { HOST_PANEL_OBSERVED_HOST_QUERY_ID } from '.'; | ||
import type { ObservedEntityData } from '../shared/observed_entity/types'; | ||
import { useObservedHostFields } from './hooks/use_observed_host_fields'; | ||
|
||
interface HostPanelContentProps { | ||
observedHost: ObservedEntityData<HostItem>; | ||
riskScoreState: RiskScoreState<RiskScoreEntity.user>; | ||
contextID: string; | ||
scopeId: string; | ||
isDraggable: boolean; | ||
} | ||
|
||
export const HostPanelContent = ({ | ||
observedHost, | ||
riskScoreState, | ||
contextID, | ||
scopeId, | ||
isDraggable, | ||
}: HostPanelContentProps) => { | ||
const observedFields = useObservedHostFields(observedHost); | ||
|
||
return ( | ||
<FlyoutBody> | ||
{riskScoreState.isModuleEnabled && riskScoreState.data?.length !== 0 && ( | ||
<> | ||
{/* TODO <RiskSummary riskScoreData={riskScoreState} queryId={HOST_PANEL_RISK_SCORE_QUERY_ID} /> */} | ||
<EuiHorizontalRule margin="m" /> | ||
</> | ||
)} | ||
<ObservedEntity | ||
observedData={observedHost} | ||
contextID={contextID} | ||
scopeId={scopeId} | ||
isDraggable={isDraggable} | ||
observedFields={observedFields} | ||
queryId={HOST_PANEL_OBSERVED_HOST_QUERY_ID} | ||
/> | ||
</FlyoutBody> | ||
); | ||
}; |
80 changes: 80 additions & 0 deletions
80
...ns/security_solution/public/flyout/entity_details/host_right/fields/basic_host_fields.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
/* | ||
* 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 React from 'react'; | ||
|
||
import { getEmptyTagValue } from '../../../../common/components/empty_value'; | ||
import type { HostItem } from '../../../../../common/search_strategy'; | ||
import { FormattedRelativePreferenceDate } from '../../../../common/components/formatted_date'; | ||
import { NetworkDetailsLink } from '../../../../common/components/links'; | ||
import * as i18n from './translations'; | ||
import type { ObservedEntityData } from '../../shared/observed_entity/types'; | ||
import type { EntityTableRows } from '../../shared/entity_table/types'; | ||
|
||
export const basicHostFields: EntityTableRows<ObservedEntityData<HostItem>> = [ | ||
{ | ||
label: i18n.HOST_ID, | ||
getValues: (hostData: ObservedEntityData<HostItem>) => hostData.details.host?.id, | ||
field: 'host.id', | ||
}, | ||
{ | ||
label: i18n.FIRST_SEEN, | ||
render: (hostData: ObservedEntityData<HostItem>) => | ||
hostData.firstSeen.date ? ( | ||
<FormattedRelativePreferenceDate value={hostData.firstSeen.date} /> | ||
) : ( | ||
getEmptyTagValue() | ||
), | ||
}, | ||
{ | ||
label: i18n.LAST_SEEN, | ||
render: (hostData: ObservedEntityData<HostItem>) => | ||
hostData.lastSeen.date ? ( | ||
<FormattedRelativePreferenceDate value={hostData.lastSeen.date} /> | ||
) : ( | ||
getEmptyTagValue() | ||
), | ||
}, | ||
{ | ||
label: i18n.IP_ADDRESSES, | ||
field: 'host.ip', | ||
getValues: (hostData: ObservedEntityData<HostItem>) => hostData.details.host?.ip, | ||
renderField: (ip: string) => { | ||
return <NetworkDetailsLink ip={ip} />; | ||
}, | ||
}, | ||
{ | ||
label: i18n.MAC_ADDRESSES, | ||
getValues: (hostData: ObservedEntityData<HostItem>) => hostData.details.host?.mac, | ||
field: 'host.mac', | ||
}, | ||
{ | ||
label: i18n.PLATFORM, | ||
getValues: (hostData: ObservedEntityData<HostItem>) => hostData.details.host?.os?.platform, | ||
field: 'host.os.platform', | ||
}, | ||
{ | ||
label: i18n.OS, | ||
getValues: (hostData: ObservedEntityData<HostItem>) => hostData.details.host?.os?.name, | ||
field: 'host.os.name', | ||
}, | ||
{ | ||
label: i18n.FAMILY, | ||
getValues: (hostData: ObservedEntityData<HostItem>) => hostData.details.host?.os?.family, | ||
field: 'host.os.family', | ||
}, | ||
{ | ||
label: i18n.VERSION, | ||
getValues: (hostData: ObservedEntityData<HostItem>) => hostData.details.host?.os?.version, | ||
field: 'host.os.version', | ||
}, | ||
{ | ||
label: i18n.ARCHITECTURE, | ||
getValues: (hostData: ObservedEntityData<HostItem>) => hostData.details.host?.architecture, | ||
field: 'host.architecture', | ||
}, | ||
]; |
Oops, something went wrong.