diff --git a/x-pack/legacy/plugins/siem/public/pages/case/translations.ts b/x-pack/legacy/plugins/siem/public/pages/case/translations.ts
index 265af0bde547f..5f0509586fc81 100644
--- a/x-pack/legacy/plugins/siem/public/pages/case/translations.ts
+++ b/x-pack/legacy/plugins/siem/public/pages/case/translations.ts
@@ -14,8 +14,8 @@ export const CANCEL = i18n.translate('xpack.siem.case.caseView.cancel', {
defaultMessage: 'Cancel',
});
-export const CASE_TITLE = i18n.translate('xpack.siem.case.caseView.caseTitle', {
- defaultMessage: 'Case Title',
+export const NAME = i18n.translate('xpack.siem.case.caseView.name', {
+ defaultMessage: 'Name',
});
export const CREATED_AT = i18n.translate('xpack.siem.case.caseView.createdAt', {
@@ -45,6 +45,13 @@ export const DESCRIPTION_REQUIRED = i18n.translate(
}
);
+export const COMMENT_REQUIRED = i18n.translate(
+ 'xpack.siem.case.caseView.commentFieldRequiredError',
+ {
+ defaultMessage: 'A comment is required.',
+ }
+);
+
export const EDIT = i18n.translate('xpack.siem.case.caseView.edit', {
defaultMessage: 'Edit',
});
@@ -58,15 +65,11 @@ export const LAST_UPDATED = i18n.translate('xpack.siem.case.caseView.updatedAt',
});
export const PAGE_SUBTITLE = i18n.translate('xpack.siem.case.caseView.pageSubtitle', {
- defaultMessage: 'Case Workflow Management within the Elastic SIEM',
+ defaultMessage: 'Cases within the Elastic SIEM',
});
export const PAGE_TITLE = i18n.translate('xpack.siem.case.pageTitle', {
- defaultMessage: 'Case Workflows',
-});
-
-export const PREVIEW = i18n.translate('xpack.siem.case.caseView.preview', {
- defaultMessage: 'Preview',
+ defaultMessage: 'Cases',
});
export const STATE = i18n.translate('xpack.siem.case.caseView.state', {
@@ -77,6 +80,10 @@ export const SUBMIT = i18n.translate('xpack.siem.case.caseView.submit', {
defaultMessage: 'Submit',
});
+export const CREATE_CASE = i18n.translate('xpack.siem.case.caseView.createCase', {
+ defaultMessage: 'Create case',
+});
+
export const TAGS = i18n.translate('xpack.siem.case.caseView.tags', {
defaultMessage: 'Tags',
});
@@ -104,3 +111,18 @@ export const CONFIGURE_CASES_PAGE_TITLE = i18n.translate(
export const CONFIGURE_CASES_BUTTON = i18n.translate('xpack.siem.case.configureCasesButton', {
defaultMessage: 'Configure cases',
});
+
+export const ADD_COMMENT = i18n.translate('xpack.siem.case.caseView.comment.addComment', {
+ defaultMessage: 'Add comment',
+});
+
+export const ADD_COMMENT_HELP_TEXT = i18n.translate(
+ 'xpack.siem.case.caseView.comment.addCommentHelpText',
+ {
+ defaultMessage: 'Add a new comment...',
+ }
+);
+
+export const SAVE = i18n.translate('xpack.siem.case.caseView.description.save', {
+ defaultMessage: 'Save',
+});
diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/add_item_form/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/add_item_form/index.tsx
index cc5e9b38eb2f8..abbaa6d6192ee 100644
--- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/add_item_form/index.tsx
+++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/add_item_form/index.tsx
@@ -18,7 +18,7 @@ import React, { ChangeEvent, useCallback, useEffect, useState, useRef } from 're
import styled from 'styled-components';
import * as RuleI18n from '../../translations';
-import { FieldHook, getFieldValidityAndErrorMessage } from '../../../../shared_imports';
+import { FieldHook, getFieldValidityAndErrorMessage } from '../../../../../shared_imports';
interface AddItemProps {
addText: string;
diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/description_step/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/description_step/index.tsx
index 1cc7bba5558db..f921c29c06ab0 100644
--- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/description_step/index.tsx
+++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/description_step/index.tsx
@@ -19,7 +19,7 @@ import { DEFAULT_TIMELINE_TITLE } from '../../../../../components/timeline/searc
import { useKibana } from '../../../../../lib/kibana';
import { IMitreEnterpriseAttack } from '../../types';
import { FieldValueTimeline } from '../pick_timeline';
-import { FormSchema } from '../../../../shared_imports';
+import { FormSchema } from '../../../../../shared_imports';
import { ListItems } from './types';
import {
buildQueryBarDescription,
diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/mitre/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/mitre/index.tsx
index b49126c8c0fe0..e87dba251ed6d 100644
--- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/mitre/index.tsx
+++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/mitre/index.tsx
@@ -20,7 +20,7 @@ import styled from 'styled-components';
import { tacticsOptions, techniquesOptions } from '../../../mitre/mitre_tactics_techniques';
import * as Rulei18n from '../../translations';
-import { FieldHook, getFieldValidityAndErrorMessage } from '../../../../shared_imports';
+import { FieldHook, getFieldValidityAndErrorMessage } from '../../../../../shared_imports';
import { threatDefault } from '../step_about_rule/default_value';
import { IMitreEnterpriseAttack } from '../../types';
import { MyAddItemButton } from '../add_item_form';
diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/pick_timeline/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/pick_timeline/index.tsx
index 56cb02c9ec817..923ec3a7f0066 100644
--- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/pick_timeline/index.tsx
+++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/pick_timeline/index.tsx
@@ -8,7 +8,7 @@ import { EuiFormRow } from '@elastic/eui';
import React, { useCallback, useEffect, useState } from 'react';
import { SearchTimelineSuperSelect } from '../../../../../components/timeline/search_super_select';
-import { FieldHook, getFieldValidityAndErrorMessage } from '../../../../shared_imports';
+import { FieldHook, getFieldValidityAndErrorMessage } from '../../../../../shared_imports';
export interface FieldValueTimeline {
id: string | null;
diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/query_bar/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/query_bar/index.tsx
index fbe854c1ee346..5886a76182eec 100644
--- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/query_bar/index.tsx
+++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/query_bar/index.tsx
@@ -29,7 +29,7 @@ import { convertKueryToElasticSearchQuery } from '../../../../../lib/keury';
import { useKibana } from '../../../../../lib/kibana';
import { TimelineModel } from '../../../../../store/timeline/model';
import { useSavedQueryServices } from '../../../../../utils/saved_query_services';
-import { FieldHook, getFieldValidityAndErrorMessage } from '../../../../shared_imports';
+import { FieldHook, getFieldValidityAndErrorMessage } from '../../../../../shared_imports';
import * as i18n from './translations';
export interface FieldValueQueryBar {
diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/schedule_item_form/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/schedule_item_form/index.tsx
index ffb6c4eda3243..1b7d17016f83c 100644
--- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/schedule_item_form/index.tsx
+++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/schedule_item_form/index.tsx
@@ -16,7 +16,7 @@ import { isEmpty } from 'lodash/fp';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import styled from 'styled-components';
-import { FieldHook, getFieldValidityAndErrorMessage } from '../../../../shared_imports';
+import { FieldHook, getFieldValidityAndErrorMessage } from '../../../../../shared_imports';
import * as I18n from './translations';
diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule/index.tsx
index 431d793d6e68a..d93c057506ca7 100644
--- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule/index.tsx
+++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule/index.tsx
@@ -30,7 +30,7 @@ import {
getUseField,
UseField,
useForm,
-} from '../../../../shared_imports';
+} from '../../../../../shared_imports';
import { defaultRiskScoreBySeverity, severityOptions, SeverityValue } from './data';
import { stepAboutDefaultValue } from './default_value';
diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule/schema.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule/schema.tsx
index 27887bcbbe600..42cf1e0d95649 100644
--- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule/schema.tsx
+++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule/schema.tsx
@@ -13,7 +13,7 @@ import {
FormSchema,
ValidationFunc,
ERROR_CODE,
-} from '../../../../shared_imports';
+} from '../../../../../shared_imports';
import { isMitreAttackInvalid } from '../mitre/helpers';
import { OptionalFieldLabel } from '../optional_field_label';
import { isUrlInvalid } from './helpers';
diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_define_rule/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_define_rule/index.tsx
index 773eb44efb26c..837bc79e968e8 100644
--- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_define_rule/index.tsx
+++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_define_rule/index.tsx
@@ -33,7 +33,7 @@ import {
getUseField,
UseField,
useForm,
-} from '../../../../shared_imports';
+} from '../../../../../shared_imports';
import { schema } from './schema';
import * as i18n from './translations';
diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_define_rule/schema.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_define_rule/schema.tsx
index bb178d7197069..e202ff030cd90 100644
--- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_define_rule/schema.tsx
+++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_define_rule/schema.tsx
@@ -17,7 +17,7 @@ import {
fieldValidators,
FormSchema,
ValidationFunc,
-} from '../../../../shared_imports';
+} from '../../../../../shared_imports';
import { CUSTOM_QUERY_REQUIRED, INVALID_CUSTOM_QUERY, INDEX_HELPER_TEXT } from './translations';
const { emptyField } = fieldValidators;
diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_schedule_rule/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_schedule_rule/index.tsx
index 2e2c7e068dd85..e9632966fdfaf 100644
--- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_schedule_rule/index.tsx
+++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_schedule_rule/index.tsx
@@ -12,7 +12,7 @@ import { setFieldValue } from '../../helpers';
import { RuleStep, RuleStepProps, ScheduleStepRule } from '../../types';
import { StepRuleDescription } from '../description_step';
import { ScheduleItem } from '../schedule_item_form';
-import { Form, UseField, useForm } from '../../../../shared_imports';
+import { Form, UseField, useForm } from '../../../../../shared_imports';
import { StepContentWrapper } from '../step_content_wrapper';
import { schema } from './schema';
import * as I18n from './translations';
diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_schedule_rule/schema.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_schedule_rule/schema.tsx
index 9932e4f6ef435..8fbfdf5f25a51 100644
--- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_schedule_rule/schema.tsx
+++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_schedule_rule/schema.tsx
@@ -7,7 +7,7 @@
import { i18n } from '@kbn/i18n';
import { OptionalFieldLabel } from '../optional_field_label';
-import { FormSchema } from '../../../../shared_imports';
+import { FormSchema } from '../../../../../shared_imports';
export const schema: FormSchema = {
interval: {
diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/create/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/create/index.tsx
index c985045b1897b..d816c7e867057 100644
--- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/create/index.tsx
+++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/create/index.tsx
@@ -17,7 +17,7 @@ import { displaySuccessToast, useStateToaster } from '../../../../components/toa
import { SpyRoute } from '../../../../utils/route/spy_routes';
import { useUserInfo } from '../../components/user_info';
import { AccordionTitle } from '../components/accordion_title';
-import { FormData, FormHook } from '../../../shared_imports';
+import { FormData, FormHook } from '../../../../shared_imports';
import { StepAboutRule } from '../components/step_about_rule';
import { StepDefineRule } from '../components/step_define_rule';
import { StepScheduleRule } from '../components/step_schedule_rule';
diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/edit/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/edit/index.tsx
index 0fac4641e54a7..5e0e4223e3e27 100644
--- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/edit/index.tsx
+++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/edit/index.tsx
@@ -26,7 +26,7 @@ import { displaySuccessToast, useStateToaster } from '../../../../components/toa
import { SpyRoute } from '../../../../utils/route/spy_routes';
import { useUserInfo } from '../../components/user_info';
import { DetectionEngineHeaderPage } from '../../components/detection_engine_header_page';
-import { FormHook, FormData } from '../../../shared_imports';
+import { FormHook, FormData } from '../../../../shared_imports';
import { StepPanel } from '../components/step_panel';
import { StepAboutRule } from '../components/step_about_rule';
import { StepDefineRule } from '../components/step_define_rule';
diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/helpers.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/helpers.tsx
index 3fab456d856ca..85f3bcbd236e9 100644
--- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/helpers.tsx
+++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/helpers.tsx
@@ -11,7 +11,7 @@ import { useLocation } from 'react-router-dom';
import { Filter } from '../../../../../../../../src/plugins/data/public';
import { Rule } from '../../../containers/detection_engine/rules';
-import { FormData, FormHook, FormSchema } from '../../shared_imports';
+import { FormData, FormHook, FormSchema } from '../../../shared_imports';
import { AboutStepRule, DefineStepRule, IMitreEnterpriseAttack, ScheduleStepRule } from './types';
interface GetStepsData {
diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/types.ts b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/types.ts
index b2650dcc2b77e..34df20de1e461 100644
--- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/types.ts
+++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/types.ts
@@ -6,7 +6,7 @@
import { Filter } from '../../../../../../../../src/plugins/data/common';
import { FieldValueQueryBar } from './components/query_bar';
-import { FormData, FormHook } from '../../shared_imports';
+import { FormData, FormHook } from '../../../shared_imports';
import { FieldValueTimeline } from './components/pick_timeline';
export interface EuiBasicTableSortTypes {
diff --git a/x-pack/legacy/plugins/siem/public/pages/home/translations.ts b/x-pack/legacy/plugins/siem/public/pages/home/translations.ts
index 581c81d9f98a0..f2bcaa07b1a25 100644
--- a/x-pack/legacy/plugins/siem/public/pages/home/translations.ts
+++ b/x-pack/legacy/plugins/siem/public/pages/home/translations.ts
@@ -27,5 +27,5 @@ export const TIMELINES = i18n.translate('xpack.siem.navigation.timelines', {
});
export const CASE = i18n.translate('xpack.siem.navigation.case', {
- defaultMessage: 'Case',
+ defaultMessage: 'Cases',
});
diff --git a/x-pack/legacy/plugins/siem/public/pages/shared_imports.ts b/x-pack/legacy/plugins/siem/public/shared_imports.ts
similarity index 52%
rename from x-pack/legacy/plugins/siem/public/pages/shared_imports.ts
rename to x-pack/legacy/plugins/siem/public/shared_imports.ts
index a41f121b36926..edd7812b3bd16 100644
--- a/x-pack/legacy/plugins/siem/public/pages/shared_imports.ts
+++ b/x-pack/legacy/plugins/siem/public/shared_imports.ts
@@ -17,7 +17,7 @@ export {
UseField,
useForm,
ValidationFunc,
-} from '../../../../../../src/plugins/es_ui_shared/static/forms/hook_form_lib';
-export { Field } from '../../../../../../src/plugins/es_ui_shared/static/forms/components';
-export { fieldValidators } from '../../../../../../src/plugins/es_ui_shared/static/forms/helpers';
-export { ERROR_CODE } from '../../../../../../src/plugins/es_ui_shared/static/forms/helpers/field_validators/types';
+} from '../../../../../src/plugins/es_ui_shared/static/forms/hook_form_lib';
+export { Field } from '../../../../../src/plugins/es_ui_shared/static/forms/components';
+export { fieldValidators } from '../../../../../src/plugins/es_ui_shared/static/forms/helpers';
+export { ERROR_CODE } from '../../../../../src/plugins/es_ui_shared/static/forms/helpers/field_validators/types';
diff --git a/x-pack/plugins/apm/common/__snapshots__/elasticsearch_fieldnames.test.ts.snap b/x-pack/plugins/apm/common/__snapshots__/elasticsearch_fieldnames.test.ts.snap
index 8f87b3473b2e4..b4b4e7866e9b7 100644
--- a/x-pack/plugins/apm/common/__snapshots__/elasticsearch_fieldnames.test.ts.snap
+++ b/x-pack/plugins/apm/common/__snapshots__/elasticsearch_fieldnames.test.ts.snap
@@ -66,6 +66,8 @@ exports[`Error SERVICE_AGENT_NAME 1`] = `"java"`;
exports[`Error SERVICE_ENVIRONMENT 1`] = `undefined`;
+exports[`Error SERVICE_FRAMEWORK_NAME 1`] = `undefined`;
+
exports[`Error SERVICE_NAME 1`] = `"service name"`;
exports[`Error SERVICE_NODE_NAME 1`] = `undefined`;
@@ -176,6 +178,8 @@ exports[`Span SERVICE_AGENT_NAME 1`] = `"java"`;
exports[`Span SERVICE_ENVIRONMENT 1`] = `undefined`;
+exports[`Span SERVICE_FRAMEWORK_NAME 1`] = `undefined`;
+
exports[`Span SERVICE_NAME 1`] = `"service name"`;
exports[`Span SERVICE_NODE_NAME 1`] = `undefined`;
@@ -286,6 +290,8 @@ exports[`Transaction SERVICE_AGENT_NAME 1`] = `"java"`;
exports[`Transaction SERVICE_ENVIRONMENT 1`] = `undefined`;
+exports[`Transaction SERVICE_FRAMEWORK_NAME 1`] = `undefined`;
+
exports[`Transaction SERVICE_NAME 1`] = `"service name"`;
exports[`Transaction SERVICE_NODE_NAME 1`] = `undefined`;
diff --git a/x-pack/plugins/apm/common/elasticsearch_fieldnames.ts b/x-pack/plugins/apm/common/elasticsearch_fieldnames.ts
index ce2db4964a412..14233aad0f53c 100644
--- a/x-pack/plugins/apm/common/elasticsearch_fieldnames.ts
+++ b/x-pack/plugins/apm/common/elasticsearch_fieldnames.ts
@@ -7,6 +7,7 @@
export const SERVICE_NAME = 'service.name';
export const SERVICE_ENVIRONMENT = 'service.environment';
export const SERVICE_AGENT_NAME = 'agent.name';
+export const SERVICE_FRAMEWORK_NAME = 'service.framework.name';
export const SERVICE_NODE_NAME = 'service.node.name';
export const SERVICE_VERSION = 'service.version';
export const URL_FULL = 'url.full';
diff --git a/x-pack/plugins/apm/common/service_map.ts b/x-pack/plugins/apm/common/service_map.ts
index 548b29346e483..f4354baa97655 100644
--- a/x-pack/plugins/apm/common/service_map.ts
+++ b/x-pack/plugins/apm/common/service_map.ts
@@ -10,6 +10,7 @@ import { ILicense } from '../../licensing/public';
export interface ServiceConnectionNode {
'service.name': string;
'service.environment': string | null;
+ 'service.framework.name': string | null;
'agent.name': string;
}
export interface ExternalConnectionNode {
diff --git a/x-pack/plugins/apm/server/lib/service_map/get_service_map.ts b/x-pack/plugins/apm/server/lib/service_map/get_service_map.ts
index 04e2a43a4b8f1..85d71784b55c7 100644
--- a/x-pack/plugins/apm/server/lib/service_map/get_service_map.ts
+++ b/x-pack/plugins/apm/server/lib/service_map/get_service_map.ts
@@ -16,7 +16,8 @@ import { getServicesProjection } from '../../../common/projections/services';
import { mergeProjection } from '../../../common/projections/util/merge_projection';
import {
SERVICE_AGENT_NAME,
- SERVICE_NAME
+ SERVICE_NAME,
+ SERVICE_FRAMEWORK_NAME
} from '../../../common/elasticsearch_fieldnames';
export interface IEnvOptions {
@@ -92,6 +93,11 @@ async function getServicesData(options: IEnvOptions) {
terms: {
field: SERVICE_AGENT_NAME
}
+ },
+ service_framework_name: {
+ terms: {
+ field: SERVICE_FRAMEWORK_NAME
+ }
}
}
}
@@ -109,7 +115,11 @@ async function getServicesData(options: IEnvOptions) {
'service.name': bucket.key as string,
'agent.name':
(bucket.agent_name.buckets[0]?.key as string | undefined) || '',
- 'service.environment': options.environment || null
+ 'service.environment': options.environment || null,
+ 'service.framework.name':
+ (bucket.service_framework_name.buckets[0]?.key as
+ | string
+ | undefined) || null
};
}) || []
);
diff --git a/x-pack/plugins/apm/server/lib/services/map.ts b/x-pack/plugins/apm/server/lib/services/map.ts
deleted file mode 100644
index 97bb925674e26..0000000000000
--- a/x-pack/plugins/apm/server/lib/services/map.ts
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-import cytoscape from 'cytoscape';
-import { PromiseReturnType } from '../../../typings/common';
-
-// This response right now just returns experimental data.
-export type ServiceMapResponse = PromiseReturnType;
-export async function getServiceMap(): Promise {
- return [
- { data: { id: 'client', agentName: 'js-base' } },
- { data: { id: 'opbeans-node', agentName: 'nodejs' } },
- { data: { id: 'opbeans-python', agentName: 'python' } },
- { data: { id: 'opbeans-java', agentName: 'java' } },
- { data: { id: 'opbeans-ruby', agentName: 'ruby' } },
- { data: { id: 'opbeans-go', agentName: 'go' } },
- { data: { id: 'opbeans-go-2', agentName: 'go' } },
- { data: { id: 'opbeans-dotnet', agentName: 'dotnet' } },
- { data: { id: 'database', agentName: 'database' } },
- { data: { id: 'external API', agentName: 'external' } },
-
- {
- data: {
- id: 'opbeans-client~opbeans-node',
- source: 'client',
- target: 'opbeans-node'
- }
- },
- {
- data: {
- id: 'opbeans-client~opbeans-python',
- source: 'client',
- target: 'opbeans-python'
- }
- },
- {
- data: {
- id: 'opbeans-python~opbeans-go',
- source: 'opbeans-python',
- target: 'opbeans-go'
- }
- },
- {
- data: {
- id: 'opbeans-python~opbeans-go-2',
- source: 'opbeans-python',
- target: 'opbeans-go-2'
- }
- },
- {
- data: {
- id: 'opbeans-python~opbeans-dotnet',
- source: 'opbeans-python',
- target: 'opbeans-dotnet'
- }
- },
- {
- data: {
- id: 'opbeans-node~opbeans-java',
- source: 'opbeans-node',
- target: 'opbeans-java'
- }
- },
- {
- data: {
- id: 'opbeans-node~database',
- source: 'opbeans-node',
- target: 'database'
- }
- },
- {
- data: {
- id: 'opbeans-go-2~opbeans-ruby',
- source: 'opbeans-go-2',
- target: 'opbeans-ruby'
- }
- },
- {
- data: {
- id: 'opbeans-go-2~external API',
- source: 'opbeans-go-2',
- target: 'external API'
- }
- }
- ];
-}
diff --git a/x-pack/plugins/case/server/routes/api/__tests__/update_comment.test.ts b/x-pack/plugins/case/server/routes/api/__tests__/update_comment.test.ts
index 5bfd121691ab4..6b4e3c194eb82 100644
--- a/x-pack/plugins/case/server/routes/api/__tests__/update_comment.test.ts
+++ b/x-pack/plugins/case/server/routes/api/__tests__/update_comment.test.ts
@@ -28,6 +28,7 @@ describe('UPDATE comment', () => {
},
body: {
comment: 'Update my comment',
+ version: 'WzEsMV0=',
},
});
@@ -37,6 +38,24 @@ describe('UPDATE comment', () => {
expect(response.status).toEqual(200);
expect(response.payload.comment).toEqual('Update my comment');
});
+ it(`Fails with 409 if version does not match`, async () => {
+ const request = httpServerMock.createKibanaRequest({
+ path: '/api/cases/comment/{id}',
+ method: 'patch',
+ params: {
+ id: 'mock-comment-1',
+ },
+ body: {
+ comment: 'Update my comment',
+ version: 'badv=',
+ },
+ });
+
+ const theContext = createRouteContext(createMockSavedObjectsRepository(mockCaseComments));
+
+ const response = await routeHandler(theContext, request, kibanaResponseFactory);
+ expect(response.status).toEqual(409);
+ });
it(`Returns an error if updateComment throws`, async () => {
const request = httpServerMock.createKibanaRequest({
path: '/api/cases/comment/{id}',
diff --git a/x-pack/plugins/case/server/routes/api/schema.ts b/x-pack/plugins/case/server/routes/api/schema.ts
index 468abc8e7226f..765f9c722219f 100644
--- a/x-pack/plugins/case/server/routes/api/schema.ts
+++ b/x-pack/plugins/case/server/routes/api/schema.ts
@@ -15,6 +15,11 @@ export const NewCommentSchema = schema.object({
comment: schema.string(),
});
+export const UpdateCommentArguments = schema.object({
+ comment: schema.string(),
+ version: schema.string(),
+});
+
export const CommentSchema = schema.object({
comment: schema.string(),
created_at: schema.string(),
diff --git a/x-pack/plugins/case/server/routes/api/update_comment.ts b/x-pack/plugins/case/server/routes/api/update_comment.ts
index 815f44a14e2e7..9f99253f76629 100644
--- a/x-pack/plugins/case/server/routes/api/update_comment.ts
+++ b/x-pack/plugins/case/server/routes/api/update_comment.ts
@@ -5,9 +5,12 @@
*/
import { schema } from '@kbn/config-schema';
+import { SavedObject } from 'kibana/server';
+import Boom from 'boom';
import { wrapError } from './utils';
-import { NewCommentSchema } from './schema';
+import { UpdateCommentArguments } from './schema';
import { RouteDeps } from '.';
+import { CommentAttributes } from './types';
export function initUpdateCommentApi({ caseService, router }: RouteDeps) {
router.patch(
@@ -17,20 +20,45 @@ export function initUpdateCommentApi({ caseService, router }: RouteDeps) {
params: schema.object({
id: schema.string(),
}),
- body: NewCommentSchema,
+ body: UpdateCommentArguments,
},
},
async (context, request, response) => {
+ let theComment: SavedObject;
+ try {
+ theComment = await caseService.getComment({
+ client: context.core.savedObjects.client,
+ commentId: request.params.id,
+ });
+ } catch (error) {
+ return response.customError(wrapError(error));
+ }
+ if (request.body.version !== theComment.version) {
+ return response.customError(
+ wrapError(
+ Boom.conflict(
+ 'This comment has been updated. Please refresh before saving additional updates.'
+ )
+ )
+ );
+ }
+ if (request.body.comment === theComment.attributes.comment) {
+ return response.customError(
+ wrapError(Boom.notAcceptable('Comment is identical to current version.'))
+ );
+ }
try {
const updatedComment = await caseService.updateComment({
client: context.core.savedObjects.client,
commentId: request.params.id,
updatedAttributes: {
- ...request.body,
+ comment: request.body.comment,
updated_at: new Date().toISOString(),
},
});
- return response.ok({ body: updatedComment.attributes });
+ return response.ok({
+ body: { ...updatedComment.attributes, version: updatedComment.version },
+ });
} catch (error) {
return response.customError(wrapError(error));
}
diff --git a/x-pack/plugins/endpoint/common/types.ts b/x-pack/plugins/endpoint/common/types.ts
index 6d904fda6f747..d804350a9002d 100644
--- a/x-pack/plugins/endpoint/common/types.ts
+++ b/x-pack/plugins/endpoint/common/types.ts
@@ -96,6 +96,59 @@ export interface EndpointResultList {
request_page_index: number;
}
+export interface OSFields {
+ full: string;
+ name: string;
+ version: string;
+ variant: string;
+}
+export interface HostFields {
+ id: string;
+ hostname: string;
+ ip: string[];
+ mac: string[];
+ os: OSFields;
+}
+export interface HashFields {
+ md5: string;
+ sha1: string;
+ sha256: string;
+}
+export interface MalwareClassifierFields {
+ identifier: string;
+ score: number;
+ threshold: number;
+ version: string;
+}
+export interface PrivilegesFields {
+ description: string;
+ name: string;
+ enabled: boolean;
+}
+export interface ThreadFields {
+ id: number;
+ service_name: string;
+ start: number;
+ start_address: number;
+ start_address_module: string;
+}
+export interface DllFields {
+ pe: {
+ architecture: string;
+ imphash: string;
+ };
+ code_signature: {
+ subject_name: string;
+ trusted: boolean;
+ };
+ compile_time: number;
+ hash: HashFields;
+ malware_classifier: MalwareClassifierFields;
+ mapped_address: number;
+ mapped_size: number;
+ path: string;
+}
+
/**
* Describes an Alert Event.
* Should be in line with ECS schema.
@@ -109,26 +162,78 @@ export type AlertEvent = Immutable<{
event: {
id: string;
action: string;
+ category: string;
+ kind: string;
+ dataset: string;
+ module: string;
+ type: string;
};
- file_classification: {
- malware_classification: {
- score: number;
+ process: {
+ code_signature: {
+ subject_name: string;
+ trusted: boolean;
};
- };
- process?: {
- unique_pid: number;
+ command_line: string;
+ domain: string;
pid: number;
+ ppid: number;
+ entity_id: string;
+ parent: {
+ pid: number;
+ entity_id: string;
+ };
+ name: string;
+ hash: HashFields;
+ pe: {
+ imphash: string;
+ };
+ executable: string;
+ sid: string;
+ start: number;
+ malware_classifier: MalwareClassifierFields;
+ token: {
+ domain: string;
+ type: string;
+ user: string;
+ sid: string;
+ integrity_level: number;
+ integrity_level_name: string;
+ privileges: PrivilegesFields[];
+ };
+ thread: ThreadFields[];
+ uptime: number;
+ user: string;
};
- host: {
- hostname: string;
- ip: string;
- os: {
- name: string;
+ file: {
+ owner: string;
+ name: string;
+ path: string;
+ accessed: number;
+ mtime: number;
+ created: number;
+ size: number;
+ hash: HashFields;
+ pe: {
+ imphash: string;
+ };
+ code_signature: {
+ trusted: boolean;
+ subject_name: string;
};
+ malware_classifier: {
+ features: {
+ data: {
+ buffer: string;
+ decompressed_size: number;
+ encoding: string;
+ };
+ };
+ } & MalwareClassifierFields;
+ temp_file_path: string;
};
+ host: HostFields;
thread: {};
- endpoint?: {};
- endgame?: {};
+ dll: DllFields[];
}>;
/**
@@ -161,18 +266,7 @@ export interface EndpointMetadata {
id: string;
name: string;
};
- host: {
- id: string;
- hostname: string;
- ip: string[];
- mac: string[];
- os: {
- name: string;
- full: string;
- version: string;
- variant: string;
- };
- };
+ host: HostFields;
}
/**
diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/store/alerts/action.ts b/x-pack/plugins/endpoint/public/applications/endpoint/store/alerts/action.ts
index a628a95003a7f..6c6310a7349ed 100644
--- a/x-pack/plugins/endpoint/public/applications/endpoint/store/alerts/action.ts
+++ b/x-pack/plugins/endpoint/public/applications/endpoint/store/alerts/action.ts
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { Immutable } from '../../../../../common/types';
+import { Immutable, AlertData } from '../../../../../common/types';
import { AlertListData } from '../../types';
interface ServerReturnedAlertsData {
@@ -12,4 +12,9 @@ interface ServerReturnedAlertsData {
readonly payload: Immutable;
}
-export type AlertAction = ServerReturnedAlertsData;
+interface ServerReturnedAlertDetailsData {
+ readonly type: 'serverReturnedAlertDetailsData';
+ readonly payload: Immutable;
+}
+
+export type AlertAction = ServerReturnedAlertsData | ServerReturnedAlertDetailsData;
diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/store/alerts/alert_details.test.ts b/x-pack/plugins/endpoint/public/applications/endpoint/store/alerts/alert_details.test.ts
new file mode 100644
index 0000000000000..4edc31831eb14
--- /dev/null
+++ b/x-pack/plugins/endpoint/public/applications/endpoint/store/alerts/alert_details.test.ts
@@ -0,0 +1,65 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { Store, createStore, applyMiddleware } from 'redux';
+import { History } from 'history';
+import { alertListReducer } from './reducer';
+import { AlertListState } from '../../types';
+import { alertMiddlewareFactory } from './middleware';
+import { AppAction } from '../action';
+import { coreMock } from 'src/core/public/mocks';
+import { createBrowserHistory } from 'history';
+
+describe('alert details tests', () => {
+ let store: Store;
+ let coreStart: ReturnType;
+ let history: History;
+ /**
+ * A function that waits until a selector returns true.
+ */
+ let selectorIsTrue: (selector: (state: AlertListState) => boolean) => Promise;
+ beforeEach(() => {
+ coreStart = coreMock.createStart();
+ history = createBrowserHistory();
+ const middleware = alertMiddlewareFactory(coreStart);
+ store = createStore(alertListReducer, applyMiddleware(middleware));
+
+ selectorIsTrue = async selector => {
+ // If the selector returns true, we're done
+ while (selector(store.getState()) !== true) {
+ // otherwise, wait til the next state change occurs
+ await new Promise(resolve => {
+ const unsubscribe = store.subscribe(() => {
+ unsubscribe();
+ resolve();
+ });
+ });
+ }
+ };
+ });
+ describe('when the user is on the alert list page with a selected alert in the url', () => {
+ beforeEach(() => {
+ const firstResponse: Promise = Promise.resolve(1);
+ const secondResponse: Promise = Promise.resolve(2);
+ coreStart.http.get.mockReturnValueOnce(firstResponse).mockReturnValueOnce(secondResponse);
+
+ // Simulates user navigating to the /alerts page
+ store.dispatch({
+ type: 'userChangedUrl',
+ payload: {
+ ...history.location,
+ pathname: '/alerts',
+ search: '?selected_alert=q9ncfh4q9ctrmc90umcq4',
+ },
+ });
+ });
+
+ it('should return alert details data', async () => {
+ // wait for alertDetails to be defined
+ await selectorIsTrue(state => state.alertDetails !== undefined);
+ });
+ });
+});
diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/store/alerts/middleware.ts b/x-pack/plugins/endpoint/public/applications/endpoint/store/alerts/middleware.ts
index 76a6867418bd8..2cb381e901b4e 100644
--- a/x-pack/plugins/endpoint/public/applications/endpoint/store/alerts/middleware.ts
+++ b/x-pack/plugins/endpoint/public/applications/endpoint/store/alerts/middleware.ts
@@ -4,10 +4,10 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { AlertResultList } from '../../../../../common/types';
+import { AlertResultList, AlertData } from '../../../../../common/types';
import { AppAction } from '../action';
import { MiddlewareFactory, AlertListState } from '../../types';
-import { isOnAlertPage, apiQueryParams } from './selectors';
+import { isOnAlertPage, apiQueryParams, hasSelectedAlert, uiQueryParams } from './selectors';
export const alertMiddlewareFactory: MiddlewareFactory = coreStart => {
return api => next => async (action: AppAction) => {
@@ -19,5 +19,12 @@ export const alertMiddlewareFactory: MiddlewareFactory = coreSta
});
api.dispatch({ type: 'serverReturnedAlertsData', payload: response });
}
+ if (action.type === 'userChangedUrl' && isOnAlertPage(state) && hasSelectedAlert(state)) {
+ const uiParams = uiQueryParams(state);
+ const response: AlertData = await coreStart.http.get(
+ `/api/endpoint/alerts/${uiParams.selected_alert}`
+ );
+ api.dispatch({ type: 'serverReturnedAlertDetailsData', payload: response });
+ }
};
};
diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/store/alerts/mock_alert_result_list.ts b/x-pack/plugins/endpoint/public/applications/endpoint/store/alerts/mock_alert_result_list.ts
index 8eadb3e7fb3df..7db94fc9d4266 100644
--- a/x-pack/plugins/endpoint/public/applications/endpoint/store/alerts/mock_alert_result_list.ts
+++ b/x-pack/plugins/endpoint/public/applications/endpoint/store/alerts/mock_alert_result_list.ts
@@ -32,29 +32,152 @@ export const mockAlertResultList: (options?: {
id: 'ced9c68e-b94a-4d66-bb4c-6106514f0a2f',
version: '3.0.0',
},
- event: {
- id: '2f1c0928-3876-4e11-acbb-9199257c7b1c',
- action: 'open',
- },
- file_classification: {
- malware_classification: {
- score: 3,
- },
- },
- process: {
- pid: 107,
- unique_pid: 1,
- },
host: {
+ id: 'xrctvybuni',
hostname: 'HD-c15-bc09190a',
- ip: '10.179.244.14',
+ ip: ['10.179.244.14'],
+ mac: ['xsertcyvbunimkn56edtyf'],
os: {
- name: 'Windows',
+ full: 'Windows 10',
+ name: 'windows',
+ version: '10',
+ variant: '3',
},
},
thread: {},
prev: null,
next: null,
+ event: {
+ id: '2f1c0928-3876-4e11-acbb-9199257c7b1c',
+ action: 'creation',
+ category: 'malware',
+ dataset: 'endpoint',
+ kind: 'alert',
+ module: 'endpoint',
+ type: 'creation',
+ },
+ file: {
+ accessed: 1542789400,
+ created: 1542789400,
+ hash: {
+ md5: '4ace3baaa509d08510405e1b169e325b',
+ sha1: '27fb21cf5db95ffca43b234affa99becc4023b9d',
+ sha256: '6ed1c836dbf099be7845bdab7671def2c157643761b52251e04e9b6ee109ec75',
+ },
+ pe: {
+ imphash: '835d619dfdf3cc727cebd91300ab3462',
+ },
+ mtime: 1542789400,
+ owner: 'Administrators',
+ name: 'test name',
+ path: 'C:\\Windows\\TEMP\\tmp0000008f\\tmp00001be5',
+ size: 188416,
+ code_signature: {
+ subject_name: 'Cybereason Inc',
+ trusted: false,
+ },
+ malware_classifier: {
+ features: {
+ data: {
+ buffer:
+ 'eAHtnU1oHHUUwHsQ7MGDiIIUD4sH8WBBxJtopiLoUY0pYo2ZTbJJ0yQ17m4+ms/NRzeVWpuUWCL4sWlEYvFQ8KJQ6NCTEA8eRD30sIo3PdSriLi7837Pko3LbHZ2M5m+XObHm/d/X////83O7jCZvzacHBpPplNdfalkdjSdyty674Ft59dN71Dpb9v5eKh8LMEHjsCF2wIfVlRKsHROYPGkQO5+gY2vBSYYdWZFYGwEO/cITHMqkxPYnBBY+07gtCuQ9gSGigJ5lPPYGXcE+jA4z3Ad1ZtAUiDUyrEEPYzqRnIKgxd/Rgc7gygPo5wn95PouN7OeEYJ1UXiJgRmvscgp/LOziIkkSyT+xRVnXhZ4DKh5goCkzidRHkGO4uvCyw9LDDtCay8ILCAzrJOJaGuZwUuvSewivJVIPsklq8JbL4qMJsTSCcExrGs83WKU295ZFo5lr2TaZbcUw5FeJy8tgTeLpCy2iGeS67ABXzlgbEi1UC5FxcZnA4y/CLK82Qxi847FGGZRTLsCUxR1aWEwOp1AmOjDRYYzgwusL9WfqBiGJxnVAanixTq7Dp22LBdlWMJzlOx8wmBK2Rx5WmBLJIRwtAijOQE+ooCb2B5xBOYRtlfNeXpLpA7oyZRTqHzGenkmIJPnhBIMrzTwSA6H93CO5l+c1NA99f6IwLH8fUKdjTmDpTbgS50+gGVnECnE4PpooC2guPoaPADSHrcncNHmEHtAFkq3+EI+A37zsrrTvH3WTkvJLoOTyBp10wx2JcgVCRahA4NrICE4a+hrMXsA3qAHItW188E8ejO7XV3eh/KCYwxlamEwCgL8lN2wTntfrhY/U0g/5KAdvUpT+AszWqBdqH7VLeeZrExK9Cv1UgIDKA8g/cx7QAEP+AhAfRaMKB2HOJh+BSFSqKjSytNGBlc6PrpxvK7lCVDxbSG3Z7AhCMwx6gelwgLAltXBXJUTH29j+U1LHdipx/QprfKfGnF0sBpdBYxmEQyTzW0h6/0khcuhhJYRufym+i4VKMocJMs/KvfoW3/UJb4PeZOSZVONThZz4djP/75TAXa/CVfOvX3RgVLIDreLPN1pP1osW7lGmHsEhjBOzf+EPBE4vndvWz5xb/cChxGcv1LAb+tluALKnZ47isf1MXvz1ZMlsCXbXtPceqhrcp1ps6YHwQeBXLEPCf7q23tl9uJui0bGBgYRAccv7uXr/g5Af+2oNTrpgTa/vnpjBvpLAwM4gRBPvIZGBgYGBgYGBgYGBgYGBgYGBgYGBgYNAOc9oMXs4GBgYFBcNBnww5QzDXgRtPSaZ5lg/itsRaslgZ3bnWEEVnhMetIBwiiVnlbCbWrEftrt11zdwWnseFW1QO63w1is3ptD1pV9xG0t+zvfUrzrvh380qwXWAVCw6h78GIfG7ZlzltXu6hd+y92fECRFhjuH3bXG8N43oXEHperdzvUbteaDxhVTUeq25fqhG1X6Ai8mtF6BDXz2wR+dzSgg4Qsxls5T11XMG+82y8GkG+b7kL69xg7mF1SFvhBgYGsYH/Xi7HE+PVkiB2jt1bNZxT+k4558jR53ydz5//1m1KOgYGBgYGBgYGEQfnsYaG2z1sdPJS79XQSu91ndobOAHCaN5vNzUk1bceQVzUpbw3iOuT+UFmR18bHrp3gyhDC56lCd1y85w2+HSNUwVhhdGC7blLf+bV/fqtvhMg1NDjCcugB1QXswbs8ekj/v1BgzFHBIIsyP+HfwFdMpzu',
+ decompressed_size: 27831,
+ encoding: 'zlib',
+ },
+ },
+ identifier: 'endpointpe',
+ score: 1,
+ threshold: 0.66,
+ version: '3.0.33',
+ },
+ temp_file_path: 'C:\\Windows\\TEMP\\1bb9abfc-ca14-47b2-9f2c-10c323df42f9',
+ },
+ process: {
+ pid: 1076,
+ ppid: 432,
+ entity_id: 'wertqwer',
+ parent: {
+ pid: 432,
+ entity_id: 'adsfsdaf',
+ },
+ name: 'test name',
+ code_signature: {
+ subject_name: 'Cybereason Inc',
+ trusted: true,
+ },
+ command_line: '"C:\\Program Files\\Cybereason ActiveProbe\\AmSvc.exe"',
+ domain: 'NT AUTHORITY',
+ executable: 'C:\\Program Files\\Cybereason ActiveProbe\\AmSvc.exe',
+ hash: {
+ md5: '1f2d082566b0fc5f2c238a5180db7451',
+ sha1: 'ca85243c0af6a6471bdaa560685c51eefd6dbc0d',
+ sha256: '8ad40c90a611d36eb8f9eb24fa04f7dbca713db383ff55a03aa0f382e92061a2',
+ },
+ pe: {
+ imphash: 'c30d230b81c734e82e86e2e2fe01cd01',
+ },
+ malware_classifier: {
+ identifier: 'Whitelisted',
+ score: 0,
+ threshold: 0,
+ version: '3.0.0',
+ },
+ thread: [
+ {
+ id: 1652,
+ service_name: 'CybereasonAntiMalware',
+ start: 1542788400,
+ start_address: 8791698721056,
+ start_address_module: 'C:\\Program Files\\Cybereason ActiveProbe\\gzfltum.dll',
+ },
+ ],
+ sid: 'S-1-5-18',
+ start: 1542788400,
+ token: {
+ domain: 'NT AUTHORITY',
+ integrity_level: 16384,
+ integrity_level_name: 'system',
+ privileges: [
+ {
+ description: 'Replace a process level token',
+ enabled: false,
+ name: 'SeAssignPrimaryTokenPrivilege',
+ },
+ ],
+ sid: 'S-1-5-18',
+ type: 'tokenPrimary',
+ user: 'SYSTEM',
+ },
+ uptime: 1025,
+ user: 'SYSTEM',
+ },
+ dll: [
+ {
+ pe: {
+ architecture: 'x64',
+ imphash: 'c30d230b81c734e82e86e2e2fe01cd01',
+ },
+ code_signature: {
+ subject_name: 'Cybereason Inc',
+ trusted: true,
+ },
+ compile_time: 1534424710,
+ hash: {
+ md5: '1f2d082566b0fc5f2c238a5180db7451',
+ sha1: 'ca85243c0af6a6471bdaa560685c51eefd6dbc0d',
+ sha256: '8ad40c90a611d36eb8f9eb24fa04f7dbca713db383ff55a03aa0f382e92061a2',
+ },
+ malware_classifier: {
+ identifier: 'Whitelisted',
+ score: 0,
+ threshold: 0,
+ version: '3.0.0',
+ },
+ mapped_address: 5362483200,
+ mapped_size: 0,
+ path: 'C:\\Program Files\\Cybereason ActiveProbe\\AmSvc.exe',
+ },
+ ],
});
}
const mock: AlertResultList = {
diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/store/alerts/reducer.ts b/x-pack/plugins/endpoint/public/applications/endpoint/store/alerts/reducer.ts
index 77d7397d72581..ee172fa80f1fe 100644
--- a/x-pack/plugins/endpoint/public/applications/endpoint/store/alerts/reducer.ts
+++ b/x-pack/plugins/endpoint/public/applications/endpoint/store/alerts/reducer.ts
@@ -11,6 +11,7 @@ import { AppAction } from '../action';
const initialState = (): AlertListState => {
return {
alerts: [],
+ alertDetails: undefined,
pageSize: 10,
pageIndex: 0,
total: 0,
@@ -43,6 +44,11 @@ export const alertListReducer: Reducer = (
...state,
location: action.payload,
};
+ } else if (action.type === 'serverReturnedAlertDetailsData') {
+ return {
+ ...state,
+ alertDetails: action.payload,
+ };
}
return state;
diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/store/alerts/selectors.ts b/x-pack/plugins/endpoint/public/applications/endpoint/store/alerts/selectors.ts
index f217e3cda9191..7ce7c2d08691e 100644
--- a/x-pack/plugins/endpoint/public/applications/endpoint/store/alerts/selectors.ts
+++ b/x-pack/plugins/endpoint/public/applications/endpoint/store/alerts/selectors.ts
@@ -15,7 +15,7 @@ import {
AlertsAPIQueryParams,
CreateStructuredSelector,
} from '../../types';
-import { Immutable, LegacyEndpointEvent } from '../../../../../common/types';
+import { Immutable } from '../../../../../common/types';
const createStructuredSelector: CreateStructuredSelector = createStructuredSelectorWithBadType;
/**
@@ -23,6 +23,8 @@ const createStructuredSelector: CreateStructuredSelector = createStructuredSelec
*/
export const alertListData = (state: AlertListState) => state.alerts;
+export const selectedAlertDetailsData = (state: AlertListState) => state.alertDetails;
+
/**
* Returns the alert list pagination data from state
*/
@@ -96,20 +98,11 @@ export const hasSelectedAlert: (state: AlertListState) => boolean = createSelect
/**
* Determine if the alert event is most likely compatible with LegacyEndpointEvent.
*/
-function isAlertEventLegacyEndpointEvent(event: { endgame?: {} }): event is LegacyEndpointEvent {
- return event.endgame !== undefined && 'unique_pid' in event.endgame;
-}
-
-export const selectedEvent: (
+export const selectedAlertIsLegacyEndpointEvent: (
state: AlertListState
-) => LegacyEndpointEvent | undefined = createSelector(
- uiQueryParams,
- alertListData,
- ({ selected_alert: selectedAlert }, alertList) => {
- const found = alertList.find(alert => alert.event.id === selectedAlert);
- if (!found) {
- return found;
- }
- return isAlertEventLegacyEndpointEvent(found) ? found : undefined;
+) => boolean = createSelector(selectedAlertDetailsData, function(event) {
+ if (event === undefined) {
+ return false;
}
-);
+ return 'endgame' in event;
+});
diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/types.ts b/x-pack/plugins/endpoint/public/applications/endpoint/types.ts
index 6498462a8fc06..b46785d3190e5 100644
--- a/x-pack/plugins/endpoint/public/applications/endpoint/types.ts
+++ b/x-pack/plugins/endpoint/public/applications/endpoint/types.ts
@@ -93,19 +93,22 @@ export type AlertListData = AlertResultList;
export interface AlertListState {
/** Array of alert items. */
- alerts: ImmutableArray;
+ readonly alerts: ImmutableArray;
/** The total number of alerts on the page. */
- total: number;
+ readonly total: number;
/** Number of alerts per page. */
- pageSize: number;
+ readonly pageSize: number;
/** Page number, starting at 0. */
- pageIndex: number;
+ readonly pageIndex: number;
/** Current location object from React Router history. */
readonly location?: Immutable;
+
+ /** Specific Alert data to be shown in the details view */
+ readonly alertDetails?: Immutable;
}
/**
diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/view/alerts/details/index.ts b/x-pack/plugins/endpoint/public/applications/endpoint/view/alerts/details/index.ts
new file mode 100644
index 0000000000000..1c78309474737
--- /dev/null
+++ b/x-pack/plugins/endpoint/public/applications/endpoint/view/alerts/details/index.ts
@@ -0,0 +1,7 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export { AlertDetailsOverview } from './overview';
diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/view/alerts/details/metadata/file_accordion.tsx b/x-pack/plugins/endpoint/public/applications/endpoint/view/alerts/details/metadata/file_accordion.tsx
new file mode 100644
index 0000000000000..ac67e54f38779
--- /dev/null
+++ b/x-pack/plugins/endpoint/public/applications/endpoint/view/alerts/details/metadata/file_accordion.tsx
@@ -0,0 +1,80 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+import React, { memo, useMemo } from 'react';
+import { i18n } from '@kbn/i18n';
+import { EuiAccordion, EuiDescriptionList } from '@elastic/eui';
+import { Immutable, AlertData } from '../../../../../../../common/types';
+import { FormattedDate } from '../../formatted_date';
+
+export const FileAccordion = memo(({ alertData }: { alertData: Immutable }) => {
+ const columns = useMemo(() => {
+ return [
+ {
+ title: i18n.translate('xpack.endpoint.application.endpoint.alertDetails.fileName', {
+ defaultMessage: 'File Name',
+ }),
+ description: alertData.file.name,
+ },
+ {
+ title: i18n.translate('xpack.endpoint.application.endpoint.alertDetails.filePath', {
+ defaultMessage: 'File Path',
+ }),
+ description: alertData.file.path,
+ },
+ {
+ title: i18n.translate('xpack.endpoint.application.endpoint.alertDetails.fileSize', {
+ defaultMessage: 'File Size',
+ }),
+ description: alertData.file.size,
+ },
+ {
+ title: i18n.translate('xpack.endpoint.application.endpoint.alertDetails.fileCreated', {
+ defaultMessage: 'File Created',
+ }),
+ description: ,
+ },
+ {
+ title: i18n.translate('xpack.endpoint.application.endpoint.alertDetails.fileModified', {
+ defaultMessage: 'File Modified',
+ }),
+ description: ,
+ },
+ {
+ title: i18n.translate('xpack.endpoint.application.endpoint.alertDetails.fileAccessed', {
+ defaultMessage: 'File Accessed',
+ }),
+ description: ,
+ },
+ {
+ title: i18n.translate('xpack.endpoint.application.endpoint.alertDetails.signer', {
+ defaultMessage: 'Signer',
+ }),
+ description: alertData.file.code_signature.subject_name,
+ },
+ {
+ title: i18n.translate('xpack.endpoint.application.endpoint.alertDetails.owner', {
+ defaultMessage: 'Owner',
+ }),
+ description: alertData.file.owner,
+ },
+ ];
+ }, [alertData]);
+
+ return (
+
+
+
+ );
+});
diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/view/alerts/details/metadata/general_accordion.tsx b/x-pack/plugins/endpoint/public/applications/endpoint/view/alerts/details/metadata/general_accordion.tsx
new file mode 100644
index 0000000000000..070c78c968585
--- /dev/null
+++ b/x-pack/plugins/endpoint/public/applications/endpoint/view/alerts/details/metadata/general_accordion.tsx
@@ -0,0 +1,68 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+import React, { memo, useMemo } from 'react';
+import { i18n } from '@kbn/i18n';
+import { EuiAccordion, EuiDescriptionList } from '@elastic/eui';
+import { Immutable, AlertData } from '../../../../../../../common/types';
+import { FormattedDate } from '../../formatted_date';
+
+export const GeneralAccordion = memo(({ alertData }: { alertData: Immutable }) => {
+ const columns = useMemo(() => {
+ return [
+ {
+ title: i18n.translate('xpack.endpoint.application.endpoint.alertDetails.alertType', {
+ defaultMessage: 'Alert Type',
+ }),
+ description: alertData.event.category,
+ },
+ {
+ title: i18n.translate('xpack.endpoint.application.endpoint.alertDetails.eventType', {
+ defaultMessage: 'Event Type',
+ }),
+ description: alertData.event.kind,
+ },
+ {
+ title: i18n.translate('xpack.endpoint.application.endpoint.alertDetails.status', {
+ defaultMessage: 'Status',
+ }),
+ description: 'TODO',
+ },
+ {
+ title: i18n.translate('xpack.endpoint.application.endpoint.alertDetails.dateCreated', {
+ defaultMessage: 'Date Created',
+ }),
+ description: ,
+ },
+ {
+ title: i18n.translate('xpack.endpoint.application.endpoint.alertDetails.malwareScore', {
+ defaultMessage: 'MalwareScore',
+ }),
+ description: alertData.file.malware_classifier.score,
+ },
+ {
+ title: i18n.translate('xpack.endpoint.application.endpoint.alertDetails.fileName', {
+ defaultMessage: 'File Name',
+ }),
+ description: alertData.file.name,
+ },
+ ];
+ }, [alertData]);
+ return (
+
+
+
+ );
+});
diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/view/alerts/details/metadata/hash_accordion.tsx b/x-pack/plugins/endpoint/public/applications/endpoint/view/alerts/details/metadata/hash_accordion.tsx
new file mode 100644
index 0000000000000..b2be083ce8f59
--- /dev/null
+++ b/x-pack/plugins/endpoint/public/applications/endpoint/view/alerts/details/metadata/hash_accordion.tsx
@@ -0,0 +1,49 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+import React, { memo, useMemo } from 'react';
+import { i18n } from '@kbn/i18n';
+import { EuiAccordion, EuiDescriptionList } from '@elastic/eui';
+import { Immutable, AlertData } from '../../../../../../../common/types';
+
+export const HashAccordion = memo(({ alertData }: { alertData: Immutable }) => {
+ const columns = useMemo(() => {
+ return [
+ {
+ title: i18n.translate('xpack.endpoint.application.endpoint.alertDetails.md5', {
+ defaultMessage: 'MD5',
+ }),
+ description: alertData.file.hash.md5,
+ },
+ {
+ title: i18n.translate('xpack.endpoint.application.endpoint.alertDetails.sha1', {
+ defaultMessage: 'SHA1',
+ }),
+ description: alertData.file.hash.sha1,
+ },
+ {
+ title: i18n.translate('xpack.endpoint.application.endpoint.alertDetails.sha256', {
+ defaultMessage: 'SHA256',
+ }),
+ description: alertData.file.hash.sha256,
+ },
+ ];
+ }, [alertData]);
+
+ return (
+
+
+
+ );
+});
diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/view/alerts/details/metadata/host_accordion.tsx b/x-pack/plugins/endpoint/public/applications/endpoint/view/alerts/details/metadata/host_accordion.tsx
new file mode 100644
index 0000000000000..4108781f0a79b
--- /dev/null
+++ b/x-pack/plugins/endpoint/public/applications/endpoint/view/alerts/details/metadata/host_accordion.tsx
@@ -0,0 +1,55 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+import React, { memo, useMemo } from 'react';
+import { i18n } from '@kbn/i18n';
+import { EuiAccordion, EuiDescriptionList } from '@elastic/eui';
+import { Immutable, AlertData } from '../../../../../../../common/types';
+
+export const HostAccordion = memo(({ alertData }: { alertData: Immutable }) => {
+ const columns = useMemo(() => {
+ return [
+ {
+ title: i18n.translate('xpack.endpoint.application.endpoint.alertDetails.hostName', {
+ defaultMessage: 'Host Name',
+ }),
+ description: alertData.host.hostname,
+ },
+ {
+ title: i18n.translate('xpack.endpoint.application.endpoint.alertDetails.hostIP', {
+ defaultMessage: 'Host IP',
+ }),
+ description: alertData.host.ip.join(', '),
+ },
+ {
+ title: i18n.translate('xpack.endpoint.application.endpoint.alertDetails.status', {
+ defaultMessage: 'Status',
+ }),
+ description: 'TODO',
+ },
+ {
+ title: i18n.translate('xpack.endpoint.application.endpoint.alertDetails.os', {
+ defaultMessage: 'OS',
+ }),
+ description: alertData.host.os.name,
+ },
+ ];
+ }, [alertData]);
+
+ return (
+
+
+
+ );
+});
diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/view/alerts/details/metadata/index.ts b/x-pack/plugins/endpoint/public/applications/endpoint/view/alerts/details/metadata/index.ts
new file mode 100644
index 0000000000000..1eb755242d701
--- /dev/null
+++ b/x-pack/plugins/endpoint/public/applications/endpoint/view/alerts/details/metadata/index.ts
@@ -0,0 +1,12 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export { GeneralAccordion } from './general_accordion';
+export { HostAccordion } from './host_accordion';
+export { HashAccordion } from './hash_accordion';
+export { FileAccordion } from './file_accordion';
+export { SourceProcessAccordion } from './source_process_accordion';
+export { SourceProcessTokenAccordion } from './source_process_token_accordion';
diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/view/alerts/details/metadata/source_process_accordion.tsx b/x-pack/plugins/endpoint/public/applications/endpoint/view/alerts/details/metadata/source_process_accordion.tsx
new file mode 100644
index 0000000000000..4c961ad4b4964
--- /dev/null
+++ b/x-pack/plugins/endpoint/public/applications/endpoint/view/alerts/details/metadata/source_process_accordion.tsx
@@ -0,0 +1,97 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+import React, { memo, useMemo } from 'react';
+import { i18n } from '@kbn/i18n';
+import { EuiAccordion, EuiDescriptionList } from '@elastic/eui';
+import { Immutable, AlertData } from '../../../../../../../common/types';
+
+export const SourceProcessAccordion = memo(({ alertData }: { alertData: Immutable }) => {
+ const columns = useMemo(() => {
+ return [
+ {
+ title: i18n.translate('xpack.endpoint.application.endpoint.alertDetails.processID', {
+ defaultMessage: 'Process ID',
+ }),
+ description: alertData.process.pid,
+ },
+ {
+ title: i18n.translate('xpack.endpoint.application.endpoint.alertDetails.processName', {
+ defaultMessage: 'Process Name',
+ }),
+ description: alertData.process.name,
+ },
+ {
+ title: i18n.translate('xpack.endpoint.application.endpoint.alertDetails.processPath', {
+ defaultMessage: 'Process Path',
+ }),
+ description: alertData.process.executable,
+ },
+ {
+ title: i18n.translate('xpack.endpoint.application.endpoint.alertDetails.md5', {
+ defaultMessage: 'MD5',
+ }),
+ description: alertData.process.hash.md5,
+ },
+ {
+ title: i18n.translate('xpack.endpoint.application.endpoint.alertDetails.sha1', {
+ defaultMessage: 'SHA1',
+ }),
+ description: alertData.process.hash.sha1,
+ },
+ {
+ title: i18n.translate('xpack.endpoint.application.endpoint.alertDetails.sha256', {
+ defaultMessage: 'SHA256',
+ }),
+ description: alertData.process.hash.sha256,
+ },
+ {
+ title: i18n.translate('xpack.endpoint.application.endpoint.alertDetails.malwareScore', {
+ defaultMessage: 'MalwareScore',
+ }),
+ description: alertData.process.malware_classifier.score,
+ },
+ {
+ title: i18n.translate('xpack.endpoint.application.endpoint.alertDetails.parentProcessID', {
+ defaultMessage: 'Parent Process ID',
+ }),
+ description: alertData.process.parent.pid,
+ },
+ {
+ title: i18n.translate('xpack.endpoint.application.endpoint.alertDetails.signer', {
+ defaultMessage: 'Signer',
+ }),
+ description: alertData.process.code_signature.subject_name,
+ },
+ {
+ title: i18n.translate('xpack.endpoint.application.endpoint.alertDetails.username', {
+ defaultMessage: 'Username',
+ }),
+ description: alertData.process.token.user,
+ },
+ {
+ title: i18n.translate('xpack.endpoint.application.endpoint.alertDetails.domain', {
+ defaultMessage: 'Domain',
+ }),
+ description: alertData.process.token.domain,
+ },
+ ];
+ }, [alertData]);
+
+ return (
+
+
+
+ );
+});
diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/view/alerts/details/metadata/source_process_token_accordion.tsx b/x-pack/plugins/endpoint/public/applications/endpoint/view/alerts/details/metadata/source_process_token_accordion.tsx
new file mode 100644
index 0000000000000..7d75d4478afb3
--- /dev/null
+++ b/x-pack/plugins/endpoint/public/applications/endpoint/view/alerts/details/metadata/source_process_token_accordion.tsx
@@ -0,0 +1,45 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+import React, { memo, useMemo } from 'react';
+import { i18n } from '@kbn/i18n';
+import { EuiAccordion, EuiDescriptionList } from '@elastic/eui';
+import { Immutable, AlertData } from '../../../../../../../common/types';
+
+export const SourceProcessTokenAccordion = memo(
+ ({ alertData }: { alertData: Immutable }) => {
+ const columns = useMemo(() => {
+ return [
+ {
+ title: i18n.translate('xpack.endpoint.application.endpoint.alertDetails.sid', {
+ defaultMessage: 'SID',
+ }),
+ description: alertData.process.token.sid,
+ },
+ {
+ title: i18n.translate('xpack.endpoint.application.endpoint.alertDetails.integrityLevel', {
+ defaultMessage: 'Integrity Level',
+ }),
+ description: alertData.process.token.integrity_level,
+ },
+ ];
+ }, [alertData]);
+
+ return (
+
+
+
+ );
+ }
+);
diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/view/alerts/details/overview/index.tsx b/x-pack/plugins/endpoint/public/applications/endpoint/view/alerts/details/overview/index.tsx
new file mode 100644
index 0000000000000..080c70ca43bae
--- /dev/null
+++ b/x-pack/plugins/endpoint/public/applications/endpoint/view/alerts/details/overview/index.tsx
@@ -0,0 +1,94 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+import React, { memo, useMemo } from 'react';
+import { i18n } from '@kbn/i18n';
+import { FormattedMessage } from '@kbn/i18n/react';
+import { EuiSpacer, EuiTitle, EuiText, EuiHealth, EuiTabbedContent } from '@elastic/eui';
+import { useAlertListSelector } from '../../hooks/use_alerts_selector';
+import * as selectors from '../../../../store/alerts/selectors';
+import { MetadataPanel } from './metadata_panel';
+import { FormattedDate } from '../../formatted_date';
+import { AlertDetailResolver } from '../../resolver';
+
+export const AlertDetailsOverview = memo(() => {
+ const alertDetailsData = useAlertListSelector(selectors.selectedAlertDetailsData);
+ if (alertDetailsData === undefined) {
+ return null;
+ }
+ const selectedAlertIsLegacyEndpointEvent = useAlertListSelector(
+ selectors.selectedAlertIsLegacyEndpointEvent
+ );
+
+ const tabs = useMemo(() => {
+ return [
+ {
+ id: 'overviewMetadata',
+ name: i18n.translate(
+ 'xpack.endpoint.application.endpoint.alertDetails.overview.tabs.overview',
+ {
+ defaultMessage: 'Overview',
+ }
+ ),
+ content: (
+ <>
+
+
+ >
+ ),
+ },
+ {
+ id: 'overviewResolver',
+ name: i18n.translate(
+ 'xpack.endpoint.application.endpoint.alertDetails.overview.tabs.resolver',
+ {
+ defaultMessage: 'Resolver',
+ }
+ ),
+ content: (
+ <>
+
+ {selectedAlertIsLegacyEndpointEvent && }
+ >
+ ),
+ },
+ ];
+ }, [selectedAlertIsLegacyEndpointEvent]);
+
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+ ,
+ }}
+ />
+
+
+
+
+ Endpoint Status: Online
+
+ Alert Status: Open
+
+
+
+ >
+ );
+});
diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/view/alerts/details/overview/metadata_panel.tsx b/x-pack/plugins/endpoint/public/applications/endpoint/view/alerts/details/overview/metadata_panel.tsx
new file mode 100644
index 0000000000000..556d7bea2e310
--- /dev/null
+++ b/x-pack/plugins/endpoint/public/applications/endpoint/view/alerts/details/overview/metadata_panel.tsx
@@ -0,0 +1,40 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React, { memo } from 'react';
+import { EuiSpacer } from '@elastic/eui';
+import { useAlertListSelector } from '../../hooks/use_alerts_selector';
+import * as selectors from '../../../../store/alerts/selectors';
+import {
+ GeneralAccordion,
+ HostAccordion,
+ HashAccordion,
+ FileAccordion,
+ SourceProcessAccordion,
+ SourceProcessTokenAccordion,
+} from '../metadata';
+
+export const MetadataPanel = memo(() => {
+ const alertDetailsData = useAlertListSelector(selectors.selectedAlertDetailsData);
+ if (alertDetailsData === undefined) {
+ return null;
+ }
+ return (
+
+ );
+});
diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/view/alerts/formatted_date.tsx b/x-pack/plugins/endpoint/public/applications/endpoint/view/alerts/formatted_date.tsx
new file mode 100644
index 0000000000000..731bd31b26cef
--- /dev/null
+++ b/x-pack/plugins/endpoint/public/applications/endpoint/view/alerts/formatted_date.tsx
@@ -0,0 +1,22 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+import React, { memo } from 'react';
+import { FormattedDate as ReactIntlFormattedDate } from '@kbn/i18n/react';
+
+export const FormattedDate = memo(({ timestamp }: { timestamp: number }) => {
+ const date = new Date(timestamp);
+ return (
+
+ );
+});
diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/view/alerts/index.test.tsx b/x-pack/plugins/endpoint/public/applications/endpoint/view/alerts/index.test.tsx
index fe362f21a178e..aae44824c3164 100644
--- a/x-pack/plugins/endpoint/public/applications/endpoint/view/alerts/index.test.tsx
+++ b/x-pack/plugins/endpoint/public/applications/endpoint/view/alerts/index.test.tsx
@@ -140,9 +140,6 @@ describe('when on the alerting page', () => {
it('should show the flyout', async () => {
await render().findByTestId('alertDetailFlyout');
});
- it('should render resolver', async () => {
- await render().findByTestId('alertResolver');
- });
describe('when the user clicks the close button on the flyout', () => {
let renderResult: reactTestingLibrary.RenderResult;
beforeEach(async () => {
diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/view/alerts/index.tsx b/x-pack/plugins/endpoint/public/applications/endpoint/view/alerts/index.tsx
index 3c229484ede4e..5d405f8c6fbae 100644
--- a/x-pack/plugins/endpoint/public/applications/endpoint/view/alerts/index.tsx
+++ b/x-pack/plugins/endpoint/public/applications/endpoint/view/alerts/index.tsx
@@ -17,15 +17,21 @@ import {
EuiFlyoutBody,
EuiTitle,
EuiBadge,
+ EuiLoadingSpinner,
+ EuiPageContentHeader,
+ EuiPageContentHeaderSection,
+ EuiPageContentBody,
+ EuiLink,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
-import { useHistory, Link } from 'react-router-dom';
-import { FormattedDate } from 'react-intl';
+import { useHistory } from 'react-router-dom';
+import { FormattedMessage } from '@kbn/i18n/react';
import { urlFromQueryParams } from './url_from_query_params';
import { AlertData } from '../../../../../common/types';
import * as selectors from '../../store/alerts/selectors';
import { useAlertListSelector } from './hooks/use_alerts_selector';
-import { AlertDetailResolver } from './resolver';
+import { AlertDetailsOverview } from './details';
+import { FormattedDate } from './formatted_date';
export const AlertIndex = memo(() => {
const history = useHistory();
@@ -87,7 +93,6 @@ export const AlertIndex = memo(() => {
const alertListData = useAlertListSelector(selectors.alertListData);
const hasSelectedAlert = useAlertListSelector(selectors.hasSelectedAlert);
const queryParams = useAlertListSelector(selectors.uiQueryParams);
- const selectedEvent = useAlertListSelector(selectors.selectedEvent);
const onChangeItemsPerPage = useCallback(
newPageSize => {
@@ -119,10 +124,10 @@ export const AlertIndex = memo(() => {
history.push(urlFromQueryParams(paramsWithoutSelectedAlert));
}, [history, queryParams]);
- const datesForRows: Map = useMemo(() => {
+ const timestampForRows: Map = useMemo(() => {
return new Map(
alertListData.map(alertData => {
- return [alertData, new Date(alertData['@timestamp'])];
+ return [alertData, alertData['@timestamp']];
})
);
}, [alertListData]);
@@ -136,9 +141,11 @@ export const AlertIndex = memo(() => {
const row = alertListData[rowIndex % pageSize];
if (columnId === 'alert_type') {
return (
-
+ history.push(urlFromQueryParams({ ...queryParams, selected_alert: row.id }))
+ }
>
{i18n.translate(
'xpack.endpoint.application.endpoint.alerts.alertType.maliciousFileDescription',
@@ -146,7 +153,7 @@ export const AlertIndex = memo(() => {
defaultMessage: 'Malicious File',
}
)}
-
+
);
} else if (columnId === 'event_type') {
return row.event.action;
@@ -157,19 +164,9 @@ export const AlertIndex = memo(() => {
} else if (columnId === 'host_name') {
return row.host.hostname;
} else if (columnId === 'timestamp') {
- const date = datesForRows.get(row)!;
- if (date && isFinite(date.getTime())) {
- return (
-
- );
+ const timestamp = timestampForRows.get(row)!;
+ if (timestamp) {
+ return ;
} else {
return (
@@ -185,11 +182,11 @@ export const AlertIndex = memo(() => {
} else if (columnId === 'archived') {
return null;
} else if (columnId === 'malware_score') {
- return row.file_classification.malware_classification.score;
+ return row.file.malware_classifier.score;
}
return null;
};
- }, [alertListData, datesForRows, pageSize, queryParams, total]);
+ }, [total, alertListData, pageSize, history, queryParams, timestampForRows]);
const pagination = useMemo(() => {
return {
@@ -201,6 +198,16 @@ export const AlertIndex = memo(() => {
};
}, [onChangeItemsPerPage, onChangePage, pageIndex, pageSize]);
+ const columnVisibility = useMemo(
+ () => ({
+ visibleColumns,
+ setVisibleColumns,
+ }),
+ [setVisibleColumns, visibleColumns]
+ );
+
+ const selectedAlertData = useAlertListSelector(selectors.selectedAlertDetailsData);
+
return (
<>
{hasSelectedAlert && (
@@ -215,29 +222,37 @@ export const AlertIndex = memo(() => {
-
+ {selectedAlertData ? : }
)}
- ({
- visibleColumns,
- setVisibleColumns,
- }),
- [setVisibleColumns, visibleColumns]
- )}
- renderCellValue={renderCellValue}
- pagination={pagination}
- data-test-subj="alertListGrid"
- data-testid="alertListGrid"
- />
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/view/alerts/resolver.tsx b/x-pack/plugins/endpoint/public/applications/endpoint/view/alerts/resolver.tsx
index c7ef7f73dfe05..ec1dab45d50ab 100644
--- a/x-pack/plugins/endpoint/public/applications/endpoint/view/alerts/resolver.tsx
+++ b/x-pack/plugins/endpoint/public/applications/endpoint/view/alerts/resolver.tsx
@@ -18,6 +18,7 @@ export const AlertDetailResolver = styled(
({ className, selectedEvent }: { className?: string; selectedEvent?: LegacyEndpointEvent }) => {
const context = useKibana();
const { store } = storeFactory(context);
+
return (
diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json
index 21500c4db9c34..a97cf608abc71 100644
--- a/x-pack/plugins/translations/translations/ja-JP.json
+++ b/x-pack/plugins/translations/translations/ja-JP.json
@@ -10986,7 +10986,6 @@
"xpack.siem.editDataProvider.doesNotExistLabel": "存在しません",
"xpack.siem.editDataProvider.existsLabel": "存在する",
"xpack.siem.editDataProvider.fieldLabel": "フィールド",
- "xpack.siem.editDataProvider.fieldPlaceholder": "フィールドを選択",
"xpack.siem.editDataProvider.isLabel": "が",
"xpack.siem.editDataProvider.isNotLabel": "is not",
"xpack.siem.editDataProvider.operatorLabel": "演算子",
diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json
index c9e7ea1ec80de..e6055680e1240 100644
--- a/x-pack/plugins/translations/translations/zh-CN.json
+++ b/x-pack/plugins/translations/translations/zh-CN.json
@@ -10986,7 +10986,6 @@
"xpack.siem.editDataProvider.doesNotExistLabel": "不存在",
"xpack.siem.editDataProvider.existsLabel": "存在",
"xpack.siem.editDataProvider.fieldLabel": "字段",
- "xpack.siem.editDataProvider.fieldPlaceholder": "选择字段",
"xpack.siem.editDataProvider.isLabel": "是",
"xpack.siem.editDataProvider.isNotLabel": "不是",
"xpack.siem.editDataProvider.operatorLabel": "运算符",
diff --git a/yarn.lock b/yarn.lock
index 338d516a796e1..e4d5dcce5bca0 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4864,6 +4864,11 @@
resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e"
integrity sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==
+"@types/normalize-path@^3.0.0":
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/@types/normalize-path/-/normalize-path-3.0.0.tgz#bb5c46cab77b93350b4cf8d7ff1153f47189ae31"
+ integrity sha512-Nd8y/5t/7CRakPYiyPzr/IAfYusy1FkcZYFEAcoMZkwpJv2n4Wm+olW+e7xBdHEXhOnWdG9ddbar0gqZWS4x5Q==
+
"@types/numeral@^0.0.25":
version "0.0.25"
resolved "https://registry.yarnpkg.com/@types/numeral/-/numeral-0.0.25.tgz#b6f55062827a4787fe4ab151cf3412a468e65271"