Skip to content

Commit b320cba

Browse files
committed
[Security Solution] relax metadata + policy response API permissions
1 parent e1363b6 commit b320cba

6 files changed

Lines changed: 41 additions & 18 deletions

File tree

x-pack/plugins/security_solution/server/endpoint/routes/metadata/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,10 @@ export function registerEndpointRoutes(
6767
{
6868
path: HOST_METADATA_GET_ROUTE,
6969
validate: GetMetadataRequestSchema,
70-
options: { authRequired: true, tags: ['access:securitySolution'] },
70+
options: { authRequired: true },
7171
},
7272
withEndpointAuthz(
73-
{ all: ['canReadSecuritySolution'] },
73+
{ any: ['canReadSecuritySolution', 'canAccessFleet'] },
7474
logger,
7575
getMetadataRequestHandler(endpointAppContext, logger)
7676
)

x-pack/plugins/security_solution/server/endpoint/routes/metadata/metadata.test.ts

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -674,7 +674,6 @@ describe('test endpoint routes', () => {
674674
expect(esSearchMock).toHaveBeenCalledTimes(1);
675675
expect(routeConfig.options).toEqual({
676676
authRequired: true,
677-
tags: ['access:securitySolution'],
678677
});
679678
expect(mockResponse.notFound).toBeCalled();
680679
const message = mockResponse.notFound.mock.calls[0][0]?.body;
@@ -706,7 +705,6 @@ describe('test endpoint routes', () => {
706705
expect(esSearchMock).toHaveBeenCalledTimes(1);
707706
expect(routeConfig.options).toEqual({
708707
authRequired: true,
709-
tags: ['access:securitySolution'],
710708
});
711709
expect(mockResponse.ok).toBeCalled();
712710
const result = mockResponse.ok.mock.calls[0][0]?.body as HostInfo;
@@ -741,7 +739,6 @@ describe('test endpoint routes', () => {
741739
expect(esSearchMock).toHaveBeenCalledTimes(1);
742740
expect(routeConfig.options).toEqual({
743741
authRequired: true,
744-
tags: ['access:securitySolution'],
745742
});
746743
expect(mockResponse.ok).toBeCalled();
747744
const result = mockResponse.ok.mock.calls[0][0]?.body as HostInfo;
@@ -778,7 +775,6 @@ describe('test endpoint routes', () => {
778775
expect(esSearchMock).toHaveBeenCalledTimes(1);
779776
expect(routeConfig.options).toEqual({
780777
authRequired: true,
781-
tags: ['access:securitySolution'],
782778
});
783779
expect(mockResponse.ok).toBeCalled();
784780
const result = mockResponse.ok.mock.calls[0][0]?.body as HostInfo;
@@ -814,15 +810,48 @@ describe('test endpoint routes', () => {
814810
expect(mockResponse.badRequest).toBeCalled();
815811
});
816812

817-
it('should get forbidden if no security solution access', async () => {
813+
it('should work if no security solution access but has fleet access', async () => {
814+
const response = legacyMetadataSearchResponseMock(
815+
new EndpointDocGenerator().generateHostMetadata()
816+
);
817+
const mockRequest = httpServerMock.createKibanaRequest({
818+
params: { id: response.hits.hits[0]._id },
819+
});
820+
const esSearchMock = mockScopedClient.asInternalUser.search;
821+
822+
mockAgentClient.getAgent.mockResolvedValue(agentGenerator.generate({ status: 'online' }));
823+
esSearchMock.mockResponseOnce(response);
824+
825+
[routeConfig, routeHandler] = routerMock.get.mock.calls.find(([{ path }]) =>
826+
path.startsWith(HOST_METADATA_GET_ROUTE)
827+
)!;
828+
829+
const contextOverrides = {
830+
endpointAuthz: getEndpointAuthzInitialStateMock({
831+
canReadSecuritySolution: false,
832+
}),
833+
};
834+
await routeHandler(
835+
createRouteHandlerContext(mockScopedClient, mockSavedObjectClient, contextOverrides),
836+
mockRequest,
837+
mockResponse
838+
);
839+
840+
expect(mockResponse.ok).toBeCalled();
841+
});
842+
843+
it('should get forbidden if no security solution or fleet access', async () => {
818844
const mockRequest = httpServerMock.createKibanaRequest();
819845

820846
[routeConfig, routeHandler] = routerMock.get.mock.calls.find(([{ path }]) =>
821847
path.startsWith(HOST_METADATA_GET_ROUTE)
822848
)!;
823849

824850
const contextOverrides = {
825-
endpointAuthz: getEndpointAuthzInitialStateMock({ canReadSecuritySolution: false }),
851+
endpointAuthz: getEndpointAuthzInitialStateMock({
852+
canAccessFleet: false,
853+
canReadSecuritySolution: false,
854+
}),
826855
};
827856
await routeHandler(
828857
createRouteHandlerContext(mockScopedClient, mockSavedObjectClient, contextOverrides),

x-pack/plugins/security_solution/server/endpoint/routes/policy/handlers.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ describe('test policy response handler', () => {
5555
const response = createSearchResponse(new EndpointDocGenerator().generatePolicyResponse());
5656
const hostPolicyResponseHandler = getHostPolicyResponseHandler();
5757

58-
mockScopedClient.asCurrentUser.search.mockResponseOnce(response);
58+
mockScopedClient.asInternalUser.search.mockResponseOnce(response);
5959
const mockRequest = httpServerMock.createKibanaRequest({
6060
params: { agentId: 'id' },
6161
});
@@ -78,7 +78,7 @@ describe('test policy response handler', () => {
7878
it('should return not found when there is no response policy for host', async () => {
7979
const hostPolicyResponseHandler = getHostPolicyResponseHandler();
8080

81-
mockScopedClient.asCurrentUser.search.mockResponseOnce(createSearchResponse());
81+
mockScopedClient.asInternalUser.search.mockResponseOnce(createSearchResponse());
8282

8383
const mockRequest = httpServerMock.createKibanaRequest({
8484
params: { agentId: 'id' },

x-pack/plugins/security_solution/server/endpoint/routes/policy/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ export function registerPolicyRoutes(router: IRouter, endpointAppContext: Endpoi
3030
options: { authRequired: true },
3131
},
3232
withEndpointAuthz(
33-
{ all: ['canAccessEndpointManagement'] },
33+
{ any: ['canReadSecuritySolution', 'canAccessFleet'] },
3434
logger,
3535
getHostPolicyResponseHandler()
3636
)

x-pack/plugins/security_solution/server/endpoint/routes/policy/service.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ export async function getPolicyResponseByAgentId(
5151
dataClient: IScopedClusterClient
5252
): Promise<GetHostPolicyResponse | undefined> {
5353
const query = getESQueryPolicyResponseByAgentID(agentID, index);
54-
const response = await dataClient.asCurrentUser.search<HostPolicyResponse>(query);
54+
const response = await dataClient.asInternalUser.search<HostPolicyResponse>(query);
5555

5656
if (response.hits.hits.length > 0 && response.hits.hits[0]._source != null) {
5757
return {

x-pack/test/security_solution_endpoint_api_int/apis/endpoint_authz.ts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
import { wrapErrorAndRejectPromise } from '@kbn/security-solution-plugin/common/endpoint/data_loaders/utils';
99
import {
1010
AGENT_POLICY_SUMMARY_ROUTE,
11-
BASE_POLICY_RESPONSE_ROUTE,
1211
GET_PROCESSES_ROUTE,
1312
ISOLATE_HOST_ROUTE,
1413
ISOLATE_HOST_ROUTE_V2,
@@ -49,11 +48,6 @@ export default function ({ getService }: FtrProviderContext) {
4948
path: '/api/endpoint/action_log/one?start_date=2021-12-01&end_date=2021-12-04',
5049
body: undefined,
5150
},
52-
{
53-
method: 'get',
54-
path: `${BASE_POLICY_RESPONSE_ROUTE}?agentId=1`,
55-
body: undefined,
56-
},
5751
{
5852
method: 'post',
5953
path: ISOLATE_HOST_ROUTE,

0 commit comments

Comments
 (0)