mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
[RAC] integrating rbac search strategy with alert flyout (#108748)
* add alert consumers for useTimelineEventDetails * set entityType to events * rename to AlertConsumers * set entityType to alerts * send entity type to search strategy * fix import * fix import * fix import Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
848085a8c3
commit
04a8a3c199
12 changed files with 70 additions and 5 deletions
|
@ -105,6 +105,7 @@ export const CaseComponent = React.memo<CaseComponentProps>(
|
|||
const [initLoadingData, setInitLoadingData] = useState(true);
|
||||
const init = useRef(true);
|
||||
const timelineUi = useTimelineContext()?.ui;
|
||||
const alertConsumers = useTimelineContext()?.alertConsumers;
|
||||
|
||||
const {
|
||||
caseUserActions,
|
||||
|
@ -486,7 +487,9 @@ export const CaseComponent = React.memo<CaseComponentProps>(
|
|||
</EuiFlexGroup>
|
||||
</ContentWrapper>
|
||||
</WhitePageWrapper>
|
||||
{timelineUi?.renderTimelineDetailsPanel ? timelineUi.renderTimelineDetailsPanel() : null}
|
||||
{timelineUi?.renderTimelineDetailsPanel
|
||||
? timelineUi.renderTimelineDetailsPanel({ alertConsumers })
|
||||
: null}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
import React, { useState } from 'react';
|
||||
import { EuiMarkdownEditorUiPlugin, EuiMarkdownAstNodePosition } from '@elastic/eui';
|
||||
import { AlertConsumers } from '@kbn/rule-data-utils';
|
||||
import { Plugin } from 'unified';
|
||||
/**
|
||||
* @description - manage the plugins, hooks, and ui components needed to enable timeline functionality within the cases plugin
|
||||
|
@ -28,6 +29,7 @@ interface TimelineProcessingPluginRendererProps {
|
|||
}
|
||||
|
||||
export interface CasesTimelineIntegration {
|
||||
alertConsumers?: AlertConsumers[];
|
||||
editor_plugins: {
|
||||
parsingPlugin: Plugin;
|
||||
processingPluginRenderer: React.FC<
|
||||
|
@ -43,7 +45,11 @@ export interface CasesTimelineIntegration {
|
|||
};
|
||||
ui?: {
|
||||
renderInvestigateInTimelineActionComponent?: (alertIds: string[]) => JSX.Element;
|
||||
renderTimelineDetailsPanel?: () => JSX.Element;
|
||||
renderTimelineDetailsPanel?: ({
|
||||
alertConsumers,
|
||||
}: {
|
||||
alertConsumers?: AlertConsumers[];
|
||||
}) => JSX.Element;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
import React, { useCallback, useRef, useState } from 'react';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { AlertConsumers } from '@kbn/rule-data-utils';
|
||||
|
||||
import {
|
||||
getCaseDetailsUrl,
|
||||
|
@ -33,6 +34,7 @@ import { SpyRoute } from '../../../common/utils/route/spy_routes';
|
|||
import * as timelineMarkdownPlugin from '../../../common/components/markdown_editor/plugins/timeline';
|
||||
import { CaseDetailsRefreshContext } from '../../../common/components/endpoint/host_isolation/endpoint_host_isolation_cases_context';
|
||||
import { getEndpointDetailsPath } from '../../../management/common/routing';
|
||||
import { EntityType } from '../../../../../timelines/common';
|
||||
|
||||
interface Props {
|
||||
caseId: string;
|
||||
|
@ -53,13 +55,17 @@ export interface CaseProps extends Props {
|
|||
updateCase: (newCase: Case) => void;
|
||||
}
|
||||
|
||||
const TimelineDetailsPanel = () => {
|
||||
const ALERT_CONSUMER: AlertConsumers[] = [AlertConsumers.SIEM];
|
||||
|
||||
const TimelineDetailsPanel = ({ alertConsumers }: { alertConsumers?: AlertConsumers[] }) => {
|
||||
const { browserFields, docValueFields } = useSourcererScope(SourcererScopeName.detections);
|
||||
|
||||
return (
|
||||
<DetailsPanel
|
||||
alertConsumers={alertConsumers}
|
||||
browserFields={browserFields}
|
||||
docValueFields={docValueFields}
|
||||
entityType={EntityType.ALERTS}
|
||||
isFlyoutView
|
||||
timelineId={TimelineId.casePage}
|
||||
/>
|
||||
|
@ -228,6 +234,7 @@ export const CaseView = React.memo(({ caseId, subCaseId, userCanCrud }: Props) =
|
|||
showAlertDetails,
|
||||
subCaseId,
|
||||
timelineIntegration: {
|
||||
alertConsumers: ALERT_CONSUMER,
|
||||
editor_plugins: {
|
||||
parsingPlugin: timelineMarkdownPlugin.parser,
|
||||
processingPluginRenderer: timelineMarkdownPlugin.renderer,
|
||||
|
|
|
@ -11,6 +11,7 @@ import deepEqual from 'fast-deep-equal';
|
|||
import styled from 'styled-components';
|
||||
|
||||
import { isEmpty } from 'lodash/fp';
|
||||
import { AlertConsumers } from '@kbn/rule-data-utils';
|
||||
import { inputsModel, inputsSelectors, State } from '../../store';
|
||||
import { inputsActions } from '../../store/actions';
|
||||
import { ControlColumnProps, RowRenderer, TimelineId } from '../../../../common/types/timeline';
|
||||
|
@ -69,6 +70,8 @@ export interface OwnProps {
|
|||
|
||||
type Props = OwnProps & PropsFromRedux;
|
||||
|
||||
const alertConsumers: AlertConsumers[] = [AlertConsumers.SIEM];
|
||||
|
||||
/**
|
||||
* The stateful events viewer component is the highest level component that is utilized across the security_solution pages layer where
|
||||
* timeline is used BESIDES the flyout. The flyout makes use of the `EventsViewer` component which is a subcomponent here
|
||||
|
@ -216,7 +219,9 @@ const StatefulEventsViewerComponent: React.FC<Props> = ({
|
|||
</InspectButtonContainer>
|
||||
</FullScreenContainer>
|
||||
<DetailsPanel
|
||||
alertConsumers={alertConsumers}
|
||||
browserFields={browserFields}
|
||||
entityType={EntityType.ALERTS}
|
||||
docValueFields={docValueFields}
|
||||
isFlyoutView
|
||||
timelineId={id}
|
||||
|
|
|
@ -17,6 +17,7 @@ import {
|
|||
import React, { useState, useCallback, useMemo } from 'react';
|
||||
import styled from 'styled-components';
|
||||
import deepEqual from 'fast-deep-equal';
|
||||
import { AlertConsumers } from '@kbn/rule-data-utils';
|
||||
import { BrowserFields, DocValueFields } from '../../../../common/containers/source';
|
||||
import { ExpandableEvent, ExpandableEventTitle } from './expandable_event';
|
||||
import { useTimelineEventsDetails } from '../../../containers/details';
|
||||
|
@ -33,6 +34,7 @@ import { useWithCaseDetailsRefresh } from '../../../../common/components/endpoin
|
|||
import { TimelineNonEcsData } from '../../../../../common';
|
||||
import { Ecs } from '../../../../../common/ecs';
|
||||
import { EventDetailsFooter } from './footer';
|
||||
import { EntityType } from '../../../../../../timelines/common';
|
||||
|
||||
const StyledEuiFlyoutBody = styled(EuiFlyoutBody)`
|
||||
.euiFlyoutBody__overflow {
|
||||
|
@ -49,8 +51,10 @@ const StyledEuiFlyoutBody = styled(EuiFlyoutBody)`
|
|||
`;
|
||||
|
||||
interface EventDetailsPanelProps {
|
||||
alertConsumers?: AlertConsumers[];
|
||||
browserFields: BrowserFields;
|
||||
docValueFields: DocValueFields[];
|
||||
entityType?: EntityType;
|
||||
expandedEvent: {
|
||||
eventId: string;
|
||||
indexName: string;
|
||||
|
@ -65,8 +69,10 @@ interface EventDetailsPanelProps {
|
|||
}
|
||||
|
||||
const EventDetailsPanelComponent: React.FC<EventDetailsPanelProps> = ({
|
||||
alertConsumers,
|
||||
browserFields,
|
||||
docValueFields,
|
||||
entityType,
|
||||
expandedEvent,
|
||||
handleOnEventClosed,
|
||||
isFlyoutView,
|
||||
|
@ -74,7 +80,9 @@ const EventDetailsPanelComponent: React.FC<EventDetailsPanelProps> = ({
|
|||
timelineId,
|
||||
}) => {
|
||||
const [loading, detailsData] = useTimelineEventsDetails({
|
||||
alertConsumers,
|
||||
docValueFields,
|
||||
entityType,
|
||||
indexName: expandedEvent.indexName ?? '',
|
||||
eventId: expandedEvent.eventId ?? '',
|
||||
skip: !expandedEvent.eventId,
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
import React, { useCallback, useMemo } from 'react';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { EuiFlyout, EuiFlyoutProps } from '@elastic/eui';
|
||||
import { AlertConsumers } from '@kbn/rule-data-utils';
|
||||
|
||||
import { timelineActions, timelineSelectors } from '../../store/timeline';
|
||||
import { timelineDefaults } from '../../store/timeline/defaults';
|
||||
import { BrowserFields, DocValueFields } from '../../../common/containers/source';
|
||||
|
@ -16,10 +18,13 @@ import { useDeepEqualSelector } from '../../../common/hooks/use_selector';
|
|||
import { EventDetailsPanel } from './event_details';
|
||||
import { HostDetailsPanel } from './host_details';
|
||||
import { NetworkDetailsPanel } from './network_details';
|
||||
import { EntityType } from '../../../../../timelines/common';
|
||||
|
||||
interface DetailsPanelProps {
|
||||
alertConsumers?: AlertConsumers[];
|
||||
browserFields: BrowserFields;
|
||||
docValueFields: DocValueFields[];
|
||||
entityType?: EntityType;
|
||||
handleOnPanelClosed?: () => void;
|
||||
isFlyoutView?: boolean;
|
||||
tabType?: TimelineTabs;
|
||||
|
@ -33,8 +38,10 @@ interface DetailsPanelProps {
|
|||
*/
|
||||
export const DetailsPanel = React.memo(
|
||||
({
|
||||
alertConsumers,
|
||||
browserFields,
|
||||
docValueFields,
|
||||
entityType,
|
||||
handleOnPanelClosed,
|
||||
isFlyoutView,
|
||||
tabType,
|
||||
|
@ -70,8 +77,10 @@ export const DetailsPanel = React.memo(
|
|||
panelSize = 'm';
|
||||
visiblePanel = (
|
||||
<EventDetailsPanel
|
||||
alertConsumers={alertConsumers}
|
||||
browserFields={browserFields}
|
||||
docValueFields={docValueFields}
|
||||
entityType={entityType}
|
||||
expandedEvent={currentTabDetail?.params}
|
||||
handleOnEventClosed={closePanel}
|
||||
isFlyoutView={isFlyoutView}
|
||||
|
|
|
@ -13,6 +13,7 @@ import {
|
|||
EuiFlyoutFooter,
|
||||
EuiBadge,
|
||||
} from '@elastic/eui';
|
||||
import { AlertConsumers } from '@kbn/rule-data-utils';
|
||||
import { isEmpty } from 'lodash/fp';
|
||||
import React, { useEffect, useCallback } from 'react';
|
||||
import styled from 'styled-components';
|
||||
|
@ -151,6 +152,8 @@ export type Props = OwnProps & PropsFromRedux;
|
|||
|
||||
const NO_SORTING: Sort[] = [];
|
||||
|
||||
const alertConsumers: AlertConsumers[] = [AlertConsumers.SIEM];
|
||||
|
||||
export const EqlTabContentComponent: React.FC<Props> = ({
|
||||
activeTab,
|
||||
columns,
|
||||
|
@ -346,6 +349,7 @@ export const EqlTabContentComponent: React.FC<Props> = ({
|
|||
<VerticalRule />
|
||||
<ScrollableFlexItem grow={1}>
|
||||
<DetailsPanel
|
||||
alertConsumers={alertConsumers}
|
||||
browserFields={browserFields}
|
||||
docValueFields={docValueFields}
|
||||
tabType={TimelineTabs.eql}
|
||||
|
|
|
@ -16,6 +16,8 @@ import {
|
|||
EuiPanel,
|
||||
EuiHorizontalRule,
|
||||
} from '@elastic/eui';
|
||||
import { AlertConsumers } from '@kbn/rule-data-utils';
|
||||
|
||||
import React, { Fragment, useCallback, useMemo, useState } from 'react';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import styled from 'styled-components';
|
||||
|
@ -64,6 +66,8 @@ const Username = styled(EuiText)`
|
|||
font-weight: bold;
|
||||
`;
|
||||
|
||||
const alertConsumers: AlertConsumers[] = [AlertConsumers.SIEM];
|
||||
|
||||
interface UsernameWithAvatar {
|
||||
username: string;
|
||||
}
|
||||
|
@ -170,6 +174,7 @@ const NotesTabContentComponent: React.FC<NotesTabContentProps> = ({ timelineId }
|
|||
() =>
|
||||
expandedDetail[TimelineTabs.notes]?.panelView ? (
|
||||
<DetailsPanel
|
||||
alertConsumers={alertConsumers}
|
||||
browserFields={browserFields}
|
||||
docValueFields={docValueFields}
|
||||
handleOnPanelClosed={handleOnPanelClosed}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
|
||||
import { EuiFlexGroup, EuiFlexItem, EuiFlyoutBody, EuiFlyoutFooter } from '@elastic/eui';
|
||||
import { AlertConsumers } from '@kbn/rule-data-utils';
|
||||
import { isEmpty } from 'lodash/fp';
|
||||
import React, { useMemo, useCallback } from 'react';
|
||||
import styled from 'styled-components';
|
||||
|
@ -88,6 +89,8 @@ const VerticalRule = styled.div`
|
|||
|
||||
VerticalRule.displayName = 'VerticalRule';
|
||||
|
||||
const alertConsumers: AlertConsumers[] = [AlertConsumers.SIEM];
|
||||
|
||||
interface OwnProps {
|
||||
renderCellValue: (props: CellValueElementProps) => React.ReactNode;
|
||||
rowRenderers: RowRenderer[];
|
||||
|
@ -266,6 +269,7 @@ export const PinnedTabContentComponent: React.FC<Props> = ({
|
|||
<VerticalRule />
|
||||
<ScrollableFlexItem grow={1}>
|
||||
<DetailsPanel
|
||||
alertConsumers={alertConsumers}
|
||||
browserFields={browserFields}
|
||||
docValueFields={docValueFields}
|
||||
handleOnPanelClosed={handleOnPanelClosed}
|
||||
|
|
|
@ -13,6 +13,7 @@ import {
|
|||
EuiFlyoutFooter,
|
||||
EuiBadge,
|
||||
} from '@elastic/eui';
|
||||
import { AlertConsumers } from '@kbn/rule-data-utils';
|
||||
import { isEmpty } from 'lodash/fp';
|
||||
import React, { useState, useMemo, useEffect, useCallback } from 'react';
|
||||
import styled from 'styled-components';
|
||||
|
@ -135,6 +136,8 @@ const EventsCountBadge = styled(EuiBadge)`
|
|||
margin-left: ${({ theme }) => theme.eui.paddingSizes.s};
|
||||
`;
|
||||
|
||||
const alertConsumers: AlertConsumers[] = [AlertConsumers.SIEM];
|
||||
|
||||
const isTimerangeSame = (prevProps: Props, nextProps: Props) =>
|
||||
prevProps.end === nextProps.end &&
|
||||
prevProps.start === nextProps.start &&
|
||||
|
@ -414,6 +417,7 @@ export const QueryTabContentComponent: React.FC<Props> = ({
|
|||
<VerticalRule />
|
||||
<ScrollableFlexItem grow={1}>
|
||||
<DetailsPanel
|
||||
alertConsumers={alertConsumers}
|
||||
browserFields={browserFields}
|
||||
docValueFields={docValueFields}
|
||||
handleOnPanelClosed={handleOnPanelClosed}
|
||||
|
|
|
@ -9,6 +9,7 @@ import { isEmpty, noop } from 'lodash/fp';
|
|||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import deepEqual from 'fast-deep-equal';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { AlertConsumers } from '@kbn/rule-data-utils';
|
||||
|
||||
import { inputsModel } from '../../../common/store';
|
||||
import { useKibana } from '../../../common/lib/kibana';
|
||||
|
@ -22,19 +23,26 @@ import {
|
|||
import { isCompleteResponse, isErrorResponse } from '../../../../../../../src/plugins/data/public';
|
||||
import { useAppToasts } from '../../../common/hooks/use_app_toasts';
|
||||
import * as i18n from './translations';
|
||||
import { EntityType } from '../../../../../timelines/common';
|
||||
|
||||
export interface EventsArgs {
|
||||
detailsData: TimelineEventsDetailsItem[] | null;
|
||||
}
|
||||
|
||||
export interface UseTimelineEventsDetailsProps {
|
||||
alertConsumers?: AlertConsumers[];
|
||||
entityType?: EntityType;
|
||||
docValueFields: DocValueFields[];
|
||||
indexName: string;
|
||||
eventId: string;
|
||||
skip: boolean;
|
||||
}
|
||||
|
||||
const EMPTY_ARRAY: AlertConsumers[] = [];
|
||||
|
||||
export const useTimelineEventsDetails = ({
|
||||
alertConsumers = EMPTY_ARRAY,
|
||||
entityType = EntityType.EVENTS,
|
||||
docValueFields,
|
||||
indexName,
|
||||
eventId,
|
||||
|
@ -104,7 +112,9 @@ export const useTimelineEventsDetails = ({
|
|||
setTimelineDetailsRequest((prevRequest) => {
|
||||
const myRequest = {
|
||||
...(prevRequest ?? {}),
|
||||
alertConsumers,
|
||||
docValueFields,
|
||||
entityType,
|
||||
indexName,
|
||||
eventId,
|
||||
factoryQueryType: TimelineEventsQueries.details,
|
||||
|
@ -114,7 +124,7 @@ export const useTimelineEventsDetails = ({
|
|||
}
|
||||
return prevRequest;
|
||||
});
|
||||
}, [docValueFields, eventId, indexName]);
|
||||
}, [alertConsumers, docValueFields, entityType, eventId, indexName]);
|
||||
|
||||
useEffect(() => {
|
||||
timelineDetailsSearch(timelineDetailsRequest);
|
||||
|
|
|
@ -43,7 +43,7 @@ export const getDataFromSourceHits = (
|
|||
category?: string,
|
||||
path?: string
|
||||
): TimelineEventsDetailsItem[] =>
|
||||
Object.keys(sources).reduce<TimelineEventsDetailsItem[]>((accumulator, source) => {
|
||||
Object.keys(sources ?? {}).reduce<TimelineEventsDetailsItem[]>((accumulator, source) => {
|
||||
const item: EventSource = get(source, sources);
|
||||
if (Array.isArray(item) || isString(item) || isNumber(item)) {
|
||||
const field = path ? `${path}.${source}` : source;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue