mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[Security Solution][Endpoint] Add ability for users to release
an isolated host in serverless tiers where Response Actions are not available (#163616)
## Summary - Fixes the loading of the Host Isolation sub-feature control into kibana - should always be loaded and includes only the `release` privilege in it - Fixes the "Take action" menu items for Host Isolation (displayed in alert details) to ensure `release` is displayed when host is isolated and user has `release` privilege only - Endpoint Response console will now NOT be available to users who only have `release` response action (this is a downgrade scenario where the user is still allowed to `release` isolated hosts)
This commit is contained in:
parent
12be587348
commit
8366d5f172
16 changed files with 245 additions and 74 deletions
|
@ -235,7 +235,15 @@ describe('Endpoint Authz service', () => {
|
|||
].executePackageAction = true;
|
||||
|
||||
const authz = calculateEndpointAuthz(licenseService, fleetAuthz, userRoles);
|
||||
expect(authz.canAccessResponseConsole).toBe(true);
|
||||
|
||||
// Having ONLY host isolation Release response action can only be true in a
|
||||
// downgrade scenario, where we allow the user to continue to release isolated
|
||||
// hosts. In that scenario, we don't show access to the response console
|
||||
if (responseConsolePrivilege === 'writeHostIsolationRelease') {
|
||||
expect(authz.canAccessResponseConsole).toBe(false);
|
||||
} else {
|
||||
expect(authz.canAccessResponseConsole).toBe(true);
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
|
||||
import type { ENDPOINT_PRIVILEGES, FleetAuthz } from '@kbn/fleet-plugin/common';
|
||||
|
||||
import { omit } from 'lodash';
|
||||
import { RESPONSE_CONSOLE_ACTION_COMMANDS_TO_REQUIRED_AUTHZ } from '../response_actions/constants';
|
||||
import type { LicenseService } from '../../../license';
|
||||
import type { EndpointAuthz } from '../../types/authz';
|
||||
import type { MaybeImmutable } from '../../types';
|
||||
|
@ -82,7 +84,7 @@ export const calculateEndpointAuthz = (
|
|||
|
||||
const canWriteExecuteOperations = hasKibanaPrivilege(fleetAuthz, 'writeExecuteOperations');
|
||||
|
||||
return {
|
||||
const authz: EndpointAuthz = {
|
||||
canWriteSecuritySolution,
|
||||
canReadSecuritySolution,
|
||||
canAccessFleet: fleetAuthz?.fleet.all ?? false,
|
||||
|
@ -95,22 +97,22 @@ export const calculateEndpointAuthz = (
|
|||
canWriteActionsLogManagement,
|
||||
canReadActionsLogManagement: canReadActionsLogManagement && isEnterpriseLicense,
|
||||
canAccessEndpointActionsLogManagement: canReadActionsLogManagement && isPlatinumPlusLicense,
|
||||
|
||||
// ---------------------------------------------------------
|
||||
// Response Actions
|
||||
// ---------------------------------------------------------
|
||||
canIsolateHost: canIsolateHost && isPlatinumPlusLicense,
|
||||
canUnIsolateHost,
|
||||
canKillProcess: canWriteProcessOperations && isEnterpriseLicense,
|
||||
canSuspendProcess: canWriteProcessOperations && isEnterpriseLicense,
|
||||
canGetRunningProcesses: canWriteProcessOperations && isEnterpriseLicense,
|
||||
canAccessResponseConsole:
|
||||
isEnterpriseLicense &&
|
||||
(canIsolateHost ||
|
||||
canUnIsolateHost ||
|
||||
canWriteProcessOperations ||
|
||||
canWriteFileOperations ||
|
||||
canWriteExecuteOperations),
|
||||
canAccessResponseConsole: false, // set further below
|
||||
canWriteExecuteOperations: canWriteExecuteOperations && isEnterpriseLicense,
|
||||
canWriteFileOperations: canWriteFileOperations && isEnterpriseLicense,
|
||||
|
||||
// ---------------------------------------------------------
|
||||
// artifacts
|
||||
// ---------------------------------------------------------
|
||||
canWriteTrustedApplications,
|
||||
canReadTrustedApplications,
|
||||
canWriteHostIsolationExceptions: canWriteHostIsolationExceptions && isPlatinumPlusLicense,
|
||||
|
@ -122,6 +124,20 @@ export const calculateEndpointAuthz = (
|
|||
canWriteEventFilters,
|
||||
canReadEventFilters,
|
||||
};
|
||||
|
||||
// Response console is only accessible when license is Enterprise and user has access to any
|
||||
// of the response actions except `release`. Sole access to `release` is something
|
||||
// that is supported for a user in a license downgrade scenario, and in that case, we don't want
|
||||
// to allow access to Response Console.
|
||||
authz.canAccessResponseConsole =
|
||||
isEnterpriseLicense &&
|
||||
Object.values(omit(RESPONSE_CONSOLE_ACTION_COMMANDS_TO_REQUIRED_AUTHZ, 'release')).some(
|
||||
(responseActionAuthzKey) => {
|
||||
return authz[responseActionAuthzKey];
|
||||
}
|
||||
);
|
||||
|
||||
return authz;
|
||||
};
|
||||
|
||||
export const getEndpointAuthzInitialState = (): EndpointAuthz => {
|
||||
|
|
|
@ -27,7 +27,9 @@ export const useHostIsolationAction = ({
|
|||
detailsData,
|
||||
isHostIsolationPanelOpen,
|
||||
onAddIsolationStatusClick,
|
||||
}: UseHostIsolationActionProps) => {
|
||||
}: UseHostIsolationActionProps): AlertTableContextMenuItem[] => {
|
||||
const { canIsolateHost, canUnIsolateHost } = useUserPrivileges().endpointPrivileges;
|
||||
|
||||
const isEndpointAlert = useMemo(() => {
|
||||
return isAlertFromEndpointEvent({ data: detailsData || [] });
|
||||
}, [detailsData]);
|
||||
|
@ -49,14 +51,14 @@ export const useHostIsolationAction = ({
|
|||
|
||||
const {
|
||||
loading: loadingHostIsolationStatus,
|
||||
isIsolated: isolationStatus,
|
||||
isIsolated: isHostIsolated,
|
||||
agentStatus,
|
||||
capabilities,
|
||||
} = useHostIsolationStatus({
|
||||
agentId,
|
||||
});
|
||||
|
||||
const isolationSupported = useMemo(() => {
|
||||
const doesHostSupportIsolation = useMemo(() => {
|
||||
return isEndpointAlert
|
||||
? isIsolationSupported({
|
||||
osName: hostOsFamily,
|
||||
|
@ -66,46 +68,45 @@ export const useHostIsolationAction = ({
|
|||
: false;
|
||||
}, [agentVersion, capabilities, hostOsFamily, isEndpointAlert]);
|
||||
|
||||
const isIsolationAllowed = useUserPrivileges().endpointPrivileges.canIsolateHost;
|
||||
|
||||
const isolateHostHandler = useCallback(() => {
|
||||
closePopover();
|
||||
if (isolationStatus === false) {
|
||||
if (!isHostIsolated) {
|
||||
onAddIsolationStatusClick('isolateHost');
|
||||
} else {
|
||||
onAddIsolationStatusClick('unisolateHost');
|
||||
}
|
||||
}, [closePopover, isolationStatus, onAddIsolationStatusClick]);
|
||||
}, [closePopover, isHostIsolated, onAddIsolationStatusClick]);
|
||||
|
||||
const isolateHostTitle = isolationStatus === false ? ISOLATE_HOST : UNISOLATE_HOST;
|
||||
return useMemo(() => {
|
||||
if (
|
||||
!isEndpointAlert ||
|
||||
!doesHostSupportIsolation ||
|
||||
loadingHostIsolationStatus ||
|
||||
isHostIsolationPanelOpen
|
||||
) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const hostIsolationAction: AlertTableContextMenuItem[] = useMemo(
|
||||
() =>
|
||||
isIsolationAllowed &&
|
||||
isEndpointAlert &&
|
||||
isolationSupported &&
|
||||
isHostIsolationPanelOpen === false &&
|
||||
loadingHostIsolationStatus === false
|
||||
? [
|
||||
{
|
||||
key: 'isolate-host-action-item',
|
||||
'data-test-subj': 'isolate-host-action-item',
|
||||
disabled: agentStatus === HostStatus.UNENROLLED,
|
||||
onClick: isolateHostHandler,
|
||||
name: isolateHostTitle,
|
||||
},
|
||||
]
|
||||
: [],
|
||||
[
|
||||
agentStatus,
|
||||
isEndpointAlert,
|
||||
isHostIsolationPanelOpen,
|
||||
isIsolationAllowed,
|
||||
isolateHostHandler,
|
||||
isolateHostTitle,
|
||||
isolationSupported,
|
||||
loadingHostIsolationStatus,
|
||||
]
|
||||
);
|
||||
return hostIsolationAction;
|
||||
const menuItems = [
|
||||
{
|
||||
key: 'isolate-host-action-item',
|
||||
'data-test-subj': 'isolate-host-action-item',
|
||||
disabled: agentStatus === HostStatus.UNENROLLED,
|
||||
onClick: isolateHostHandler,
|
||||
name: isHostIsolated ? UNISOLATE_HOST : ISOLATE_HOST,
|
||||
},
|
||||
];
|
||||
|
||||
return canIsolateHost || (isHostIsolated && canUnIsolateHost) ? menuItems : [];
|
||||
}, [
|
||||
isEndpointAlert,
|
||||
doesHostSupportIsolation,
|
||||
loadingHostIsolationStatus,
|
||||
isHostIsolationPanelOpen,
|
||||
agentStatus,
|
||||
isolateHostHandler,
|
||||
canIsolateHost,
|
||||
isHostIsolated,
|
||||
canUnIsolateHost,
|
||||
]);
|
||||
};
|
||||
|
|
|
@ -122,9 +122,14 @@ export const getSecurityBaseKibanaFeature = (): BaseKibanaFeatureConfig => ({
|
|||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* Returns the list of Security SubFeature IDs that should be loaded and available in
|
||||
* kibana regardless of PLI or License level.
|
||||
* @param _
|
||||
*/
|
||||
export const getSecurityBaseKibanaSubFeatureIds = (
|
||||
_: ExperimentalFeatures // currently un-used, but left here as a convenience for possible future use
|
||||
): SecuritySubFeatureId[] => [];
|
||||
): SecuritySubFeatureId[] => [SecuritySubFeatureId.hostIsolation];
|
||||
|
||||
/**
|
||||
* Maps the AppFeatures keys to Kibana privileges that will be merged
|
||||
|
@ -214,12 +219,13 @@ export const getSecurityAppFeaturesConfig = (
|
|||
SecuritySubFeatureId.hostIsolationExceptions,
|
||||
|
||||
SecuritySubFeatureId.responseActionsHistory,
|
||||
SecuritySubFeatureId.hostIsolation,
|
||||
SecuritySubFeatureId.processOperations,
|
||||
SecuritySubFeatureId.fileOperations,
|
||||
SecuritySubFeatureId.executeAction,
|
||||
],
|
||||
subFeaturesPrivileges: [
|
||||
// Adds the privilege to Isolate hosts to the already loaded `host_isolation_all`
|
||||
// sub-feature (always loaded), which included the `release` privilege already
|
||||
{
|
||||
id: 'host_isolation_all',
|
||||
api: [`${APP_ID}-writeHostIsolation`],
|
||||
|
|
|
@ -396,7 +396,6 @@ const hostIsolationSubFeature: SubFeatureConfig = {
|
|||
groupType: 'mutually_exclusive',
|
||||
privileges: [
|
||||
{
|
||||
api: [`${APP_ID}-writeHostIsolationRelease`],
|
||||
id: 'host_isolation_all',
|
||||
includeIn: 'none',
|
||||
name: 'All',
|
||||
|
@ -404,6 +403,11 @@ const hostIsolationSubFeature: SubFeatureConfig = {
|
|||
all: [],
|
||||
read: [],
|
||||
},
|
||||
// FYI: The current set of values below (`api`, `ui`) cover only `release` response action.
|
||||
// There is a second set of values for API and UI that are added later if `endpointResponseActions`
|
||||
// appFeature is enabled. Needed to ensure that in a downgrade of license condition,
|
||||
// users are still able to un-isolate a host machine.
|
||||
api: [`${APP_ID}-writeHostIsolationRelease`],
|
||||
ui: ['writeHostIsolationRelease'],
|
||||
},
|
||||
],
|
||||
|
|
|
@ -24,12 +24,7 @@ export const PLI_APP_FEATURES: PliAppFeatures = {
|
|||
],
|
||||
},
|
||||
endpoint: {
|
||||
essentials: [
|
||||
AppFeatureKey.endpointHostManagement,
|
||||
AppFeatureKey.endpointPolicyManagement,
|
||||
AppFeatureKey.endpointPolicyProtections,
|
||||
AppFeatureKey.endpointArtifactManagement,
|
||||
],
|
||||
essentials: [AppFeatureKey.endpointPolicyProtections, AppFeatureKey.endpointArtifactManagement],
|
||||
complete: [
|
||||
AppFeatureKey.endpointResponseActions,
|
||||
AppFeatureKey.osqueryAutomatedResponseActions,
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { login } from '../../tasks/login';
|
||||
import {
|
||||
getConsoleActionMenuItem,
|
||||
getUnIsolateActionMenuItem,
|
||||
openRowActionMenu,
|
||||
visitEndpointList,
|
||||
} from '../../screens/endpoint_management';
|
||||
import {
|
||||
CyIndexEndpointHosts,
|
||||
indexEndpointHosts,
|
||||
} from '../../tasks/endpoint_management/index_endpoint_hosts';
|
||||
|
||||
describe(
|
||||
'When on the Endpoint List in Security Essentials PLI',
|
||||
{
|
||||
env: {
|
||||
ftrConfig: {
|
||||
productTypes: [{ product_line: 'security', product_tier: 'essentials' }],
|
||||
},
|
||||
},
|
||||
},
|
||||
() => {
|
||||
describe('and Isolated hosts exist', () => {
|
||||
let indexedEndpointData: CyIndexEndpointHosts;
|
||||
|
||||
before(() => {
|
||||
indexEndpointHosts({ isolation: true }).then((response) => {
|
||||
indexedEndpointData = response;
|
||||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
if (indexedEndpointData) {
|
||||
indexedEndpointData.cleanup();
|
||||
}
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
login();
|
||||
visitEndpointList();
|
||||
openRowActionMenu();
|
||||
});
|
||||
|
||||
it('should display `release` options in host row actions', () => {
|
||||
getUnIsolateActionMenuItem().should('exist');
|
||||
});
|
||||
|
||||
it('should NOT display access to response console', () => {
|
||||
getConsoleActionMenuItem().should('not.exist');
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
|
@ -12,7 +12,7 @@ import { getEndpointManagementPageList } from '../../../screens/endpoint_managem
|
|||
import { ensureResponseActionAuthzAccess } from '../../../tasks/endpoint_management';
|
||||
|
||||
describe(
|
||||
'App Features for Complete PLI',
|
||||
'App Features for Security Complete PLI',
|
||||
{
|
||||
env: {
|
||||
ftrConfig: { productTypes: [{ product_line: 'security', product_tier: 'complete' }] },
|
||||
|
@ -50,10 +50,17 @@ describe(
|
|||
});
|
||||
}
|
||||
|
||||
for (const actionName of RESPONSE_ACTION_API_COMMANDS_NAMES) {
|
||||
// No access to response actions (except `unisolate`)
|
||||
for (const actionName of RESPONSE_ACTION_API_COMMANDS_NAMES.filter(
|
||||
(apiName) => apiName !== 'unisolate'
|
||||
)) {
|
||||
it(`should not allow access to Response Action: ${actionName}`, () => {
|
||||
ensureResponseActionAuthzAccess('none', actionName, username, password);
|
||||
});
|
||||
}
|
||||
|
||||
it('should have access to `unisolate` api', () => {
|
||||
ensureResponseActionAuthzAccess('all', 'unisolate', username, password);
|
||||
});
|
||||
}
|
||||
);
|
||||
|
|
|
@ -12,7 +12,7 @@ import { getEndpointManagementPageList } from '../../../screens/endpoint_managem
|
|||
import { ensureResponseActionAuthzAccess } from '../../../tasks/endpoint_management';
|
||||
|
||||
describe(
|
||||
'App Features for Complete PLI with Endpoint Complete',
|
||||
'App Features for Security Complete PLI with Endpoint Complete Addon',
|
||||
{
|
||||
env: {
|
||||
ftrConfig: {
|
||||
|
|
|
@ -12,7 +12,7 @@ import { ensureResponseActionAuthzAccess } from '../../../tasks/endpoint_managem
|
|||
import { getEndpointManagementPageList } from '../../../screens/endpoint_management';
|
||||
|
||||
describe(
|
||||
'App Features for Essential PLI',
|
||||
'App Features for Security Essential PLI',
|
||||
{
|
||||
env: {
|
||||
ftrConfig: {
|
||||
|
@ -52,10 +52,17 @@ describe(
|
|||
});
|
||||
}
|
||||
|
||||
for (const actionName of RESPONSE_ACTION_API_COMMANDS_NAMES) {
|
||||
it(`should NOT allow access to Response Action: ${actionName}`, () => {
|
||||
// No access to response actions (except `unisolate`)
|
||||
for (const actionName of RESPONSE_ACTION_API_COMMANDS_NAMES.filter(
|
||||
(apiName) => apiName !== 'unisolate'
|
||||
)) {
|
||||
it(`should not allow access to Response Action: ${actionName}`, () => {
|
||||
ensureResponseActionAuthzAccess('none', actionName, username, password);
|
||||
});
|
||||
}
|
||||
|
||||
it('should have access to `unisolate` api', () => {
|
||||
ensureResponseActionAuthzAccess('all', 'unisolate', username, password);
|
||||
});
|
||||
}
|
||||
);
|
||||
|
|
|
@ -12,7 +12,7 @@ import { getEndpointManagementPageMap } from '../../../screens/endpoint_manageme
|
|||
import { ensureResponseActionAuthzAccess } from '../../../tasks/endpoint_management';
|
||||
|
||||
describe(
|
||||
'App Features for Essentials PLI with Endpoint Essentials',
|
||||
'App Features for Security Essentials PLI with Endpoint Essentials Addon',
|
||||
{
|
||||
env: {
|
||||
ftrConfig: {
|
||||
|
@ -57,12 +57,18 @@ describe(
|
|||
});
|
||||
}
|
||||
|
||||
for (const actionName of RESPONSE_ACTION_API_COMMANDS_NAMES) {
|
||||
for (const actionName of RESPONSE_ACTION_API_COMMANDS_NAMES.filter(
|
||||
(apiName) => apiName !== 'unisolate'
|
||||
)) {
|
||||
it(`should not allow access to Response Action: ${actionName}`, () => {
|
||||
ensureResponseActionAuthzAccess('none', actionName, username, password);
|
||||
});
|
||||
}
|
||||
|
||||
it('should have access to `unisolate` api', () => {
|
||||
ensureResponseActionAuthzAccess('all', 'unisolate', username, password);
|
||||
});
|
||||
|
||||
it(`should have access to Fleet`, () => {
|
||||
visitFleetAgentList();
|
||||
getAgentListTable().should('exist');
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { IndexedHostsAndAlertsResponse } from '@kbn/security-solution-plugin/common/endpoint/index_data';
|
||||
import { pick } from 'lodash';
|
||||
import { login } from '../../../tasks/login';
|
||||
import { ServerlessRoleName } from '../../../../../../../shared/lib';
|
||||
|
@ -33,6 +32,10 @@ import {
|
|||
openConsoleHelpPanel,
|
||||
} from '../../../screens/endpoint_management/response_console';
|
||||
import { ensurePolicyDetailsPageAuthzAccess } from '../../../screens/endpoint_management/policy_details';
|
||||
import {
|
||||
CyIndexEndpointHosts,
|
||||
indexEndpointHosts,
|
||||
} from '../../../tasks/endpoint_management/index_endpoint_hosts';
|
||||
|
||||
describe(
|
||||
'User Roles for Security Complete PLI with Endpoint Complete addon',
|
||||
|
@ -51,17 +54,17 @@ describe(
|
|||
const pageById = getEndpointManagementPageMap();
|
||||
const consoleHelpPanelResponseActionsTestSubj = getConsoleHelpPanelResponseActionTestSubj();
|
||||
|
||||
let loadedEndpoints: IndexedHostsAndAlertsResponse;
|
||||
let loadedEndpoints: CyIndexEndpointHosts;
|
||||
|
||||
before(() => {
|
||||
cy.task('indexEndpointHosts', {}, { timeout: 240000 }).then((response) => {
|
||||
indexEndpointHosts().then((response) => {
|
||||
loadedEndpoints = response;
|
||||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
if (loadedEndpoints) {
|
||||
cy.task('deleteIndexedEndpointHosts', loadedEndpoints);
|
||||
loadedEndpoints.cleanup();
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -136,7 +139,11 @@ describe(
|
|||
|
||||
it('should have read access to Endpoint Policy Management', () => {
|
||||
ensurePolicyListPageAuthzAccess('read', true);
|
||||
ensurePolicyDetailsPageAuthzAccess(loadedEndpoints.integrationPolicies[0].id, 'read', true);
|
||||
ensurePolicyDetailsPageAuthzAccess(
|
||||
loadedEndpoints.data.integrationPolicies[0].id,
|
||||
'read',
|
||||
true
|
||||
);
|
||||
});
|
||||
|
||||
for (const { title, id } of artifactPagesFullAccess) {
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { IndexedHostsAndAlertsResponse } from '@kbn/security-solution-plugin/common/endpoint/index_data';
|
||||
import { login } from '../../../tasks/login';
|
||||
import {
|
||||
getNoPrivilegesPage,
|
||||
|
@ -24,6 +23,10 @@ import {
|
|||
} from '../../../screens';
|
||||
import { ServerlessRoleName } from '../../../../../../../shared/lib';
|
||||
import { ensurePolicyDetailsPageAuthzAccess } from '../../../screens/endpoint_management/policy_details';
|
||||
import {
|
||||
CyIndexEndpointHosts,
|
||||
indexEndpointHosts,
|
||||
} from '../../../tasks/endpoint_management/index_endpoint_hosts';
|
||||
|
||||
describe(
|
||||
'Roles for Security Essential PLI with Endpoint Essentials addon',
|
||||
|
@ -41,17 +44,17 @@ describe(
|
|||
const allPages = getEndpointManagementPageList();
|
||||
const pageById = getEndpointManagementPageMap();
|
||||
|
||||
let loadedEndpoints: IndexedHostsAndAlertsResponse;
|
||||
let loadedEndpoints: CyIndexEndpointHosts;
|
||||
|
||||
before(() => {
|
||||
cy.task('indexEndpointHosts', {}, { timeout: 240000 }).then((response) => {
|
||||
indexEndpointHosts().then((response) => {
|
||||
loadedEndpoints = response;
|
||||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
if (loadedEndpoints) {
|
||||
cy.task('deleteIndexedEndpointHosts', loadedEndpoints);
|
||||
loadedEndpoints.cleanup();
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -99,7 +102,11 @@ describe(
|
|||
|
||||
it('should have read access to Endpoint Policy Management', () => {
|
||||
ensurePolicyListPageAuthzAccess('read', true);
|
||||
ensurePolicyDetailsPageAuthzAccess(loadedEndpoints.integrationPolicies[0].id, 'read', true);
|
||||
ensurePolicyDetailsPageAuthzAccess(
|
||||
loadedEndpoints.data.integrationPolicies[0].id,
|
||||
'read',
|
||||
true
|
||||
);
|
||||
});
|
||||
|
||||
for (const { title, id } of artifactPagesFullAccess) {
|
||||
|
@ -175,7 +182,11 @@ describe(
|
|||
|
||||
it('should have access to policy management', () => {
|
||||
ensurePolicyListPageAuthzAccess('all', true);
|
||||
ensurePolicyDetailsPageAuthzAccess(loadedEndpoints.integrationPolicies[0].id, 'all', true);
|
||||
ensurePolicyDetailsPageAuthzAccess(
|
||||
loadedEndpoints.data.integrationPolicies[0].id,
|
||||
'all',
|
||||
true
|
||||
);
|
||||
});
|
||||
|
||||
it(`should NOT have access to Host Isolation Exceptions`, () => {
|
||||
|
|
|
@ -73,3 +73,11 @@ export const openRowActionMenu = (options?: ListRowOptions): Cypress.Chainable =
|
|||
export const openConsoleFromEndpointList = (options?: ListRowOptions): Cypress.Chainable => {
|
||||
return openRowActionMenu(options).findByTestSubj('console').click();
|
||||
};
|
||||
|
||||
export const getUnIsolateActionMenuItem = (): Cypress.Chainable => {
|
||||
return cy.getByTestSubj('tableRowActionsMenuPanel').findByTestSubj('unIsolateLink');
|
||||
};
|
||||
|
||||
export const getConsoleActionMenuItem = (): Cypress.Chainable => {
|
||||
return cy.getByTestSubj('tableRowActionsMenuPanel').findByTestSubj('console');
|
||||
};
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import {
|
||||
DeleteIndexedHostsAndAlertsResponse,
|
||||
IndexedHostsAndAlertsResponse,
|
||||
} from '@kbn/security-solution-plugin/common/endpoint/index_data';
|
||||
import { IndexEndpointHostsCyTaskOptions } from '@kbn/security-solution-plugin/public/management/cypress/types';
|
||||
|
||||
export interface CyIndexEndpointHosts {
|
||||
data: IndexedHostsAndAlertsResponse;
|
||||
cleanup: () => Cypress.Chainable<DeleteIndexedHostsAndAlertsResponse>;
|
||||
}
|
||||
|
||||
export const indexEndpointHosts = (
|
||||
options: IndexEndpointHostsCyTaskOptions = {}
|
||||
): Cypress.Chainable<CyIndexEndpointHosts> => {
|
||||
return cy.task('indexEndpointHosts', options, { timeout: 240000 }).then((indexHosts) => {
|
||||
return {
|
||||
data: indexHosts,
|
||||
cleanup: () => {
|
||||
cy.log(
|
||||
'Deleting Endpoint Host data',
|
||||
indexHosts.hosts.map((host) => `${host.host.name} (${host.host.id})`)
|
||||
);
|
||||
|
||||
return cy.task('deleteIndexedEndpointHosts', indexHosts);
|
||||
},
|
||||
};
|
||||
});
|
||||
};
|
Loading…
Add table
Add a link
Reference in a new issue