[SIEM] New Platform Saved Objects Registration (#64029)

* WIP: Register saved objects types in NP

This works, but responsibilities are spread around. Refactor incoming.

* Moves new SO definitions into corresponding folders

This way our top-level file still acts as the index, but these are
more/less unconnected if/when we split these out into separate
applications.

* Replace raw SO updates with our ruleStatusSavedObjectsClient

This mainly consolidates the SO type name and the attributes type to a single
file so that we don't have to import both any time we want to work with
RuleStatus SavedObjects.
This commit is contained in:
Ryland Herrick 2020-04-21 15:33:27 -05:00 committed by GitHub
parent ed912751c1
commit 592a0ff224
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
24 changed files with 464 additions and 529 deletions

View file

@ -8,9 +8,6 @@ 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 } from '../../../plugins/siem/common/constants';
import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/utils';
@ -46,7 +43,6 @@ export const siem = (kibana: any) => {
category: DEFAULT_APP_CATEGORIES.security,
},
],
mappings: savedObjectMappings,
},
config(Joi: Root) {
return Joi.object()

View file

@ -9,10 +9,8 @@ import uuid from 'uuid';
import { IRouter } from '../../../../../../../../src/core/server';
import { DETECTION_ENGINE_RULES_URL } from '../../../../../common/constants';
import { createRules } from '../../rules/create_rules';
import { IRuleSavedAttributesSavedObjectAttributes } from '../../rules/types';
import { readRules } from '../../rules/read_rules';
import { RuleAlertParamsRest } from '../../types';
import { ruleStatusSavedObjectType } from '../../rules/saved_object_mappings';
import { transformValidate } from './validate';
import { getIndexExists } from '../../index/get_index_exists';
import { createRulesSchema } from '../schemas/create_rules_schema';
@ -23,6 +21,7 @@ import {
validateLicenseForRuleType,
} from '../utils';
import { updateRulesNotifications } from '../../rules/update_rules_notifications';
import { ruleStatusSavedObjectsClientFactory } from '../../signals/rule_status_saved_objects_client';
export const createRulesRoute = (router: IRouter): void => {
router.post(
@ -145,10 +144,7 @@ export const createRulesRoute = (router: IRouter): void => {
name,
});
const ruleStatuses = await savedObjectsClient.find<
IRuleSavedAttributesSavedObjectAttributes
>({
type: ruleStatusSavedObjectType,
const ruleStatuses = await ruleStatusSavedObjectsClientFactory(savedObjectsClient).find({
perPage: 1,
sortField: 'statusDate',
sortOrder: 'desc',

View file

@ -11,14 +11,11 @@ import { rulesBulkSchema } from '../schemas/response/rules_bulk_schema';
import { getIdBulkError } from './utils';
import { transformValidateBulkError, validate } from './validate';
import { transformBulkError, buildRouteValidation, buildSiemResponse } from '../utils';
import {
IRuleSavedAttributesSavedObjectAttributes,
DeleteRulesRequestParams,
} from '../../rules/types';
import { DeleteRulesRequestParams } from '../../rules/types';
import { deleteRules } from '../../rules/delete_rules';
import { deleteNotifications } from '../../notifications/delete_notifications';
import { ruleStatusSavedObjectType } from '../../rules/saved_object_mappings';
import { deleteRuleActionsSavedObject } from '../../rule_actions/delete_rule_actions_saved_object';
import { ruleStatusSavedObjectsClientFactory } from '../../signals/rule_status_saved_objects_client';
type Config = RouteConfig<unknown, unknown, DeleteRulesRequestParams, 'delete' | 'post'>;
type Handler = RequestHandler<unknown, unknown, DeleteRulesRequestParams, 'delete' | 'post'>;
@ -44,6 +41,8 @@ export const deleteRulesBulkRoute = (router: IRouter) => {
return siemResponse.error({ statusCode: 404 });
}
const ruleStatusClient = ruleStatusSavedObjectsClientFactory(savedObjectsClient);
const rules = await Promise.all(
request.body.map(async payloadRule => {
const { id, rule_id: ruleId } = payloadRule;
@ -61,17 +60,12 @@ export const deleteRulesBulkRoute = (router: IRouter) => {
ruleAlertId: rule.id,
savedObjectsClient,
});
const ruleStatuses = await savedObjectsClient.find<
IRuleSavedAttributesSavedObjectAttributes
>({
type: ruleStatusSavedObjectType,
const ruleStatuses = await ruleStatusClient.find({
perPage: 6,
search: rule.id,
searchFields: ['alertId'],
});
ruleStatuses.saved_objects.forEach(async obj =>
savedObjectsClient.delete(ruleStatusSavedObjectType, obj.id)
);
ruleStatuses.saved_objects.forEach(async obj => ruleStatusClient.delete(obj.id));
return transformValidateBulkError(idOrRuleIdOrUnknown, rule, undefined, ruleStatuses);
} else {
return getIdBulkError({ id, ruleId });

View file

@ -11,13 +11,10 @@ import { queryRulesSchema } from '../schemas/query_rules_schema';
import { getIdError } from './utils';
import { transformValidate } from './validate';
import { buildRouteValidation, transformError, buildSiemResponse } from '../utils';
import {
DeleteRuleRequestParams,
IRuleSavedAttributesSavedObjectAttributes,
} from '../../rules/types';
import { ruleStatusSavedObjectType } from '../../rules/saved_object_mappings';
import { DeleteRuleRequestParams } from '../../rules/types';
import { deleteNotifications } from '../../notifications/delete_notifications';
import { deleteRuleActionsSavedObject } from '../../rule_actions/delete_rule_actions_saved_object';
import { ruleStatusSavedObjectsClientFactory } from '../../signals/rule_status_saved_objects_client';
export const deleteRulesRoute = (router: IRouter) => {
router.delete(
@ -44,6 +41,7 @@ export const deleteRulesRoute = (router: IRouter) => {
return siemResponse.error({ statusCode: 404 });
}
const ruleStatusClient = ruleStatusSavedObjectsClientFactory(savedObjectsClient);
const rule = await deleteRules({
actionsClient,
alertsClient,
@ -56,17 +54,12 @@ export const deleteRulesRoute = (router: IRouter) => {
ruleAlertId: rule.id,
savedObjectsClient,
});
const ruleStatuses = await savedObjectsClient.find<
IRuleSavedAttributesSavedObjectAttributes
>({
type: ruleStatusSavedObjectType,
const ruleStatuses = await ruleStatusClient.find({
perPage: 6,
search: rule.id,
searchFields: ['alertId'],
});
ruleStatuses.saved_objects.forEach(async obj =>
savedObjectsClient.delete(ruleStatusSavedObjectType, obj.id)
);
ruleStatuses.saved_objects.forEach(async obj => ruleStatusClient.delete(obj.id));
const [validated, errors] = transformValidate(
rule,
undefined,

View file

@ -7,15 +7,12 @@
import { IRouter } from '../../../../../../../../src/core/server';
import { DETECTION_ENGINE_RULES_URL } from '../../../../../common/constants';
import { findRules } from '../../rules/find_rules';
import {
FindRulesRequestParams,
IRuleSavedAttributesSavedObjectAttributes,
} from '../../rules/types';
import { FindRulesRequestParams } from '../../rules/types';
import { findRulesSchema } from '../schemas/find_rules_schema';
import { transformValidateFindAlerts } from './validate';
import { buildRouteValidation, transformError, buildSiemResponse } from '../utils';
import { ruleStatusSavedObjectType } from '../../rules/saved_object_mappings';
import { getRuleActionsSavedObject } from '../../rule_actions/get_rule_actions_saved_object';
import { ruleStatusSavedObjectsClientFactory } from '../../signals/rule_status_saved_objects_client';
export const findRulesRoute = (router: IRouter) => {
router.get(
@ -40,6 +37,7 @@ export const findRulesRoute = (router: IRouter) => {
return siemResponse.error({ statusCode: 404 });
}
const ruleStatusClient = ruleStatusSavedObjectsClientFactory(savedObjectsClient);
const rules = await findRules({
alertsClient,
perPage: query.per_page,
@ -50,10 +48,7 @@ export const findRulesRoute = (router: IRouter) => {
});
const ruleStatuses = await Promise.all(
rules.data.map(async rule => {
const results = await savedObjectsClient.find<
IRuleSavedAttributesSavedObjectAttributes
>({
type: ruleStatusSavedObjectType,
const results = await ruleStatusClient.find({
perPage: 1,
sortField: 'statusDate',
sortOrder: 'desc',

View file

@ -9,17 +9,16 @@ import { DETECTION_ENGINE_RULES_URL } from '../../../../../common/constants';
import { findRulesStatusesSchema } from '../schemas/find_rules_statuses_schema';
import {
FindRulesStatusesRequestParams,
IRuleSavedAttributesSavedObjectAttributes,
RuleStatusResponse,
IRuleStatusAttributes,
} from '../../rules/types';
import { ruleStatusSavedObjectType } from '../../rules/saved_object_mappings';
import {
buildRouteValidation,
transformError,
convertToSnakeCase,
buildSiemResponse,
} from '../utils';
import { ruleStatusSavedObjectsClientFactory } from '../../signals/rule_status_saved_objects_client';
export const findRulesStatusesRoute = (router: IRouter) => {
router.post(
@ -50,12 +49,10 @@ export const findRulesStatusesRoute = (router: IRouter) => {
}
*/
try {
const ruleStatusClient = ruleStatusSavedObjectsClientFactory(savedObjectsClient);
const statuses = await body.ids.reduce<Promise<RuleStatusResponse | {}>>(
async (acc, id) => {
const lastFiveErrorsForId = await savedObjectsClient.find<
IRuleSavedAttributesSavedObjectAttributes
>({
type: ruleStatusSavedObjectType,
const lastFiveErrorsForId = await ruleStatusClient.find({
perPage: 6,
sortField: 'statusDate',
sortOrder: 'desc',

View file

@ -6,10 +6,7 @@
import { IRouter } from '../../../../../../../../src/core/server';
import { DETECTION_ENGINE_RULES_URL } from '../../../../../common/constants';
import {
IRuleSavedAttributesSavedObjectAttributes,
PatchRuleAlertParamsRest,
} from '../../rules/types';
import { PatchRuleAlertParamsRest } from '../../rules/types';
import {
transformBulkError,
buildRouteValidation,
@ -21,8 +18,8 @@ import { transformValidateBulkError, validate } from './validate';
import { patchRulesBulkSchema } from '../schemas/patch_rules_bulk_schema';
import { rulesBulkSchema } from '../schemas/response/rules_bulk_schema';
import { patchRules } from '../../rules/patch_rules';
import { ruleStatusSavedObjectType } from '../../rules/saved_object_mappings';
import { updateRulesNotifications } from '../../rules/update_rules_notifications';
import { ruleStatusSavedObjectsClientFactory } from '../../signals/rule_status_saved_objects_client';
export const patchRulesBulkRoute = (router: IRouter) => {
router.patch(
@ -46,6 +43,7 @@ export const patchRulesBulkRoute = (router: IRouter) => {
return siemResponse.error({ statusCode: 404 });
}
const ruleStatusClient = ruleStatusSavedObjectsClientFactory(savedObjectsClient);
const rules = await Promise.all(
request.body.map(async payloadRule => {
const {
@ -131,10 +129,7 @@ export const patchRulesBulkRoute = (router: IRouter) => {
throttle,
name: rule.name,
});
const ruleStatuses = await savedObjectsClient.find<
IRuleSavedAttributesSavedObjectAttributes
>({
type: ruleStatusSavedObjectType,
const ruleStatuses = await ruleStatusClient.find({
perPage: 1,
sortField: 'statusDate',
sortOrder: 'desc',

View file

@ -7,10 +7,7 @@
import { IRouter } from '../../../../../../../../src/core/server';
import { DETECTION_ENGINE_RULES_URL } from '../../../../../common/constants';
import { patchRules } from '../../rules/patch_rules';
import {
PatchRuleAlertParamsRest,
IRuleSavedAttributesSavedObjectAttributes,
} from '../../rules/types';
import { PatchRuleAlertParamsRest } from '../../rules/types';
import { patchRulesSchema } from '../schemas/patch_rules_schema';
import {
buildRouteValidation,
@ -20,8 +17,8 @@ import {
} from '../utils';
import { getIdError } from './utils';
import { transformValidate } from './validate';
import { ruleStatusSavedObjectType } from '../../rules/saved_object_mappings';
import { updateRulesNotifications } from '../../rules/update_rules_notifications';
import { ruleStatusSavedObjectsClientFactory } from '../../signals/rule_status_saved_objects_client';
export const patchRulesRoute = (router: IRouter) => {
router.patch(
@ -83,6 +80,7 @@ export const patchRulesRoute = (router: IRouter) => {
return siemResponse.error({ statusCode: 404 });
}
const ruleStatusClient = ruleStatusSavedObjectsClientFactory(savedObjectsClient);
const rule = await patchRules({
actionsClient,
alertsClient,
@ -127,10 +125,7 @@ export const patchRulesRoute = (router: IRouter) => {
throttle,
name: rule.name,
});
const ruleStatuses = await savedObjectsClient.find<
IRuleSavedAttributesSavedObjectAttributes
>({
type: ruleStatusSavedObjectType,
const ruleStatuses = await ruleStatusClient.find({
perPage: 1,
sortField: 'statusDate',
sortOrder: 'desc',

View file

@ -11,12 +11,9 @@ import { transformValidate } from './validate';
import { buildRouteValidation, transformError, buildSiemResponse } from '../utils';
import { readRules } from '../../rules/read_rules';
import { queryRulesSchema } from '../schemas/query_rules_schema';
import {
ReadRuleRequestParams,
IRuleSavedAttributesSavedObjectAttributes,
} from '../../rules/types';
import { ruleStatusSavedObjectType } from '../../rules/saved_object_mappings';
import { ReadRuleRequestParams } from '../../rules/types';
import { getRuleActionsSavedObject } from '../../rule_actions/get_rule_actions_saved_object';
import { ruleStatusSavedObjectsClientFactory } from '../../signals/rule_status_saved_objects_client';
export const readRulesRoute = (router: IRouter) => {
router.get(
@ -41,6 +38,7 @@ export const readRulesRoute = (router: IRouter) => {
return siemResponse.error({ statusCode: 404 });
}
const ruleStatusClient = ruleStatusSavedObjectsClientFactory(savedObjectsClient);
const rule = await readRules({
alertsClient,
id,
@ -51,10 +49,7 @@ export const readRulesRoute = (router: IRouter) => {
savedObjectsClient,
ruleAlertId: rule.id,
});
const ruleStatuses = await savedObjectsClient.find<
IRuleSavedAttributesSavedObjectAttributes
>({
type: ruleStatusSavedObjectType,
const ruleStatuses = await ruleStatusClient.find({
perPage: 1,
sortField: 'statusDate',
sortOrder: 'desc',

View file

@ -6,10 +6,7 @@
import { IRouter } from '../../../../../../../../src/core/server';
import { DETECTION_ENGINE_RULES_URL } from '../../../../../common/constants';
import {
IRuleSavedAttributesSavedObjectAttributes,
UpdateRuleAlertParamsRest,
} from '../../rules/types';
import { UpdateRuleAlertParamsRest } from '../../rules/types';
import { getIdBulkError } from './utils';
import { transformValidateBulkError, validate } from './validate';
import {
@ -19,10 +16,10 @@ import {
validateLicenseForRuleType,
} from '../utils';
import { updateRulesBulkSchema } from '../schemas/update_rules_bulk_schema';
import { ruleStatusSavedObjectType } from '../../rules/saved_object_mappings';
import { updateRules } from '../../rules/update_rules';
import { rulesBulkSchema } from '../schemas/response/rules_bulk_schema';
import { updateRulesNotifications } from '../../rules/update_rules_notifications';
import { ruleStatusSavedObjectsClientFactory } from '../../signals/rule_status_saved_objects_client';
export const updateRulesBulkRoute = (router: IRouter) => {
router.put(
@ -47,6 +44,7 @@ export const updateRulesBulkRoute = (router: IRouter) => {
return siemResponse.error({ statusCode: 404 });
}
const ruleStatusClient = ruleStatusSavedObjectsClientFactory(savedObjectsClient);
const rules = await Promise.all(
request.body.map(async payloadRule => {
const {
@ -134,10 +132,7 @@ export const updateRulesBulkRoute = (router: IRouter) => {
throttle,
name,
});
const ruleStatuses = await savedObjectsClient.find<
IRuleSavedAttributesSavedObjectAttributes
>({
type: ruleStatusSavedObjectType,
const ruleStatuses = await ruleStatusClient.find({
perPage: 1,
sortField: 'statusDate',
sortOrder: 'desc',

View file

@ -6,10 +6,7 @@
import { IRouter } from '../../../../../../../../src/core/server';
import { DETECTION_ENGINE_RULES_URL } from '../../../../../common/constants';
import {
UpdateRuleAlertParamsRest,
IRuleSavedAttributesSavedObjectAttributes,
} from '../../rules/types';
import { UpdateRuleAlertParamsRest } from '../../rules/types';
import { updateRulesSchema } from '../schemas/update_rules_schema';
import {
buildRouteValidation,
@ -19,9 +16,9 @@ import {
} from '../utils';
import { getIdError } from './utils';
import { transformValidate } from './validate';
import { ruleStatusSavedObjectType } from '../../rules/saved_object_mappings';
import { updateRules } from '../../rules/update_rules';
import { updateRulesNotifications } from '../../rules/update_rules_notifications';
import { ruleStatusSavedObjectsClientFactory } from '../../signals/rule_status_saved_objects_client';
export const updateRulesRoute = (router: IRouter) => {
router.put(
@ -78,6 +75,7 @@ export const updateRulesRoute = (router: IRouter) => {
const actionsClient = context.actions?.getActionsClient();
const savedObjectsClient = context.core.savedObjects.client;
const siemClient = context.siem?.getSiemClient();
const ruleStatusClient = ruleStatusSavedObjectsClientFactory(savedObjectsClient);
if (!siemClient || !actionsClient || !alertsClient) {
return siemResponse.error({ statusCode: 404 });
@ -131,10 +129,7 @@ export const updateRulesRoute = (router: IRouter) => {
throttle,
name,
});
const ruleStatuses = await savedObjectsClient.find<
IRuleSavedAttributesSavedObjectAttributes
>({
type: ruleStatusSavedObjectType,
const ruleStatuses = await ruleStatusClient.find({
perPage: 1,
sortField: 'statusDate',
sortOrder: 'desc',

View file

@ -4,37 +4,45 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { SavedObjectsType } from '../../../../../../../src/core/server';
export const ruleActionsSavedObjectType = 'siem-detection-engine-rule-actions';
export const ruleActionsSavedObjectMappings = {
[ruleActionsSavedObjectType]: {
properties: {
alertThrottle: {
type: 'keyword',
},
ruleAlertId: {
type: 'keyword',
},
ruleThrottle: {
type: 'keyword',
},
actions: {
properties: {
group: {
type: 'keyword',
},
id: {
type: 'keyword',
},
action_type_id: {
type: 'keyword',
},
params: {
dynamic: true,
properties: {},
},
properties: {
alertThrottle: {
type: 'keyword',
},
ruleAlertId: {
type: 'keyword',
},
ruleThrottle: {
type: 'keyword',
},
actions: {
properties: {
group: {
type: 'keyword',
},
id: {
type: 'keyword',
},
action_type_id: {
type: 'keyword',
},
params: {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
dynamic: true as any,
properties: {},
},
},
},
},
};
export const type: SavedObjectsType = {
name: ruleActionsSavedObjectType,
hidden: false,
namespaceType: 'single',
mappings: ruleActionsSavedObjectMappings,
};

View file

@ -7,10 +7,10 @@
import { defaults } from 'lodash/fp';
import { PartialAlert } from '../../../../../alerting/server';
import { readRules } from './read_rules';
import { PatchRuleParams, IRuleSavedAttributesSavedObjectAttributes } from './types';
import { PatchRuleParams } from './types';
import { addTags } from './add_tags';
import { ruleStatusSavedObjectType } from './saved_object_mappings';
import { calculateVersion, calculateName, calculateInterval } from './utils';
import { ruleStatusSavedObjectsClientFactory } from '../signals/rule_status_saved_objects_client';
export const patchRules = async ({
alertsClient,
@ -134,22 +134,22 @@ export const patchRules = async ({
await alertsClient.disable({ id: rule.id });
} else if (!rule.enabled && enabled === true) {
await alertsClient.enable({ id: rule.id });
const ruleCurrentStatus = savedObjectsClient
? await savedObjectsClient.find<IRuleSavedAttributesSavedObjectAttributes>({
type: ruleStatusSavedObjectType,
perPage: 1,
sortField: 'statusDate',
sortOrder: 'desc',
search: rule.id,
searchFields: ['alertId'],
})
: null;
const ruleStatusClient = ruleStatusSavedObjectsClientFactory(savedObjectsClient);
const ruleCurrentStatus = await ruleStatusClient.find({
perPage: 1,
sortField: 'statusDate',
sortOrder: 'desc',
search: rule.id,
searchFields: ['alertId'],
});
// set current status for this rule to be 'going to run'
if (ruleCurrentStatus && ruleCurrentStatus.saved_objects.length > 0) {
const currentStatusToDisable = ruleCurrentStatus.saved_objects[0];
currentStatusToDisable.attributes.status = 'going to run';
await savedObjectsClient?.update(ruleStatusSavedObjectType, currentStatusToDisable.id, {
await ruleStatusClient.update(currentStatusToDisable.id, {
...currentStatusToDisable.attributes,
status: 'going to run',
});
}
} else {

View file

@ -4,44 +4,51 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { SavedObjectsType } from '../../../../../../../src/core/server';
export const ruleStatusSavedObjectType = 'siem-detection-engine-rule-status';
export const ruleStatusSavedObjectMappings = {
[ruleStatusSavedObjectType]: {
properties: {
alertId: {
type: 'keyword',
},
status: {
type: 'keyword',
},
statusDate: {
type: 'date',
},
lastFailureAt: {
type: 'date',
},
lastSuccessAt: {
type: 'date',
},
lastFailureMessage: {
type: 'text',
},
lastSuccessMessage: {
type: 'text',
},
lastLookBackDate: {
type: 'date',
},
gap: {
type: 'text',
},
bulkCreateTimeDurations: {
type: 'float',
},
searchAfterTimeDurations: {
type: 'float',
},
properties: {
alertId: {
type: 'keyword',
},
status: {
type: 'keyword',
},
statusDate: {
type: 'date',
},
lastFailureAt: {
type: 'date',
},
lastSuccessAt: {
type: 'date',
},
lastFailureMessage: {
type: 'text',
},
lastSuccessMessage: {
type: 'text',
},
lastLookBackDate: {
type: 'date',
},
gap: {
type: 'text',
},
bulkCreateTimeDurations: {
type: 'float',
},
searchAfterTimeDurations: {
type: 'float',
},
},
};
export const type: SavedObjectsType = {
name: ruleStatusSavedObjectType,
hidden: false,
namespaceType: 'single',
mappings: ruleStatusSavedObjectMappings,
};

View file

@ -7,11 +7,11 @@
import { transformRuleToAlertAction } from '../../../../common/detection_engine/transform_actions';
import { PartialAlert } from '../../../../../alerting/server';
import { readRules } from './read_rules';
import { IRuleSavedAttributesSavedObjectAttributes, UpdateRuleParams } from './types';
import { UpdateRuleParams } from './types';
import { addTags } from './add_tags';
import { ruleStatusSavedObjectType } from './saved_object_mappings';
import { calculateVersion } from './utils';
import { hasListsFeature } from '../feature_flags';
import { ruleStatusSavedObjectsClientFactory } from '../signals/rule_status_saved_objects_client';
export const updateRules = async ({
alertsClient,
@ -129,22 +129,22 @@ export const updateRules = async ({
await alertsClient.disable({ id: rule.id });
} else if (!rule.enabled && enabled === true) {
await alertsClient.enable({ id: rule.id });
const ruleCurrentStatus = savedObjectsClient
? await savedObjectsClient.find<IRuleSavedAttributesSavedObjectAttributes>({
type: ruleStatusSavedObjectType,
perPage: 1,
sortField: 'statusDate',
sortOrder: 'desc',
search: rule.id,
searchFields: ['alertId'],
})
: null;
const ruleStatusClient = ruleStatusSavedObjectsClientFactory(savedObjectsClient);
const ruleCurrentStatus = await ruleStatusClient.find({
perPage: 1,
sortField: 'statusDate',
sortOrder: 'desc',
search: rule.id,
searchFields: ['alertId'],
});
// set current status for this rule to be 'going to run'
if (ruleCurrentStatus && ruleCurrentStatus.saved_objects.length > 0) {
const currentStatusToDisable = ruleCurrentStatus.saved_objects[0];
currentStatusToDisable.attributes.status = 'going to run';
await savedObjectsClient?.update(ruleStatusSavedObjectType, currentStatusToDisable.id, {
await ruleStatusClient.update(currentStatusToDisable.id, {
...currentStatusToDisable.attributes,
status: 'going to run',
});
}
}

View file

@ -13,7 +13,7 @@ import {
import { loggingServiceMock } from '../../../../../../../../src/core/server/mocks';
import { RuleTypeParams, OutputRuleAlertRest } from '../../types';
import { IRuleStatusAttributes } from '../../rules/types';
import { ruleStatusSavedObjectType } from '../../../../saved_objects';
import { ruleStatusSavedObjectType } from '../../rules/saved_object_mappings';
export const sampleRuleAlertParams = (
maxSignals?: number | undefined,

View file

@ -25,9 +25,9 @@ import {
import { FrameworkRequest } from '../framework';
import { SavedNote, NoteSavedObjectRuntimeType, NoteSavedObject } from './types';
import { noteSavedObjectType } from './saved_object_mappings';
import { timelineSavedObjectType } from '../../saved_objects';
import { pickSavedTimeline } from '../timeline/pick_saved_timeline';
import { convertSavedObjectToSavedTimeline } from '../timeline/convert_saved_object_to_savedtimeline';
import { timelineSavedObjectType } from '../timeline/saved_object_mappings';
export class Note {
public async deleteNote(request: FrameworkRequest, noteIds: string[]) {

View file

@ -4,37 +4,39 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { ElasticsearchMappingOf } from '../../utils/typed_elasticsearch_mappings';
import { SavedNote } from './types';
import { SavedObjectsType } from '../../../../../../src/core/server';
export const noteSavedObjectType = 'siem-ui-timeline-note';
export const noteSavedObjectMappings: {
[noteSavedObjectType]: ElasticsearchMappingOf<SavedNote>;
} = {
[noteSavedObjectType]: {
properties: {
timelineId: {
type: 'keyword',
},
eventId: {
type: 'keyword',
},
note: {
type: 'text',
},
created: {
type: 'date',
},
createdBy: {
type: 'text',
},
updated: {
type: 'date',
},
updatedBy: {
type: 'text',
},
export const noteSavedObjectMappings = {
properties: {
timelineId: {
type: 'keyword',
},
eventId: {
type: 'keyword',
},
note: {
type: 'text',
},
created: {
type: 'date',
},
createdBy: {
type: 'text',
},
updated: {
type: 'date',
},
updatedBy: {
type: 'text',
},
},
};
export const type: SavedObjectsType = {
name: noteSavedObjectType,
hidden: false,
namespaceType: 'single',
mappings: noteSavedObjectMappings,
};

View file

@ -20,9 +20,10 @@ import {
SavedPinnedEvent,
} from './types';
import { PageInfoNote, SortNote, PinnedEvent as PinnedEventResponse } from '../../graphql/types';
import { pinnedEventSavedObjectType, timelineSavedObjectType } from '../../saved_objects';
import { pickSavedTimeline } from '../timeline/pick_saved_timeline';
import { convertSavedObjectToSavedTimeline } from '../timeline/convert_saved_object_to_savedtimeline';
import { pinnedEventSavedObjectType } from './saved_object_mappings';
import { timelineSavedObjectType } from '../timeline/saved_object_mappings';
export class PinnedEvent {
public async deletePinnedEventOnTimeline(request: FrameworkRequest, pinnedEventIds: string[]) {

View file

@ -4,34 +4,36 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { ElasticsearchMappingOf } from '../../utils/typed_elasticsearch_mappings';
import { SavedPinnedEvent } from './types';
import { SavedObjectsType } from '../../../../../../src/core/server';
export const pinnedEventSavedObjectType = 'siem-ui-timeline-pinned-event';
export const pinnedEventSavedObjectMappings: {
[pinnedEventSavedObjectType]: ElasticsearchMappingOf<SavedPinnedEvent>;
} = {
[pinnedEventSavedObjectType]: {
properties: {
timelineId: {
type: 'keyword',
},
eventId: {
type: 'keyword',
},
created: {
type: 'date',
},
createdBy: {
type: 'text',
},
updated: {
type: 'date',
},
updatedBy: {
type: 'text',
},
export const pinnedEventSavedObjectMappings = {
properties: {
timelineId: {
type: 'keyword',
},
eventId: {
type: 'keyword',
},
created: {
type: 'date',
},
createdBy: {
type: 'text',
},
updated: {
type: 'date',
},
updatedBy: {
type: 'text',
},
},
};
export const type: SavedObjectsType = {
name: pinnedEventSavedObjectType,
hidden: false,
namespaceType: 'single',
mappings: pinnedEventSavedObjectMappings,
};

View file

@ -4,12 +4,6 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { set as _set } from 'lodash/fp';
import {
noteSavedObjectType,
pinnedEventSavedObjectType,
timelineSavedObjectType,
} from '../../../../saved_objects';
import { NoteSavedObject } from '../../../note/types';
import { PinnedEventSavedObject } from '../../../pinned_event/types';
import { convertSavedObjectToSavedTimeline } from '../../convert_saved_object_to_savedtimeline';
@ -30,6 +24,9 @@ import {
TimelineSavedObject,
} from '../../types';
import { transformDataToNdjson } from '../../../../utils/read_stream/create_stream_from_ndjson';
import { pinnedEventSavedObjectType } from '../../../pinned_event/saved_object_mappings';
import { noteSavedObjectType } from '../../../note/saved_object_mappings';
import { timelineSavedObjectType } from '../../saved_object_mappings';
export type TimelineSavedObjectsClient = Pick<
SavedObjectsClient,

View file

@ -4,272 +4,274 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { ElasticsearchMappingOf } from '../../utils/typed_elasticsearch_mappings';
import { SavedTimeline } from './types';
import { SavedObjectsType } from '../../../../../../src/core/server';
export const timelineSavedObjectType = 'siem-ui-timeline';
export const timelineSavedObjectMappings: {
[timelineSavedObjectType]: ElasticsearchMappingOf<SavedTimeline>;
} = {
[timelineSavedObjectType]: {
properties: {
columns: {
properties: {
aggregatable: {
type: 'boolean',
},
category: {
type: 'keyword',
},
columnHeaderType: {
type: 'keyword',
},
description: {
type: 'text',
},
example: {
type: 'text',
},
indexes: {
type: 'keyword',
},
id: {
type: 'keyword',
},
name: {
type: 'text',
},
placeholder: {
type: 'text',
},
searchable: {
type: 'boolean',
},
type: {
type: 'keyword',
},
export const timelineSavedObjectMappings = {
properties: {
columns: {
properties: {
aggregatable: {
type: 'boolean',
},
category: {
type: 'keyword',
},
columnHeaderType: {
type: 'keyword',
},
description: {
type: 'text',
},
example: {
type: 'text',
},
indexes: {
type: 'keyword',
},
id: {
type: 'keyword',
},
name: {
type: 'text',
},
placeholder: {
type: 'text',
},
searchable: {
type: 'boolean',
},
type: {
type: 'keyword',
},
},
dataProviders: {
properties: {
id: {
type: 'keyword',
},
name: {
type: 'text',
},
enabled: {
type: 'boolean',
},
excluded: {
type: 'boolean',
},
kqlQuery: {
type: 'text',
},
queryMatch: {
properties: {
field: {
type: 'text',
},
displayField: {
type: 'text',
},
value: {
type: 'text',
},
displayValue: {
type: 'text',
},
operator: {
type: 'text',
},
},
dataProviders: {
properties: {
id: {
type: 'keyword',
},
name: {
type: 'text',
},
enabled: {
type: 'boolean',
},
excluded: {
type: 'boolean',
},
kqlQuery: {
type: 'text',
},
queryMatch: {
properties: {
field: {
type: 'text',
},
displayField: {
type: 'text',
},
value: {
type: 'text',
},
displayValue: {
type: 'text',
},
operator: {
type: 'text',
},
},
and: {
properties: {
id: {
type: 'keyword',
},
name: {
type: 'text',
},
enabled: {
type: 'boolean',
},
excluded: {
type: 'boolean',
},
kqlQuery: {
type: 'text',
},
queryMatch: {
properties: {
field: {
type: 'text',
},
displayField: {
type: 'text',
},
value: {
type: 'text',
},
displayValue: {
type: 'text',
},
operator: {
type: 'text',
},
},
and: {
properties: {
id: {
type: 'keyword',
},
name: {
type: 'text',
},
enabled: {
type: 'boolean',
},
excluded: {
type: 'boolean',
},
kqlQuery: {
type: 'text',
},
queryMatch: {
properties: {
field: {
type: 'text',
},
displayField: {
type: 'text',
},
value: {
type: 'text',
},
displayValue: {
type: 'text',
},
operator: {
type: 'text',
},
},
},
},
},
},
description: {
type: 'text',
},
eventType: {
type: 'keyword',
},
favorite: {
properties: {
keySearch: {
type: 'text',
},
fullName: {
type: 'text',
},
userName: {
type: 'text',
},
favoriteDate: {
type: 'date',
},
},
description: {
type: 'text',
},
eventType: {
type: 'keyword',
},
favorite: {
properties: {
keySearch: {
type: 'text',
},
fullName: {
type: 'text',
},
userName: {
type: 'text',
},
favoriteDate: {
type: 'date',
},
},
filters: {
properties: {
meta: {
properties: {
alias: {
type: 'text',
},
controlledBy: {
type: 'text',
},
disabled: {
type: 'boolean',
},
field: {
type: 'text',
},
formattedValue: {
type: 'text',
},
index: {
type: 'keyword',
},
key: {
type: 'keyword',
},
negate: {
type: 'boolean',
},
params: {
type: 'text',
},
type: {
type: 'keyword',
},
value: {
type: 'text',
},
},
filters: {
properties: {
meta: {
properties: {
alias: {
type: 'text',
},
controlledBy: {
type: 'text',
},
disabled: {
type: 'boolean',
},
field: {
type: 'text',
},
formattedValue: {
type: 'text',
},
index: {
type: 'keyword',
},
key: {
type: 'keyword',
},
negate: {
type: 'boolean',
},
params: {
type: 'text',
},
type: {
type: 'keyword',
},
value: {
type: 'text',
},
},
exists: {
type: 'text',
},
match_all: {
type: 'text',
},
missing: {
type: 'text',
},
query: {
type: 'text',
},
range: {
type: 'text',
},
script: {
type: 'text',
},
},
exists: {
type: 'text',
},
match_all: {
type: 'text',
},
missing: {
type: 'text',
},
query: {
type: 'text',
},
range: {
type: 'text',
},
script: {
type: 'text',
},
},
kqlMode: {
type: 'keyword',
},
kqlQuery: {
properties: {
filterQuery: {
properties: {
kuery: {
properties: {
kind: {
type: 'keyword',
},
expression: {
type: 'text',
},
},
kqlMode: {
type: 'keyword',
},
kqlQuery: {
properties: {
filterQuery: {
properties: {
kuery: {
properties: {
kind: {
type: 'keyword',
},
expression: {
type: 'text',
},
},
serializedQuery: {
type: 'text',
},
},
serializedQuery: {
type: 'text',
},
},
},
},
title: {
type: 'text',
},
dateRange: {
properties: {
start: {
type: 'date',
},
end: {
type: 'date',
},
},
title: {
type: 'text',
},
dateRange: {
properties: {
start: {
type: 'date',
},
end: {
type: 'date',
},
},
savedQueryId: {
type: 'keyword',
},
sort: {
properties: {
columnId: {
type: 'keyword',
},
sortDirection: {
type: 'keyword',
},
},
savedQueryId: {
type: 'keyword',
},
sort: {
properties: {
columnId: {
type: 'keyword',
},
sortDirection: {
type: 'keyword',
},
},
created: {
type: 'date',
},
createdBy: {
type: 'text',
},
updated: {
type: 'date',
},
updatedBy: {
type: 'text',
},
},
created: {
type: 'date',
},
createdBy: {
type: 'text',
},
updated: {
type: 'date',
},
updatedBy: {
type: 'text',
},
},
};
export const type: SavedObjectsType = {
name: timelineSavedObjectType,
hidden: false,
namespaceType: 'single',
mappings: timelineSavedObjectMappings,
};

View file

@ -34,13 +34,7 @@ import { signalRulesAlertType } from './lib/detection_engine/signals/signal_rule
import { rulesNotificationAlertType } from './lib/detection_engine/notifications/rules_notification_alert_type';
import { isNotificationAlertExecutor } from './lib/detection_engine/notifications/types';
import { hasListsFeature, listsEnvFeatureFlagName } from './lib/detection_engine/feature_flags';
import {
noteSavedObjectType,
pinnedEventSavedObjectType,
timelineSavedObjectType,
ruleStatusSavedObjectType,
ruleActionsSavedObjectType,
} from './saved_objects';
import { initSavedObjects, savedObjectTypes } from './saved_objects';
import { SiemClientFactory } from './client';
import { createConfig$, ConfigType } from './config';
import { initUiSettings } from './ui_settings';
@ -93,6 +87,7 @@ export class Plugin implements IPlugin<PluginSetup, PluginStart, SetupPlugins, S
);
}
initSavedObjects(core.savedObjects);
initUiSettings(core.uiSettings);
const router = core.http.createRouter();
@ -134,15 +129,11 @@ export class Plugin implements IPlugin<PluginSetup, PluginStart, SetupPlugins, S
'alert',
'action',
'action_task_params',
noteSavedObjectType,
pinnedEventSavedObjectType,
timelineSavedObjectType,
ruleStatusSavedObjectType,
ruleActionsSavedObjectType,
'cases',
'cases-comments',
'cases-configure',
'cases-user-actions',
...savedObjectTypes,
],
read: ['config'],
},
@ -165,15 +156,11 @@ export class Plugin implements IPlugin<PluginSetup, PluginStart, SetupPlugins, S
all: ['alert', 'action', 'action_task_params'],
read: [
'config',
noteSavedObjectType,
pinnedEventSavedObjectType,
timelineSavedObjectType,
ruleStatusSavedObjectType,
ruleActionsSavedObjectType,
'cases',
'cases-comments',
'cases-configure',
'cases-user-actions',
...savedObjectTypes,
],
},
ui: [

View file

@ -4,35 +4,18 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { noteSavedObjectType, noteSavedObjectMappings } from './lib/note/saved_object_mappings';
import {
pinnedEventSavedObjectType,
pinnedEventSavedObjectMappings,
} from './lib/pinned_event/saved_object_mappings';
import {
timelineSavedObjectType,
timelineSavedObjectMappings,
} from './lib/timeline/saved_object_mappings';
import {
ruleStatusSavedObjectMappings,
ruleStatusSavedObjectType,
} from './lib/detection_engine/rules/saved_object_mappings';
import {
ruleActionsSavedObjectMappings,
ruleActionsSavedObjectType,
} from './lib/detection_engine/rule_actions/saved_object_mappings';
import { CoreSetup } from '../../../../src/core/server';
export {
noteSavedObjectType,
pinnedEventSavedObjectType,
ruleStatusSavedObjectType,
ruleActionsSavedObjectType,
timelineSavedObjectType,
};
export const savedObjectMappings = {
...timelineSavedObjectMappings,
...noteSavedObjectMappings,
...pinnedEventSavedObjectMappings,
...ruleStatusSavedObjectMappings,
...ruleActionsSavedObjectMappings,
import { type as noteType } from './lib/note/saved_object_mappings';
import { type as pinnedEventType } from './lib/pinned_event/saved_object_mappings';
import { type as timelineType } from './lib/timeline/saved_object_mappings';
import { type as ruleStatusType } from './lib/detection_engine/rules/saved_object_mappings';
import { type as ruleActionsType } from './lib/detection_engine/rule_actions/saved_object_mappings';
const types = [noteType, pinnedEventType, ruleActionsType, ruleStatusType, timelineType];
export const savedObjectTypes = types.map(type => type.name);
export const initSavedObjects = (savedObjects: CoreSetup['savedObjects']) => {
types.forEach(type => savedObjects.registerType(type));
};