diff --git a/x-pack/plugins/security_solution/common/endpoint/schema/policy.ts b/x-pack/plugins/security_solution/common/endpoint/schema/policy.ts index 9b02ab073c9ce..dab0845dd252d 100644 --- a/x-pack/plugins/security_solution/common/endpoint/schema/policy.ts +++ b/x-pack/plugins/security_solution/common/endpoint/schema/policy.ts @@ -19,3 +19,21 @@ export const GetAgentPolicySummaryRequestSchema = { policy_id: schema.nullable(schema.string()), }), }; + +const ListWithKuerySchema = schema.object({ + page: schema.maybe(schema.number({ defaultValue: 1 })), + pageSize: schema.maybe(schema.number({ defaultValue: 20 })), + sort: schema.maybe(schema.string()), + sortOrder: schema.maybe(schema.oneOf([schema.literal('desc'), schema.literal('asc')])), + showUpgradeable: schema.maybe(schema.boolean()), + kuery: schema.maybe( + schema.oneOf([ + schema.string(), + schema.any(), // KueryNode + ]) + ), +}); + +export const GetEndpointPackagePolicyRequestSchema = { + query: ListWithKuerySchema, +}; diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/policy/handlers.test.ts b/x-pack/plugins/security_solution/server/endpoint/routes/policy/handlers.test.ts index b8efa2636d8c7..527afe23b694d 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/policy/handlers.test.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/policy/handlers.test.ts @@ -11,8 +11,17 @@ import { createMockEndpointAppContextServiceStartContract, createRouteHandlerContext, } from '../../mocks'; -import { createMockAgentClient, createMockAgentService } from '../../../../../fleet/server/mocks'; -import { getHostPolicyResponseHandler, getAgentPolicySummaryHandler } from './handlers'; +import { + createMockAgentClient, + createMockAgentService, + createPackagePolicyServiceMock, +} from '../../../../../fleet/server/mocks'; +import { PACKAGE_POLICY_SAVED_OBJECT_TYPE } from '../../../../../fleet/common'; +import { + getHostPolicyResponseHandler, + getAgentPolicySummaryHandler, + getPolicyListHandler, +} from './handlers'; import { KibanaResponseFactory, SavedObjectsClientContract, @@ -33,6 +42,7 @@ import { AgentClient, AgentService } from '../../../../../fleet/server/services' import { get } from 'lodash'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { ScopedClusterClientMock } from '../../../../../../../src/core/server/elasticsearch/client/mocks'; +import { PackagePolicyServiceInterface } from '../../../../../fleet/server'; describe('test policy response handler', () => { let endpointAppContextService: EndpointAppContextService; @@ -236,6 +246,80 @@ describe('test policy response handler', () => { }); }); }); + describe('test GET policy list handler', () => { + let mockPackagePolicyService: jest.Mocked; + let policyHandler: ReturnType; + + beforeEach(() => { + mockScopedClient = elasticsearchServiceMock.createScopedClusterClient(); + mockSavedObjectClient = savedObjectsClientMock.create(); + mockResponse = httpServerMock.createResponseFactory(); + mockPackagePolicyService = createPackagePolicyServiceMock(); + mockPackagePolicyService.list.mockImplementation(() => { + return Promise.resolve({ + items: [], + total: 0, + page: 1, + perPage: 10, + }); + }); + endpointAppContextService = new EndpointAppContextService(); + endpointAppContextService.setup(createMockEndpointAppContextServiceSetupContract()); + endpointAppContextService.start({ + ...createMockEndpointAppContextServiceStartContract(), + ...{ packagePolicyService: mockPackagePolicyService }, + }); + policyHandler = getPolicyListHandler({ + logFactory: loggingSystemMock.create(), + service: endpointAppContextService, + config: () => Promise.resolve(createMockConfig()), + experimentalFeatures: parseExperimentalConfigValue(createMockConfig().enableExperimental), + }); + }); + + afterEach(() => endpointAppContextService.stop()); + + it('should return a list of endpoint package policies', async () => { + const mockRequest = httpServerMock.createKibanaRequest({ + query: {}, + }); + + await policyHandler( + createRouteHandlerContext(mockScopedClient, mockSavedObjectClient), + mockRequest, + mockResponse + ); + expect(mockPackagePolicyService.list.mock.calls[0][1]).toEqual({ + kuery: `${PACKAGE_POLICY_SAVED_OBJECT_TYPE}.package.name: endpoint`, + perPage: undefined, + sortField: undefined, + }); + expect(mockResponse.ok).toBeCalled(); + expect(mockResponse.ok.mock.calls[0][0]?.body).toEqual({ + items: [], + total: 0, + page: 1, + perPage: 10, + }); + }); + + it('should add endpoint-specific kuery to the requests kuery', async () => { + const mockRequest = httpServerMock.createKibanaRequest({ + query: { kuery: 'some query' }, + }); + + await policyHandler( + createRouteHandlerContext(mockScopedClient, mockSavedObjectClient), + mockRequest, + mockResponse + ); + expect(mockPackagePolicyService.list.mock.calls[0][1]).toEqual({ + kuery: `(some query) and ${PACKAGE_POLICY_SAVED_OBJECT_TYPE}.package.name: endpoint`, + perPage: undefined, + sortField: undefined, + }); + }); + }); }); /** diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/policy/handlers.ts b/x-pack/plugins/security_solution/server/endpoint/routes/policy/handlers.ts index 0e40836c28337..9a63f898277a8 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/policy/handlers.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/policy/handlers.ts @@ -11,10 +11,13 @@ import { policyIndexPattern } from '../../../../common/endpoint/constants'; import { GetPolicyResponseSchema, GetAgentPolicySummaryRequestSchema, + GetEndpointPackagePolicyRequestSchema, } from '../../../../common/endpoint/schema/policy'; import { EndpointAppContext } from '../../types'; import { getAgentPolicySummary, getPolicyResponseByAgentId } from './service'; import { GetAgentSummaryResponse } from '../../../../common/endpoint/types'; +import { wrapErrorIfNeeded } from '../../utils'; +import { PACKAGE_POLICY_SAVED_OBJECT_TYPE } from '../../../../../fleet/common'; export const getHostPolicyResponseHandler = function (): RequestHandler< undefined, @@ -64,3 +67,33 @@ export const getAgentPolicySummaryHandler = function ( }); }; }; + +export const getPolicyListHandler = function ( + endpointAppContext: EndpointAppContext +): RequestHandler< + undefined, + TypeOf, + undefined +> { + return async (context, request, response) => { + const soClient = context.core.savedObjects.client; + const fleetServices = endpointAppContext.service.getScopedFleetServices(request); + const endpointFilteredKuery = `${ + request?.query?.kuery ? `(${request.query.kuery}) and ` : '' + }${PACKAGE_POLICY_SAVED_OBJECT_TYPE}.package.name: endpoint`; + try { + const listResponse = await fleetServices.packagePolicy.list(soClient, { + ...request.query, + perPage: request.query.pageSize, + sortField: request.query.sort, + kuery: endpointFilteredKuery, + }); + + return response.ok({ + body: listResponse, + }); + } catch (error) { + throw wrapErrorIfNeeded(error); + } + }; +}; diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/policy/index.ts b/x-pack/plugins/security_solution/server/endpoint/routes/policy/index.ts index 50a68debc1125..c4432e9f0163e 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/policy/index.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/policy/index.ts @@ -10,10 +10,16 @@ import { EndpointAppContext } from '../../types'; import { GetPolicyResponseSchema, GetAgentPolicySummaryRequestSchema, + GetEndpointPackagePolicyRequestSchema, } from '../../../../common/endpoint/schema/policy'; -import { getHostPolicyResponseHandler, getAgentPolicySummaryHandler } from './handlers'; +import { + getHostPolicyResponseHandler, + getAgentPolicySummaryHandler, + getPolicyListHandler, +} from './handlers'; import { AGENT_POLICY_SUMMARY_ROUTE, + BASE_POLICY_ROUTE, BASE_POLICY_RESPONSE_ROUTE, } from '../../../../common/endpoint/constants'; @@ -37,4 +43,13 @@ export function registerPolicyRoutes(router: IRouter, endpointAppContext: Endpoi }, getAgentPolicySummaryHandler(endpointAppContext) ); + + router.get( + { + path: BASE_POLICY_ROUTE, + validate: GetEndpointPackagePolicyRequestSchema, + options: { authRequired: true }, + }, + getPolicyListHandler(endpointAppContext) + ); }