mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[Defend Workflows] Remove SO.attributes spread from Osquery (#160356)
This commit is contained in:
parent
8acbc43d8c
commit
036a736088
11 changed files with 301 additions and 40 deletions
|
@ -44,11 +44,13 @@ export interface SavedQuerySavedObject {
|
|||
snapshot?: boolean;
|
||||
removed?: boolean;
|
||||
platform: string;
|
||||
ecs_mapping?: Array<Record<string, unknown>>;
|
||||
ecs_mapping?: Array<{ key: string; value: Record<string, object> }>;
|
||||
created_at: string;
|
||||
created_by: string | undefined;
|
||||
updated_at: string;
|
||||
updated_by: string | undefined;
|
||||
prebuilt?: boolean;
|
||||
version: number;
|
||||
}
|
||||
|
||||
export interface HTTPError extends Error {
|
||||
|
|
|
@ -28,6 +28,7 @@ import {
|
|||
} from './utils';
|
||||
import { convertShardsToArray, getInternalSavedObjectsClient } from '../utils';
|
||||
import type { PackSavedObject } from '../../common/types';
|
||||
import type { PackResponseData } from './types';
|
||||
|
||||
type PackSavedObjectLimited = Omit<PackSavedObject, 'saved_object_id' | 'references'>;
|
||||
|
||||
|
@ -174,9 +175,26 @@ export const createPackRoute = (router: IRouter, osqueryContext: OsqueryAppConte
|
|||
|
||||
set(packSO, 'attributes.queries', queries);
|
||||
|
||||
const { attributes } = packSO;
|
||||
|
||||
const data: PackResponseData = {
|
||||
name: attributes.name,
|
||||
description: attributes.description,
|
||||
queries: attributes.queries,
|
||||
version: attributes.version,
|
||||
enabled: attributes.enabled,
|
||||
created_at: attributes.created_at,
|
||||
created_by: attributes.created_by,
|
||||
updated_at: attributes.updated_at,
|
||||
updated_by: attributes.updated_by,
|
||||
policy_ids: attributes.policy_ids,
|
||||
shards: attributes.shards,
|
||||
saved_object_id: packSO.id,
|
||||
};
|
||||
|
||||
return response.ok({
|
||||
body: {
|
||||
data: { ...packSO.attributes, saved_object_id: packSO.id },
|
||||
data,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ import type { IRouter } from '@kbn/core/server';
|
|||
import { packSavedObjectType } from '../../../common/types';
|
||||
import { PLUGIN_ID } from '../../../common';
|
||||
import type { PackSavedObject } from '../../common/types';
|
||||
import type { PackResponseData } from './types';
|
||||
|
||||
export const findPackRoute = (router: IRouter) => {
|
||||
router.get(
|
||||
|
@ -43,14 +44,24 @@ export const findPackRoute = (router: IRouter) => {
|
|||
sortOrder: request.query.sortOrder ?? 'desc',
|
||||
});
|
||||
|
||||
const packSavedObjects = map(soClientResponse.saved_objects, (pack) => {
|
||||
const packSavedObjects: PackResponseData[] = map(soClientResponse.saved_objects, (pack) => {
|
||||
const policyIds = map(
|
||||
filter(pack.references, ['type', AGENT_POLICY_SAVED_OBJECT_TYPE]),
|
||||
'id'
|
||||
);
|
||||
|
||||
const { attributes } = pack;
|
||||
|
||||
return {
|
||||
...pack.attributes,
|
||||
name: attributes.name,
|
||||
description: attributes.description,
|
||||
queries: attributes.queries,
|
||||
version: attributes.version,
|
||||
enabled: attributes.enabled,
|
||||
created_at: attributes.created_at,
|
||||
created_by: attributes.created_by,
|
||||
updated_at: attributes.updated_at,
|
||||
updated_by: attributes.updated_by,
|
||||
saved_object_id: pack.id,
|
||||
policy_ids: policyIds,
|
||||
};
|
||||
|
|
|
@ -15,6 +15,7 @@ import { PLUGIN_ID } from '../../../common';
|
|||
import { packSavedObjectType } from '../../../common/types';
|
||||
import { convertSOQueriesToPack } from './utils';
|
||||
import { convertShardsToObject } from '../utils';
|
||||
import type { ReadPackResponseData } from './types';
|
||||
|
||||
export const readPackRoute = (router: IRouter) => {
|
||||
router.get(
|
||||
|
@ -39,17 +40,30 @@ export const readPackRoute = (router: IRouter) => {
|
|||
const policyIds = map(filter(references, ['type', AGENT_POLICY_SAVED_OBJECT_TYPE]), 'id');
|
||||
const osqueryPackAssetReference = !!filter(references, ['type', 'osquery-pack-asset']);
|
||||
|
||||
const data: ReadPackResponseData = {
|
||||
type: rest.type,
|
||||
namespaces: rest.namespaces,
|
||||
migrationVersion: rest.migrationVersion,
|
||||
managed: rest.managed,
|
||||
coreMigrationVersion: rest.coreMigrationVersion,
|
||||
name: attributes.name,
|
||||
description: attributes.description,
|
||||
version: attributes.version,
|
||||
enabled: attributes.enabled,
|
||||
created_at: attributes.created_at,
|
||||
created_by: attributes.created_by,
|
||||
updated_at: attributes.updated_at,
|
||||
updated_by: attributes.updated_by,
|
||||
saved_object_id: id,
|
||||
queries: convertSOQueriesToPack(attributes.queries),
|
||||
shards: convertShardsToObject(attributes.shards),
|
||||
policy_ids: policyIds,
|
||||
read_only: attributes.version !== undefined && osqueryPackAssetReference,
|
||||
};
|
||||
|
||||
return response.ok({
|
||||
body: {
|
||||
data: {
|
||||
...rest,
|
||||
...attributes,
|
||||
saved_object_id: id,
|
||||
queries: convertSOQueriesToPack(attributes.queries),
|
||||
shards: convertShardsToObject(attributes.shards),
|
||||
policy_ids: policyIds,
|
||||
read_only: attributes.version !== undefined && osqueryPackAssetReference,
|
||||
},
|
||||
data,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
53
x-pack/plugins/osquery/server/routes/pack/types.ts
Normal file
53
x-pack/plugins/osquery/server/routes/pack/types.ts
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* 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 type { SOShard } from '../../common/types';
|
||||
interface PackQuery {
|
||||
id: string;
|
||||
name: string;
|
||||
query: string;
|
||||
interval: number;
|
||||
snapshot?: boolean;
|
||||
removed?: boolean;
|
||||
ecs_mapping?: Record<string, unknown>;
|
||||
}
|
||||
|
||||
export interface PackResponseData {
|
||||
saved_object_id: string;
|
||||
name: string;
|
||||
description: string | undefined;
|
||||
queries: PackQuery[];
|
||||
version?: number;
|
||||
enabled: boolean | undefined;
|
||||
created_at: string;
|
||||
created_by: string | undefined;
|
||||
updated_at: string;
|
||||
updated_by: string | undefined;
|
||||
policy_ids?: string[];
|
||||
shards?: SOShard;
|
||||
}
|
||||
|
||||
export interface ReadPackResponseData {
|
||||
saved_object_id: string;
|
||||
name: string;
|
||||
description: string | undefined;
|
||||
queries: Record<string, PackQuery>;
|
||||
version?: number;
|
||||
enabled: boolean | undefined;
|
||||
created_at: string;
|
||||
created_by: string | undefined;
|
||||
updated_at: string;
|
||||
updated_by: string | undefined;
|
||||
policy_ids?: string[];
|
||||
shards: Record<string, number>;
|
||||
read_only?: boolean;
|
||||
type: string;
|
||||
namespaces?: string[];
|
||||
migrationVersion?: Record<string, string>;
|
||||
managed?: boolean;
|
||||
coreMigrationVersion?: string;
|
||||
}
|
|
@ -31,6 +31,7 @@ import {
|
|||
|
||||
import { convertShardsToArray, getInternalSavedObjectsClient } from '../utils';
|
||||
import type { PackSavedObject } from '../../common/types';
|
||||
import type { PackResponseData } from './types';
|
||||
|
||||
export const updatePackRoute = (router: IRouter, osqueryContext: OsqueryAppContext) => {
|
||||
router.put(
|
||||
|
@ -181,12 +182,12 @@ export const updatePackRoute = (router: IRouter, osqueryContext: OsqueryAppConte
|
|||
filter(currentPackSO.references, ['type', AGENT_POLICY_SAVED_OBJECT_TYPE]),
|
||||
'id'
|
||||
);
|
||||
const updatedPackSO = await savedObjectsClient.get<{
|
||||
name: string;
|
||||
enabled: boolean;
|
||||
queries: Record<string, unknown>;
|
||||
}>(packSavedObjectType, request.params.id);
|
||||
const updatedPackSO = await savedObjectsClient.get<PackSavedObject>(
|
||||
packSavedObjectType,
|
||||
request.params.id
|
||||
);
|
||||
|
||||
// @ts-expect-error update types
|
||||
updatedPackSO.attributes.queries = convertSOQueriesToPack(updatedPackSO.attributes.queries);
|
||||
|
||||
if (enabled == null && !currentPackSO.attributes.enabled) {
|
||||
|
@ -349,8 +350,25 @@ export const updatePackRoute = (router: IRouter, osqueryContext: OsqueryAppConte
|
|||
);
|
||||
}
|
||||
|
||||
const { attributes } = updatedPackSO;
|
||||
|
||||
const data: PackResponseData = {
|
||||
name: attributes.name,
|
||||
description: attributes.description,
|
||||
queries: attributes.queries,
|
||||
version: attributes.version,
|
||||
enabled: attributes.enabled,
|
||||
created_at: attributes.created_at,
|
||||
created_by: attributes.created_by,
|
||||
updated_at: attributes.updated_at,
|
||||
updated_by: attributes.updated_by,
|
||||
policy_ids: attributes.policy_ids,
|
||||
shards: attributes.shards,
|
||||
saved_object_id: updatedPackSO.id,
|
||||
};
|
||||
|
||||
return response.ok({
|
||||
body: { data: { ...updatedPackSO.attributes, saved_object_id: updatedPackSO.id } },
|
||||
body: { data },
|
||||
});
|
||||
}
|
||||
);
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
|
||||
import { isEmpty, pickBy, some, isBoolean } from 'lodash';
|
||||
import type { IRouter } from '@kbn/core/server';
|
||||
import type { SavedQueryResponse } from './types';
|
||||
import type { SavedQuerySavedObject } from '../../common/types';
|
||||
import { PLUGIN_ID } from '../../../common';
|
||||
import type { CreateSavedQueryRequestSchemaDecoded } from '../../../common/schemas/routes/saved_query/create_saved_query_request_schema';
|
||||
import { createSavedQueryRequestSchema } from '../../../common/schemas/routes/saved_query/create_saved_query_request_schema';
|
||||
|
@ -46,7 +48,7 @@ export const createSavedQueryRoute = (router: IRouter, osqueryContext: OsqueryAp
|
|||
|
||||
const currentUser = await osqueryContext.security.authc.getCurrentUser(request)?.username;
|
||||
|
||||
const conflictingEntries = await savedObjectsClient.find({
|
||||
const conflictingEntries = await savedObjectsClient.find<SavedQuerySavedObject>({
|
||||
type: savedQuerySavedObjectType,
|
||||
filter: `${savedQuerySavedObjectType}.attributes.id: "${id}"`,
|
||||
});
|
||||
|
@ -80,16 +82,31 @@ export const createSavedQueryRoute = (router: IRouter, osqueryContext: OsqueryAp
|
|||
)
|
||||
);
|
||||
|
||||
const { attributes } = savedQuerySO;
|
||||
|
||||
const data: Partial<SavedQueryResponse> = pickBy(
|
||||
{
|
||||
created_at: attributes.created_at,
|
||||
created_by: attributes.created_by,
|
||||
description: attributes.description,
|
||||
id: attributes.id,
|
||||
removed: attributes.removed,
|
||||
snapshot: attributes.snapshot,
|
||||
version: attributes.version,
|
||||
interval: attributes.interval,
|
||||
platform: attributes.platform,
|
||||
query: attributes.query,
|
||||
updated_at: attributes.updated_at,
|
||||
updated_by: attributes.updated_by,
|
||||
saved_object_id: savedQuerySO.id,
|
||||
ecs_mapping,
|
||||
},
|
||||
(value) => !isEmpty(value)
|
||||
);
|
||||
|
||||
return response.ok({
|
||||
body: {
|
||||
data: pickBy(
|
||||
{
|
||||
...savedQuerySO.attributes,
|
||||
saved_object_id: savedQuerySO.id,
|
||||
ecs_mapping,
|
||||
},
|
||||
(value) => !isEmpty(value)
|
||||
),
|
||||
data,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
|
@ -9,6 +9,8 @@ import { schema } from '@kbn/config-schema';
|
|||
import type { IRouter } from '@kbn/core/server';
|
||||
|
||||
import { omit } from 'lodash';
|
||||
import type { SavedQueryResponse } from './types';
|
||||
import type { SavedQuerySavedObject } from '../../common/types';
|
||||
import type { OsqueryAppContext } from '../../lib/osquery_app_context_services';
|
||||
import { PLUGIN_ID } from '../../../common';
|
||||
import { savedQuerySavedObjectType } from '../../../common/types';
|
||||
|
@ -36,10 +38,7 @@ export const findSavedQueryRoute = (router: IRouter, osqueryContext: OsqueryAppC
|
|||
const savedObjectsClient = coreContext.savedObjects.client;
|
||||
|
||||
try {
|
||||
const savedQueries = await savedObjectsClient.find<{
|
||||
ecs_mapping: Array<{ field: string; value: string }>;
|
||||
prebuilt: boolean;
|
||||
}>({
|
||||
const savedQueries = await savedObjectsClient.find<SavedQuerySavedObject>({
|
||||
type: savedQuerySavedObjectType,
|
||||
page: request.query.page,
|
||||
perPage: request.query.pageSize,
|
||||
|
@ -50,7 +49,7 @@ export const findSavedQueryRoute = (router: IRouter, osqueryContext: OsqueryAppC
|
|||
const prebuiltSavedQueriesMap = await getInstalledSavedQueriesMap(
|
||||
osqueryContext.service.getPackageService()?.asInternalUser
|
||||
);
|
||||
const savedObjects = savedQueries.saved_objects.map((savedObject) => {
|
||||
const savedObjects: SavedQueryResponse[] = savedQueries.saved_objects.map((savedObject) => {
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
const ecs_mapping = savedObject.attributes.ecs_mapping;
|
||||
|
||||
|
@ -61,8 +60,38 @@ export const findSavedQueryRoute = (router: IRouter, osqueryContext: OsqueryAppC
|
|||
savedObject.attributes.ecs_mapping = convertECSMappingToObject(ecs_mapping);
|
||||
}
|
||||
|
||||
const {
|
||||
created_at: createdAt,
|
||||
created_by: createdBy,
|
||||
description,
|
||||
id,
|
||||
interval,
|
||||
platform,
|
||||
query,
|
||||
removed,
|
||||
snapshot,
|
||||
version,
|
||||
ecs_mapping: ecsMapping,
|
||||
updated_at: updatedAt,
|
||||
updated_by: updatedBy,
|
||||
prebuilt,
|
||||
} = savedObject.attributes;
|
||||
|
||||
return {
|
||||
...savedObject.attributes,
|
||||
created_at: createdAt,
|
||||
created_by: createdBy,
|
||||
description,
|
||||
id,
|
||||
removed,
|
||||
snapshot,
|
||||
version,
|
||||
ecs_mapping: ecsMapping,
|
||||
interval,
|
||||
platform,
|
||||
query,
|
||||
updated_at: updatedAt,
|
||||
updated_by: updatedBy,
|
||||
prebuilt,
|
||||
saved_object_id: savedObject.id,
|
||||
};
|
||||
});
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
|
||||
import { schema } from '@kbn/config-schema';
|
||||
import type { IRouter } from '@kbn/core/server';
|
||||
import type { SavedQueryResponse } from './types';
|
||||
import type { SavedQuerySavedObject } from '../../common/types';
|
||||
import { isSavedQueryPrebuilt } from './utils';
|
||||
import type { OsqueryAppContext } from '../../lib/osquery_app_context_services';
|
||||
import { PLUGIN_ID } from '../../../common';
|
||||
|
@ -28,10 +30,10 @@ export const readSavedQueryRoute = (router: IRouter, osqueryContext: OsqueryAppC
|
|||
const coreContext = await context.core;
|
||||
const savedObjectsClient = coreContext.savedObjects.client;
|
||||
|
||||
const savedQuery = await savedObjectsClient.get<{
|
||||
ecs_mapping: Array<{ key: string; value: Record<string, object> }>;
|
||||
prebuilt: boolean;
|
||||
}>(savedQuerySavedObjectType, request.params.id);
|
||||
const savedQuery = await savedObjectsClient.get<SavedQuerySavedObject>(
|
||||
savedQuerySavedObjectType,
|
||||
request.params.id
|
||||
);
|
||||
|
||||
if (savedQuery.attributes.ecs_mapping) {
|
||||
// @ts-expect-error update types
|
||||
|
@ -45,8 +47,45 @@ export const readSavedQueryRoute = (router: IRouter, osqueryContext: OsqueryAppC
|
|||
savedQuery.id
|
||||
);
|
||||
|
||||
const {
|
||||
created_at: createdAt,
|
||||
created_by: createdBy,
|
||||
description,
|
||||
id,
|
||||
interval,
|
||||
platform,
|
||||
query,
|
||||
removed,
|
||||
snapshot,
|
||||
version,
|
||||
ecs_mapping: ecsMapping,
|
||||
updated_at: updatedAt,
|
||||
updated_by: updatedBy,
|
||||
prebuilt,
|
||||
} = savedQuery.attributes;
|
||||
|
||||
const data: SavedQueryResponse = {
|
||||
created_at: createdAt,
|
||||
created_by: createdBy,
|
||||
description,
|
||||
id,
|
||||
removed,
|
||||
snapshot,
|
||||
version,
|
||||
ecs_mapping: ecsMapping,
|
||||
interval,
|
||||
platform,
|
||||
query,
|
||||
updated_at: updatedAt,
|
||||
updated_by: updatedBy,
|
||||
prebuilt,
|
||||
saved_object_id: savedQuery.id,
|
||||
};
|
||||
|
||||
return response.ok({
|
||||
body: { data: { ...savedQuery.attributes, saved_object_id: savedQuery.id } },
|
||||
body: {
|
||||
data,
|
||||
},
|
||||
});
|
||||
}
|
||||
);
|
||||
|
|
42
x-pack/plugins/osquery/server/routes/saved_query/types.ts
Normal file
42
x-pack/plugins/osquery/server/routes/saved_query/types.ts
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export interface SavedQueryResponse {
|
||||
saved_object_id: string;
|
||||
id: string;
|
||||
description: string | undefined;
|
||||
query: string;
|
||||
interval: number | string;
|
||||
snapshot?: boolean;
|
||||
removed?: boolean;
|
||||
platform?: string;
|
||||
ecs_mapping?: Array<{ key: string; value: Record<string, object> }>;
|
||||
created_at: string;
|
||||
created_by: string | undefined;
|
||||
updated_at: string;
|
||||
updated_by: string | undefined;
|
||||
prebuilt?: boolean;
|
||||
version: number | string;
|
||||
}
|
||||
|
||||
export interface UpdateSavedQueryResponse {
|
||||
saved_object_id: string;
|
||||
id: string;
|
||||
description: string | undefined;
|
||||
query: string;
|
||||
interval: number | string;
|
||||
snapshot?: boolean;
|
||||
removed?: boolean;
|
||||
platform?: string;
|
||||
ecs_mapping?: Array<{ key: string; value: object }>;
|
||||
created_at: string;
|
||||
created_by: string | undefined;
|
||||
updated_at: string;
|
||||
updated_by: string | undefined;
|
||||
prebuilt?: boolean;
|
||||
version: string;
|
||||
}
|
|
@ -14,6 +14,7 @@ import { PLUGIN_ID } from '../../../common';
|
|||
import { savedQuerySavedObjectType } from '../../../common/types';
|
||||
import type { OsqueryAppContext } from '../../lib/osquery_app_context_services';
|
||||
import { convertECSMappingToArray, convertECSMappingToObject } from '../utils';
|
||||
import type { UpdateSavedQueryResponse } from './types';
|
||||
|
||||
export const updateSavedQueryRoute = (router: IRouter, osqueryContext: OsqueryAppContext) => {
|
||||
router.put(
|
||||
|
@ -122,9 +123,26 @@ export const updateSavedQueryRoute = (router: IRouter, osqueryContext: OsqueryAp
|
|||
{};
|
||||
}
|
||||
|
||||
const { attributes } = updatedSavedQuerySO;
|
||||
|
||||
const data: Partial<UpdateSavedQueryResponse> = {
|
||||
description: attributes.description,
|
||||
id: attributes.id,
|
||||
removed: attributes.removed,
|
||||
snapshot: attributes.snapshot,
|
||||
version: attributes.version,
|
||||
ecs_mapping: attributes.ecs_mapping,
|
||||
interval: attributes.interval,
|
||||
platform: attributes.platform,
|
||||
query: attributes.query,
|
||||
updated_at: attributes.updated_at,
|
||||
updated_by: attributes.updated_by,
|
||||
saved_object_id: updatedSavedQuerySO.id,
|
||||
};
|
||||
|
||||
return response.ok({
|
||||
body: {
|
||||
data: { ...updatedSavedQuerySO.attributes, saved_object_id: updatedSavedQuerySO.id },
|
||||
data,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue