Skip to content

Commit e97b451

Browse files
[SIEM] add custom reputation link (#57814)
* add custom reputation link * fix unit test * add number of limitation to reputation links * fix dependency * apply defaultFieldRendererOverflow to reputation link * fix unit test * fix url template * fix display links * fix types * fix for review * update test case * update snapshot * add icons and tooltips * fix style * update test * add external link component * update test * fix types * fix style * update snapshot * remove useMemo * update description * code review * review II * code review * update description * fix unit test * fix unit test * fix unit test * fix unit test * fix types * fix styles * fix style * fix style * fix review Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
1 parent 8021fd8 commit e97b451

File tree

11 files changed

+3876
-152
lines changed

11 files changed

+3876
-152
lines changed

x-pack/legacy/plugins/siem/common/constants.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,15 @@ export const NEWS_FEED_URL_SETTING = 'siem:newsFeedUrl';
3838
/** The default value for News feed widget */
3939
export const NEWS_FEED_URL_SETTING_DEFAULT = 'https://feeds.elastic.co/security-solution';
4040

41+
/** This Kibana Advanced Setting specifies the URLs of `IP Reputation Links`*/
42+
export const IP_REPUTATION_LINKS_SETTING = 'siem:ipReputationLinks';
43+
44+
/** The default value for `IP Reputation Links` */
45+
export const IP_REPUTATION_LINKS_SETTING_DEFAULT = `[
46+
{ "name": "virustotal.com", "url_template": "https://www.virustotal.com/gui/search/{{ip}}" },
47+
{ "name": "talosIntelligence.com", "url_template": "https://talosintelligence.com/reputation_center/lookup?search={{ip}}" }
48+
]`;
49+
4150
/**
4251
* Id for the signals alerting type
4352
*/

x-pack/legacy/plugins/siem/index.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ import {
2828
NEWS_FEED_URL_SETTING,
2929
NEWS_FEED_URL_SETTING_DEFAULT,
3030
SIGNALS_INDEX_KEY,
31+
IP_REPUTATION_LINKS_SETTING,
32+
IP_REPUTATION_LINKS_SETTING_DEFAULT,
3133
} from './common/constants';
3234
import { defaultIndexPattern } from './default_index_pattern';
3335
import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/utils';
@@ -144,6 +146,19 @@ export const siem = (kibana: any) => {
144146
category: ['siem'],
145147
requiresPageReload: true,
146148
},
149+
[IP_REPUTATION_LINKS_SETTING]: {
150+
name: i18n.translate('xpack.siem.uiSettings.ipReputationLinks', {
151+
defaultMessage: 'IP Reputation Links',
152+
}),
153+
value: IP_REPUTATION_LINKS_SETTING_DEFAULT,
154+
type: 'json',
155+
description: i18n.translate('xpack.siem.uiSettings.ipReputationLinksDescription', {
156+
defaultMessage:
157+
'Array of URL templates to build the list of reputation URLs to be displayed on the IP Details page.',
158+
}),
159+
category: ['siem'],
160+
requiresPageReload: true,
161+
},
147162
},
148163
mappings: savedObjectMappings,
149164
},

x-pack/legacy/plugins/siem/public/components/field_renderers/__snapshots__/field_renderers.test.tsx.snap

Lines changed: 6 additions & 14 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

x-pack/legacy/plugins/siem/public/components/field_renderers/field_renderers.tsx

Lines changed: 56 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { escapeDataProviderId } from '../drag_and_drop/helpers';
1515
import { DefaultDraggable } from '../draggables';
1616
import { getEmptyTagValue } from '../empty_value';
1717
import { FormattedRelativePreferenceDate } from '../formatted_date';
18-
import { HostDetailsLink, ReputationLink, VirusTotalLink, WhoIsLink } from '../links';
18+
import { HostDetailsLink, ReputationLink, WhoIsLink, ReputationLinkSetting } from '../links';
1919
import { Spacer } from '../page';
2020
import * as i18n from '../page/network/ip_overview/translations';
2121

@@ -132,11 +132,7 @@ export const hostNameRenderer = (host: HostEcsFields, ipFilter?: string): React.
132132
export const whoisRenderer = (ip: string) => <WhoIsLink domain={ip}>{i18n.VIEW_WHOIS}</WhoIsLink>;
133133

134134
export const reputationRenderer = (ip: string): React.ReactElement => (
135-
<>
136-
<VirusTotalLink link={ip}>{i18n.VIEW_VIRUS_TOTAL}</VirusTotalLink>
137-
{', '}
138-
<ReputationLink domain={ip}>{i18n.VIEW_TALOS_INTELLIGENCE}</ReputationLink>
139-
</>
135+
<ReputationLink domain={ip} direction="column" />
140136
);
141137

142138
interface DefaultFieldRendererProps {
@@ -148,73 +144,78 @@ interface DefaultFieldRendererProps {
148144
moreMaxHeight?: string;
149145
}
150146

147+
type OverflowRenderer = (item: string | ReputationLinkSetting) => JSX.Element;
148+
151149
// TODO: This causes breaks between elements until the ticket below is fixed
152150
// https://github.com/elastic/ingest-dev/issues/474
153-
export const DefaultFieldRenderer = React.memo<DefaultFieldRendererProps>(
154-
({
155-
attrName,
156-
displayCount = 1,
157-
idPrefix,
158-
moreMaxHeight = DEFAULT_MORE_MAX_HEIGHT,
159-
render,
160-
rowItems,
161-
}) => {
162-
if (rowItems != null && rowItems.length > 0) {
163-
const draggables = rowItems.slice(0, displayCount).map((rowItem, index) => {
164-
const id = escapeDataProviderId(
165-
`default-field-renderer-default-draggable-${idPrefix}-${attrName}-${rowItem}`
166-
);
167-
return (
168-
<EuiFlexItem key={id} grow={false}>
169-
{index !== 0 && (
170-
<>
171-
{','}
172-
<Spacer />
173-
</>
174-
)}
151+
export const DefaultFieldRendererComponent: React.FC<DefaultFieldRendererProps> = ({
152+
attrName,
153+
displayCount = 1,
154+
idPrefix,
155+
moreMaxHeight = DEFAULT_MORE_MAX_HEIGHT,
156+
render,
157+
rowItems,
158+
}) => {
159+
if (rowItems != null && rowItems.length > 0) {
160+
const draggables = rowItems.slice(0, displayCount).map((rowItem, index) => {
161+
const id = escapeDataProviderId(
162+
`default-field-renderer-default-draggable-${idPrefix}-${attrName}-${rowItem}`
163+
);
164+
return (
165+
<EuiFlexItem key={id} grow={false}>
166+
{index !== 0 && (
167+
<>
168+
{','}
169+
<Spacer />
170+
</>
171+
)}
172+
{typeof rowItem === 'string' && (
175173
<DefaultDraggable id={id} field={attrName} value={rowItem}>
176174
{render ? render(rowItem) : rowItem}
177175
</DefaultDraggable>
178-
</EuiFlexItem>
179-
);
180-
});
181-
182-
return draggables.length > 0 ? (
183-
<DraggableContainerFlexGroup alignItems="center" gutterSize="none" component="span">
184-
{draggables}{' '}
185-
{
186-
<DefaultFieldRendererOverflow
187-
rowItems={rowItems}
188-
idPrefix={idPrefix}
189-
render={render}
190-
overflowIndexStart={displayCount}
191-
moreMaxHeight={moreMaxHeight}
192-
/>
193-
}
194-
</DraggableContainerFlexGroup>
195-
) : (
196-
getEmptyTagValue()
176+
)}
177+
</EuiFlexItem>
197178
);
198-
} else {
199-
return getEmptyTagValue();
200-
}
179+
});
180+
181+
return draggables.length > 0 ? (
182+
<DraggableContainerFlexGroup alignItems="center" gutterSize="none" component="span">
183+
<EuiFlexItem grow={false}>{draggables} </EuiFlexItem>
184+
<EuiFlexItem grow={false}>
185+
<DefaultFieldRendererOverflow
186+
rowItems={rowItems}
187+
idPrefix={idPrefix}
188+
render={render as OverflowRenderer}
189+
overflowIndexStart={displayCount}
190+
moreMaxHeight={moreMaxHeight}
191+
/>
192+
</EuiFlexItem>
193+
</DraggableContainerFlexGroup>
194+
) : (
195+
getEmptyTagValue()
196+
);
197+
} else {
198+
return getEmptyTagValue();
201199
}
202-
);
200+
};
201+
202+
export const DefaultFieldRenderer = React.memo(DefaultFieldRendererComponent);
203203

204204
DefaultFieldRenderer.displayName = 'DefaultFieldRenderer';
205205

206+
type RowItemTypes = string | ReputationLinkSetting;
206207
interface DefaultFieldRendererOverflowProps {
207-
rowItems: string[];
208+
rowItems: string[] | ReputationLinkSetting[];
208209
idPrefix: string;
209-
render?: (item: string) => React.ReactNode;
210+
render?: (item: RowItemTypes) => React.ReactNode;
210211
overflowIndexStart?: number;
211212
moreMaxHeight: string;
212213
}
213214

214215
interface MoreContainerProps {
215216
idPrefix: string;
216-
render?: (item: string) => React.ReactNode;
217-
rowItems: string[];
217+
render?: (item: RowItemTypes) => React.ReactNode;
218+
rowItems: RowItemTypes[];
218219
moreMaxHeight: string;
219220
overflowIndexStart: number;
220221
}

0 commit comments

Comments
 (0)