-
Notifications
You must be signed in to change notification settings - Fork 8.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Security Solution] Migrates siem-detection-engine-rule-status alertId to saved object references array #114585
Changes from 9 commits
bec9779
bbb7fc3
bd30df7
0ec7dd6
122f015
a55c1d0
2bf2bd9
503e55b
e31c9da
5f41332
ddccdfe
8cd206e
248b197
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,27 +5,33 @@ | |
* 2.0. | ||
*/ | ||
|
||
import { get } from 'lodash'; | ||
import { | ||
SavedObjectsClientContract, | ||
SavedObject, | ||
SavedObjectsUpdateResponse, | ||
SavedObjectsClientContract, | ||
SavedObjectsCreateOptions, | ||
SavedObjectsFindOptions, | ||
SavedObjectsFindOptionsReference, | ||
SavedObjectsFindResult, | ||
} from '../../../../../../../../src/core/server'; | ||
import { ruleStatusSavedObjectType } from '../../rules/saved_object_mappings'; | ||
SavedObjectsUpdateResponse, | ||
} from 'kibana/server'; | ||
import { get } from 'lodash'; | ||
// eslint-disable-next-line no-restricted-imports | ||
import { legacyRuleStatusSavedObjectType } from '../../rules/legacy_rule_status/legacy_rule_status_saved_object_mappings'; | ||
import { IRuleStatusSOAttributes } from '../../rules/types'; | ||
import { buildChunkedOrFilter } from '../../signals/utils'; | ||
|
||
export interface RuleStatusSavedObjectsClient { | ||
find: ( | ||
options?: Omit<SavedObjectsFindOptions, 'type'> | ||
) => Promise<Array<SavedObjectsFindResult<IRuleStatusSOAttributes>>>; | ||
findBulk: (ids: string[], statusesPerId: number) => Promise<FindBulkResponse>; | ||
create: (attributes: IRuleStatusSOAttributes) => Promise<SavedObject<IRuleStatusSOAttributes>>; | ||
create: ( | ||
attributes: IRuleStatusSOAttributes, | ||
options?: SavedObjectsCreateOptions | ||
) => Promise<SavedObject<IRuleStatusSOAttributes>>; | ||
update: ( | ||
id: string, | ||
attributes: Partial<IRuleStatusSOAttributes> | ||
attributes: Partial<IRuleStatusSOAttributes>, | ||
options?: SavedObjectsCreateOptions | ||
) => Promise<SavedObjectsUpdateResponse<IRuleStatusSOAttributes>>; | ||
delete: (id: string) => Promise<{}>; | ||
} | ||
|
@@ -35,63 +41,80 @@ export interface FindBulkResponse { | |
} | ||
|
||
/** | ||
* @pdeprecated Use RuleExecutionLogClient instead | ||
* @deprecated Use RuleExecutionLogClient instead | ||
*/ | ||
export const ruleStatusSavedObjectsClientFactory = ( | ||
savedObjectsClient: SavedObjectsClientContract | ||
): RuleStatusSavedObjectsClient => ({ | ||
find: async (options) => { | ||
const result = await savedObjectsClient.find<IRuleStatusSOAttributes>({ | ||
...options, | ||
type: ruleStatusSavedObjectType, | ||
type: legacyRuleStatusSavedObjectType, | ||
}); | ||
return result.saved_objects; | ||
}, | ||
findBulk: async (ids, statusesPerId) => { | ||
if (ids.length === 0) { | ||
return {}; | ||
} | ||
const filter = buildChunkedOrFilter(`${ruleStatusSavedObjectType}.attributes.alertId`, ids); | ||
const references = ids.map<SavedObjectsFindOptionsReference>((alertId) => ({ | ||
id: alertId, | ||
type: 'alert', | ||
})); | ||
const order: 'desc' = 'desc'; | ||
const aggs = { | ||
alertIds: { | ||
terms: { | ||
field: `${ruleStatusSavedObjectType}.attributes.alertId`, | ||
size: ids.length, | ||
references: { | ||
nested: { | ||
path: `${legacyRuleStatusSavedObjectType}.references`, | ||
}, | ||
aggs: { | ||
most_recent_statuses: { | ||
top_hits: { | ||
sort: [ | ||
{ | ||
[`${ruleStatusSavedObjectType}.statusDate`]: { | ||
order, | ||
alertIds: { | ||
terms: { | ||
field: `${legacyRuleStatusSavedObjectType}.references.id`, | ||
size: ids.length, | ||
}, | ||
aggs: { | ||
rule_status: { | ||
reverse_nested: {}, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ended up running into issues going the two query route as well too as it wasn't possible to do a Touched base w/ @XavierM and just ended up adding support for |
||
aggs: { | ||
most_recent_statuses: { | ||
top_hits: { | ||
sort: [ | ||
{ | ||
[`${legacyRuleStatusSavedObjectType}.statusDate`]: { | ||
spong marked this conversation as resolved.
Show resolved
Hide resolved
|
||
order, | ||
}, | ||
}, | ||
], | ||
size: statusesPerId, | ||
}, | ||
}, | ||
}, | ||
], | ||
size: statusesPerId, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}; | ||
const results = await savedObjectsClient.find({ | ||
filter, | ||
hasReference: references, | ||
aggs, | ||
type: ruleStatusSavedObjectType, | ||
type: legacyRuleStatusSavedObjectType, | ||
perPage: 0, | ||
}); | ||
const buckets = get(results, 'aggregations.alertIds.buckets'); | ||
const buckets = get(results, 'aggregations.references.alertIds.buckets'); | ||
return buckets.reduce((acc: Record<string, unknown>, bucket: unknown) => { | ||
const key = get(bucket, 'key'); | ||
const hits = get(bucket, 'most_recent_statuses.hits.hits'); | ||
const hits = get(bucket, 'rule_status.most_recent_statuses.hits.hits'); | ||
// eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
const statuses = hits.map((hit: any) => hit._source['siem-detection-engine-rule-status']); | ||
acc[key] = statuses; | ||
acc[key] = hits.map((hit: any) => hit._source[legacyRuleStatusSavedObjectType]); | ||
return acc; | ||
}, {}); | ||
}, | ||
create: (attributes) => savedObjectsClient.create(ruleStatusSavedObjectType, attributes), | ||
update: (id, attributes) => savedObjectsClient.update(ruleStatusSavedObjectType, id, attributes), | ||
delete: (id) => savedObjectsClient.delete(ruleStatusSavedObjectType, id), | ||
create: (attributes, options) => { | ||
return savedObjectsClient.create(legacyRuleStatusSavedObjectType, attributes, options); | ||
}, | ||
update: (id, attributes, options) => | ||
savedObjectsClient.update(legacyRuleStatusSavedObjectType, id, attributes, options), | ||
delete: (id) => savedObjectsClient.delete(legacyRuleStatusSavedObjectType, id), | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Create
/Update
interfaces updated to includeSavedObjectsCreateOptions
so the SOreferences[]
can be supplied and the correct document is updated (otherwise we'll end up with new docs w/oreferences[]
).