mirror of
https://github.com/elastic/kibana.git
synced 2025-04-25 02:09:32 -04:00
[Security Solution] use endpoint rbac for isolate/unisolate host (#141810)
This commit is contained in:
parent
27483d5aa9
commit
e4080d5b64
9 changed files with 137 additions and 42 deletions
|
@ -15,7 +15,10 @@ import { ENDPOINT_PRIVILEGES } from './constants';
|
||||||
|
|
||||||
const SECURITY_SOLUTION_ID = DEFAULT_APP_CATEGORIES.security.id;
|
const SECURITY_SOLUTION_ID = DEFAULT_APP_CATEGORIES.security.id;
|
||||||
|
|
||||||
function generateActions(privileges: string[] = [], overrides: Record<string, boolean> = {}) {
|
function generateActions(
|
||||||
|
privileges: typeof ENDPOINT_PRIVILEGES,
|
||||||
|
overrides: Record<string, boolean> = {}
|
||||||
|
) {
|
||||||
return privileges.reduce((acc, privilege) => {
|
return privileges.reduce((acc, privilege) => {
|
||||||
const executePackageAction = overrides[privilege] || false;
|
const executePackageAction = overrides[privilege] || false;
|
||||||
|
|
||||||
|
|
|
@ -23,4 +23,4 @@ export const ENDPOINT_PRIVILEGES = [
|
||||||
'writeHostIsolation',
|
'writeHostIsolation',
|
||||||
'writeProcessOperations',
|
'writeProcessOperations',
|
||||||
'writeFileOperations',
|
'writeFileOperations',
|
||||||
];
|
] as const;
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
import type { DeletePackagePoliciesResponse, NewPackagePolicy, PackagePolicy } from './types';
|
import type { DeletePackagePoliciesResponse, NewPackagePolicy, PackagePolicy } from './types';
|
||||||
import type { FleetAuthz } from './authz';
|
import type { FleetAuthz } from './authz';
|
||||||
|
import { ENDPOINT_PRIVILEGES } from './constants';
|
||||||
|
|
||||||
export const createNewPackagePolicyMock = (): NewPackagePolicy => {
|
export const createNewPackagePolicyMock = (): NewPackagePolicy => {
|
||||||
return {
|
return {
|
||||||
|
@ -61,6 +62,15 @@ export const deletePackagePolicyMock = (): DeletePackagePoliciesResponse => {
|
||||||
* Creates mock `authz` object
|
* Creates mock `authz` object
|
||||||
*/
|
*/
|
||||||
export const createFleetAuthzMock = (): FleetAuthz => {
|
export const createFleetAuthzMock = (): FleetAuthz => {
|
||||||
|
const endpointActions = ENDPOINT_PRIVILEGES.reduce((acc, privilege) => {
|
||||||
|
return {
|
||||||
|
...acc,
|
||||||
|
[privilege]: {
|
||||||
|
executePackageAction: true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}, {});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
fleet: {
|
fleet: {
|
||||||
all: true,
|
all: true,
|
||||||
|
@ -80,5 +90,10 @@ export const createFleetAuthzMock = (): FleetAuthz => {
|
||||||
readIntegrationPolicies: true,
|
readIntegrationPolicies: true,
|
||||||
writeIntegrationPolicies: true,
|
writeIntegrationPolicies: true,
|
||||||
},
|
},
|
||||||
|
packagePrivileges: {
|
||||||
|
endpoint: {
|
||||||
|
actions: endpointActions,
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -107,6 +107,40 @@ describe('Endpoint Authz service', () => {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('endpoint rbac is enabled', () => {
|
||||||
|
describe('canIsolateHost', () => {
|
||||||
|
it('should be true if packagePrivilege.writeHostIsolation is true', () => {
|
||||||
|
fleetAuthz.packagePrivileges!.endpoint.actions.writeHostIsolation.executePackageAction =
|
||||||
|
true;
|
||||||
|
const authz = calculateEndpointAuthz(licenseService, fleetAuthz, userRoles, true);
|
||||||
|
expect(authz.canIsolateHost).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be false if packagePrivilege.writeHostIsolation is false', () => {
|
||||||
|
fleetAuthz.packagePrivileges!.endpoint.actions.writeHostIsolation.executePackageAction =
|
||||||
|
false;
|
||||||
|
const authz = calculateEndpointAuthz(licenseService, fleetAuthz, userRoles, true);
|
||||||
|
expect(authz.canIsolateHost).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('canUnIsolateHost', () => {
|
||||||
|
it('should be true if packagePrivilege.writeHostIsolation is true', () => {
|
||||||
|
fleetAuthz.packagePrivileges!.endpoint.actions.writeHostIsolation.executePackageAction =
|
||||||
|
true;
|
||||||
|
const authz = calculateEndpointAuthz(licenseService, fleetAuthz, userRoles, true);
|
||||||
|
expect(authz.canUnIsolateHost).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be false if packagePrivilege.writeHostIsolation is false', () => {
|
||||||
|
fleetAuthz.packagePrivileges!.endpoint.actions.writeHostIsolation.executePackageAction =
|
||||||
|
false;
|
||||||
|
const authz = calculateEndpointAuthz(licenseService, fleetAuthz, userRoles, true);
|
||||||
|
expect(authz.canUnIsolateHost).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('getEndpointAuthzInitialState()', () => {
|
describe('getEndpointAuthzInitialState()', () => {
|
||||||
|
|
|
@ -28,14 +28,18 @@ export const calculateEndpointAuthz = (
|
||||||
const isPlatinumPlusLicense = licenseService.isPlatinumPlus();
|
const isPlatinumPlusLicense = licenseService.isPlatinumPlus();
|
||||||
const isEnterpriseLicense = licenseService.isEnterprise();
|
const isEnterpriseLicense = licenseService.isEnterprise();
|
||||||
const hasEndpointManagementAccess = userRoles.includes('superuser');
|
const hasEndpointManagementAccess = userRoles.includes('superuser');
|
||||||
|
const canIsolateHost = isEndpointRbacEnabled
|
||||||
|
? fleetAuthz.packagePrivileges?.endpoint?.actions?.writeHostIsolation?.executePackageAction ||
|
||||||
|
false
|
||||||
|
: hasEndpointManagementAccess;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
canAccessFleet: fleetAuthz?.fleet.all ?? userRoles.includes('superuser'),
|
canAccessFleet: fleetAuthz?.fleet.all ?? userRoles.includes('superuser'),
|
||||||
canAccessEndpointManagement: hasEndpointManagementAccess,
|
canAccessEndpointManagement: hasEndpointManagementAccess,
|
||||||
canCreateArtifactsByPolicy: hasEndpointManagementAccess && isPlatinumPlusLicense,
|
canCreateArtifactsByPolicy: hasEndpointManagementAccess && isPlatinumPlusLicense,
|
||||||
// Response Actions
|
// Response Actions
|
||||||
canIsolateHost: isPlatinumPlusLicense && hasEndpointManagementAccess,
|
canIsolateHost: isPlatinumPlusLicense && canIsolateHost,
|
||||||
canUnIsolateHost: hasEndpointManagementAccess,
|
canUnIsolateHost: canIsolateHost,
|
||||||
canKillProcess: hasEndpointManagementAccess && isEnterpriseLicense,
|
canKillProcess: hasEndpointManagementAccess && isEnterpriseLicense,
|
||||||
canSuspendProcess: hasEndpointManagementAccess && isEnterpriseLicense,
|
canSuspendProcess: hasEndpointManagementAccess && isEnterpriseLicense,
|
||||||
canGetRunningProcesses: hasEndpointManagementAccess && isEnterpriseLicense,
|
canGetRunningProcesses: hasEndpointManagementAccess && isEnterpriseLicense,
|
||||||
|
|
|
@ -7,15 +7,19 @@
|
||||||
|
|
||||||
import type { RenderHookResult, RenderResult } from '@testing-library/react-hooks';
|
import type { RenderHookResult, RenderResult } from '@testing-library/react-hooks';
|
||||||
import { act, renderHook } from '@testing-library/react-hooks';
|
import { act, renderHook } from '@testing-library/react-hooks';
|
||||||
import { useCurrentUser, useKibana } from '../../../lib/kibana';
|
|
||||||
import { useEndpointPrivileges } from './use_endpoint_privileges';
|
|
||||||
import { securityMock } from '@kbn/security-plugin/public/mocks';
|
import { securityMock } from '@kbn/security-plugin/public/mocks';
|
||||||
import type { AuthenticatedUser } from '@kbn/security-plugin/common';
|
import type { AuthenticatedUser } from '@kbn/security-plugin/common';
|
||||||
import { licenseService } from '../../../hooks/use_license';
|
import { createFleetAuthzMock } from '@kbn/fleet-plugin/common';
|
||||||
import { getEndpointPrivilegesInitialStateMock } from './mocks';
|
|
||||||
import type { EndpointPrivileges } from '../../../../../common/endpoint/types';
|
import type { EndpointPrivileges } from '../../../../../common/endpoint/types';
|
||||||
|
import { useCurrentUser, useKibana } from '../../../lib/kibana';
|
||||||
|
import { licenseService } from '../../../hooks/use_license';
|
||||||
|
import { useEndpointPrivileges } from './use_endpoint_privileges';
|
||||||
|
import { getEndpointPrivilegesInitialStateMock } from './mocks';
|
||||||
import { getEndpointPrivilegesInitialState } from './utils';
|
import { getEndpointPrivilegesInitialState } from './utils';
|
||||||
|
|
||||||
|
const useKibanaMock = useKibana as jest.Mocked<typeof useKibana>;
|
||||||
jest.mock('../../../lib/kibana');
|
jest.mock('../../../lib/kibana');
|
||||||
jest.mock('../../../hooks/use_license', () => {
|
jest.mock('../../../hooks/use_license', () => {
|
||||||
const licenseServiceInstance = {
|
const licenseServiceInstance = {
|
||||||
|
@ -47,6 +51,7 @@ describe('When using useEndpointPrivileges hook', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
(useCurrentUser as jest.Mock).mockReturnValue(authenticatedUser);
|
(useCurrentUser as jest.Mock).mockReturnValue(authenticatedUser);
|
||||||
|
useKibanaMock().services.fleet!.authz = createFleetAuthzMock();
|
||||||
|
|
||||||
licenseServiceMock.isPlatinumPlus.mockReturnValue(true);
|
licenseServiceMock.isPlatinumPlus.mockReturnValue(true);
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,9 @@ import { act } from '@testing-library/react';
|
||||||
import { endpointPageHttpMock } from '../../../mocks';
|
import { endpointPageHttpMock } from '../../../mocks';
|
||||||
import { fireEvent } from '@testing-library/dom';
|
import { fireEvent } from '@testing-library/dom';
|
||||||
import { licenseService } from '../../../../../../common/hooks/use_license';
|
import { licenseService } from '../../../../../../common/hooks/use_license';
|
||||||
|
import { useUserPrivileges } from '../../../../../../common/components/user_privileges';
|
||||||
|
import { initialUserPrivilegesState } from '../../../../../../common/components/user_privileges/user_privileges_context';
|
||||||
|
import { getUserPrivilegesMockDefaultValue } from '../../../../../../common/components/user_privileges/__mocks__';
|
||||||
|
|
||||||
jest.mock('../../../../../../common/lib/kibana/kibana_react', () => {
|
jest.mock('../../../../../../common/lib/kibana/kibana_react', () => {
|
||||||
const originalModule = jest.requireActual('../../../../../../common/lib/kibana/kibana_react');
|
const originalModule = jest.requireActual('../../../../../../common/lib/kibana/kibana_react');
|
||||||
|
@ -31,6 +34,7 @@ jest.mock('../../../../../../common/lib/kibana/kibana_react', () => {
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
jest.mock('../../../../../../common/hooks/use_license');
|
jest.mock('../../../../../../common/hooks/use_license');
|
||||||
|
jest.mock('../../../../../../common/components/user_privileges');
|
||||||
|
|
||||||
describe('When using the Endpoint Details Actions Menu', () => {
|
describe('When using the Endpoint Details Actions Menu', () => {
|
||||||
let render: () => Promise<ReturnType<AppContextTestRender['render']>>;
|
let render: () => Promise<ReturnType<AppContextTestRender['render']>>;
|
||||||
|
@ -59,6 +63,8 @@ describe('When using the Endpoint Details Actions Menu', () => {
|
||||||
waitForAction = mockedContext.middlewareSpy.waitForAction;
|
waitForAction = mockedContext.middlewareSpy.waitForAction;
|
||||||
httpMocks = endpointPageHttpMock(mockedContext.coreStart.http);
|
httpMocks = endpointPageHttpMock(mockedContext.coreStart.http);
|
||||||
|
|
||||||
|
(useUserPrivileges as jest.Mock).mockReturnValue(getUserPrivilegesMockDefaultValue());
|
||||||
|
|
||||||
act(() => {
|
act(() => {
|
||||||
mockedContext.history.push(
|
mockedContext.history.push(
|
||||||
'/administration/endpoints?selected_endpoint=5fe11314-678c-413e-87a2-b4a3461878ee'
|
'/administration/endpoints?selected_endpoint=5fe11314-678c-413e-87a2-b4a3461878ee'
|
||||||
|
@ -80,6 +86,10 @@ describe('When using the Endpoint Details Actions Menu', () => {
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
(useUserPrivileges as jest.Mock).mockClear();
|
||||||
|
});
|
||||||
|
|
||||||
it('should not show the response actions history link', async () => {
|
it('should not show the response actions history link', async () => {
|
||||||
await render();
|
await render();
|
||||||
expect(renderResult.queryByTestId('actionsLink')).toBeNull();
|
expect(renderResult.queryByTestId('actionsLink')).toBeNull();
|
||||||
|
@ -121,6 +131,7 @@ describe('When using the Endpoint Details Actions Menu', () => {
|
||||||
describe('and endpoint host is isolated', () => {
|
describe('and endpoint host is isolated', () => {
|
||||||
beforeEach(() => setEndpointMetadataResponse(true));
|
beforeEach(() => setEndpointMetadataResponse(true));
|
||||||
|
|
||||||
|
describe('and user has unisolate privilege', () => {
|
||||||
it('should display Unisolate action', async () => {
|
it('should display Unisolate action', async () => {
|
||||||
await render();
|
await render();
|
||||||
expect(renderResult.getByTestId('unIsolateLink')).not.toBeNull();
|
expect(renderResult.getByTestId('unIsolateLink')).not.toBeNull();
|
||||||
|
@ -136,6 +147,25 @@ describe('When using the Endpoint Details Actions Menu', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('and user does not have unisolate privilege', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
(useUserPrivileges as jest.Mock).mockReturnValue({
|
||||||
|
...initialUserPrivilegesState(),
|
||||||
|
endpointPrivileges: {
|
||||||
|
...initialUserPrivilegesState().endpointPrivileges,
|
||||||
|
canIsolateHost: false,
|
||||||
|
canUnIsolateHost: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not display unisolate action', async () => {
|
||||||
|
await render();
|
||||||
|
expect(renderResult.queryByTestId('unIsolateLink')).toBeNull();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('and license is NOT PlatinumPlus', () => {
|
describe('and license is NOT PlatinumPlus', () => {
|
||||||
const licenseServiceMock = licenseService as jest.Mocked<typeof licenseService>;
|
const licenseServiceMock = licenseService as jest.Mocked<typeof licenseService>;
|
||||||
|
|
||||||
|
@ -143,12 +173,6 @@ describe('When using the Endpoint Details Actions Menu', () => {
|
||||||
|
|
||||||
afterEach(() => licenseServiceMock.isPlatinumPlus.mockReturnValue(true));
|
afterEach(() => licenseServiceMock.isPlatinumPlus.mockReturnValue(true));
|
||||||
|
|
||||||
it('should not show the `isolate` action', async () => {
|
|
||||||
setEndpointMetadataResponse();
|
|
||||||
await render();
|
|
||||||
expect(renderResult.queryByTestId('isolateLink')).toBeNull();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should still show `unisolate` action for endpoints that are currently isolated', async () => {
|
it('should still show `unisolate` action for endpoints that are currently isolated', async () => {
|
||||||
setEndpointMetadataResponse(true);
|
setEndpointMetadataResponse(true);
|
||||||
await render();
|
await render();
|
||||||
|
|
|
@ -19,7 +19,6 @@ import { agentPolicies, uiQueryParams } from '../../store/selectors';
|
||||||
import { useAppUrl } from '../../../../../common/lib/kibana/hooks';
|
import { useAppUrl } from '../../../../../common/lib/kibana/hooks';
|
||||||
import type { ContextMenuItemNavByRouterProps } from '../../../../components/context_menu_with_router_support/context_menu_item_nav_by_router';
|
import type { ContextMenuItemNavByRouterProps } from '../../../../components/context_menu_with_router_support/context_menu_item_nav_by_router';
|
||||||
import { isEndpointHostIsolated } from '../../../../../common/utils/validators';
|
import { isEndpointHostIsolated } from '../../../../../common/utils/validators';
|
||||||
import { useLicense } from '../../../../../common/hooks/use_license';
|
|
||||||
import { isIsolationSupported } from '../../../../../../common/endpoint/service/host_isolation/utils';
|
import { isIsolationSupported } from '../../../../../../common/endpoint/service/host_isolation/utils';
|
||||||
import { useDoesEndpointSupportResponder } from '../../../../../common/hooks/endpoint/use_does_endpoint_support_responder';
|
import { useDoesEndpointSupportResponder } from '../../../../../common/hooks/endpoint/use_does_endpoint_support_responder';
|
||||||
import { UPGRADE_ENDPOINT_FOR_RESPONDER } from '../../../../../common/translations';
|
import { UPGRADE_ENDPOINT_FOR_RESPONDER } from '../../../../../common/translations';
|
||||||
|
@ -36,7 +35,6 @@ export const useEndpointActionItems = (
|
||||||
endpointMetadata: MaybeImmutable<HostMetadata> | undefined,
|
endpointMetadata: MaybeImmutable<HostMetadata> | undefined,
|
||||||
options?: Options
|
options?: Options
|
||||||
): ContextMenuItemNavByRouterProps[] => {
|
): ContextMenuItemNavByRouterProps[] => {
|
||||||
const isPlatinumPlus = useLicense().isPlatinumPlus();
|
|
||||||
const { getAppUrl } = useAppUrl();
|
const { getAppUrl } = useAppUrl();
|
||||||
const fleetAgentPolicies = useEndpointSelector(agentPolicies);
|
const fleetAgentPolicies = useEndpointSelector(agentPolicies);
|
||||||
const allCurrentUrlParams = useEndpointSelector(uiQueryParams);
|
const allCurrentUrlParams = useEndpointSelector(uiQueryParams);
|
||||||
|
@ -44,7 +42,8 @@ export const useEndpointActionItems = (
|
||||||
const isResponseActionsConsoleEnabled = useIsExperimentalFeatureEnabled(
|
const isResponseActionsConsoleEnabled = useIsExperimentalFeatureEnabled(
|
||||||
'responseActionsConsoleEnabled'
|
'responseActionsConsoleEnabled'
|
||||||
);
|
);
|
||||||
const canAccessResponseConsole = useUserPrivileges().endpointPrivileges.canAccessResponseConsole;
|
const { canAccessResponseConsole, canIsolateHost, canUnIsolateHost } =
|
||||||
|
useUserPrivileges().endpointPrivileges;
|
||||||
const isResponderCapabilitiesEnabled = useDoesEndpointSupportResponder(endpointMetadata);
|
const isResponderCapabilitiesEnabled = useDoesEndpointSupportResponder(endpointMetadata);
|
||||||
|
|
||||||
return useMemo<ContextMenuItemNavByRouterProps[]>(() => {
|
return useMemo<ContextMenuItemNavByRouterProps[]>(() => {
|
||||||
|
@ -82,8 +81,8 @@ export const useEndpointActionItems = (
|
||||||
|
|
||||||
const isolationActions = [];
|
const isolationActions = [];
|
||||||
|
|
||||||
if (isIsolated) {
|
if (isIsolated && canUnIsolateHost) {
|
||||||
// Un-isolate is always available to users regardless of license level
|
// Un-isolate is available to users regardless of license level if they have unisolate permissions
|
||||||
isolationActions.push({
|
isolationActions.push({
|
||||||
'data-test-subj': 'unIsolateLink',
|
'data-test-subj': 'unIsolateLink',
|
||||||
icon: 'lockOpen',
|
icon: 'lockOpen',
|
||||||
|
@ -100,7 +99,7 @@ export const useEndpointActionItems = (
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
} else if (isPlatinumPlus && isolationSupported) {
|
} else if (isolationSupported && canIsolateHost) {
|
||||||
// For Platinum++ licenses, users also have ability to isolate
|
// For Platinum++ licenses, users also have ability to isolate
|
||||||
isolationActions.push({
|
isolationActions.push({
|
||||||
'data-test-subj': 'isolateLink',
|
'data-test-subj': 'isolateLink',
|
||||||
|
@ -260,10 +259,11 @@ export const useEndpointActionItems = (
|
||||||
endpointMetadata,
|
endpointMetadata,
|
||||||
fleetAgentPolicies,
|
fleetAgentPolicies,
|
||||||
getAppUrl,
|
getAppUrl,
|
||||||
isPlatinumPlus,
|
|
||||||
isResponseActionsConsoleEnabled,
|
isResponseActionsConsoleEnabled,
|
||||||
showEndpointResponseActionsConsole,
|
showEndpointResponseActionsConsole,
|
||||||
options?.isEndpointList,
|
options?.isEndpointList,
|
||||||
isResponderCapabilitiesEnabled,
|
isResponderCapabilitiesEnabled,
|
||||||
|
canIsolateHost,
|
||||||
|
canUnIsolateHost,
|
||||||
]);
|
]);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1007,6 +1007,7 @@ describe('when on the endpoint list page', () => {
|
||||||
let agentId: string;
|
let agentId: string;
|
||||||
let agentPolicyId: string;
|
let agentPolicyId: string;
|
||||||
let renderResult: ReturnType<AppContextTestRender['render']>;
|
let renderResult: ReturnType<AppContextTestRender['render']>;
|
||||||
|
let endpointActionsButton: HTMLElement;
|
||||||
|
|
||||||
// 2nd endpoint only has isolation capabilities
|
// 2nd endpoint only has isolation capabilities
|
||||||
const mockEndpointListApi = () => {
|
const mockEndpointListApi = () => {
|
||||||
|
@ -1081,13 +1082,7 @@ describe('when on the endpoint list page', () => {
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
mockEndpointListApi();
|
mockEndpointListApi();
|
||||||
(useUserPrivileges as jest.Mock).mockReturnValue({
|
(useUserPrivileges as jest.Mock).mockReturnValue(getUserPrivilegesMockDefaultValue());
|
||||||
...mockInitialUserPrivilegesState(),
|
|
||||||
endpointPrivileges: {
|
|
||||||
...mockInitialUserPrivilegesState().endpointPrivileges,
|
|
||||||
canAccessResponseConsole: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
reactTestingLibrary.act(() => {
|
reactTestingLibrary.act(() => {
|
||||||
history.push(`${MANAGEMENT_PATH}/endpoints`);
|
history.push(`${MANAGEMENT_PATH}/endpoints`);
|
||||||
|
@ -1097,9 +1092,7 @@ describe('when on the endpoint list page', () => {
|
||||||
await middlewareSpy.waitForAction('serverReturnedEndpointList');
|
await middlewareSpy.waitForAction('serverReturnedEndpointList');
|
||||||
await middlewareSpy.waitForAction('serverReturnedEndpointAgentPolicies');
|
await middlewareSpy.waitForAction('serverReturnedEndpointAgentPolicies');
|
||||||
|
|
||||||
const endpointActionsButton = (
|
endpointActionsButton = (await renderResult.findAllByTestId('endpointTableRowActions'))[0];
|
||||||
await renderResult.findAllByTestId('endpointTableRowActions')
|
|
||||||
)[0];
|
|
||||||
|
|
||||||
reactTestingLibrary.act(() => {
|
reactTestingLibrary.act(() => {
|
||||||
reactTestingLibrary.fireEvent.click(endpointActionsButton);
|
reactTestingLibrary.fireEvent.click(endpointActionsButton);
|
||||||
|
@ -1108,7 +1101,6 @@ describe('when on the endpoint list page', () => {
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
jest.clearAllMocks();
|
jest.clearAllMocks();
|
||||||
(useUserPrivileges as jest.Mock).mockReturnValue(getUserPrivilegesMockDefaultValue());
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('shows the Responder option when all 3 processes capabilities are present in the endpoint', async () => {
|
it('shows the Responder option when all 3 processes capabilities are present in the endpoint', async () => {
|
||||||
|
@ -1141,6 +1133,24 @@ describe('when on the endpoint list page', () => {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('hides isolate host option if canIsolateHost is false', () => {
|
||||||
|
(useUserPrivileges as jest.Mock).mockReturnValue({
|
||||||
|
...mockInitialUserPrivilegesState(),
|
||||||
|
endpointPrivileges: {
|
||||||
|
...mockInitialUserPrivilegesState().endpointPrivileges,
|
||||||
|
canIsolateHost: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
reactTestingLibrary.act(() => {
|
||||||
|
reactTestingLibrary.fireEvent.click(endpointActionsButton);
|
||||||
|
});
|
||||||
|
reactTestingLibrary.act(() => {
|
||||||
|
reactTestingLibrary.fireEvent.click(endpointActionsButton);
|
||||||
|
});
|
||||||
|
const isolateLink = screen.queryByTestId('isolateLink');
|
||||||
|
expect(isolateLink).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
it('navigates to the Security Solution Host Details page', async () => {
|
it('navigates to the Security Solution Host Details page', async () => {
|
||||||
const hostLink = await renderResult.findByTestId('hostLink');
|
const hostLink = await renderResult.findByTestId('hostLink');
|
||||||
expect(hostLink.getAttribute('href')).toEqual(
|
expect(hostLink.getAttribute('href')).toEqual(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue