From 37654794371cd395a92b50c07f7167c691833db9 Mon Sep 17 00:00:00 2001 From: Matthew Kime Date: Mon, 2 Dec 2024 15:52:33 -0600 Subject: [PATCH] [index management] better privilege checking for enrich policies (#201717) ## Summary Kibana roles with only `manage_enrich` or `monitor_enrich` will now have access to the Enrich Policy tab in Index Management. --- The `registerElasticsearchFeature` api is too restrictive to use for index management as it only allows a single set of privileges to determine whether a given management app is shown AND any stated privilege is combined in an `AND` logic statement. We need `OR` - index management may cover a number of different privileges that don't overlap. The solution - use an observable to subscribe to the capabilities api and register the management app based on that. This pr focuses on Enrich Policies and removes UI elements as appropriate based on `manage_enrich` or `monitor_enrich` and leaves other index management tabs alone as these will be addressed in follow up PRs. Part of https://github.com/elastic/kibana/issues/178654 --- .../create_enrich_policy.test.tsx | 4 - .../helpers/http_requests.ts | 4 - .../helpers/setup_environment.tsx | 5 + .../home/enrich_policies.test.tsx | 28 ---- .../__jest__/components/index_table.test.js | 5 + .../public/application/app_context.tsx | 5 + .../components/enrich_policies/index.ts | 9 -- .../enrich_policies/with_privileges.tsx | 82 ----------- .../application/mount_management_section.ts | 7 + .../enrich_policy_create.tsx | 14 +- .../enrich_policies_list.tsx | 20 +-- .../policies_table/policies_table.tsx | 137 ++++++++++-------- .../public/application/sections/home/home.tsx | 14 +- .../plugins/index_management/public/plugin.ts | 55 ++++--- .../plugins/index_management/server/plugin.ts | 13 +- .../translations/translations/fr-FR.json | 4 - .../translations/translations/ja-JP.json | 4 - .../translations/translations/zh-CN.json | 4 - .../apps/index_management/config.ts | 84 ++++++++++- .../enrich_policies_tab.ts | 29 +++- 20 files changed, 266 insertions(+), 261 deletions(-) delete mode 100644 x-pack/plugins/index_management/public/application/components/enrich_policies/index.ts delete mode 100644 x-pack/plugins/index_management/public/application/components/enrich_policies/with_privileges.tsx diff --git a/x-pack/plugins/index_management/__jest__/client_integration/create_enrich_policy/create_enrich_policy.test.tsx b/x-pack/plugins/index_management/__jest__/client_integration/create_enrich_policy/create_enrich_policy.test.tsx index a9675b592aa39..e9d93e6baf631 100644 --- a/x-pack/plugins/index_management/__jest__/client_integration/create_enrich_policy/create_enrich_policy.test.tsx +++ b/x-pack/plugins/index_management/__jest__/client_integration/create_enrich_policy/create_enrich_policy.test.tsx @@ -57,10 +57,6 @@ describe('Create enrich policy', () => { beforeEach(async () => { httpRequestsMockHelpers.setGetMatchingIndices(getMatchingIndices()); - httpRequestsMockHelpers.setGetPrivilegesResponse({ - hasAllPrivileges: true, - missingPrivileges: { cluster: [] }, - }); httpRequestsMockHelpers.setGetMatchingDataStreams(getMatchingDataStreams()); await act(async () => { diff --git a/x-pack/plugins/index_management/__jest__/client_integration/helpers/http_requests.ts b/x-pack/plugins/index_management/__jest__/client_integration/helpers/http_requests.ts index 0504f9bf40b7a..a9f1dac15ed1f 100644 --- a/x-pack/plugins/index_management/__jest__/client_integration/helpers/http_requests.ts +++ b/x-pack/plugins/index_management/__jest__/client_integration/helpers/http_requests.ts @@ -188,9 +188,6 @@ const registerHttpRequestMockHelpers = ( error ); - const setGetPrivilegesResponse = (response?: HttpResponse, error?: ResponseError) => - mockResponse('GET', `${INTERNAL_API_BASE_PATH}/enrich_policies/privileges`, response, error); - const setCreateEnrichPolicy = (response?: HttpResponse, error?: ResponseError) => mockResponse('POST', `${INTERNAL_API_BASE_PATH}/enrich_policies`, response, error); @@ -253,7 +250,6 @@ const registerHttpRequestMockHelpers = ( setCreateIndexResponse, setGetMatchingIndices, setGetFieldsFromIndices, - setGetPrivilegesResponse, setCreateEnrichPolicy, setInferenceModels, setGetMatchingDataStreams, diff --git a/x-pack/plugins/index_management/__jest__/client_integration/helpers/setup_environment.tsx b/x-pack/plugins/index_management/__jest__/client_integration/helpers/setup_environment.tsx index 633ed96ec8225..24f641ae2833f 100644 --- a/x-pack/plugins/index_management/__jest__/client_integration/helpers/setup_environment.tsx +++ b/x-pack/plugins/index_management/__jest__/client_integration/helpers/setup_environment.tsx @@ -91,6 +91,11 @@ const appDependencies = { overlays: { openConfirm: jest.fn(), }, + privs: { + monitor: true, + manageEnrich: true, + monitorEnrich: true, + }, } as any; export const kibanaVersion = new SemVer(MAJOR_VERSION); diff --git a/x-pack/plugins/index_management/__jest__/client_integration/home/enrich_policies.test.tsx b/x-pack/plugins/index_management/__jest__/client_integration/home/enrich_policies.test.tsx index 77c7757fe9202..040602a058e25 100644 --- a/x-pack/plugins/index_management/__jest__/client_integration/home/enrich_policies.test.tsx +++ b/x-pack/plugins/index_management/__jest__/client_integration/home/enrich_policies.test.tsx @@ -38,11 +38,6 @@ describe('Enrich policies tab', () => { describe('empty states', () => { beforeEach(async () => { setDelayResponse(false); - - httpRequestsMockHelpers.setGetPrivilegesResponse({ - hasAllPrivileges: true, - missingPrivileges: { cluster: [] }, - }); }); test('displays a loading prompt', async () => { @@ -82,24 +77,6 @@ describe('Enrich policies tab', () => { }); }); - describe('permissions check', () => { - it('shows a permissions error when the user does not have sufficient privileges', async () => { - httpRequestsMockHelpers.setGetPrivilegesResponse({ - hasAllPrivileges: false, - missingPrivileges: { cluster: ['manage_enrich'] }, - }); - - testBed = await setup(httpSetup); - await act(async () => { - testBed.actions.goToEnrichPoliciesTab(); - }); - - testBed.component.update(); - - expect(testBed.exists('enrichPoliciesInsuficientPrivileges')).toBe(true); - }); - }); - describe('policies list', () => { let testPolicy: ReturnType; beforeEach(async () => { @@ -110,11 +87,6 @@ describe('Enrich policies tab', () => { createTestEnrichPolicy('policy-range', 'range'), ]); - httpRequestsMockHelpers.setGetPrivilegesResponse({ - hasAllPrivileges: true, - missingPrivileges: { cluster: [] }, - }); - testBed = await setup(httpSetup); await act(async () => { testBed.actions.goToEnrichPoliciesTab(); diff --git a/x-pack/plugins/index_management/__jest__/components/index_table.test.js b/x-pack/plugins/index_management/__jest__/components/index_table.test.js index 2ae162b421001..0a59fef7be6e6 100644 --- a/x-pack/plugins/index_management/__jest__/components/index_table.test.js +++ b/x-pack/plugins/index_management/__jest__/components/index_table.test.js @@ -168,6 +168,11 @@ describe('index table', () => { enableIndexActions: true, enableIndexStats: true, }, + privs: { + monitor: true, + manageEnrich: true, + monitorEnrich: true, + }, }; component = ( diff --git a/x-pack/plugins/index_management/public/application/app_context.tsx b/x-pack/plugins/index_management/public/application/app_context.tsx index 6df01a109a036..3573ae33812d9 100644 --- a/x-pack/plugins/index_management/public/application/app_context.tsx +++ b/x-pack/plugins/index_management/public/application/app_context.tsx @@ -80,6 +80,11 @@ export interface AppDependencies { kibanaVersion: SemVer; overlays: OverlayStart; canUseSyntheticSource: boolean; + privs: { + monitor: boolean; + manageEnrich: boolean; + monitorEnrich: boolean; + }; } export const AppContextProvider = ({ diff --git a/x-pack/plugins/index_management/public/application/components/enrich_policies/index.ts b/x-pack/plugins/index_management/public/application/components/enrich_policies/index.ts deleted file mode 100644 index de8fa4ebf5ac7..0000000000000 --- a/x-pack/plugins/index_management/public/application/components/enrich_policies/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -/* - * 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. - */ - -export { EnrichPoliciesWithPrivileges } from './with_privileges'; -export { EnrichPoliciesAuthProvider } from './auth_provider'; diff --git a/x-pack/plugins/index_management/public/application/components/enrich_policies/with_privileges.tsx b/x-pack/plugins/index_management/public/application/components/enrich_policies/with_privileges.tsx deleted file mode 100644 index 09a79343b2210..0000000000000 --- a/x-pack/plugins/index_management/public/application/components/enrich_policies/with_privileges.tsx +++ /dev/null @@ -1,82 +0,0 @@ -/* - * 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 { FormattedMessage } from '@kbn/i18n-react'; -import React, { FunctionComponent } from 'react'; - -import { - PageLoading, - PageError, - useAuthorizationContext, - WithPrivileges, - NotAuthorizedSection, -} from '../../../shared_imports'; -import { ENRICH_POLICIES_REQUIRED_PRIVILEGES } from '../../constants'; - -export const EnrichPoliciesWithPrivileges: FunctionComponent<{ - children?: React.ReactNode; -}> = ({ children }) => { - const { apiError } = useAuthorizationContext(); - - if (apiError) { - return ( - - } - error={apiError} - /> - ); - } - - return ( - `cluster.${privilege}`)} - > - {({ isLoading, hasPrivileges, privilegesMissing }) => { - if (isLoading) { - return ( - - - - ); - } - - if (!hasPrivileges) { - return ( - - } - message={ - - } - /> - ); - } - - return <>{children}; - }} - - ); -}; diff --git a/x-pack/plugins/index_management/public/application/mount_management_section.ts b/x-pack/plugins/index_management/public/application/mount_management_section.ts index 48a45579a01fc..83cf620a0e8e0 100644 --- a/x-pack/plugins/index_management/public/application/mount_management_section.ts +++ b/x-pack/plugins/index_management/public/application/mount_management_section.ts @@ -73,6 +73,8 @@ export function getIndexManagementDependencies({ }): AppDependencies { const { docLinks, application, uiSettings, settings } = core; const { url } = startDependencies.share; + const { monitor, manageEnrich, monitorEnrich } = application.capabilities.index_management; + return { core: { getUrlForApp: application.getUrlForApp, @@ -103,6 +105,11 @@ export function getIndexManagementDependencies({ kibanaVersion, overlays: core.overlays, canUseSyntheticSource, + privs: { + monitor: !!monitor, + manageEnrich: !!manageEnrich, + monitorEnrich: !!monitorEnrich, + }, }; } diff --git a/x-pack/plugins/index_management/public/application/sections/enrich_policy_create/enrich_policy_create.tsx b/x-pack/plugins/index_management/public/application/sections/enrich_policy_create/enrich_policy_create.tsx index f7ef260b14651..321dee68ae8aa 100644 --- a/x-pack/plugins/index_management/public/application/sections/enrich_policy_create/enrich_policy_create.tsx +++ b/x-pack/plugins/index_management/public/application/sections/enrich_policy_create/enrich_policy_create.tsx @@ -14,12 +14,8 @@ import { breadcrumbService, IndexManagementBreadcrumb } from '../../services/bre import { CreatePolicyWizard } from './create_policy_wizard'; import { CreatePolicyContextProvider } from './create_policy_context'; -import { - EnrichPoliciesAuthProvider, - EnrichPoliciesWithPrivileges, -} from '../../components/enrich_policies'; -const CreateView: React.FunctionComponent = () => { +export const EnrichPolicyCreate: React.FunctionComponent = () => { useEffect(() => { breadcrumbService.setBreadcrumbs(IndexManagementBreadcrumb.enrichPoliciesCreate); }, []); @@ -64,11 +60,3 @@ const CreateView: React.FunctionComponent = () => { ); }; - -export const EnrichPolicyCreate: React.FunctionComponent = (props) => ( - - - - - -); diff --git a/x-pack/plugins/index_management/public/application/sections/home/enrich_policies_list/enrich_policies_list.tsx b/x-pack/plugins/index_management/public/application/sections/home/enrich_policies_list/enrich_policies_list.tsx index a036273ebdde9..eeba7b9e03fd8 100644 --- a/x-pack/plugins/index_management/public/application/sections/home/enrich_policies_list/enrich_policies_list.tsx +++ b/x-pack/plugins/index_management/public/application/sections/home/enrich_policies_list/enrich_policies_list.tsx @@ -17,10 +17,6 @@ import { APP_WRAPPER_CLASS, useExecutionContext } from '../../../../shared_impor import { useAppContext } from '../../../app_context'; import { useRedirectPath } from '../../../hooks/redirect_path'; -import { - EnrichPoliciesAuthProvider, - EnrichPoliciesWithPrivileges, -} from '../../../components/enrich_policies'; import { breadcrumbService, IndexManagementBreadcrumb } from '../../../services/breadcrumbs'; import { documentationService } from '../../../services/documentation'; import { useLoadEnrichPolicies } from '../../../services/api'; @@ -34,9 +30,13 @@ const getEnrichPolicyNameFromLocation = (location: Location) => { return policy; }; -const ListView: React.FunctionComponent = ({ history, location }) => { +export const EnrichPoliciesList: React.FunctionComponent = ({ + history, + location, +}) => { const { core: { executionContext }, + privs, } = useAppContext(); const redirectTo = useRedirectPath(history); @@ -79,7 +79,7 @@ const ListView: React.FunctionComponent = ({ history, locat return ; } - if (policies?.length === 0) { + if (privs.manageEnrich && policies?.length === 0) { return ; } @@ -151,11 +151,3 @@ const ListView: React.FunctionComponent = ({ history, locat ); }; - -export const EnrichPoliciesList: React.FunctionComponent = (props) => ( - - - - - -); diff --git a/x-pack/plugins/index_management/public/application/sections/home/enrich_policies_list/policies_table/policies_table.tsx b/x-pack/plugins/index_management/public/application/sections/home/enrich_policies_list/policies_table/policies_table.tsx index e78e08b829997..61574a70fa545 100644 --- a/x-pack/plugins/index_management/public/application/sections/home/enrich_policies_list/policies_table/policies_table.tsx +++ b/x-pack/plugins/index_management/public/application/sections/home/enrich_policies_list/policies_table/policies_table.tsx @@ -33,43 +33,84 @@ export const PoliciesTable: FunctionComponent = ({ onDeletePolicyClick, onExecutePolicyClick, }) => { - const { history } = useAppContext(); + const { history, privs } = useAppContext(); - const renderToolsRight = () => { - return [ - - - , - - - , - ]; - }; + const createBtn = ( + + + + ); + + const toolsRight = [ + + + , + ]; + + if (privs.manageEnrich) { + toolsRight.push(createBtn); + } const search: EuiSearchBarProps = { - toolsRight: renderToolsRight(), + toolsRight, box: { incremental: true, }, }; + const actions: EuiBasicTableColumn = { + name: i18n.translate('xpack.idxMgmt.enrichPolicies.table.actionsField', { + defaultMessage: 'Actions', + }), + actions: [ + { + isPrimary: true, + name: i18n.translate('xpack.idxMgmt.enrichPolicies.table.executeAction', { + defaultMessage: 'Execute', + }), + description: i18n.translate('xpack.idxMgmt.enrichPolicies.table.executeDescription', { + defaultMessage: 'Execute this enrich policy', + }), + type: 'icon', + icon: 'play', + 'data-test-subj': 'executePolicyButton', + onClick: ({ name }) => onExecutePolicyClick(name), + }, + { + isPrimary: true, + name: i18n.translate('xpack.idxMgmt.enrichPolicies.table.deleteAction', { + defaultMessage: 'Delete', + }), + description: i18n.translate('xpack.idxMgmt.enrichPolicies.table.deleteDescription', { + defaultMessage: 'Delete this enrich policy', + }), + type: 'icon', + icon: 'trash', + color: 'danger', + 'data-test-subj': 'deletePolicyButton', + onClick: ({ name }) => onDeletePolicyClick(name), + }, + ], + }; + const columns: Array> = [ { field: 'name', @@ -120,42 +161,12 @@ export const PoliciesTable: FunctionComponent = ({ truncateText: true, render: (fields: string[]) => {fields.join(', ')}, }, - { - name: i18n.translate('xpack.idxMgmt.enrichPolicies.table.actionsField', { - defaultMessage: 'Actions', - }), - actions: [ - { - isPrimary: true, - name: i18n.translate('xpack.idxMgmt.enrichPolicies.table.executeAction', { - defaultMessage: 'Execute', - }), - description: i18n.translate('xpack.idxMgmt.enrichPolicies.table.executeDescription', { - defaultMessage: 'Execute this enrich policy', - }), - type: 'icon', - icon: 'play', - 'data-test-subj': 'executePolicyButton', - onClick: ({ name }) => onExecutePolicyClick(name), - }, - { - isPrimary: true, - name: i18n.translate('xpack.idxMgmt.enrichPolicies.table.deleteAction', { - defaultMessage: 'Delete', - }), - description: i18n.translate('xpack.idxMgmt.enrichPolicies.table.deleteDescription', { - defaultMessage: 'Delete this enrich policy', - }), - type: 'icon', - icon: 'trash', - color: 'danger', - 'data-test-subj': 'deletePolicyButton', - onClick: ({ name }) => onDeletePolicyClick(name), - }, - ], - }, ]; + if (privs.manageEnrich) { + columns.push(actions); + } + const { pageSize, sorting, onTableChange } = useEuiTablePersist({ tableId: 'enrichPolicies', initialPageSize: 50, diff --git a/x-pack/plugins/index_management/public/application/sections/home/home.tsx b/x-pack/plugins/index_management/public/application/sections/home/home.tsx index e7de896fa4b38..2d0fc7d4ec108 100644 --- a/x-pack/plugins/index_management/public/application/sections/home/home.tsx +++ b/x-pack/plugins/index_management/public/application/sections/home/home.tsx @@ -41,6 +41,7 @@ export const IndexManagementHome: React.FunctionComponent { const { plugins: { console: consolePlugin }, + privs, } = useAppContext(); const tabs = [ { @@ -74,7 +75,10 @@ export const IndexManagementHome: React.FunctionComponent ), }, - { + ]; + + if (privs.monitorEnrich) { + tabs.push({ id: Section.EnrichPolicies, name: ( ), - }, - ]; + }); + } const onSectionChange = (newSection: Section) => { history.push(`/${newSection}`); @@ -143,7 +147,9 @@ export const IndexManagementHome: React.FunctionComponent - + {privs.monitorEnrich && ( + + )} {consolePlugin?.EmbeddableConsole ? : null} diff --git a/x-pack/plugins/index_management/public/plugin.ts b/x-pack/plugins/index_management/public/plugin.ts index 82ba6505696aa..06adcc75d80b3 100644 --- a/x-pack/plugins/index_management/public/plugin.ts +++ b/x-pack/plugins/index_management/public/plugin.ts @@ -6,6 +6,7 @@ */ import { i18n } from '@kbn/i18n'; +import { Subject } from 'rxjs'; import SemVer from 'semver/classes/semver'; import { @@ -14,6 +15,7 @@ import { Plugin, PluginInitializerContext, ScopedHistory, + Capabilities, } from '@kbn/core/public'; import { IndexManagementPluginSetup, @@ -61,6 +63,8 @@ export class IndexMgmtUIPlugin private canUseSyntheticSource: boolean = false; private licensingSubscription?: Subscription; + private capabilities$ = new Subject(); + constructor(ctx: PluginInitializerContext) { // Temporary hack to provide the service instances in module files in order to avoid a big refactor // For the selectors we should expose them through app dependencies and read them from there on each container component. @@ -98,29 +102,34 @@ export class IndexMgmtUIPlugin coreSetup: CoreSetup, plugins: SetupDependencies ): IndexManagementPluginSetup { - if (this.config.isIndexManagementUiEnabled) { - const { fleet, usageCollection, management, cloud } = plugins; + const { fleet, usageCollection, management, cloud } = plugins; - management.sections.section.data.registerApp({ - id: PLUGIN.id, - title: i18n.translate('xpack.idxMgmt.appTitle', { defaultMessage: 'Index Management' }), - order: 0, - mount: async (params) => { - const { mountManagementSection } = await import('./application/mount_management_section'); - return mountManagementSection({ - coreSetup, - usageCollection, - params, - extensionsService: this.extensionsService, - isFleetEnabled: Boolean(fleet), - kibanaVersion: this.kibanaVersion, - config: this.config, - cloud, - canUseSyntheticSource: this.canUseSyntheticSource, - }); - }, - }); - } + this.capabilities$.subscribe((capabilities) => { + const { monitor, manageEnrich, monitorEnrich } = capabilities.index_management; + if (this.config.isIndexManagementUiEnabled && (monitor || manageEnrich || monitorEnrich)) { + management.sections.section.data.registerApp({ + id: PLUGIN.id, + title: i18n.translate('xpack.idxMgmt.appTitle', { defaultMessage: 'Index Management' }), + order: 0, + mount: async (params) => { + const { mountManagementSection } = await import( + './application/mount_management_section' + ); + return mountManagementSection({ + coreSetup, + usageCollection, + params, + extensionsService: this.extensionsService, + isFleetEnabled: Boolean(fleet), + kibanaVersion: this.kibanaVersion, + config: this.config, + cloud, + canUseSyntheticSource: this.canUseSyntheticSource, + }); + }, + }); + } + }); this.locator = plugins.share.url.locators.create( new IndexManagementLocatorDefinition({ @@ -138,6 +147,8 @@ export class IndexMgmtUIPlugin public start(coreStart: CoreStart, plugins: StartDependencies): IndexManagementPluginStart { const { fleet, usageCollection, cloud, share, console, ml, licensing } = plugins; + this.capabilities$.next(coreStart.application.capabilities); + this.licensingSubscription = licensing?.license$.subscribe((next) => { this.canUseSyntheticSource = next.hasAtLeast('enterprise'); }); diff --git a/x-pack/plugins/index_management/server/plugin.ts b/x-pack/plugins/index_management/server/plugin.ts index 0ba15c463d4ec..ab6b058cddc78 100644 --- a/x-pack/plugins/index_management/server/plugin.ts +++ b/x-pack/plugins/index_management/server/plugin.ts @@ -37,15 +37,20 @@ export class IndexMgmtServerPlugin implements Plugin { describe('Enrich policies tab', function () { before(async () => { await log.debug('Creating required index and enrich policy'); + + try { + await es.indices.delete({ index: ENRICH_INDEX_NAME }); + // eslint-disable-next-line no-empty + } catch (e) {} + try { await es.indices.create({ index: ENRICH_INDEX_NAME, @@ -94,7 +100,22 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { expect(await successToast.getVisibleText()).to.contain(`Executed ${ENRICH_POLICY_NAME}`); }); + it('read only access', async () => { + await security.testUser.setRoles(['index_management_monitor_enrich_only']); + await pageObjects.common.navigateToApp('indexManagement'); + await pageObjects.indexManagement.changeTabs('enrich_policiesTab'); + await pageObjects.header.waitUntilLoadingHasFinished(); + + await testSubjects.missingOrFail('createPolicyButton'); + await testSubjects.missingOrFail('deletePolicyButton'); + }); + it('can delete a policy', async () => { + await security.testUser.setRoles(['index_management_user']); + await pageObjects.common.navigateToApp('indexManagement'); + // Navigate to the enrich policies tab + await pageObjects.indexManagement.changeTabs('enrich_policiesTab'); + await pageObjects.header.waitUntilLoadingHasFinished(); // Since we disabled wait_for_completion in the server request, we dont know when // a given policy will finish executing. Until that happens the policy cannot // be deleted. 2s seems to be plenty enough to guarantee that, at least for this @@ -104,8 +125,14 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await pageObjects.indexManagement.clickDeleteEnrichPolicyAt(0); await pageObjects.indexManagement.clickConfirmModalButton(); - const successToast = await toasts.getElementByIndex(2); + const successToast = await toasts.getElementByIndex(1); expect(await successToast.getVisibleText()).to.contain(`Deleted ${ENRICH_POLICY_NAME}`); }); + + it('no access', async () => { + await security.testUser.setRoles(['index_management_monitor_only']); + await pageObjects.common.navigateToApp('indexManagement'); + await testSubjects.missingOrFail('enrich_policiesTab'); + }); }); };