mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Alerting: Update fixed roles to include silences permissions (#85826)
* update fixed roles to include silences * add silence actions to managed permissions * update documentation
This commit is contained in:
@@ -46,6 +46,9 @@ The following list contains role-based access control actions.
|
||||
| `alert.rules:delete` | `folders:*`<br>`folders:uid:*` | Delete Grafana alert rules in a folder and its subfolders. Combine this permission with `folders:read` in a scope that includes the folder and `datasources:query` in the scope of data sources the user can query. |
|
||||
| `alert.rules:read` | `folders:*`<br>`folders:uid:*` | Read Grafana alert rules in a folder and its subfolders. Combine this permission with `folders:read` in a scope that includes the folder and `datasources:query` in the scope of data sources the user can query. |
|
||||
| `alert.rules:write` | `folders:*`<br>`folders:uid:*` | Update Grafana alert rules in a folder and its subfolders. Combine this permission with `folders:read` in a scope that includes the folder and `datasources:query` in the scope of data sources the user can query. |
|
||||
| `alert.silences:create` | `folders:*`<br>`folders:uid:*` | Create rule-specific silences in a folder and its subfolders. |
|
||||
| `alert.silences:read` | `folders:*`<br>`folders:uid:*` | Read general and rule-specific silences in a folder and its subfolders. |
|
||||
| `alert.silences:write` | `folders:*`<br>`folders:uid:*` | Update and expire rule-specific silences in a folder and its subfolders. |
|
||||
| `alert.provisioning:read` | n/a | Read all Grafana alert rules, notification policies, etc via provisioning API. Permissions to folders and datasource are not required. |
|
||||
| `alert.provisioning.secrets:read` | n/a | Same as `alert.provisioning:read` plus ability to export resources with decrypted secrets. |
|
||||
| `alert.provisioning:write` | n/a | Update all Grafana alert rules, notification policies, etc via provisioning API. Permissions to folders and datasource are not required. |
|
||||
|
||||
@@ -34,13 +34,13 @@ The following tables list permissions associated with basic and fixed roles.
|
||||
## Fixed role definitions
|
||||
|
||||
| Fixed role | Permissions | Description |
|
||||
| -------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| -------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `fixed:alerting.instances:writer` | All permissions from `fixed:alerting.instances:reader` and<br> `alert.instances:create`<br>`alert.instances:write` for organization scope <br> `alert.instances.external:write` for scope `datasources:*` | Create, update and expire all silences in the organization produced by Grafana, Mimir, and Loki.[\*](#alerting-roles) |
|
||||
| `fixed:alerting.instances:reader` | `alert.instances:read` for organization scope <br> `alert.instances.external:read` for scope `datasources:*` | Read all alerts and silences in the organization produced by Grafana Alerts and Mimir and Loki alerts and silences.[\*](#alerting-roles) |
|
||||
| `fixed:alerting.notifications:writer` | All permissions from `fixed:alerting.notifications:reader` and<br>`alert.notifications:write`for organization scope<br>`alert.notifications.external:read` for scope `datasources:*` | Create, update, and delete contact points, templates, mute timings and notification policies for Grafana and external Alertmanager.[\*](#alerting-roles) |
|
||||
| `fixed:alerting.notifications:reader` | `alert.notifications:read` for organization scope<br>`alert.notifications.external:read` for scope `datasources:*` | Read all Grafana and Alertmanager contact points, templates, and notification policies.[\*](#alerting-roles) |
|
||||
| `fixed:alerting.rules:writer` | All permissions from `fixed:alerting.rules:reader` and <br> `alert.rule:create` <br> `alert.rule:write` <br> `alert.rule:delete` for scope `folders:*` <br> `alert.rules.external:write` for scope `datasources:*` | Create, update, and delete all\* Grafana, Mimir, and Loki alert rules.[\*](#alerting-roles) |
|
||||
| `fixed:alerting.rules:reader` | `alert.rule:read` for scope `folders:*` <br> `alert.rules.external:read` for scope `datasources:*` | Read all\* Grafana, Mimir, and Loki alert rules.[\*](#alerting-roles) |
|
||||
| `fixed:alerting.rules:writer` | All permissions from `fixed:alerting.rules:reader` and <br> `alert.rule:create` <br> `alert.rule:write` <br> `alert.rule:delete` <br> `alert.silences:create` <br> `alert.silences:write` for scope `folders:*` <br> `alert.rules.external:write` for scope `datasources:*` | Create, update, and delete all\* Grafana, Mimir, and Loki alert rules.[\*](#alerting-roles) and manage rule-specific silences |
|
||||
| `fixed:alerting.rules:reader` | `alert.rule:read`, `alert.silences:read` for scope `folders:*` <br> `alert.rules.external:read` for scope `datasources:*` <br> `alert.notifications.time-intervals:read` <br> `alert.notifications.receivers:list` | Read all\* Grafana, Mimir, and Loki alert rules.[\*](#alerting-roles) and read rule-specific silences |
|
||||
| `fixed:alerting:writer` | All permissions from `fixed:alerting.rules:writer` <br>`fixed:alerting.instances:writer`<br>`fixed:alerting.notifications:writer` | Create, update, and delete Grafana, Mimir, Loki and Alertmanager alert rules\*, silences, contact points, templates, mute timings, and notification policies.[\*](#alerting-roles) |
|
||||
| `fixed:alerting:reader` | All permissions from `fixed:alerting.rules:reader` <br>`fixed:alerting.instances:reader`<br>`fixed:alerting.notifications:reader` | Read-only permissions for all Grafana, Mimir, Loki and Alertmanager alert rules\*, alerts, contact points, and notification policies.[\*](#alerting-roles) |
|
||||
| `fixed:alerting.provisioning.secrets:reader` | `alert.provisioning:read` and `alert.provisioning.secrets:read` | Read-only permissions for Provisioning API and let export resources with decrypted secrets [\*](#alerting-roles) |
|
||||
|
||||
@@ -218,7 +218,7 @@ type FolderPermissionsService struct {
|
||||
*resourcepermissions.Service
|
||||
}
|
||||
|
||||
var FolderViewActions = []string{dashboards.ActionFoldersRead, accesscontrol.ActionAlertingRuleRead, libraryelements.ActionLibraryPanelsRead}
|
||||
var FolderViewActions = []string{dashboards.ActionFoldersRead, accesscontrol.ActionAlertingRuleRead, libraryelements.ActionLibraryPanelsRead, accesscontrol.ActionAlertingSilencesRead}
|
||||
var FolderEditActions = append(FolderViewActions, []string{
|
||||
dashboards.ActionFoldersWrite,
|
||||
dashboards.ActionFoldersDelete,
|
||||
@@ -226,6 +226,8 @@ var FolderEditActions = append(FolderViewActions, []string{
|
||||
accesscontrol.ActionAlertingRuleCreate,
|
||||
accesscontrol.ActionAlertingRuleUpdate,
|
||||
accesscontrol.ActionAlertingRuleDelete,
|
||||
accesscontrol.ActionAlertingSilencesCreate,
|
||||
accesscontrol.ActionAlertingSilencesWrite,
|
||||
libraryelements.ActionLibraryPanelsCreate,
|
||||
libraryelements.ActionLibraryPanelsWrite,
|
||||
libraryelements.ActionLibraryPanelsDelete,
|
||||
|
||||
@@ -25,6 +25,10 @@ var (
|
||||
Action: accesscontrol.ActionAlertingRuleExternalRead,
|
||||
Scope: datasources.ScopeAll,
|
||||
},
|
||||
{
|
||||
Action: accesscontrol.ActionAlertingSilencesRead,
|
||||
Scope: dashboards.ScopeFoldersAll,
|
||||
},
|
||||
// Following are needed for simplified notification policies
|
||||
{
|
||||
Action: accesscontrol.ActionAlertingNotificationsTimeIntervalsRead,
|
||||
@@ -59,6 +63,14 @@ var (
|
||||
Action: accesscontrol.ActionAlertingRuleExternalWrite,
|
||||
Scope: datasources.ScopeAll,
|
||||
},
|
||||
{
|
||||
Action: accesscontrol.ActionAlertingSilencesWrite,
|
||||
Scope: dashboards.ScopeFoldersAll,
|
||||
},
|
||||
{
|
||||
Action: accesscontrol.ActionAlertingSilencesCreate,
|
||||
Scope: dashboards.ScopeFoldersAll,
|
||||
},
|
||||
}),
|
||||
},
|
||||
}
|
||||
|
||||
@@ -843,6 +843,113 @@ WHERE r.uid IN (?, ?, ?) AND p.action LIKE 'annotations:%' AND p.scope IN ('*',
|
||||
return true, nil
|
||||
}
|
||||
|
||||
const ManagedFolderAlertingSilencesActionsMigratorID = "managed folder permissions alerting silences actions migration"
|
||||
|
||||
func AddManagedFolderAlertingSilencesActionsMigrator(mg *migrator.Migrator) {
|
||||
mg.AddMigration(ManagedFolderAlertingSilencesActionsMigratorID, &managedFolderAlertingSilencesActionsMigrator{})
|
||||
}
|
||||
|
||||
type managedFolderAlertingSilencesActionsMigrator struct {
|
||||
migrator.MigrationBase
|
||||
}
|
||||
|
||||
func (m *managedFolderAlertingSilencesActionsMigrator) SQL(_ migrator.Dialect) string {
|
||||
return CodeMigrationSQL
|
||||
}
|
||||
|
||||
func (m *managedFolderAlertingSilencesActionsMigrator) Exec(sess *xorm.Session, _ *migrator.Migrator) error {
|
||||
var ids []any
|
||||
if err := sess.SQL("SELECT id FROM role WHERE name LIKE 'managed:%'").Find(&ids); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(ids) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
var permissions []ac.Permission
|
||||
if err := sess.SQL("SELECT role_id, action, scope FROM permission WHERE role_id IN(?"+strings.Repeat(" ,?", len(ids)-1)+") AND scope LIKE 'folders:%'", ids...).Find(&permissions); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
mapped := make(map[int64]map[string][]ac.Permission, len(ids)-1)
|
||||
for _, p := range permissions {
|
||||
if mapped[p.RoleID] == nil {
|
||||
mapped[p.RoleID] = make(map[string][]ac.Permission)
|
||||
}
|
||||
mapped[p.RoleID][p.Scope] = append(mapped[p.RoleID][p.Scope], p)
|
||||
}
|
||||
|
||||
var toAdd []ac.Permission
|
||||
now := time.Now()
|
||||
|
||||
for id, a := range mapped {
|
||||
for scope, p := range a {
|
||||
// Create a temporary permission to split the scope into kind, attribute and identifier
|
||||
kind, attribute, identifier := ac.Permission{Scope: scope}.SplitScope()
|
||||
|
||||
if hasFolderView(p) {
|
||||
if !hasAction(ac.ActionAlertingSilencesRead, p) {
|
||||
toAdd = append(toAdd, ac.Permission{
|
||||
RoleID: id,
|
||||
Action: ac.ActionAlertingSilencesRead,
|
||||
Scope: scope,
|
||||
Kind: kind,
|
||||
Attribute: attribute,
|
||||
Identifier: identifier,
|
||||
Updated: now,
|
||||
Created: now,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if hasFolderAdmin(p) || hasFolderEdit(p) {
|
||||
if !hasAction(ac.ActionAlertingSilencesCreate, p) {
|
||||
toAdd = append(toAdd, ac.Permission{
|
||||
RoleID: id,
|
||||
Action: ac.ActionAlertingSilencesCreate,
|
||||
Scope: scope,
|
||||
Kind: kind,
|
||||
Attribute: attribute,
|
||||
Identifier: identifier,
|
||||
Updated: now,
|
||||
Created: now,
|
||||
})
|
||||
}
|
||||
if !hasAction(ac.ActionAlertingSilencesWrite, p) {
|
||||
toAdd = append(toAdd, ac.Permission{
|
||||
RoleID: id,
|
||||
Action: ac.ActionAlertingSilencesWrite,
|
||||
Scope: scope,
|
||||
Kind: kind,
|
||||
Attribute: attribute,
|
||||
Identifier: identifier,
|
||||
Updated: now,
|
||||
Created: now,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(toAdd) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
err := batch(len(toAdd), batchSize, func(start, end int) error {
|
||||
if _, err := sess.InsertMulti(toAdd[start:end]); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func hasFolderAdmin(permissions []ac.Permission) bool {
|
||||
return hasActions(folderPermissionTranslation[dashboardaccess.PERMISSION_ADMIN], permissions)
|
||||
}
|
||||
|
||||
@@ -119,6 +119,8 @@ func (oss *OSSMigrations) AddMigration(mg *Migrator) {
|
||||
ualert.AddRuleNotificationSettingsColumns(mg)
|
||||
|
||||
accesscontrol.AddAlertingScopeRemovalMigration(mg)
|
||||
|
||||
accesscontrol.AddManagedFolderAlertingSilencesActionsMigrator(mg)
|
||||
}
|
||||
|
||||
func addStarMigrations(mg *Migrator) {
|
||||
|
||||
Reference in New Issue
Block a user