[Fleet] Add cypress test for subfeature privileges (#179781)

This commit is contained in:
Nicolas Chaulet 2024-04-03 06:35:27 +08:00 committed by GitHub
parent 9215efb6aa
commit 8abdfb4401
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 151 additions and 48 deletions

View file

@ -0,0 +1,65 @@
/*
* 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 { FLEET } from '../tasks/navigation';
import {
deleteUsers,
FleetAgentsReadIntegrNoneRole,
FleetAgentsReadIntegrNoneUser,
createUsersAndRoles,
} from '../tasks/privileges';
import { login, loginWithUserAndWaitForPage, logout } from '../tasks/login';
import {
MISSING_PRIVILEGES,
AGENTS_TAB,
ADD_AGENT_BUTTON,
ADD_FLEET_SERVER_HEADER,
AGENT_POLICIES_TAB,
SETTINGS_TAB,
UNINSTALL_TOKENS_TAB,
} from '../screens/fleet';
const rolesToCreate = [FleetAgentsReadIntegrNoneRole];
const usersToCreate = [FleetAgentsReadIntegrNoneUser];
describe('When the user has Fleet Agents Read built-in role', () => {
before(() => {
createUsersAndRoles(usersToCreate, rolesToCreate);
});
beforeEach(() => {
login();
});
afterEach(() => {
logout();
});
after(() => {
deleteUsers(usersToCreate);
});
describe('Fleet', () => {
it('is accessible but user cannot perform any write actions on agent tabs', () => {
loginWithUserAndWaitForPage(FLEET, FleetAgentsReadIntegrNoneUser);
cy.getBySel(AGENTS_TAB).should('exist');
cy.getBySel(MISSING_PRIVILEGES.TITLE).should('not.exist');
cy.getBySel(ADD_AGENT_BUTTON).should('not.exist');
cy.getBySel(ADD_FLEET_SERVER_HEADER).should('not.exist');
});
it('is accessible and user only see agents tab', () => {
loginWithUserAndWaitForPage(FLEET, FleetAgentsReadIntegrNoneUser);
cy.getBySel(AGENTS_TAB).should('exist');
cy.getBySel(AGENT_POLICIES_TAB).should('not.exist');
cy.getBySel(SETTINGS_TAB).should('not.exist');
cy.getBySel(UNINSTALL_TOKENS_TAB).should('not.exist');
});
});
});

View file

@ -11,11 +11,7 @@ import { login, loginWithUserAndWaitForPage, logout } from '../tasks/login';
import { getIntegrationCard } from '../screens/integrations';
import {
FLEET_SERVER_MISSING_PRIVILEGES,
ADD_AGENT_BUTTON_TOP,
AGENT_FLYOUT,
} from '../screens/fleet';
import { LANDING_PAGE_ADD_FLEET_SERVER_BUTTON } from '../screens/fleet';
import { ADD_INTEGRATION_POLICY_BTN } from '../screens/integrations';
import { scrollToIntegration } from '../tasks/integrations';
@ -44,18 +40,9 @@ describe('When the user has Editor built-in role', () => {
navigateTo(FLEET);
});
describe('When there are no agent policies', () => {
it('If fleet server is not set up, Fleet shows a callout', () => {
loginWithUserAndWaitForPage(FLEET, BuiltInEditorUser);
cy.getBySel(FLEET_SERVER_MISSING_PRIVILEGES.MESSAGE).should(
'contain',
'Fleet Server needs to be set up.'
);
cy.getBySel(ADD_AGENT_BUTTON_TOP).click();
cy.getBySel(AGENT_FLYOUT.MANAGED_TAB).click();
cy.getBySel(FLEET_SERVER_MISSING_PRIVILEGES.PROMPT).should('exist');
});
it('It should not show a callout', () => {
loginWithUserAndWaitForPage(FLEET, BuiltInEditorUser);
cy.getBySel(LANDING_PAGE_ADD_FLEET_SERVER_BUTTON).should('exist');
});
});

View file

@ -35,12 +35,8 @@ describe('When the user has All privilege for Fleet but None for integrations',
deleteUsersAndRoles(usersToCreate, rolesToCreate);
});
it('Fleet access is blocked with a callout', () => {
it('Fleet is accessible', () => {
loginWithUserAndWaitForPage(FLEET, FleetAllIntegrNoneUser);
cy.getBySel(MISSING_PRIVILEGES.TITLE).should('have.text', 'Permission denied');
cy.getBySel(MISSING_PRIVILEGES.MESSAGE).should(
'contain',
'You are not authorized to access Fleet.'
);
cy.getBySel(MISSING_PRIVILEGES.TITLE).should('not.exist');
});
});

View file

@ -18,8 +18,6 @@ import { cleanupAgentPolicies, unenrollAgent } from '../tasks/cleanup';
import { getIntegrationCard } from '../screens/integrations';
import {
FLEET_SERVER_MISSING_PRIVILEGES,
ADD_AGENT_BUTTON_TOP,
AGENT_POLICIES_TAB,
AGENT_POLICY_SAVE_INTEGRATION,
ADD_PACKAGE_POLICY_BTN,
@ -68,18 +66,6 @@ describe('When the user has All privilege for Fleet but Read for integrations',
});
});
describe('When there are no agent policies', () => {
it('If fleet server is not set up, Fleet shows a callout', () => {
loginWithUserAndWaitForPage(FLEET, FleetAllIntegrReadUser);
cy.getBySel(FLEET_SERVER_MISSING_PRIVILEGES.TITLE).should('have.text', 'Permission denied');
cy.getBySel(FLEET_SERVER_MISSING_PRIVILEGES.MESSAGE).should(
'contain',
'Fleet Server needs to be set up.'
);
cy.getBySel(ADD_AGENT_BUTTON_TOP).should('not.be.disabled');
});
});
describe('Integrations', () => {
it('are visible but cannot be added', () => {
loginWithUserAndWaitForPage(INTEGRATIONS, FleetAllIntegrReadUser);

View file

@ -11,9 +11,20 @@ import { login, loginWithUserAndWaitForPage, logout } from '../tasks/login';
import { getIntegrationCard } from '../screens/integrations';
import { MISSING_PRIVILEGES } from '../screens/fleet';
import {
MISSING_PRIVILEGES,
AGENTS_TAB,
ADD_AGENT_BUTTON,
ADD_FLEET_SERVER_HEADER,
AGENT_POLICIES_TAB,
ADD_AGENT_POLICY_BTN,
SETTINGS_TAB,
SETTINGS_OUTPUTS,
SETTINGS_FLEET_SERVER_HOSTS,
} from '../screens/fleet';
import { ADD_INTEGRATION_POLICY_BTN } from '../screens/integrations';
import { scrollToIntegration } from '../tasks/integrations';
import { navigateToTab } from '../tasks/fleet';
const usersToCreate = [BuiltInViewerUser];
@ -36,13 +47,29 @@ describe('When the user has Viewer built-in role', () => {
});
describe('Fleet', () => {
it('is blocked with a callout', () => {
it('is accessible but user cannot perform any write actions on agent tabs', () => {
loginWithUserAndWaitForPage(FLEET, BuiltInViewerUser);
cy.getBySel(MISSING_PRIVILEGES.TITLE).should('have.text', 'Permission denied');
cy.getBySel(MISSING_PRIVILEGES.MESSAGE).should(
'contain',
'You are not authorized to access Fleet.'
);
cy.getBySel(AGENTS_TAB).should('exist');
cy.getBySel(MISSING_PRIVILEGES.TITLE).should('not.exist');
cy.getBySel(ADD_AGENT_BUTTON).should('not.exist');
cy.getBySel(ADD_FLEET_SERVER_HEADER).should('not.exist');
});
it('is accessible but user cannot perform any write actions on agent policies tabs', () => {
loginWithUserAndWaitForPage(FLEET, BuiltInViewerUser);
navigateToTab(AGENT_POLICIES_TAB);
// Not write actions
cy.getBySel(ADD_AGENT_POLICY_BTN).should('not.be.enabled');
});
it('is accessible but user cannot perform any write actions on settings tabs', () => {
loginWithUserAndWaitForPage(FLEET, BuiltInViewerUser);
navigateToTab(SETTINGS_TAB);
// Not write actions
cy.getBySel(SETTINGS_OUTPUTS.ADD_BTN).should('not.exist');
cy.getBySel(SETTINGS_FLEET_SERVER_HOSTS.ADD_BUTTON).should('not.exist');
});
});

View file

@ -33,6 +33,7 @@ export const PACKAGE_POLICY_TABLE_LINK = 'PackagePoliciesTableLink';
export const ADD_PACKAGE_POLICY_BTN = 'addPackagePolicyButton';
export const GENERATE_FLEET_SERVER_POLICY_BUTTON = 'generateFleetServerPolicyButton';
export const ADD_FLEET_SERVER_HEADER = 'addFleetServerHeader';
export const ADD_AGENT_POLICY_BTN = 'createAgentPolicyButton';
export const PLATFORM_TYPE_LINUX_BUTTON = 'platformTypeLinux';
export const ADVANCED_FLEET_SERVER_ADD_HOST_BUTTON = 'fleetServerAddHostBtn';

View file

@ -133,6 +133,33 @@ export const FleetAllIntegrNoneUser: User = {
password: 'password',
roles: [FleetAllIntegrNoneRole.name],
};
export const FleetAgentsReadIntegrNoneRole: Role = {
name: 'fleet_agents_read_int_none_role',
privileges: {
elasticsearch: {
indices: [
{
names: ['*'],
privileges: ['all'],
},
],
},
kibana: [
{
feature: {
fleetv2: ['minimal_read', 'agents_read'],
fleet: ['none'],
},
spaces: ['*'],
},
],
},
};
export const FleetAgentsReadIntegrNoneUser: User = {
username: 'fleet_agents_read_int_none_role',
password: 'password',
roles: [FleetAgentsReadIntegrNoneRole.name],
};
export const FleetNoneIntegrAllRole: Role = {
name: 'fleet_none_int_all_role',
privileges: {

View file

@ -35,6 +35,7 @@ describe('AppRoutes', () => {
fleet: {
readAgents: true,
},
integrations: {},
},
},
{
@ -44,6 +45,7 @@ describe('AppRoutes', () => {
'You are not authorized to access that page. It requires the Agents Read Kibana privilege for Fleet.',
authz: {
fleet: {},
integrations: {},
},
},
{
@ -54,6 +56,7 @@ describe('AppRoutes', () => {
fleet: {
readAgentPolicies: true,
},
integrations: {},
},
},
{
@ -63,6 +66,7 @@ describe('AppRoutes', () => {
'You are not authorized to access that page. It requires the Agent policies Read Kibana privilege for Fleet.',
authz: {
fleet: {},
integrations: {},
},
},
{
@ -73,6 +77,7 @@ describe('AppRoutes', () => {
fleet: {
readSettings: true,
},
integrations: {},
},
},
{
@ -82,6 +87,7 @@ describe('AppRoutes', () => {
'You are not authorized to access that page. It requires the Settings Read Kibana privilege for Fleet.',
authz: {
fleet: {},
integrations: {},
},
},
];

View file

@ -49,7 +49,9 @@ jest.mock('../../../hooks', () => ({
sendGetAgentStatus: jest.fn(),
sendGetAgentPolicies: jest.fn().mockResolvedValue({ data: { items: [] } }),
sendGetAgentTags: jest.fn().mockReturnValue({ data: { items: ['tag1', 'tag2'] } }),
useAuthz: jest.fn().mockReturnValue({ fleet: { all: true, allAgents: true, readAgents: true } }),
useAuthz: jest
.fn()
.mockReturnValue({ fleet: { all: true, allAgents: true, readAgents: true }, integrations: {} }),
useStartServices: jest.fn().mockReturnValue({
notifications: {
toasts: {

View file

@ -95,6 +95,9 @@ describe('useFleetServerUnhealthy', () => {
allAgents: true,
readAgentPolicies: true,
},
integrations: {
readIntegrationPolicies: true,
},
} as any);
});
it('should return isUnHealthy:false with an online fleet slerver', async () => {

View file

@ -70,12 +70,12 @@ export function useFleetServerUnhealthy() {
}, [notifications.toasts]);
useEffect(() => {
if (!authz.fleet.allAgents || !authz.fleet.readAgentPolicies) {
if (!authz.fleet.allAgents || !authz.integrations.readIntegrationPolicies) {
setIsLoading(false);
return;
}
fetchData();
}, [fetchData, authz.fleet.allAgents, authz.fleet.readAgentPolicies]);
}, [fetchData, authz.fleet.allAgents, authz.integrations.readIntegrationPolicies]);
return {
isLoading,

View file

@ -41,7 +41,10 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) {
`--elasticsearch.ssl.certificateAuthorities=${CA_CERT_PATH}`,
// add feature flags here
`--xpack.fleet.enableExperimental=${JSON.stringify(['agentTamperProtectionEnabled'])}`,
`--xpack.fleet.enableExperimental=${JSON.stringify([
'agentTamperProtectionEnabled',
'subfeaturePrivileges',
])}`,
`--logging.loggers=${JSON.stringify([
...getKibanaCliLoggers(xpackFunctionalTestsConfig.get('kbnTestServer.serverArgs')),