[RAM] Add featureIds as a property for find alerts (#151567)

## Summary

Resolve: https://github.com/elastic/kibana/issues/150169


### Checklist

- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios
This commit is contained in:
Xavier Mouligneau 2023-02-21 15:13:40 -05:00 committed by GitHub
parent 1d1848e96c
commit 0faccf92c0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 78 additions and 25 deletions

View file

@ -847,25 +847,35 @@ export class AlertsClient {
}
public async find<Params extends RuleTypeParams = never>({
query,
aggs,
_source,
track_total_hits: trackTotalHits,
size,
featureIds,
index,
sort,
query,
search_after: searchAfter,
size,
sort,
track_total_hits: trackTotalHits,
_source,
}: {
query?: object | undefined;
aggs?: object | undefined;
index: string | undefined;
track_total_hits?: boolean | undefined;
_source?: string[] | undefined;
size?: number | undefined;
sort?: estypes.SortOptions[] | undefined;
search_after?: Array<string | number> | undefined;
aggs?: object;
featureIds?: string[];
index?: string;
query?: object;
search_after?: Array<string | number>;
size?: number;
sort?: estypes.SortOptions[];
track_total_hits?: boolean;
_source?: string[];
}) {
try {
let indexToUse = index;
if (featureIds && !isEmpty(featureIds)) {
const tempIndexToUse = await this.getAuthorizedAlertsIndices(featureIds);
if (!isEmpty(tempIndexToUse)) {
indexToUse = (tempIndexToUse ?? []).join();
}
}
// first search for the alert by id, then use the alert info to check if user has access to it
const alertsSearchResponse = await this.singleSearchAfterAndAudit({
query,
@ -873,7 +883,7 @@ export class AlertsClient {
_source,
track_total_hits: trackTotalHits,
size,
index,
index: indexToUse,
operation: ReadOperations.Find,
sort,
lastSortIds: searchAfter,

View file

@ -24,12 +24,13 @@ export const findAlertsByQueryRoute = (router: IRouter<RacRequestHandlerContext>
body: buildRouteValidation(
t.exact(
t.partial({
aggs: t.record(t.string, t.intersection([metricsAggsSchemas, bucketAggsSchemas])),
feature_ids: t.union([t.array(t.string), t.undefined]),
index: t.string,
query: t.object,
aggs: t.record(t.string, t.intersection([metricsAggsSchemas, bucketAggsSchemas])),
sort: t.union([t.array(t.object), t.undefined]),
search_after: t.union([t.array(t.number), t.array(t.string), t.undefined]),
size: t.union([PositiveInteger, t.undefined]),
sort: t.union([t.array(t.object), t.undefined]),
track_total_hits: t.union([t.boolean, t.undefined]),
_source: t.union([t.array(t.string), t.undefined]),
})
@ -42,20 +43,31 @@ export const findAlertsByQueryRoute = (router: IRouter<RacRequestHandlerContext>
},
async (context, request, response) => {
try {
// eslint-disable-next-line @typescript-eslint/naming-convention
const { query, aggs, _source, track_total_hits, size, index, sort, search_after } =
request.body;
const {
aggs,
feature_ids: featureIds,
index,
query,
// eslint-disable-next-line @typescript-eslint/naming-convention
search_after,
size,
sort,
// eslint-disable-next-line @typescript-eslint/naming-convention
track_total_hits,
_source,
} = request.body;
const racContext = await context.rac;
const alertsClient = await racContext.getAlertsClient();
const alerts = await alertsClient.find({
query,
aggs,
_source,
track_total_hits,
size,
featureIds,
index,
sort: sort as SortOptions[],
query,
search_after,
size,
sort: sort as SortOptions[],
track_total_hits,
_source,
});
if (alerts == null) {
return response.notFound({

View file

@ -6,7 +6,10 @@
*/
import expect from '@kbn/expect';
import { ALERT_WORKFLOW_STATUS } from '@kbn/rule-registry-plugin/common/technical_rule_data_field_names';
import {
ALERT_RULE_CONSUMER,
ALERT_WORKFLOW_STATUS,
} from '@kbn/rule-registry-plugin/common/technical_rule_data_field_names';
import {
superUser,
globalRead,
@ -265,6 +268,34 @@ export default ({ getService }: FtrProviderContext) => {
expect(found.body.aggregations.nbr_consumer.value).to.be.equal(2);
});
it(`${superUser.username} should handle 'siem' featureIds`, async () => {
const found = await supertestWithoutAuth
.post(`${getSpaceUrlPrefix(SPACE1)}${TEST_URL}/find`)
.auth(superUser.username, superUser.password)
.set('kbn-xsrf', 'true')
.send({
feature_ids: ['siem'],
});
expect(found.body.hits.hits.every((hit: any) => hit[ALERT_RULE_CONSUMER] === 'siem')).equal(
true
);
});
it(`${superUser.username} should handle 'apm' featureIds`, async () => {
const found = await supertestWithoutAuth
.post(`${getSpaceUrlPrefix(SPACE1)}${TEST_URL}/find`)
.auth(superUser.username, superUser.password)
.set('kbn-xsrf', 'true')
.send({
feature_ids: ['apm'],
});
expect(found.body.hits.hits.every((hit: any) => hit[ALERT_RULE_CONSUMER] === 'apm')).equal(
true
);
});
function addTests({ space, authorizedUsers, unauthorizedUsers, alertId, index }: TestCase) {
authorizedUsers.forEach(({ username, password }) => {
it(`${username} should finds alerts which match query in ${space}/${index}`, async () => {