From ba84602455671f0f6175bbc0fd2e8f302c60bbe6 Mon Sep 17 00:00:00 2001 From: Tomasz Ciecierski <ciecierskitomek@gmail.com> Date: Mon, 23 May 2022 13:33:20 +0200 Subject: [PATCH] [Osquery] Change prebuilt saved queries to include prebuilt flag (#132651) --- .../routes/saved_queries/edit/index.tsx | 2 +- .../saved_query/delete_saved_query_route.ts | 9 +++- .../saved_query/find_saved_query_route.ts | 9 +++- .../server/routes/saved_query/index.ts | 6 +-- .../saved_query/read_saved_query_route.ts | 7 ++- .../saved_query/update_saved_query_route.ts | 7 +++ .../server/routes/saved_query/utils.ts | 54 +++++++++++++++++++ 7 files changed, 87 insertions(+), 7 deletions(-) create mode 100644 x-pack/plugins/osquery/server/routes/saved_query/utils.ts diff --git a/x-pack/plugins/osquery/public/routes/saved_queries/edit/index.tsx b/x-pack/plugins/osquery/public/routes/saved_queries/edit/index.tsx index 94b1f092e1ede..cb7a95b4271e7 100644 --- a/x-pack/plugins/osquery/public/routes/saved_queries/edit/index.tsx +++ b/x-pack/plugins/osquery/public/routes/saved_queries/edit/index.tsx @@ -44,7 +44,7 @@ const EditSavedQueryPageComponent = () => { useBreadcrumbs('saved_query_edit', { savedQueryName: savedQueryDetails?.attributes?.id ?? '' }); const elasticPrebuiltQuery = useMemo( - () => savedQueryDetails?.attributes?.version, + () => savedQueryDetails?.attributes?.prebuilt, [savedQueryDetails] ); const viewMode = useMemo( diff --git a/x-pack/plugins/osquery/server/routes/saved_query/delete_saved_query_route.ts b/x-pack/plugins/osquery/server/routes/saved_query/delete_saved_query_route.ts index c2a2ad7fa8619..a27c4a0953098 100644 --- a/x-pack/plugins/osquery/server/routes/saved_query/delete_saved_query_route.ts +++ b/x-pack/plugins/osquery/server/routes/saved_query/delete_saved_query_route.ts @@ -9,8 +9,10 @@ import { schema } from '@kbn/config-schema'; import { IRouter } from '@kbn/core/server'; import { PLUGIN_ID } from '../../../common'; import { savedQuerySavedObjectType } from '../../../common/types'; +import { OsqueryAppContext } from '../../lib/osquery_app_context_services'; +import { isSavedQueryPrebuilt } from './utils'; -export const deleteSavedQueryRoute = (router: IRouter) => { +export const deleteSavedQueryRoute = (router: IRouter, osqueryContext: OsqueryAppContext) => { router.delete( { path: '/internal/osquery/saved_query/{id}', @@ -25,6 +27,11 @@ export const deleteSavedQueryRoute = (router: IRouter) => { const coreContext = await context.core; const savedObjectsClient = coreContext.savedObjects.client; + const isPrebuilt = await isSavedQueryPrebuilt(osqueryContext, request.params.id); + if (isPrebuilt) { + return response.conflict({ body: `Elastic prebuilt Saved query cannot be deleted.` }); + } + await savedObjectsClient.delete(savedQuerySavedObjectType, request.params.id, { refresh: 'wait_for', }); diff --git a/x-pack/plugins/osquery/server/routes/saved_query/find_saved_query_route.ts b/x-pack/plugins/osquery/server/routes/saved_query/find_saved_query_route.ts index a2b85dbf539d9..abf62ca782daa 100644 --- a/x-pack/plugins/osquery/server/routes/saved_query/find_saved_query_route.ts +++ b/x-pack/plugins/osquery/server/routes/saved_query/find_saved_query_route.ts @@ -7,11 +7,14 @@ import { schema } from '@kbn/config-schema'; import { IRouter } from '@kbn/core/server'; + +import { OsqueryAppContext } from '../../lib/osquery_app_context_services'; import { PLUGIN_ID } from '../../../common'; import { savedQuerySavedObjectType } from '../../../common/types'; import { convertECSMappingToObject } from '../utils'; +import { getInstalledSavedQueriesMap } from './utils'; -export const findSavedQueryRoute = (router: IRouter) => { +export const findSavedQueryRoute = (router: IRouter, osqueryContext: OsqueryAppContext) => { router.get( { path: '/internal/osquery/saved_query', @@ -34,6 +37,7 @@ export const findSavedQueryRoute = (router: IRouter) => { const savedQueries = await savedObjectsClient.find<{ ecs_mapping: Array<{ field: string; value: string }>; + prebuilt: boolean; }>({ type: savedQuerySavedObjectType, page: parseInt(request.query.pageIndex ?? '0', 10) + 1, @@ -43,10 +47,13 @@ export const findSavedQueryRoute = (router: IRouter) => { sortOrder: request.query.sortDirection ?? 'desc', }); + const prebuiltSavedQueriesMap = await getInstalledSavedQueriesMap(osqueryContext); const savedObjects = savedQueries.saved_objects.map((savedObject) => { // eslint-disable-next-line @typescript-eslint/naming-convention const ecs_mapping = savedObject.attributes.ecs_mapping; + savedObject.attributes.prebuilt = !!prebuiltSavedQueriesMap[savedObject.id]; + if (ecs_mapping) { // @ts-expect-error update types savedObject.attributes.ecs_mapping = convertECSMappingToObject(ecs_mapping); diff --git a/x-pack/plugins/osquery/server/routes/saved_query/index.ts b/x-pack/plugins/osquery/server/routes/saved_query/index.ts index e0bf4f622c42c..025199dcba6b6 100644 --- a/x-pack/plugins/osquery/server/routes/saved_query/index.ts +++ b/x-pack/plugins/osquery/server/routes/saved_query/index.ts @@ -16,8 +16,8 @@ import { OsqueryAppContext } from '../../lib/osquery_app_context_services'; export const initSavedQueryRoutes = (router: IRouter, context: OsqueryAppContext) => { createSavedQueryRoute(router, context); - deleteSavedQueryRoute(router); - findSavedQueryRoute(router); - readSavedQueryRoute(router); + deleteSavedQueryRoute(router, context); + findSavedQueryRoute(router, context); + readSavedQueryRoute(router, context); updateSavedQueryRoute(router, context); }; diff --git a/x-pack/plugins/osquery/server/routes/saved_query/read_saved_query_route.ts b/x-pack/plugins/osquery/server/routes/saved_query/read_saved_query_route.ts index 1c206464d1f65..d1627d220682a 100644 --- a/x-pack/plugins/osquery/server/routes/saved_query/read_saved_query_route.ts +++ b/x-pack/plugins/osquery/server/routes/saved_query/read_saved_query_route.ts @@ -7,11 +7,13 @@ import { schema } from '@kbn/config-schema'; import { IRouter } from '@kbn/core/server'; +import { isSavedQueryPrebuilt } from './utils'; +import { OsqueryAppContext } from '../../lib/osquery_app_context_services'; import { PLUGIN_ID } from '../../../common'; import { savedQuerySavedObjectType } from '../../../common/types'; import { convertECSMappingToObject } from '../utils'; -export const readSavedQueryRoute = (router: IRouter) => { +export const readSavedQueryRoute = (router: IRouter, osqueryContext: OsqueryAppContext) => { router.get( { path: '/internal/osquery/saved_query/{id}', @@ -28,6 +30,7 @@ export const readSavedQueryRoute = (router: IRouter) => { const savedQuery = await savedObjectsClient.get<{ ecs_mapping: Array<{ key: string; value: Record<string, object> }>; + prebuilt: boolean; }>(savedQuerySavedObjectType, request.params.id); if (savedQuery.attributes.ecs_mapping) { @@ -37,6 +40,8 @@ export const readSavedQueryRoute = (router: IRouter) => { ); } + savedQuery.attributes.prebuilt = await isSavedQueryPrebuilt(osqueryContext, savedQuery.id); + return response.ok({ body: savedQuery, }); diff --git a/x-pack/plugins/osquery/server/routes/saved_query/update_saved_query_route.ts b/x-pack/plugins/osquery/server/routes/saved_query/update_saved_query_route.ts index 1d2bf153afd7f..e2686868b7eff 100644 --- a/x-pack/plugins/osquery/server/routes/saved_query/update_saved_query_route.ts +++ b/x-pack/plugins/osquery/server/routes/saved_query/update_saved_query_route.ts @@ -9,6 +9,7 @@ import { filter } from 'lodash'; import { schema } from '@kbn/config-schema'; import { IRouter } from '@kbn/core/server'; +import { isSavedQueryPrebuilt } from './utils'; import { PLUGIN_ID } from '../../../common'; import { savedQuerySavedObjectType } from '../../../common/types'; import { OsqueryAppContext } from '../../lib/osquery_app_context_services'; @@ -63,6 +64,12 @@ export const updateSavedQueryRoute = (router: IRouter, osqueryContext: OsqueryAp ecs_mapping, } = request.body; + const isPrebuilt = await isSavedQueryPrebuilt(osqueryContext, request.params.id); + + if (isPrebuilt) { + return response.conflict({ body: `Elastic prebuilt Saved query cannot be updated.` }); + } + const conflictingEntries = await savedObjectsClient.find<{ id: string }>({ type: savedQuerySavedObjectType, filter: `${savedQuerySavedObjectType}.attributes.id: "${id}"`, diff --git a/x-pack/plugins/osquery/server/routes/saved_query/utils.ts b/x-pack/plugins/osquery/server/routes/saved_query/utils.ts new file mode 100644 index 0000000000000..d99d5b70f0dab --- /dev/null +++ b/x-pack/plugins/osquery/server/routes/saved_query/utils.ts @@ -0,0 +1,54 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { find, reduce } from 'lodash'; +import { KibanaAssetReference } from '@kbn/fleet-plugin/common'; + +import { OSQUERY_INTEGRATION_NAME } from '../../../common'; +import { savedQuerySavedObjectType } from '../../../common/types'; +import { OsqueryAppContext } from '../../lib/osquery_app_context_services'; + +const getInstallation = async (osqueryContext: OsqueryAppContext) => + await osqueryContext.service + .getPackageService() + ?.asInternalUser?.getInstallation(OSQUERY_INTEGRATION_NAME); + +export const getInstalledSavedQueriesMap = async (osqueryContext: OsqueryAppContext) => { + const installation = await getInstallation(osqueryContext); + if (installation) { + return reduce( + installation.installed_kibana, + // @ts-expect-error not sure why it shouts, but still it's properly typed + (acc: Record<string, KibanaAssetReference>, item: KibanaAssetReference) => { + if (item.type === savedQuerySavedObjectType) { + return { ...acc, [item.id]: item }; + } + }, + {} + ); + } + + return {}; +}; + +export const isSavedQueryPrebuilt = async ( + osqueryContext: OsqueryAppContext, + savedQueryId: string +) => { + const installation = await getInstallation(osqueryContext); + + if (installation) { + const installationSavedQueries = find( + installation.installed_kibana, + (item) => item.type === savedQuerySavedObjectType && item.id === savedQueryId + ); + + return !!installationSavedQueries; + } + + return false; +};