Skip to content

Commit

Permalink
Add support for threat.feed.name (#120250)
Browse files Browse the repository at this point in the history
* Add support for threat.feed.name

* fix cy tests

* Remove provider field

* fix tests

* Provider to feed.name

* Fix tests

* Fix tests

* fix comments

* Fix i18n

* fix type

* Fix types

* fix tests

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
  • Loading branch information
nkhristinin and kibanamachine authored Dec 7, 2021
1 parent 3c0c315 commit a8405fe
Show file tree
Hide file tree
Showing 28 changed files with 198 additions and 59 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2925,6 +2925,16 @@ export const ecsFieldMap = {
array: false,
required: false,
},
'threat.enrichments.feed': {
type: 'object',
array: false,
required: false,
},
'threat.enrichments.feed.name': {
type: 'keyword',
array: false,
required: false,
},
'threat.enrichments.matched.atomic': {
type: 'keyword',
array: false,
Expand Down
3 changes: 3 additions & 0 deletions x-pack/plugins/security_solution/common/cti/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ export const FIRST_SEEN = 'indicator.first_seen';
export const LAST_SEEN = 'indicator.last_seen';
export const PROVIDER = 'indicator.provider';
export const REFERENCE = 'indicator.reference';
export const FEED_NAME = 'feed.name';

export const FEED_NAME_PATH = `threat.${FEED_NAME}`;

export const INDICATOR_FIRSTSEEN = `${ENRICHMENT_DESTINATION_PATH}.${FIRST_SEEN}`;
export const INDICATOR_LASTSEEN = `${ENRICHMENT_DESTINATION_PATH}.${LAST_SEEN}`;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export interface CtiEnrichmentIdentifiers {
field: string | undefined;
value: string | undefined;
type: string | undefined;
provider: string | undefined;
feedName: string | undefined;
}

export interface CtiEventEnrichmentStrategyResponse extends IEsSearchResponse {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ describe('CTI Enrichment', () => {
it('Displays persisted enrichments on the JSON view', () => {
const expectedEnrichment = [
{
feed: {},
indicator: {
first_seen: '2021-03-10T08:02:14.000Z',
file: {
Expand Down Expand Up @@ -176,7 +177,7 @@ describe('CTI Enrichment', () => {
const investigationTimeEnrichment = {
field: 'source.ip',
value: '192.168.1.1',
provider: 'another_provider',
feedName: 'feed_name',
};

expandFirstAlert();
Expand All @@ -194,7 +195,7 @@ describe('CTI Enrichment', () => {
.should('exist')
.should(
'have.text',
`${investigationTimeEnrichment.field} ${investigationTimeEnrichment.value} from ${investigationTimeEnrichment.provider}`
`${investigationTimeEnrichment.field} ${investigationTimeEnrichment.value} from ${investigationTimeEnrichment.feedName}`
);
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ const EnrichmentAccordion: React.FC<{
const {
id = `threat-details-item`,
field,
provider,
feedName,
type,
value,
} = getEnrichmentIdentifiers(enrichment);
Expand All @@ -98,7 +98,7 @@ const EnrichmentAccordion: React.FC<{
key={accordionId}
initialIsOpen={true}
arrowDisplay="right"
buttonContent={<EnrichmentButtonContent field={field} provider={provider} value={value} />}
buttonContent={<EnrichmentButtonContent field={field} feedName={feedName} value={value} />}
extraAction={
isInvestigationTimeEnrichment(type) && (
<EuiFlexItem grow={false}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,16 @@ import { mount } from 'enzyme';
import { EnrichmentButtonContent } from './enrichment_button_content';

describe('EnrichmentButtonContent', () => {
it('renders string with provider if provider is present', () => {
it('renders string with feedName if feedName is present', () => {
const wrapper = mount(
<EnrichmentButtonContent field={'source.ip'} value={'127.0.0.1'} provider={'eceintel'} />
<EnrichmentButtonContent field={'source.ip'} value={'127.0.0.1'} feedName={'eceintel'} />
);
expect(wrapper.find('[data-test-subj="enrichment-button-content"]').hostNodes().text()).toEqual(
'source.ip 127.0.0.1 from eceintel'
);
});

it('renders string without provider if provider is not present', () => {
it('renders string without feedName if feedName is not present', () => {
const wrapper = mount(<EnrichmentButtonContent field={'source.ip'} value={'127.0.0.1'} />);
expect(wrapper.find('[data-test-subj="enrichment-button-content"]').hostNodes().text()).toEqual(
'source.ip 127.0.0.1'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ const OverflowContainer = styled.div`

export const EnrichmentButtonContent: React.FC<{
field?: string;
provider?: string;
feedName?: string;
value?: string;
}> = ({ field = '', provider = '', value = '' }) => {
const title = `${field} ${value}${provider ? ` ${i18n.PROVIDER_PREPOSITION} ${provider}` : ''}`;
}> = ({ field = '', feedName = '', value = '' }) => {
const title = `${field} ${value}${feedName ? ` ${i18n.FEED_NAME_PREPOSITION} ${feedName}` : ''}`;
return (
<EuiToolTip content={value}>
<OverflowParent data-test-subj={'enrichment-button-content'}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,13 @@ export interface ThreatSummaryDescription {
data: FieldsData | undefined;
eventId: string;
index: number;
provider: string | undefined;
feedName: string | undefined;
timelineId: string;
value: string | undefined;
isDraggable?: boolean;
}

const EnrichmentFieldProvider = styled.span`
const EnrichmentFieldFeedName = styled.span`
margin-left: ${({ theme }) => theme.eui.paddingSizes.xs};
white-space: nowrap;
font-style: italic;
Expand All @@ -46,13 +46,13 @@ const EnrichmentDescription: React.FC<ThreatSummaryDescription> = ({
data,
eventId,
index,
provider,
feedName,
timelineId,
value,
isDraggable,
}) => {
if (!data || !value) return null;
const key = `alert-details-value-formatted-field-value-${timelineId}-${eventId}-${data.field}-${value}-${index}-${provider}`;
const key = `alert-details-value-formatted-field-value-${timelineId}-${eventId}-${data.field}-${value}-${index}-${feedName}`;
return (
<EuiFlexGroup key={key} direction="row" gutterSize="none" alignItems="center">
<EuiFlexItem grow={false}>
Expand All @@ -67,10 +67,10 @@ const EnrichmentDescription: React.FC<ThreatSummaryDescription> = ({
isObjectArray={data.isObjectArray}
value={value}
/>
{provider && (
<EnrichmentFieldProvider>
{i18n.PROVIDER_PREPOSITION} {provider}
</EnrichmentFieldProvider>
{feedName && (
<EnrichmentFieldFeedName>
{i18n.FEED_NAME_PREPOSITION} {feedName}
</EnrichmentFieldFeedName>
)}
</div>
</EuiFlexItem>
Expand Down Expand Up @@ -99,7 +99,7 @@ const EnrichmentSummaryComponent: React.FC<{
isDraggable?: boolean;
}> = ({ browserFields, data, enrichments, timelineId, eventId, isDraggable }) => {
const parsedEnrichments = enrichments.map((enrichment, index) => {
const { field, type, provider, value } = getEnrichmentIdentifiers(enrichment);
const { field, type, feedName, value } = getEnrichmentIdentifiers(enrichment);
const eventData = data.find((item) => item.field === field);
const category = eventData?.category ?? '';
const browserField = get([category, 'fields', field ?? ''], browserFields);
Expand All @@ -114,7 +114,7 @@ const EnrichmentSummaryComponent: React.FC<{
return {
fieldsData,
type,
provider,
feedName,
index,
field,
browserField,
Expand All @@ -136,15 +136,15 @@ const EnrichmentSummaryComponent: React.FC<{
toolTipContent={i18n.INDICATOR_TOOLTIP_CONTENT}
/>

{indicator.map(({ fieldsData, index, field, provider, browserField, value }) => (
{indicator.map(({ fieldsData, index, field, feedName, browserField, value }) => (
<EnrichedDataRow
key={field}
field={field}
value={
<EnrichmentDescription
eventId={eventId}
index={index}
provider={provider}
feedName={feedName}
timelineId={timelineId}
value={value}
data={fieldsData}
Expand All @@ -166,15 +166,15 @@ const EnrichmentSummaryComponent: React.FC<{
toolTipContent={i18n.INVESTIGATION_TOOLTIP_CONTENT}
/>

{investigation.map(({ fieldsData, index, field, provider, browserField, value }) => (
{investigation.map(({ fieldsData, index, field, feedName, browserField, value }) => (
<EnrichedDataRow
key={field}
field={field}
value={
<EnrichmentDescription
eventId={eventId}
index={index}
provider={provider}
feedName={feedName}
timelineId={timelineId}
value={value}
data={fieldsData}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
filterDuplicateEnrichments,
getEnrichmentFields,
parseExistingEnrichments,
getEnrichmentIdentifiers,
} from './helpers';

describe('parseExistingEnrichments', () => {
Expand Down Expand Up @@ -356,3 +357,23 @@ describe('getEnrichmentFields', () => {
});
});
});

describe('getEnrichmentIdentifiers', () => {
it(`return feed name as feedName if it's present in enrichment`, () => {
expect(
getEnrichmentIdentifiers({
'matched.id': [1],
'matched.field': ['matched field'],
'matched.atomic': ['matched atomic'],
'matched.type': ['matched type'],
'feed.name': ['feed name'],
})
).toEqual({
id: 1,
field: 'matched field',
value: 'matched atomic',
type: 'matched type',
feedName: 'feed name',
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
MATCHED_FIELD,
MATCHED_ID,
MATCHED_TYPE,
PROVIDER,
FEED_NAME,
} from '../../../../../common/cti/constants';
import { TimelineEventsDetailsItem } from '../../../../../common/search_strategy';
import {
Expand Down Expand Up @@ -81,7 +81,7 @@ export const getEnrichmentIdentifiers = (enrichment: CtiEnrichment): CtiEnrichme
field: getEnrichmentValue(enrichment, MATCHED_FIELD),
value: getEnrichmentValue(enrichment, MATCHED_ATOMIC),
type: getEnrichmentValue(enrichment, MATCHED_TYPE),
provider: getShimmedIndicatorValue(enrichment, PROVIDER),
feedName: getShimmedIndicatorValue(enrichment, FEED_NAME),
});

const buildEnrichmentId = (enrichment: CtiEnrichment): string => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@

import { i18n } from '@kbn/i18n';

export const PROVIDER_PREPOSITION = i18n.translate(
'xpack.securitySolution.eventDetails.ctiSummary.providerPreposition',
export const FEED_NAME_PREPOSITION = i18n.translate(
'xpack.securitySolution.eventDetails.ctiSummary.feedNamePreposition',
{
defaultMessage: 'from',
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1106,6 +1106,9 @@ export const mockTimelineData: TimelineItem[] = [
field: ['source.ip'],
type: ['ip'],
},
feed: {
name: ['feed_name'],
},
},
],
},
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { FormattedMessage } from '@kbn/i18n-react';

import {
INDICATOR_MATCHED_TYPE,
INDICATOR_PROVIDER,
FEED_NAME,
INDICATOR_REFERENCE,
} from '../../../../../../../common/cti/constants';
import { DraggableBadge } from '../../../../../../common/components/draggables';
Expand All @@ -21,7 +21,7 @@ import { HorizontalSpacer } from './helpers';
interface IndicatorDetailsProps {
contextId: string;
eventId: string;
indicatorProvider: string | undefined;
feedName: string | undefined;
indicatorReference: string | undefined;
indicatorType: string | undefined;
isDraggable?: boolean;
Expand All @@ -30,7 +30,7 @@ interface IndicatorDetailsProps {
export const IndicatorDetails: React.FC<IndicatorDetailsProps> = ({
contextId,
eventId,
indicatorProvider,
feedName,
indicatorReference,
indicatorType,
isDraggable,
Expand All @@ -55,7 +55,7 @@ export const IndicatorDetails: React.FC<IndicatorDetailsProps> = ({
/>
</EuiFlexItem>
)}
{indicatorProvider && (
{feedName && (
<>
<EuiFlexItem grow={false} component="span">
<HorizontalSpacer>
Expand All @@ -68,11 +68,11 @@ export const IndicatorDetails: React.FC<IndicatorDetailsProps> = ({
<EuiFlexItem grow={false}>
<DraggableBadge
contextId={contextId}
data-test-subj="threat-match-indicator-details-indicator-provider"
data-test-subj="threat-match-indicator-details-indicator-feedName"
eventId={eventId}
field={INDICATOR_PROVIDER}
field={FEED_NAME}
isDraggable={isDraggable}
value={indicatorProvider}
value={feedName}
/>
</EuiFlexItem>
</>
Expand Down
Loading

0 comments on commit a8405fe

Please sign in to comment.