Skip to content

Commit

Permalink
do not fetch package policies without needed privileges
Browse files Browse the repository at this point in the history
  • Loading branch information
gergoabraham committed Nov 22, 2024
1 parent 63ca011 commit ffafa14
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 41 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import {
calculateEndpointAuthz,
canFetchAgentPolicies,
canFetchPackageAndAgentPolicies,
getEndpointAuthzInitialState,
} from './authz';
import type { FleetAuthz } from '@kbn/fleet-plugin/common';
Expand Down Expand Up @@ -355,7 +355,7 @@ describe('Endpoint Authz service', () => {
});
});

describe('canFetchAgentPolicies()', () => {
describe('canFetchPackageAndAgentPolicies()', () => {
describe('without granular Fleet permissions', () => {
it.each`
readFleet | readIntegrations | readPolicyManagement | result
Expand All @@ -376,7 +376,7 @@ describe('Endpoint Authz service', () => {
fleet: { read: readIntegrations },
};

expect(canFetchAgentPolicies(capabilities as Capabilities)).toBe(result);
expect(canFetchPackageAndAgentPolicies(capabilities as Capabilities)).toBe(result);
}
);
});
Expand Down Expand Up @@ -409,7 +409,7 @@ describe('Endpoint Authz service', () => {
fleet: { read: readIntegrations },
};

expect(canFetchAgentPolicies(capabilities as Capabilities)).toBe(result);
expect(canFetchPackageAndAgentPolicies(capabilities as Capabilities)).toBe(result);
}
);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ export const getEndpointAuthzInitialState = (): EndpointAuthz => {
*
* @param capabilities Capabilities from coreStart.application
*/
export const canFetchAgentPolicies = (capabilities: Capabilities): boolean => {
export const canFetchPackageAndAgentPolicies = (capabilities: Capabilities): boolean => {
const canReadPolicyManagement = (capabilities.siem?.readPolicyManagement ?? false) as boolean;

const fleetv2 = capabilities.fleetv2;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,13 @@ import {
import { endpointPageHttpMock, failedTransformStateMock } from '../mocks';
import { HOST_METADATA_LIST_ROUTE } from '../../../../../common/endpoint/constants';
import { INGEST_API_PACKAGE_POLICIES } from '../../../services/policies/ingest';
import { canFetchAgentPolicies } from '../../../../../common/endpoint/service/authz/authz';
import { canFetchPackageAndAgentPolicies } from '../../../../../common/endpoint/service/authz/authz';

const mockSendBulkGetPackagePolicies = jest.fn();
jest.mock('../../../services/policies/ingest', () => ({
sendGetAgentConfigList: () => Promise.resolve({ items: [] }),
sendGetAgentPolicyList: () => Promise.resolve({ items: [] }),
sendBulkGetPackagePolicies: () => Promise.resolve({ items: [] }),
sendBulkGetPackagePolicies: () => mockSendBulkGetPackagePolicies(),
sendGetEndpointSecurityPackage: () => Promise.resolve({ version: '1.1.1' }),
}));

Expand All @@ -61,9 +62,9 @@ jest.mock('rxjs', () => ({

jest.mock('../../../../../common/endpoint/service/authz/authz', () => ({
...jest.requireActual('../../../../../common/endpoint/service/authz/authz'),
canFetchAgentPolicies: jest.fn(),
canFetchPackageAndAgentPolicies: jest.fn(),
}));
const canFetchAgentPoliciesMock = canFetchAgentPolicies as jest.Mock;
const canFetchAgentPoliciesMock = canFetchPackageAndAgentPolicies as jest.Mock;

type EndpointListStore = Store<Immutable<EndpointState>, Immutable<AppAction>>;

Expand Down Expand Up @@ -110,36 +111,66 @@ describe('endpoint list middleware', () => {
history = createBrowserHistory();
getKibanaServicesMock.mockReturnValue(fakeCoreStart);
canFetchAgentPoliciesMock.mockReturnValue(false);
mockSendBulkGetPackagePolicies.mockResolvedValue({ items: [] });
});

describe('handles `userChangedUrl`', () => {
it('should not fetch agent policies if there are hosts', async () => {
endpointPageHttpMock(fakeHttpServices);
const apiResponse = getEndpointListApiResponse();
fakeHttpServices.get.mockResolvedValue(apiResponse);

dispatchUserChangedUrlToEndpointList();

await Promise.all([
waitForAction('serverReturnedEndpointList'),
waitForAction('serverReturnedEndpointExistValue', {
validate: ({ payload }) => payload === true,
}),
waitForAction('serverCancelledPolicyItemsLoading'),
]);
expect(fakeHttpServices.get).toHaveBeenNthCalledWith(1, HOST_METADATA_LIST_ROUTE, {
query: {
page: '0',
pageSize: '10',
kuery: '',
},
version: '2023-10-31',
describe('when there are hosts', () => {
let apiResponse: MetadataListResponse;

beforeEach(() => {
endpointPageHttpMock(fakeHttpServices);
apiResponse = getEndpointListApiResponse();
fakeHttpServices.get.mockResolvedValue(apiResponse);
});

it('should not fetch agent policies if there are hosts', async () => {
dispatchUserChangedUrlToEndpointList();

await Promise.all([
waitForAction('serverReturnedEndpointList'),
waitForAction('serverReturnedEndpointExistValue', {
validate: ({ payload }) => payload === true,
}),
waitForAction('serverCancelledPolicyItemsLoading'),
]);
expect(fakeHttpServices.get).toHaveBeenNthCalledWith(1, HOST_METADATA_LIST_ROUTE, {
query: {
page: '0',
pageSize: '10',
kuery: '',
},
version: '2023-10-31',
});
expect(listData(getState())).toEqual(apiResponse.data);
expect(fakeHttpServices.get).not.toHaveBeenCalledWith(
INGEST_API_PACKAGE_POLICIES,
expect.objectContaining({})
);
});

describe('fetching non-existing policies', () => {
it('should not fetch package policies without required privileges', async () => {
canFetchAgentPoliciesMock.mockReturnValue(false);

dispatchUserChangedUrlToEndpointList();

await waitForAction('serverFinishedInitialization');
expect(mockSendBulkGetPackagePolicies).not.toBeCalled();
});

it('should fetch package policies with required privileges', async () => {
canFetchAgentPoliciesMock.mockReturnValue(true);

dispatchUserChangedUrlToEndpointList();

await Promise.all([
waitForAction('serverFinishedInitialization'),
waitForAction('serverReturnedEndpointNonExistingPolicies'),
]);
expect(mockSendBulkGetPackagePolicies).toBeCalled();
});
});
expect(listData(getState())).toEqual(apiResponse.data);
expect(fakeHttpServices.get).not.toHaveBeenCalledWith(
INGEST_API_PACKAGE_POLICIES,
expect.objectContaining({})
);
});

describe('when there are no hosts', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import type {
IndexFieldsStrategyRequest,
IndexFieldsStrategyResponse,
} from '@kbn/timelines-plugin/common';
import { canFetchAgentPolicies } from '../../../../../common/endpoint/service/authz/authz';
import { canFetchPackageAndAgentPolicies } from '../../../../../common/endpoint/service/authz/authz';
import type {
IsolationRouteRequestBody,
UnisolationRouteRequestBody,
Expand Down Expand Up @@ -321,7 +321,7 @@ async function endpointListMiddleware({
payload: endpointResponse,
});

fetchNonExistingPolicies({ http: coreStart.http, hosts: endpointResponse.data, store });
fetchNonExistingPolicies({ coreStart, hosts: endpointResponse.data, store });
} catch (error) {
dispatch({
type: 'serverFailedToReturnEndpointList',
Expand Down Expand Up @@ -367,7 +367,7 @@ async function endpointListMiddleware({
payload: false,
});

if (canFetchAgentPolicies(coreStart.application.capabilities)) {
if (canFetchPackageAndAgentPolicies(coreStart.application.capabilities)) {
try {
const policyDataResponse: GetPolicyListResponse =
await sendGetEndpointSpecificPackagePolicies(http, {
Expand Down Expand Up @@ -447,16 +447,20 @@ export async function handleLoadMetadataTransformStats(http: HttpStart, store: E
async function fetchNonExistingPolicies({
store,
hosts,
http,
coreStart,
}: {
store: EndpointPageStore;
hosts: HostResultList['hosts'];
http: HttpStart;
coreStart: CoreStart;
}) {
if (!canFetchPackageAndAgentPolicies(coreStart.application.capabilities)) {
return;
}

const { getState, dispatch } = store;
try {
const missingPolicies = await getNonExistingPoliciesForEndpointList(
http,
coreStart.http,
hosts,
nonExistingPolicies(getState())
);
Expand Down

0 comments on commit ffafa14

Please sign in to comment.