Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master' into ingest/data-streams
Browse files Browse the repository at this point in the history
  • Loading branch information
jen-huang committed Apr 21, 2020
2 parents f0b0b39 + ea4eb33 commit a151754
Show file tree
Hide file tree
Showing 129 changed files with 2,258 additions and 1,034 deletions.
2 changes: 2 additions & 0 deletions docs/management/advanced-options.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,8 @@ might increase the search time. This setting is off by default. Users must opt-i
[horizontal]
`siem:defaultAnomalyScore`:: The threshold above which Machine Learning job anomalies are displayed in the SIEM app.
`siem:defaultIndex`:: A comma-delimited list of Elasticsearch indices from which the SIEM app collects events.
`siem:ipReputationLinks`:: A JSON array containing links for verifying the reputation of an IP address. The links are displayed on
{siem-guide}/siem-ui-overview.html#network-ui[IP detail] pages.
`siem:enableNewsFeed`:: Enables the security news feed on the SIEM *Overview*
page.
`siem:newsFeedUrl`:: The URL from which the security news feed content is
Expand Down
Binary file added docs/siem/images/cases-ui.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
18 changes: 17 additions & 1 deletion docs/siem/siem-ui.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ image::siem/images/network-ui.png[]

[float]
[[detections-ui]]
=== Detections (Beta)
=== Detections (beta)

The Detections feature automatically searches for threats and creates
signals when they are detected. Signal detection rules define the conditions
Expand All @@ -50,6 +50,22 @@ or the Detections API.
[role="screenshot"]
image::siem/images/detections-ui.png[]

[float]
[[cases-ui]]
=== Cases (beta)

Cases are used to open and track security issues directly in SIEM.
Cases list the original reporter and all users who contribute to a case
(`participants`). Case comments support Markdown syntax, and allow linking to
saved Timelines. Additionally, you can send cases to external systems from
within SIEM (currently ServiceNow).

For information about opening, updating, and closing cases, see
{siem-guide}/cases-overview.html[Cases] in the SIEM Guide.

[role="screenshot"]
image::siem/images/cases-ui.png[]

[float]
[[timelines-ui]]
=== Timeline
Expand Down
7 changes: 7 additions & 0 deletions packages/kbn-storybook/storybook_config/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,13 @@ module.exports = async ({ config }) => {
},
});

config.module.rules.push({
test: /\.(html|md|txt|tmpl)$/,
use: {
loader: 'raw-loader',
},
});

// Handle Typescript files
config.module.rules.push({
test: /\.tsx?$/,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ export class PlaceholderEmbeddableFactory implements EmbeddableFactoryDefinition
return false;
}

public canCreateNew() {
return false;
}

public async create(initialInput: EmbeddableInput, parent?: IContainer) {
return new PlaceholderEmbeddable(initialInput, parent);
}
Expand Down
37 changes: 35 additions & 2 deletions x-pack/legacy/plugins/maps/public/angular/map_controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import {
replaceLayerList,
setQuery,
clearTransientLayerStateAndCloseFlyout,
setMapSettings,
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
} from '../../../../../plugins/maps/public/actions/map_actions';
import {
Expand All @@ -52,10 +53,14 @@ import {
setReadOnly,
setIsLayerTOCOpen,
setOpenTOCDetails,
openMapSettings,
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
} from '../../../../../plugins/maps/public/actions/ui_actions';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { getIsFullScreen } from '../../../../../plugins/maps/public/selectors/ui_selectors';
import {
getIsFullScreen,
getFlyoutDisplay,
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
} from '../../../../../plugins/maps/public/selectors/ui_selectors';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { copyPersistentState } from '../../../../../plugins/maps/public/reducers/util';
import {
Expand Down Expand Up @@ -395,6 +400,9 @@ app.controller(
if (mapState.filters) {
savedObjectFilters = mapState.filters;
}
if (mapState.settings) {
store.dispatch(setMapSettings(mapState.settings));
}
}

if (savedMap.uiStateJSON) {
Expand Down Expand Up @@ -453,6 +461,7 @@ app.controller(

$scope.isFullScreen = false;
$scope.isSaveDisabled = false;
$scope.isOpenSettingsDisabled = false;
function handleStoreChanges(store) {
const nextIsFullScreen = getIsFullScreen(store.getState());
if (nextIsFullScreen !== $scope.isFullScreen) {
Expand All @@ -474,6 +483,14 @@ app.controller(
$scope.isSaveDisabled = nextIsSaveDisabled;
});
}

const flyoutDisplay = getFlyoutDisplay(store.getState());
const nextIsOpenSettingsDisabled = flyoutDisplay !== FLYOUT_STATE.NONE;
if (nextIsOpenSettingsDisabled !== $scope.isOpenSettingsDisabled) {
$scope.$evalAsync(() => {
$scope.isOpenSettingsDisabled = nextIsOpenSettingsDisabled;
});
}
}

$scope.$on('$destroy', () => {
Expand Down Expand Up @@ -591,6 +608,22 @@ app.controller(
getInspector().open(inspectorAdapters, {});
},
},
{
id: 'mapSettings',
label: i18n.translate('xpack.maps.mapController.openSettingsButtonLabel', {
defaultMessage: `Map settings`,
}),
description: i18n.translate('xpack.maps.mapController.openSettingsDescription', {
defaultMessage: `Open map settings`,
}),
testId: 'openSettingsButton',
disableButton() {
return $scope.isOpenSettingsDisabled;
},
run() {
store.dispatch(openMapSettings());
},
},
...(getMapsCapabilities().save
? [
{
Expand Down
117 changes: 1 addition & 116 deletions x-pack/legacy/plugins/siem/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,7 @@ import { i18n } from '@kbn/i18n';
import { resolve } from 'path';
import { Root } from 'joi';

// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { savedObjectMappings } from '../../../plugins/siem/server/saved_objects';

import {
APP_ID,
APP_NAME,
DEFAULT_INDEX_KEY,
DEFAULT_ANOMALY_SCORE,
DEFAULT_SIEM_TIME_RANGE,
DEFAULT_SIEM_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_INDEX_PATTERN,
} from '../../../plugins/siem/common/constants';
import { APP_ID, APP_NAME } from '../../../plugins/siem/common/constants';
import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/utils';

// eslint-disable-next-line @typescript-eslint/no-explicit-any
Expand Down Expand Up @@ -63,101 +43,6 @@ export const siem = (kibana: any) => {
category: DEFAULT_APP_CATEGORIES.security,
},
],
uiSettingDefaults: {
[DEFAULT_SIEM_REFRESH_INTERVAL]: {
type: 'json',
name: i18n.translate('xpack.siem.uiSettings.defaultRefreshIntervalLabel', {
defaultMessage: 'Time filter refresh interval',
}),
value: `{
"pause": ${DEFAULT_INTERVAL_PAUSE},
"value": ${DEFAULT_INTERVAL_VALUE}
}`,
description: i18n.translate('xpack.siem.uiSettings.defaultRefreshIntervalDescription', {
defaultMessage:
'<p>Default refresh interval for the SIEM time filter, in milliseconds.</p>',
}),
category: ['siem'],
requiresPageReload: true,
},
[DEFAULT_SIEM_TIME_RANGE]: {
type: 'json',
name: i18n.translate('xpack.siem.uiSettings.defaultTimeRangeLabel', {
defaultMessage: 'Time filter period',
}),
value: `{
"from": "${DEFAULT_FROM}",
"to": "${DEFAULT_TO}"
}`,
description: i18n.translate('xpack.siem.uiSettings.defaultTimeRangeDescription', {
defaultMessage: '<p>Default period of time in the SIEM time filter.</p>',
}),
category: ['siem'],
requiresPageReload: true,
},
[DEFAULT_INDEX_KEY]: {
name: i18n.translate('xpack.siem.uiSettings.defaultIndexLabel', {
defaultMessage: 'Elasticsearch indices',
}),
value: DEFAULT_INDEX_PATTERN,
description: i18n.translate('xpack.siem.uiSettings.defaultIndexDescription', {
defaultMessage:
'<p>Comma-delimited list of Elasticsearch indices from which the SIEM app collects events.</p>',
}),
category: ['siem'],
requiresPageReload: true,
},
[DEFAULT_ANOMALY_SCORE]: {
name: i18n.translate('xpack.siem.uiSettings.defaultAnomalyScoreLabel', {
defaultMessage: 'Anomaly threshold',
}),
value: 50,
type: 'number',
description: i18n.translate('xpack.siem.uiSettings.defaultAnomalyScoreDescription', {
defaultMessage:
'<p>Value above which Machine Learning job anomalies are displayed in the SIEM app.</p><p>Valid values: 0 to 100.</p>',
}),
category: ['siem'],
requiresPageReload: true,
},
[ENABLE_NEWS_FEED_SETTING]: {
name: i18n.translate('xpack.siem.uiSettings.enableNewsFeedLabel', {
defaultMessage: 'News feed',
}),
value: true,
description: i18n.translate('xpack.siem.uiSettings.enableNewsFeedDescription', {
defaultMessage: '<p>Enables the News feed</p>',
}),
type: 'boolean',
category: ['siem'],
requiresPageReload: true,
},
[NEWS_FEED_URL_SETTING]: {
name: i18n.translate('xpack.siem.uiSettings.newsFeedUrl', {
defaultMessage: 'News feed URL',
}),
value: NEWS_FEED_URL_SETTING_DEFAULT,
description: i18n.translate('xpack.siem.uiSettings.newsFeedUrlDescription', {
defaultMessage: '<p>News feed content will be retrieved from this URL</p>',
}),
category: ['siem'],
requiresPageReload: true,
},
[IP_REPUTATION_LINKS_SETTING]: {
name: i18n.translate('xpack.siem.uiSettings.ipReputationLinks', {
defaultMessage: 'IP Reputation Links',
}),
value: IP_REPUTATION_LINKS_SETTING_DEFAULT,
type: 'json',
description: i18n.translate('xpack.siem.uiSettings.ipReputationLinksDescription', {
defaultMessage:
'Array of URL templates to build the list of reputation URLs to be displayed on the IP Details page.',
}),
category: ['siem'],
requiresPageReload: true,
},
},
mappings: savedObjectMappings,
},
config(Joi: Root) {
return Joi.object()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { useForm } from '../../../../../../../../../src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks';
jest.mock(
'../../../../../../../../../src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/use_form'
);
export const mockFormHook = {
isSubmitted: false,
isSubmitting: false,
Expand Down Expand Up @@ -35,3 +39,5 @@ export const getFormMock = (sampleData: any) => ({
}),
getFormData: () => sampleData,
});

export const useFormMock = useForm as jest.Mock;
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import { Router, routeData, mockHistory, mockLocation } from '../__mock__/router

import { useInsertTimeline } from '../../../../components/timeline/insert_timeline_popover/use_insert_timeline';
import { usePostCase } from '../../../../containers/case/use_post_case';
import { useGetTags } from '../../../../containers/case/use_get_tags';

jest.mock('../../../../components/timeline/insert_timeline_popover/use_insert_timeline');
jest.mock('../../../../containers/case/use_post_case');
import { useForm } from '../../../../../../../../../src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks';
Expand All @@ -22,6 +24,14 @@ import { SiemPageName } from '../../../home/types';
jest.mock(
'../../../../../../../../../src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/use_form'
);
jest.mock('../../../../containers/case/use_get_tags');
jest.mock(
'../../../../../../../../../src/plugins/es_ui_shared/static/forms/hook_form_lib/components/form_data_provider',
() => ({
FormDataProvider: ({ children }: { children: ({ tags }: { tags: string[] }) => void }) =>
children({ tags: ['rad', 'dude'] }),
})
);

export const useFormMock = useForm as jest.Mock;

Expand All @@ -40,9 +50,11 @@ const defaultInsertTimeline = {
handleCursorChange,
handleOnTimelineChange,
};

const sampleTags = ['coke', 'pepsi'];
const sampleData = {
description: 'what a great description',
tags: ['coke', 'pepsi'],
tags: sampleTags,
title: 'what a cool title',
};
const defaultPostCase = {
Expand All @@ -52,14 +64,28 @@ const defaultPostCase = {
postCase,
};
describe('Create case', () => {
// Suppress warnings about "noSuggestions" prop
/* eslint-disable no-console */
const originalError = console.error;
beforeAll(() => {
console.error = jest.fn();
});
afterAll(() => {
console.error = originalError;
});
/* eslint-enable no-console */
const fetchTags = jest.fn();
const formHookMock = getFormMock(sampleData);

beforeEach(() => {
jest.resetAllMocks();
useInsertTimelineMock.mockImplementation(() => defaultInsertTimeline);
usePostCaseMock.mockImplementation(() => defaultPostCase);
useFormMock.mockImplementation(() => ({ form: formHookMock }));
jest.spyOn(routeData, 'useLocation').mockReturnValue(mockLocation);
(useGetTags as jest.Mock).mockImplementation(() => ({
tags: sampleTags,
fetchTags,
}));
});

it('should post case on submit click', async () => {
Expand Down Expand Up @@ -118,4 +144,19 @@ describe('Create case', () => {
);
expect(wrapper.find(`[data-test-subj="create-case-loading-spinner"]`).exists()).toBeTruthy();
});
it('Tag options render with new tags added', () => {
const wrapper = mount(
<TestProviders>
<Router history={mockHistory}>
<Create />
</Router>
</TestProviders>
);
expect(
wrapper
.find(`[data-test-subj="caseTags"] [data-test-subj="input"]`)
.first()
.prop('options')
).toEqual([{ label: 'coke' }, { label: 'pepsi' }, { label: 'rad' }, { label: 'dude' }]);
});
});
Loading

0 comments on commit a151754

Please sign in to comment.