Alerting: Fix permission checks for the Import to GMA (#109950)

Fix permission checks for the Import rules buttons and import to GMA page
This commit is contained in:
Konrad Lalik 2025-08-26 08:39:36 +02:00 committed by GitHub
parent 6b67b394fd
commit 6a050ff551
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 36 additions and 12 deletions

View File

@ -226,7 +226,10 @@ export function getAlertingRoutes(cfg = config): RouteDescriptor[] {
},
{
path: '/alerting/import-datasource-managed-rules',
roles: () => ['Admin'],
roles: evaluateAccess([
AccessControlAction.AlertingRuleCreate,
AccessControlAction.AlertingProvisioningSetStatus,
]),
component: config.featureToggles.alertingMigrationUI
? importAlertingComponent(
() =>

View File

@ -6,6 +6,8 @@ import { GrafanaTheme2, urlUtil } from '@grafana/data';
import { Trans, t } from '@grafana/i18n';
import { config } from '@grafana/runtime';
import { Badge, LinkButton, LoadingPlaceholder, Pagination, Spinner, Stack, Text, useStyles2 } from '@grafana/ui';
import { contextSrv } from 'app/core/services/context_srv';
import { AccessControlAction } from 'app/types/accessControl';
import { CombinedRuleNamespace } from 'app/types/unified-alerting';
import { DEFAULT_PER_PAGE_PAGINATION } from '../../../../../core/constants';
@ -14,7 +16,6 @@ import { usePagination } from '../../hooks/usePagination';
import { useUnifiedAlertingSelector } from '../../hooks/useUnifiedAlertingSelector';
import { getPaginationStyles } from '../../styles/pagination';
import { getRulesDataSources, getRulesSourceUid } from '../../utils/datasource';
import { isAdmin } from '../../utils/misc';
import { isAsyncRequestStatePending } from '../../utils/redux';
import { createRelativeUrl } from '../../utils/url';
@ -49,7 +50,11 @@ export const CloudRules = ({ namespaces, expandAll }: Props) => {
DEFAULT_PER_PAGE_PAGINATION
);
const canMigrateToGMA = hasDataSourcesConfigured && isAdmin() && config.featureToggles.alertingMigrationUI;
const canMigrateToGMA =
hasDataSourcesConfigured &&
config.featureToggles.alertingMigrationUI &&
contextSrv.hasPermission(AccessControlAction.AlertingRuleCreate) &&
contextSrv.hasPermission(AccessControlAction.AlertingProvisioningSetStatus);
return (
<section className={styles.wrapper}>

View File

@ -255,9 +255,12 @@ describe('RuleListActions', () => {
describe('Import Alert Rules', () => {
testWithFeatureToggles(['alertingMigrationUI']);
it('should show "Import alert rules" option when user is admin and feature toggle is enabled', async () => {
grantUserRole(OrgRole.Admin);
grantUserPermissions([AccessControlAction.AlertingRuleRead]);
it('should show "Import alert rules" option when user has required permissions and feature toggle is enabled', async () => {
grantUserPermissions([
AccessControlAction.AlertingRuleRead,
AccessControlAction.AlertingRuleCreate,
AccessControlAction.AlertingProvisioningSetStatus,
]);
const { user } = render(<RuleListActions />);
@ -267,8 +270,8 @@ describe('RuleListActions', () => {
expect(ui.menuOptions.importAlertRules.query(menu)).toBeInTheDocument();
});
it('should not show "Import alert rules" option when user is not admin', async () => {
// Keep default Viewer role
it('should not show "Import alert rules" option when user lacks required permissions', async () => {
// Keep default Viewer role and only read permissions
grantUserPermissions([AccessControlAction.AlertingRuleRead]);
const { user } = render(<RuleListActions />);
@ -280,8 +283,11 @@ describe('RuleListActions', () => {
});
it('should have correct URL for "Import alert rules" menu item', async () => {
grantUserRole(OrgRole.Admin);
grantUserPermissions([AccessControlAction.AlertingRuleRead]);
grantUserPermissions([
AccessControlAction.AlertingRuleRead,
AccessControlAction.AlertingRuleCreate,
AccessControlAction.AlertingProvisioningSetStatus,
]);
const { user } = render(<RuleListActions />);

View File

@ -4,6 +4,8 @@ import { useToggle } from 'react-use';
import { Trans, t } from '@grafana/i18n';
import { config } from '@grafana/runtime';
import { Button, Dropdown, Icon, LinkButton, Menu, Stack } from '@grafana/ui';
import { contextSrv } from 'app/core/services/context_srv';
import { AccessControlAction } from 'app/types/accessControl';
import { AlertingPageWrapper } from '../components/AlertingPageWrapper';
import { GrafanaRulesExporter } from '../components/export/GrafanaRulesExporter';
@ -11,7 +13,6 @@ import { useListViewMode } from '../components/rules/Filter/RulesViewModeSelecto
import { AIAlertRuleButtonComponent } from '../enterprise-components/AI/AIGenAlertRuleButton/addAIAlertRuleButton';
import { AlertingAction, useAlertingAbility } from '../hooks/useAbilities';
import { useRulesFilter } from '../hooks/useFilteredRules';
import { isAdmin } from '../utils/misc';
import { FilterView } from './FilterView';
import { GroupedView } from './GroupedView';
@ -44,7 +45,11 @@ export function RuleListActions() {
const canExportRules = exportRulesSupported && exportRulesAllowed;
const canCreateRules = canCreateGrafanaRules || canCreateCloudRules;
const canImportRulesToGMA = isAdmin() && config.featureToggles.alertingMigrationUI;
// Align import UI permission with convert endpoint requirements: rule create + provisioning set status
const canImportRulesToGMA =
config.featureToggles.alertingMigrationUI &&
contextSrv.hasPermission(AccessControlAction.AlertingRuleCreate) &&
contextSrv.hasPermission(AccessControlAction.AlertingProvisioningSetStatus);
const [showExportDrawer, toggleShowExportDrawer] = useToggle(false);

View File

@ -129,6 +129,11 @@ export enum AccessControlAction {
AlertingProvisioningReadSecrets = 'alert.provisioning.secrets:read',
AlertingProvisioningRead = 'alert.provisioning:read',
AlertingProvisioningWrite = 'alert.provisioning:write',
AlertingRulesProvisioningRead = 'alert.rules.provisioning:read',
AlertingRulesProvisioningWrite = 'alert.rules.provisioning:write',
AlertingNotificationsProvisioningRead = 'alert.notifications.provisioning:read',
AlertingNotificationsProvisioningWrite = 'alert.notifications.provisioning:write',
AlertingProvisioningSetStatus = 'alert.provisioning.provenance:write',
// Alerting receivers actions
AlertingReceiversPermissionsRead = 'receivers.permissions:read',