Alerting: Relax permissions for access a rule (#103664)

This makes it so that it is:
- No longer required to have datasource permissions to delete a rule.
- No longer required to have datasource permissions to update non-query related fields of a rule.
This commit is contained in:
Moustafa Baiou
2025-04-11 00:58:37 +01:00
committed by GitHub
parent 3a71a48a88
commit 032299011a
6 changed files with 304 additions and 52 deletions
+33 -7
View File
@@ -81,6 +81,24 @@ func TestRouteDeleteAlertRules(t *testing.T) {
t.Run("when fine-grained access is enabled", func(t *testing.T) {
t.Run("and group argument is empty", func(t *testing.T) {
t.Run("allow deleting without access to datasource", func(t *testing.T) {
ruleStore := initFakeRuleStore(t)
provisioningStore := fakes.NewFakeProvisioningStore()
folderGen := gen.With(gen.WithNamespace(folder.ToFolderReference()))
authorizedRulesInFolder := folderGen.With(gen.WithGroupPrefix("authz-")).GenerateManyRef(1, 5)
ruleStore.PutRule(context.Background(), authorizedRulesInFolder...)
permissions := createPermissionsForRulesWithoutDS(authorizedRulesInFolder, orgID)
requestCtx := createRequestContextWithPerms(orgID, permissions, nil)
response := createServiceWithProvenanceStore(ruleStore, provisioningStore).RouteDeleteAlertRules(requestCtx, folder.UID, "")
require.Equalf(t, 202, response.Status(), "Expected 202 but got %d: %v", response.Status(), string(response.Body()))
assertRulesDeleted(t, authorizedRulesInFolder, ruleStore)
})
t.Run("return Forbidden if user is not authorized to access any group in the folder", func(t *testing.T) {
ruleStore := initFakeRuleStore(t)
ruleStore.PutRule(context.Background(), gen.With(gen.WithNamespace(folder.ToFolderReference())).GenerateManyRef(1, 5)...)
@@ -108,8 +126,6 @@ func TestRouteDeleteAlertRules(t *testing.T) {
ruleStore.PutRule(context.Background(), authorizedRulesInFolder...)
ruleStore.PutRule(context.Background(), provisionedRulesInFolder...)
// more rules in the same namespace but user does not have access to them
ruleStore.PutRule(context.Background(), folderGen.With(gen.WithGroupPrefix("unauthz")).GenerateManyRef(1, 5)...)
permissions := createPermissionsForRules(append(authorizedRulesInFolder, provisionedRulesInFolder...), orgID)
requestCtx := createRequestContextWithPerms(orgID, permissions, nil)
@@ -130,8 +146,6 @@ func TestRouteDeleteAlertRules(t *testing.T) {
require.NoError(t, err)
ruleStore.PutRule(context.Background(), provisionedRulesInFolder...)
// more rules in the same namespace but user does not have access to them
ruleStore.PutRule(context.Background(), folderGen.With(gen.WithSameGroup()).GenerateManyRef(1, 5)...)
permissions := createPermissionsForRules(provisionedRulesInFolder, orgID)
requestCtx := createRequestContextWithPerms(orgID, permissions, nil)
@@ -159,10 +173,8 @@ func TestRouteDeleteAlertRules(t *testing.T) {
authorizedRulesInGroup := groupGen.GenerateManyRef(1, 5)
ruleStore.PutRule(context.Background(), authorizedRulesInGroup...)
// more rules in the same group but user is not authorized to access them
ruleStore.PutRule(context.Background(), groupGen.GenerateManyRef(1, 5)...)
permissions := createPermissionsForRules(authorizedRulesInGroup, orgID)
permissions := createPermissionsForRules([]*models.AlertRule{}, orgID)
requestCtx := createRequestContextWithPerms(orgID, permissions, nil)
response := createService(ruleStore, nil).RouteDeleteAlertRules(requestCtx, folder.UID, authorizedRulesInGroup[0].RuleGroup)
@@ -1014,3 +1026,17 @@ func createPermissionsForRules(rules []*models.AlertRule, orgID int64) map[int64
}
return map[int64]map[string][]string{orgID: permissions}
}
func createPermissionsForRulesWithoutDS(rules []*models.AlertRule, orgID int64) map[int64]map[string][]string {
ns := map[string]any{}
permissions := map[string][]string{}
for _, rule := range rules {
if _, ok := ns[rule.NamespaceUID]; !ok {
scope := dashboards.ScopeFoldersProvider.GetResourceScopeUID(rule.NamespaceUID)
permissions[dashboards.ActionFoldersRead] = append(permissions[dashboards.ActionFoldersRead], scope)
permissions[ac.ActionAlertingRuleRead] = append(permissions[ac.ActionAlertingRuleRead], scope)
ns[rule.NamespaceUID] = struct{}{}
}
}
return map[int64]map[string][]string{orgID: permissions}
}