mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[CTI] adds securitySoluion:defaultThreatIndex uiSetting (#108389)
This commit is contained in:
parent
8ea29b6c5a
commit
f952643e54
15 changed files with 124 additions and 42 deletions
|
@ -19,6 +19,10 @@ export const stackManagementSchema: MakeSchemaFrom<UsageStats> = {
|
|||
type: 'keyword',
|
||||
_meta: { description: 'Default value of the setting was changed.' },
|
||||
},
|
||||
'securitySolution:defaultThreatIndex': {
|
||||
type: 'keyword',
|
||||
_meta: { description: 'Default value of the setting was changed.' },
|
||||
},
|
||||
'securitySolution:newsFeedUrl': {
|
||||
type: 'keyword',
|
||||
_meta: { description: 'Default value of the setting was changed.' },
|
||||
|
|
|
@ -12,6 +12,7 @@ export interface UsageStats {
|
|||
*/
|
||||
'timelion:quandl.key': string;
|
||||
'securitySolution:defaultIndex': string;
|
||||
'securitySolution:defaultThreatIndex': string;
|
||||
'securitySolution:newsFeedUrl': string;
|
||||
'xpackReporting:customPdfLogo': string;
|
||||
'notifications:banner': string;
|
||||
|
|
|
@ -7168,6 +7168,12 @@
|
|||
"description": "Default value of the setting was changed."
|
||||
}
|
||||
},
|
||||
"securitySolution:defaultThreatIndex": {
|
||||
"type": "keyword",
|
||||
"_meta": {
|
||||
"description": "Default value of the setting was changed."
|
||||
}
|
||||
},
|
||||
"securitySolution:newsFeedUrl": {
|
||||
"type": "keyword",
|
||||
"_meta": {
|
||||
|
@ -9330,4 +9336,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,6 +62,8 @@ export const DEFAULT_SPACE_ID = 'default';
|
|||
// to enrich signals, and are copied to threat.indicator.
|
||||
export const DEFAULT_INDICATOR_SOURCE_PATH = 'threatintel.indicator';
|
||||
export const INDICATOR_DESTINATION_PATH = 'threat.indicator';
|
||||
export const DEFAULT_THREAT_INDEX_KEY = 'securitySolution:defaultThreatIndex';
|
||||
export const DEFAULT_THREAT_INDEX_VALUE = ['filebeat-*'];
|
||||
|
||||
export enum SecurityPageName {
|
||||
administration = 'administration',
|
||||
|
|
|
@ -69,5 +69,3 @@ export const CTI_DATASET_KEY_MAP: { [key: string]: string } = {
|
|||
MISP: 'threatintel.misp',
|
||||
'Recorded Future': 'threatintel.recordedfuture',
|
||||
};
|
||||
|
||||
export const DEFAULT_CTI_SOURCE_INDEX = ['filebeat-*'];
|
||||
|
|
|
@ -6,7 +6,11 @@
|
|||
*/
|
||||
|
||||
import { formatMitreAttackDescription } from '../../helpers/rules';
|
||||
import { getIndexPatterns, getNewThreatIndicatorRule } from '../../objects/rule';
|
||||
import {
|
||||
getIndexPatterns,
|
||||
getNewThreatIndicatorRule,
|
||||
getThreatIndexPatterns,
|
||||
} from '../../objects/rule';
|
||||
|
||||
import {
|
||||
ALERT_RULE_NAME,
|
||||
|
@ -136,26 +140,21 @@ describe('indicator match', () => {
|
|||
});
|
||||
|
||||
it('Does NOT show invalidation text on initial page load if indicator index pattern is filled out', () => {
|
||||
getIndicatorIndicatorIndex().type(
|
||||
`${getNewThreatIndicatorRule().indicatorIndexPattern}{enter}`
|
||||
);
|
||||
getDefineContinueButton().click();
|
||||
getIndexPatternInvalidationText().should('not.exist');
|
||||
});
|
||||
|
||||
it('Shows invalidation text when you try to continue without filling it out', () => {
|
||||
getIndexPatternClearButton().click();
|
||||
getIndicatorIndicatorIndex().type(
|
||||
`${getNewThreatIndicatorRule().indicatorIndexPattern}{enter}`
|
||||
);
|
||||
getIndicatorIndicatorIndex().type(`{backspace}{enter}`);
|
||||
getDefineContinueButton().click();
|
||||
getIndexPatternInvalidationText().should('exist');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Indicator index patterns', () => {
|
||||
it('Contains empty index pattern', () => {
|
||||
getIndicatorIndicatorIndex().should('have.text', '');
|
||||
it('Contains a predefined index pattern', () => {
|
||||
getIndicatorIndicatorIndex().should('have.text', getThreatIndexPatterns().join(''));
|
||||
});
|
||||
|
||||
it('Does NOT show invalidation text on initial page load', () => {
|
||||
|
@ -163,6 +162,7 @@ describe('indicator match', () => {
|
|||
});
|
||||
|
||||
it('Shows invalidation text if you try to continue without filling it out', () => {
|
||||
getIndicatorIndicatorIndex().type(`{backspace}{enter}`);
|
||||
getDefineContinueButton().click();
|
||||
getIndexPatternInvalidationText().should('exist');
|
||||
});
|
||||
|
|
|
@ -107,6 +107,8 @@ export const getIndexPatterns = (): string[] => [
|
|||
'winlogbeat-*',
|
||||
];
|
||||
|
||||
export const getThreatIndexPatterns = (): string[] => ['filebeat-*'];
|
||||
|
||||
const getMitre1 = (): Mitre => ({
|
||||
tactic: `${getMockThreatData().tactic.name} (${getMockThreatData().tactic.id})`,
|
||||
techniques: [
|
||||
|
|
|
@ -273,7 +273,7 @@ export const fillDefineThresholdRule = (rule: ThresholdRule) => {
|
|||
|
||||
cy.get(IMPORT_QUERY_FROM_SAVED_TIMELINE_LINK).click();
|
||||
cy.get(TIMELINE(rule.timeline.id!)).click();
|
||||
cy.get(COMBO_BOX_CLEAR_BTN).click();
|
||||
cy.get(COMBO_BOX_CLEAR_BTN).first().click();
|
||||
|
||||
rule.index.forEach((index) => {
|
||||
cy.get(COMBO_BOX_INPUT).first().type(`${index}{enter}`);
|
||||
|
@ -447,7 +447,7 @@ export const getIndicatorIndicatorIndex = () =>
|
|||
cy.get(THREAT_MATCH_INDICATOR_INDICATOR_INDEX).eq(0);
|
||||
|
||||
/** Returns the index pattern's clear button */
|
||||
export const getIndexPatternClearButton = () => cy.get(COMBO_BOX_CLEAR_BTN);
|
||||
export const getIndexPatternClearButton = () => cy.get(COMBO_BOX_CLEAR_BTN).first();
|
||||
|
||||
/** Returns the custom query input */
|
||||
export const getCustomQueryInput = () => cy.get(THREAT_MATCH_CUSTOM_QUERY_INPUT).eq(0);
|
||||
|
|
|
@ -11,7 +11,6 @@ import { isEmpty } from 'lodash';
|
|||
|
||||
import { EventFields } from '../../../../../common/search_strategy/security_solution/cti';
|
||||
import {
|
||||
DEFAULT_CTI_SOURCE_INDEX,
|
||||
DEFAULT_EVENT_ENRICHMENT_FROM,
|
||||
DEFAULT_EVENT_ENRICHMENT_TO,
|
||||
} from '../../../../../common/cti/constants';
|
||||
|
@ -20,13 +19,16 @@ import { useKibana } from '../../../lib/kibana';
|
|||
import { inputsActions } from '../../../store/actions';
|
||||
import * as i18n from './translations';
|
||||
import { useEventEnrichmentComplete } from '.';
|
||||
import { DEFAULT_THREAT_INDEX_KEY } from '../../../../../common/constants';
|
||||
|
||||
export const QUERY_ID = 'investigation_time_enrichment';
|
||||
const noop = () => {};
|
||||
|
||||
export const useInvestigationTimeEnrichment = (eventFields: EventFields) => {
|
||||
const { addError } = useAppToasts();
|
||||
const kibana = useKibana();
|
||||
const { data, uiSettings } = useKibana().services;
|
||||
const defaultThreatIndices = uiSettings.get<string[]>(DEFAULT_THREAT_INDEX_KEY);
|
||||
|
||||
const dispatch = useDispatch();
|
||||
const [{ from, to }, setRange] = useState({
|
||||
from: DEFAULT_EVENT_ENRICHMENT_FROM,
|
||||
|
@ -66,14 +68,14 @@ export const useInvestigationTimeEnrichment = (eventFields: EventFields) => {
|
|||
useEffect(() => {
|
||||
if (!isEmpty(eventFields)) {
|
||||
start({
|
||||
data: kibana.services.data,
|
||||
data,
|
||||
timerange: { from, to, interval: '' },
|
||||
defaultIndex: DEFAULT_CTI_SOURCE_INDEX,
|
||||
defaultIndex: defaultThreatIndices,
|
||||
eventFields,
|
||||
filterQuery: '',
|
||||
});
|
||||
}
|
||||
}, [from, start, kibana.services.data, to, eventFields]);
|
||||
}, [from, start, data, to, eventFields, defaultThreatIndices]);
|
||||
|
||||
return {
|
||||
loading,
|
||||
|
|
|
@ -11,7 +11,7 @@ import styled from 'styled-components';
|
|||
import { isEqual } from 'lodash';
|
||||
|
||||
import { IndexPattern } from 'src/plugins/data/public';
|
||||
import { DEFAULT_INDEX_KEY } from '../../../../../common/constants';
|
||||
import { DEFAULT_INDEX_KEY, DEFAULT_THREAT_INDEX_KEY } from '../../../../../common/constants';
|
||||
import { DEFAULT_TIMELINE_TITLE } from '../../../../timelines/components/timeline/translations';
|
||||
import { isMlRule } from '../../../../../common/machine_learning/helpers';
|
||||
import { hasMlAdminPermissions } from '../../../../../common/machine_learning/has_ml_admin_permissions';
|
||||
|
@ -102,7 +102,7 @@ const threatQueryBarDefaultValue: DefineStepRule['queryBar'] = {
|
|||
query: { ...stepDefineDefaultValue.queryBar.query, query: '*:*' },
|
||||
};
|
||||
|
||||
const MyLabelButton = styled(EuiButtonEmpty)`
|
||||
export const MyLabelButton = styled(EuiButtonEmpty)`
|
||||
height: 18px;
|
||||
font-size: 12px;
|
||||
|
||||
|
@ -135,10 +135,13 @@ const StepDefineRuleComponent: FC<StepDefineRuleProps> = ({
|
|||
const mlCapabilities = useMlCapabilities();
|
||||
const [openTimelineSearch, setOpenTimelineSearch] = useState(false);
|
||||
const [indexModified, setIndexModified] = useState(false);
|
||||
const [threatIndexModified, setThreatIndexModified] = useState(false);
|
||||
const [indicesConfig] = useUiSetting$<string[]>(DEFAULT_INDEX_KEY);
|
||||
const [threatIndicesConfig] = useUiSetting$<string[]>(DEFAULT_THREAT_INDEX_KEY);
|
||||
const initialState = defaultValues ?? {
|
||||
...stepDefineDefaultValue,
|
||||
index: indicesConfig,
|
||||
threatIndex: threatIndicesConfig,
|
||||
};
|
||||
const { form } = useForm<DefineStepRule>({
|
||||
defaultValue: initialState,
|
||||
|
@ -206,6 +209,10 @@ const StepDefineRuleComponent: FC<StepDefineRuleProps> = ({
|
|||
setIndexModified(!isEqual(index, indicesConfig));
|
||||
}, [index, indicesConfig]);
|
||||
|
||||
useEffect(() => {
|
||||
setThreatIndexModified(!isEqual(threatIndex, threatIndicesConfig));
|
||||
}, [threatIndex, threatIndicesConfig]);
|
||||
|
||||
/**
|
||||
* When a rule type is changed to or from a threat match this will modify the
|
||||
* default query string to either:
|
||||
|
@ -269,6 +276,11 @@ const StepDefineRuleComponent: FC<StepDefineRuleProps> = ({
|
|||
indexField.setValue(indicesConfig);
|
||||
}, [getFields, indicesConfig]);
|
||||
|
||||
const handleResetThreatIndices = useCallback(() => {
|
||||
const threatIndexField = getFields().threatIndex;
|
||||
threatIndexField.setValue(threatIndicesConfig);
|
||||
}, [getFields, threatIndicesConfig]);
|
||||
|
||||
const handleOpenTimelineSearch = useCallback(() => {
|
||||
setOpenTimelineSearch(true);
|
||||
}, []);
|
||||
|
@ -293,14 +305,23 @@ const StepDefineRuleComponent: FC<StepDefineRuleProps> = ({
|
|||
const ThreatMatchInputChildren = useCallback(
|
||||
({ threatMapping }) => (
|
||||
<ThreatMatchInput
|
||||
threatBrowserFields={threatBrowserFields}
|
||||
handleResetThreatIndices={handleResetThreatIndices}
|
||||
indexPatterns={indexPatterns as IndexPattern}
|
||||
threatBrowserFields={threatBrowserFields}
|
||||
threatIndexModified={threatIndexModified}
|
||||
threatIndexPatterns={threatIndexPatterns as IndexPattern}
|
||||
threatMapping={threatMapping}
|
||||
threatIndexPatternsLoading={threatIndexPatternsLoading}
|
||||
threatMapping={threatMapping}
|
||||
/>
|
||||
),
|
||||
[threatBrowserFields, threatIndexPatternsLoading, threatIndexPatterns, indexPatterns]
|
||||
[
|
||||
handleResetThreatIndices,
|
||||
indexPatterns,
|
||||
threatBrowserFields,
|
||||
threatIndexModified,
|
||||
threatIndexPatterns,
|
||||
threatIndexPatternsLoading,
|
||||
]
|
||||
);
|
||||
return isReadOnlyView ? (
|
||||
<StepContentWrapper data-test-subj="definitionRule" addPadding={addPadding}>
|
||||
|
|
|
@ -22,6 +22,8 @@ import { DefineStepRule } from '../../../pages/detection_engine/rules/types';
|
|||
import { schema } from '../step_define_rule/schema';
|
||||
import { QueryBarDefineRule } from '../query_bar';
|
||||
import { IndexPattern } from '../../../../../../../../src/plugins/data/public';
|
||||
import * as i18n from '../step_define_rule/translations';
|
||||
import { MyLabelButton } from '../step_define_rule';
|
||||
|
||||
const CommonUseField = getUseField({ component: Field });
|
||||
|
||||
|
@ -31,9 +33,13 @@ interface ThreatMatchInputProps {
|
|||
threatIndexPatterns: IndexPattern;
|
||||
indexPatterns: IndexPattern;
|
||||
threatIndexPatternsLoading: boolean;
|
||||
threatIndexModified: boolean;
|
||||
handleResetThreatIndices: () => void;
|
||||
}
|
||||
|
||||
const ThreatMatchInputComponent: React.FC<ThreatMatchInputProps> = ({
|
||||
threatIndexModified,
|
||||
handleResetThreatIndices,
|
||||
threatMapping,
|
||||
indexPatterns,
|
||||
threatIndexPatterns,
|
||||
|
@ -57,7 +63,11 @@ const ThreatMatchInputComponent: React.FC<ThreatMatchInputProps> = ({
|
|||
path="threatIndex"
|
||||
config={{
|
||||
...schema.threatIndex,
|
||||
labelAppend: null,
|
||||
labelAppend: threatIndexModified ? (
|
||||
<MyLabelButton onClick={handleResetThreatIndices} iconType="refresh">
|
||||
{i18n.RESET_DEFAULT_INDEX}
|
||||
</MyLabelButton>
|
||||
) : null,
|
||||
}}
|
||||
componentProps={{
|
||||
idAria: 'detectionEngineStepDefineRuleThreatMatchIndices',
|
||||
|
|
|
@ -22,6 +22,7 @@ import {
|
|||
import { mockTheme, mockProps, mockCtiEventCountsResponse, mockCtiLinksResponse } from './mock';
|
||||
import { useCtiEventCounts } from '../../containers/overview_cti_links/use_cti_event_counts';
|
||||
import { useCtiDashboardLinks } from '../../containers/overview_cti_links';
|
||||
import { useRequestEventCounts } from '../../containers/overview_cti_links/use_request_event_counts';
|
||||
|
||||
jest.mock('../../../common/lib/kibana');
|
||||
|
||||
|
@ -29,6 +30,10 @@ jest.mock('../../containers/overview_cti_links/use_cti_event_counts');
|
|||
const useCTIEventCountsMock = useCtiEventCounts as jest.Mock;
|
||||
useCTIEventCountsMock.mockReturnValue(mockCtiEventCountsResponse);
|
||||
|
||||
jest.mock('../../containers/overview_cti_links/use_request_event_counts');
|
||||
const useRequestEventCountsMock = useRequestEventCounts as jest.Mock;
|
||||
useRequestEventCountsMock.mockReturnValue([true, {}]);
|
||||
|
||||
jest.mock('../../containers/overview_cti_links');
|
||||
const useCtiDashboardLinksMock = useCtiDashboardLinks as jest.Mock;
|
||||
useCtiDashboardLinksMock.mockReturnValue(mockCtiLinksResponse);
|
||||
|
|
|
@ -19,10 +19,20 @@ import {
|
|||
mockGlobalState,
|
||||
SUB_PLUGINS_REDUCER,
|
||||
} from '../../../common/mock';
|
||||
import { mockTheme, mockProps } from './mock';
|
||||
import { mockTheme, mockProps, mockCtiEventCountsResponse } from './mock';
|
||||
import { useRequestEventCounts } from '../../containers/overview_cti_links/use_request_event_counts';
|
||||
import { useCtiEventCounts } from '../../containers/overview_cti_links/use_cti_event_counts';
|
||||
|
||||
jest.mock('../../../common/lib/kibana');
|
||||
|
||||
jest.mock('../../containers/overview_cti_links/use_request_event_counts');
|
||||
const useRequestEventCountsMock = useRequestEventCounts as jest.Mock;
|
||||
useRequestEventCountsMock.mockReturnValue([true, {}]);
|
||||
|
||||
jest.mock('../../containers/overview_cti_links/use_cti_event_counts');
|
||||
const useCTIEventCountsMock = useCtiEventCounts as jest.Mock;
|
||||
useCTIEventCountsMock.mockReturnValue(mockCtiEventCountsResponse);
|
||||
|
||||
describe('ThreatIntelLinkPanel', () => {
|
||||
const state: State = mockGlobalState;
|
||||
|
||||
|
|
|
@ -9,12 +9,14 @@ import { i18n } from '@kbn/i18n';
|
|||
import { convertToBuildEsQuery } from '../../../common/lib/keury';
|
||||
import { esQuery } from '../../../../../../../src/plugins/data/public';
|
||||
import { MatrixHistogramType } from '../../../../common/search_strategy';
|
||||
import { EVENT_DATASET, DEFAULT_CTI_SOURCE_INDEX } from '../../../../common/cti/constants';
|
||||
import { EVENT_DATASET } from '../../../../common/cti/constants';
|
||||
import { useMatrixHistogram } from '../../../common/containers/matrix_histogram';
|
||||
import { useKibana } from '../../../common/lib/kibana';
|
||||
import { DEFAULT_THREAT_INDEX_KEY } from '../../../../common/constants';
|
||||
|
||||
export const useRequestEventCounts = (to: string, from: string) => {
|
||||
const { uiSettings } = useKibana().services;
|
||||
const defaultThreatIndices = uiSettings.get<string[]>(DEFAULT_THREAT_INDEX_KEY);
|
||||
|
||||
const [filterQuery] = convertToBuildEsQuery({
|
||||
config: esQuery.getEsQueryConfig(uiSettings),
|
||||
|
@ -28,7 +30,7 @@ export const useRequestEventCounts = (to: string, from: string) => {
|
|||
esTypes: ['keyword'],
|
||||
},
|
||||
],
|
||||
title: 'filebeat-*',
|
||||
title: defaultThreatIndices.toString(),
|
||||
},
|
||||
queries: [{ query: 'event.type:indicator', language: 'kuery' }],
|
||||
filters: [],
|
||||
|
@ -42,12 +44,12 @@ export const useRequestEventCounts = (to: string, from: string) => {
|
|||
}),
|
||||
filterQuery,
|
||||
histogramType: MatrixHistogramType.events,
|
||||
indexNames: DEFAULT_CTI_SOURCE_INDEX,
|
||||
indexNames: defaultThreatIndices,
|
||||
stackByField: EVENT_DATASET,
|
||||
startDate: from,
|
||||
size: 0,
|
||||
};
|
||||
}, [to, from, filterQuery]);
|
||||
}, [to, from, filterQuery, defaultThreatIndices]);
|
||||
|
||||
const results = useMatrixHistogram(matrixHistogramRequest);
|
||||
|
||||
|
|
|
@ -11,27 +11,29 @@ import { schema } from '@kbn/config-schema';
|
|||
import { CoreSetup } from '../../../../src/core/server';
|
||||
import {
|
||||
APP_ID,
|
||||
DEFAULT_ANOMALY_SCORE,
|
||||
DEFAULT_APP_REFRESH_INTERVAL,
|
||||
DEFAULT_APP_TIME_RANGE,
|
||||
DEFAULT_FROM,
|
||||
DEFAULT_INDEX_KEY,
|
||||
DEFAULT_INDEX_PATTERN,
|
||||
DEFAULT_INDEX_PATTERN_EXPERIMENTAL,
|
||||
DEFAULT_ANOMALY_SCORE,
|
||||
DEFAULT_APP_TIME_RANGE,
|
||||
DEFAULT_APP_REFRESH_INTERVAL,
|
||||
DEFAULT_INTERVAL_PAUSE,
|
||||
DEFAULT_INTERVAL_VALUE,
|
||||
DEFAULT_FROM,
|
||||
DEFAULT_TO,
|
||||
ENABLE_NEWS_FEED_SETTING,
|
||||
NEWS_FEED_URL_SETTING,
|
||||
NEWS_FEED_URL_SETTING_DEFAULT,
|
||||
IP_REPUTATION_LINKS_SETTING,
|
||||
IP_REPUTATION_LINKS_SETTING_DEFAULT,
|
||||
DEFAULT_RULES_TABLE_REFRESH_SETTING,
|
||||
DEFAULT_RULE_REFRESH_IDLE_VALUE,
|
||||
DEFAULT_RULE_REFRESH_INTERVAL_ON,
|
||||
DEFAULT_RULE_REFRESH_INTERVAL_VALUE,
|
||||
DEFAULT_RULE_REFRESH_IDLE_VALUE,
|
||||
DEFAULT_RULES_TABLE_REFRESH_SETTING,
|
||||
DEFAULT_THREAT_INDEX_KEY,
|
||||
DEFAULT_THREAT_INDEX_VALUE,
|
||||
DEFAULT_TO,
|
||||
DEFAULT_TRANSFORMS,
|
||||
DEFAULT_TRANSFORMS_SETTING,
|
||||
ENABLE_NEWS_FEED_SETTING,
|
||||
IP_REPUTATION_LINKS_SETTING,
|
||||
IP_REPUTATION_LINKS_SETTING_DEFAULT,
|
||||
NEWS_FEED_URL_SETTING,
|
||||
NEWS_FEED_URL_SETTING_DEFAULT,
|
||||
} from '../common/constants';
|
||||
import { transformConfigSchema } from '../common/transforms/types';
|
||||
import { ExperimentalFeatures } from '../common/experimental_features';
|
||||
|
@ -100,6 +102,23 @@ export const initUiSettings = (
|
|||
requiresPageReload: true,
|
||||
schema: schema.arrayOf(schema.string()),
|
||||
},
|
||||
[DEFAULT_THREAT_INDEX_KEY]: {
|
||||
name: i18n.translate('xpack.securitySolution.uiSettings.defaultThreatIndexLabel', {
|
||||
defaultMessage: 'Threat indices',
|
||||
}),
|
||||
sensitive: true,
|
||||
value: DEFAULT_THREAT_INDEX_VALUE,
|
||||
description: i18n.translate(
|
||||
'xpack.securitySolution.uiSettings.defaultThreatIndexDescription',
|
||||
{
|
||||
defaultMessage:
|
||||
'<p>Comma-delimited list of Threat Intelligence indices from which the Security app collects indicators.</p>',
|
||||
}
|
||||
),
|
||||
category: [APP_ID],
|
||||
requiresPageReload: true,
|
||||
schema: schema.arrayOf(schema.string()),
|
||||
},
|
||||
[DEFAULT_ANOMALY_SCORE]: {
|
||||
name: i18n.translate('xpack.securitySolution.uiSettings.defaultAnomalyScoreLabel', {
|
||||
defaultMessage: 'Anomaly threshold',
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue