Skip to content
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

[8.x] [Cloud Security] Added filter support to graph API (#199048) #199702

Merged
merged 2 commits into from
Nov 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,26 @@
*/

import { schema } from '@kbn/config-schema';
import { ApiMessageCode } from '../../types/graph/v1';

export const graphRequestSchema = schema.object({
nodesLimit: schema.maybe(schema.number()),
showUnknownTarget: schema.maybe(schema.boolean()),
query: schema.object({
actorIds: schema.arrayOf(schema.string()),
eventIds: schema.arrayOf(schema.string()),
// TODO: use zod for range validation instead of config schema
start: schema.oneOf([schema.number(), schema.string()]),
end: schema.oneOf([schema.number(), schema.string()]),
esQuery: schema.maybe(
schema.object({
bool: schema.object({
filter: schema.maybe(schema.arrayOf(schema.object({}, { unknowns: 'allow' }))),
must: schema.maybe(schema.arrayOf(schema.object({}, { unknowns: 'allow' }))),
should: schema.maybe(schema.arrayOf(schema.object({}, { unknowns: 'allow' }))),
must_not: schema.maybe(schema.arrayOf(schema.object({}, { unknowns: 'allow' }))),
}),
})
),
}),
});

Expand All @@ -23,6 +35,9 @@ export const graphResponseSchema = () =>
schema.oneOf([entityNodeDataSchema, groupNodeDataSchema, labelNodeDataSchema])
),
edges: schema.arrayOf(edgeDataSchema),
messages: schema.maybe(
schema.arrayOf(schema.oneOf([schema.literal(ApiMessageCode.ReachedNodesLimit)]))
),
});

export const colorSchema = schema.oneOf([
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,6 @@
"@kbn/i18n",
"@kbn/analytics",
"@kbn/usage-collection-plugin",
"@kbn/es-query",
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*/

import type { TypeOf } from '@kbn/config-schema';
import type { BoolQuery } from '@kbn/es-query';
import {
colorSchema,
edgeDataSchema,
Expand All @@ -17,13 +18,21 @@ import {
nodeShapeSchema,
} from '../../schema/graph/v1';

export type GraphRequest = TypeOf<typeof graphRequestSchema>;
export type GraphResponse = TypeOf<typeof graphResponseSchema>;
export type GraphRequest = Omit<TypeOf<typeof graphRequestSchema>, 'query.esQuery'> & {
query: { esQuery?: { bool: Partial<BoolQuery> } };
};
export type GraphResponse = Omit<TypeOf<typeof graphResponseSchema>, 'messages'> & {
messages?: ApiMessageCode[];
};

export type Color = typeof colorSchema.type;

export type NodeShape = TypeOf<typeof nodeShapeSchema>;

export enum ApiMessageCode {
ReachedNodesLimit = 'REACHED_NODES_LIMIT',
}

export type EntityNodeDataModel = TypeOf<typeof entityNodeDataSchema>;

export type GroupNodeDataModel = TypeOf<typeof groupNodeDataSchema>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
graphResponseSchema,
} from '@kbn/cloud-security-posture-common/schema/graph/latest';
import { transformError } from '@kbn/securitysolution-es-utils';
import type { GraphRequest } from '@kbn/cloud-security-posture-common/types/graph/v1';
import { GRAPH_ROUTE_PATH } from '../../../common/constants';
import { CspRouter } from '../../types';
import { getGraph as getGraphV1 } from './v1';
Expand Down Expand Up @@ -39,26 +40,29 @@ export const defineGraphRoute = (router: CspRouter) =>
},
},
async (context, request, response) => {
const { actorIds, eventIds, start, end } = request.body.query;
const { nodesLimit, showUnknownTarget = false } = request.body;
const { eventIds, start, end, esQuery } = request.body.query as GraphRequest['query'];
const cspContext = await context.csp;
const spaceId = (await cspContext.spaces?.spacesService?.getActiveSpace(request))?.id;

try {
const { nodes, edges } = await getGraphV1(
{
const resp = await getGraphV1({
services: {
logger: cspContext.logger,
esClient: cspContext.esClient,
},
{
actorIds,
query: {
eventIds,
spaceId,
start,
end,
}
);
esQuery,
},
showUnknownTarget,
nodesLimit,
});

return response.ok({ body: { nodes, edges } });
return response.ok({ body: resp });
} catch (err) {
const error = transformError(err);
cspContext.logger.error(`Failed to fetch graph ${err}`);
Expand Down

This file was deleted.

Loading