Skip to content
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 @@ -8,7 +8,7 @@
import { filter, unset } from 'lodash';
import { produce } from 'immer';
import { PACKAGE_POLICY_SAVED_OBJECT_TYPE } from '@kbn/fleet-plugin/common';
import type { IRouter } from '@kbn/core/server';
import { type IRouter, SavedObjectsErrorHelpers } from '@kbn/core/server';

import { DEFAULT_SPACE_ID } from '@kbn/spaces-utils';
import type { DeletePacksRequestParamsSchema } from '../../../common/api';
Expand Down Expand Up @@ -60,10 +60,21 @@ export const deletePackRoute = (router: IRouter, osqueryContext: OsqueryAppConte
? (await osqueryContext.service.getActiveSpace(request))?.id || DEFAULT_SPACE_ID
: DEFAULT_SPACE_ID;

const currentPackSO = await spaceScopedClient.get<{ name: string }>(
packSavedObjectType,
request.params.id
);
let currentPackSO;
try {
currentPackSO = await spaceScopedClient.get<{ name: string }>(
packSavedObjectType,
request.params.id
);
} catch (err) {
if (SavedObjectsErrorHelpers.isNotFoundError(err)) {
return response.notFound({
body: { message: `Pack ${request.params.id} not found` },
});
}

throw err;
}

await spaceScopedClient.delete(packSavedObjectType, request.params.id, {
refresh: 'wait_for',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import { filter, map, mapValues } from 'lodash';
import { LEGACY_AGENT_POLICY_SAVED_OBJECT_TYPE } from '@kbn/fleet-plugin/common';
import type { IRouter } from '@kbn/core/server';
import { type IRouter, SavedObjectsErrorHelpers } from '@kbn/core/server';

import { createInternalSavedObjectsClientForSpaceId } from '../../utils/get_internal_saved_object_client';
import type { ReadPacksRequestParamsSchema } from '../../../common/api';
Expand Down Expand Up @@ -52,8 +52,23 @@ export const readPackRoute = (router: IRouter, osqueryContext: OsqueryAppContext
request
);

const { attributes, references, id, ...rest } =
await spaceScopedClient.get<PackSavedObject>(packSavedObjectType, request.params.id);
let packSO;
try {
packSO = await spaceScopedClient.get<PackSavedObject>(
packSavedObjectType,
request.params.id
);
} catch (err) {
Comment thread
csr marked this conversation as resolved.
if (SavedObjectsErrorHelpers.isNotFoundError(err)) {
return response.notFound({
body: { message: `Pack ${request.params.id} not found` },
});
}

throw err;
}

const { attributes, references, id, ...rest } = packSO;

const policyIds = map(
filter(references, ['type', LEGACY_AGENT_POLICY_SAVED_OBJECT_TYPE]),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import {
LEGACY_AGENT_POLICY_SAVED_OBJECT_TYPE,
PACKAGE_POLICY_SAVED_OBJECT_TYPE,
} from '@kbn/fleet-plugin/common';
import type { IRouter } from '@kbn/core/server';
import { type IRouter, SavedObjectsErrorHelpers } from '@kbn/core/server';

import { DEFAULT_SPACE_ID } from '@kbn/spaces-utils';
import { createInternalSavedObjectsClientForSpaceId } from '../../utils/get_internal_saved_object_client';
Expand Down Expand Up @@ -122,10 +122,21 @@ export const updatePackRoute = (router: IRouter, osqueryContext: OsqueryAppConte
shards = {},
} = request.body;

const currentPackSO = await spaceScopedClient.get<PackSavedObject>(
packSavedObjectType,
request.params.id
);
let currentPackSO;
try {
currentPackSO = await spaceScopedClient.get<PackSavedObject>(
packSavedObjectType,
request.params.id
);
} catch (err) {
if (SavedObjectsErrorHelpers.isNotFoundError(err)) {
return response.notFound({
body: { message: `Pack ${request.params.id} not found` },
});
}

throw err;
}

const existingScheduleIds = keyBy(
(currentPackSO.attributes.queries ?? []).filter(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* 2.0.
*/

import type { IRouter } from '@kbn/core/server';
import { type IRouter, SavedObjectsErrorHelpers } from '@kbn/core/server';
import { DEFAULT_SPACE_ID } from '@kbn/spaces-utils';
import { createInternalSavedObjectsClientForSpaceId } from '../../utils/get_internal_saved_object_client';
import { buildRouteValidation } from '../../utils/build_validation/route_validation';
Expand Down Expand Up @@ -59,9 +59,19 @@ export const deleteSavedQueryRoute = (router: IRouter, osqueryContext: OsqueryAp
return response.conflict({ body: `Elastic prebuilt Saved query cannot be deleted.` });
}

await spaceScopedClient.delete(savedQuerySavedObjectType, request.params.id, {
refresh: 'wait_for',
});
try {
await spaceScopedClient.delete(savedQuerySavedObjectType, request.params.id, {
refresh: 'wait_for',
});
} catch (err) {
if (SavedObjectsErrorHelpers.isNotFoundError(err)) {
return response.notFound({
body: { message: `Saved query ${request.params.id} not found` },
});
}

throw err;
}

return response.ok({
body: {},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* 2.0.
*/

import type { IRouter } from '@kbn/core/server';
import { type IRouter, SavedObjectsErrorHelpers } from '@kbn/core/server';
import { DEFAULT_SPACE_ID } from '@kbn/spaces-utils';
import { createInternalSavedObjectsClientForSpaceId } from '../../utils/get_internal_saved_object_client';
import { buildRouteValidation } from '../../utils/build_validation/route_validation';
Expand Down Expand Up @@ -52,10 +52,21 @@ export const readSavedQueryRoute = (router: IRouter, osqueryContext: OsqueryAppC
const space = await osqueryContext.service.getActiveSpace(request);
const spaceId = space?.id ?? DEFAULT_SPACE_ID;

const savedQuery = await spaceScopedClient.get<SavedQuerySavedObject>(
savedQuerySavedObjectType,
request.params.id
);
let savedQuery;
try {
savedQuery = await spaceScopedClient.get<SavedQuerySavedObject>(
savedQuerySavedObjectType,
request.params.id
);
} catch (err) {
if (SavedObjectsErrorHelpers.isNotFoundError(err)) {
return response.notFound({
body: { message: `Saved query ${request.params.id} not found` },
});
}

throw err;
}

if (savedQuery.attributes.ecs_mapping) {
// @ts-expect-error update types
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import { filter, some } from 'lodash';

import type { IRouter } from '@kbn/core/server';
import { type IRouter, SavedObjectsErrorHelpers } from '@kbn/core/server';
import { DEFAULT_SPACE_ID } from '@kbn/spaces-utils';
import { createInternalSavedObjectsClientForSpaceId } from '../../utils/get_internal_saved_object_client';
import { buildRouteValidation } from '../../utils/build_validation/route_validation';
Expand Down Expand Up @@ -115,28 +115,39 @@ export const updateSavedQueryRoute = (router: IRouter, osqueryContext: OsqueryAp
return response.conflict({ body: `Saved query with id "${id}" already exists.` });
}

const updatedSavedQuerySO = await spaceScopedClient.update(
savedQuerySavedObjectType,
request.params.id,
{
id,
description: description || '',
platform,
query,
version,
interval,
timeout,
snapshot,
removed,
ecs_mapping: convertECSMappingToArray(ecs_mapping),
updated_by: username,
updated_by_profile_uid: profileUid,
updated_at: new Date().toISOString(),
},
{
refresh: 'wait_for',
let updatedSavedQuerySO;
try {
updatedSavedQuerySO = await spaceScopedClient.update(
savedQuerySavedObjectType,
request.params.id,
{
id,
description: description || '',
platform,
query,
version,
interval,
timeout,
snapshot,
removed,
ecs_mapping: convertECSMappingToArray(ecs_mapping),
updated_by: username,
updated_by_profile_uid: profileUid,
updated_at: new Date().toISOString(),
},
{
refresh: 'wait_for',
}
);
} catch (err) {
if (SavedObjectsErrorHelpers.isNotFoundError(err)) {
return response.notFound({
body: { message: `Saved query ${request.params.id} not found` },
});
}
);

throw err;
}

if (ecs_mapping || updatedSavedQuerySO.attributes.ecs_mapping) {
// @ts-expect-error update types
Expand Down
23 changes: 23 additions & 0 deletions x-pack/platform/test/api_integration/apis/osquery/packs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -280,5 +280,28 @@ export default function ({ getService }: FtrProviderContext) {
inputs[0].config.osquery.value.packs['default--TestPack'].queries.testQuery.query
).to.be(singleLineQuery);
});

describe('404 for non-existent resources', () => {
Copy link
Copy Markdown
Member Author

@csr csr Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Making sure these changes have coverage (they previously didn't). While it's true that some (if not all) of these tests will be replaced by Scout, let's ensure these changes are correct right away. These new FTR tests are passing locally.

it('returns 404 when reading a non-existent pack', async () => {
await withOsqueryHeaders(supertest.get('/api/osquery/packs/non-existent-id')).expect(404);
});

it('returns 404 when updating a non-existent pack', async () => {
await withOsqueryHeaders(supertest.put('/api/osquery/packs/non-existent-id'))
.send({
name: 'Updated Pack',
description: 'Updated',
enabled: true,
queries: { q1: { query: 'select 1;', interval: 3600 } },
})
.expect(404);
});

it('returns 404 when deleting a non-existent pack', async () => {
await withOsqueryHeaders(supertest.delete('/api/osquery/packs/non-existent-id')).expect(
404
);
});
});
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -175,5 +175,19 @@ export default function ({ getService }: FtrProviderContext) {
expect(response.body.total).to.be(0);
});
});

describe('404 for non-existent resources', () => {
it('returns 404 when reading a non-existent saved query', async () => {
await getSavedQuery('non-existent-id').expect(404);
});

it('returns 404 when updating a non-existent saved query', async () => {
await updateSavedQuery('non-existent-id', 'updated-name').expect(404);
});

it('returns 404 when deleting a non-existent saved query', async () => {
await deleteSavedQuery('non-existent-id').expect(404);
});
});
});
}
Loading