package api import ( "fmt" "net/http" "github.com/grafana/grafana/pkg/middleware" ac "github.com/grafana/grafana/pkg/services/accesscontrol" acmiddleware "github.com/grafana/grafana/pkg/services/accesscontrol/middleware" "github.com/grafana/grafana/pkg/services/dashboards" "github.com/grafana/grafana/pkg/services/datasources" "github.com/grafana/grafana/pkg/web" ) //nolint:gocyclo func (api *API) authorize(method, path string) web.Handler { authorize := acmiddleware.Middleware(api.AccessControl) var eval ac.Evaluator = nil switch method + path { // Alert Rules // Grafana Paths case http.MethodDelete + "/api/ruler/grafana/api/v1/rules/{Namespace}/{Groupname}": eval = ac.EvalPermission(ac.ActionAlertingRuleDelete, dashboards.ScopeFoldersProvider.GetResourceScopeName(ac.Parameter(":Namespace"))) case http.MethodDelete + "/api/ruler/grafana/api/v1/rules/{Namespace}": eval = ac.EvalPermission(ac.ActionAlertingRuleDelete, dashboards.ScopeFoldersProvider.GetResourceScopeName(ac.Parameter(":Namespace"))) case http.MethodGet + "/api/ruler/grafana/api/v1/rules/{Namespace}/{Groupname}": eval = ac.EvalPermission(ac.ActionAlertingRuleRead, dashboards.ScopeFoldersProvider.GetResourceScopeName(ac.Parameter(":Namespace"))) case http.MethodGet + "/api/ruler/grafana/api/v1/rules/{Namespace}": eval = ac.EvalPermission(ac.ActionAlertingRuleRead, dashboards.ScopeFoldersProvider.GetResourceScopeName(ac.Parameter(":Namespace"))) case http.MethodGet + "/api/ruler/grafana/api/v1/rules": eval = ac.EvalPermission(ac.ActionAlertingRuleRead) case http.MethodPost + "/api/ruler/grafana/api/v1/rules/{Namespace}": scope := dashboards.ScopeFoldersProvider.GetResourceScopeName(ac.Parameter(":Namespace")) // more granular permissions are enforced by the handler via "authorizeRuleChanges" eval = ac.EvalAny( ac.EvalPermission(ac.ActionAlertingRuleUpdate, scope), ac.EvalPermission(ac.ActionAlertingRuleCreate, scope), ac.EvalPermission(ac.ActionAlertingRuleDelete, scope), ) // Grafana, Prometheus-compatible Paths case http.MethodGet + "/api/prometheus/grafana/api/v1/rules": eval = ac.EvalPermission(ac.ActionAlertingRuleRead) // Grafana Rules Testing Paths case http.MethodPost + "/api/v1/rule/test/grafana": // additional authorization is done in the request handler eval = ac.EvalPermission(ac.ActionAlertingRuleRead) case http.MethodPost + "/api/v1/eval": // additional authorization is done in the request handler eval = ac.EvalPermission(ac.ActionAlertingRuleRead) // Lotex Paths case http.MethodDelete + "/api/ruler/{Recipient}/api/v1/rules/{Namespace}": eval = ac.EvalPermission(ac.ActionAlertingRuleExternalWrite, datasources.ScopeProvider.GetResourceScope(ac.Parameter(":Recipient"))) case http.MethodDelete + "/api/ruler/{Recipient}/api/v1/rules/{Namespace}/{Groupname}": eval = ac.EvalPermission(ac.ActionAlertingRuleExternalWrite, datasources.ScopeProvider.GetResourceScope(ac.Parameter(":Recipient"))) case http.MethodGet + "/api/ruler/{Recipient}/api/v1/rules/{Namespace}": eval = ac.EvalPermission(ac.ActionAlertingRuleExternalRead, datasources.ScopeProvider.GetResourceScope(ac.Parameter(":Recipient"))) case http.MethodGet + "/api/ruler/{Recipient}/api/v1/rules/{Namespace}/{Groupname}": eval = ac.EvalPermission(ac.ActionAlertingRuleExternalRead, datasources.ScopeProvider.GetResourceScope(ac.Parameter(":Recipient"))) case http.MethodGet + "/api/ruler/{Recipient}/api/v1/rules": eval = ac.EvalPermission(ac.ActionAlertingRuleExternalRead, datasources.ScopeProvider.GetResourceScope(ac.Parameter(":Recipient"))) case http.MethodPost + "/api/ruler/{Recipient}/api/v1/rules/{Namespace}": eval = ac.EvalPermission(ac.ActionAlertingInstancesExternalWrite, datasources.ScopeProvider.GetResourceScope(ac.Parameter(":Recipient"))) // Lotex Prometheus-compatible Paths case http.MethodGet + "/api/prometheus/{Recipient}/api/v1/rules": eval = ac.EvalPermission(ac.ActionAlertingRuleExternalRead, datasources.ScopeProvider.GetResourceScope(ac.Parameter(":Recipient"))) // Lotex Rules testing case http.MethodPost + "/api/v1/rule/test/{Recipient}": eval = ac.EvalPermission(ac.ActionAlertingRuleExternalRead, datasources.ScopeProvider.GetResourceScope(ac.Parameter(":Recipient"))) // Alert Instances and Silences // Silences. Grafana Paths case http.MethodDelete + "/api/alertmanager/grafana/api/v2/silence/{SilenceId}": eval = ac.EvalPermission(ac.ActionAlertingInstanceUpdate) // delete endpoint actually expires silence case http.MethodGet + "/api/alertmanager/grafana/api/v2/silence/{SilenceId}": eval = ac.EvalPermission(ac.ActionAlertingInstanceRead) case http.MethodGet + "/api/alertmanager/grafana/api/v2/silences": eval = ac.EvalPermission(ac.ActionAlertingInstanceRead) case http.MethodPost + "/api/alertmanager/grafana/api/v2/silences": // additional authorization is done in the request handler eval = ac.EvalAny(ac.EvalPermission(ac.ActionAlertingInstanceCreate), ac.EvalPermission(ac.ActionAlertingInstanceUpdate)) // Alert Instances. Grafana Paths case http.MethodGet + "/api/alertmanager/grafana/api/v2/alerts/groups": eval = ac.EvalPermission(ac.ActionAlertingInstanceRead) case http.MethodGet + "/api/alertmanager/grafana/api/v2/alerts": eval = ac.EvalPermission(ac.ActionAlertingInstanceRead) case http.MethodPost + "/api/alertmanager/grafana/api/v2/alerts": eval = ac.EvalAny(ac.EvalPermission(ac.ActionAlertingInstanceCreate), ac.EvalPermission(ac.ActionAlertingInstanceUpdate)) // Grafana Prometheus-compatible Paths case http.MethodGet + "/api/prometheus/grafana/api/v1/alerts": eval = ac.EvalPermission(ac.ActionAlertingInstanceRead) // Silences. External AM. case http.MethodDelete + "/api/alertmanager/{Recipient}/api/v2/silence/{SilenceId}": eval = ac.EvalPermission(ac.ActionAlertingInstancesExternalWrite, datasources.ScopeProvider.GetResourceScope(ac.Parameter(":Recipient"))) case http.MethodPost + "/api/alertmanager/{Recipient}/api/v2/silences": eval = ac.EvalPermission(ac.ActionAlertingInstancesExternalWrite, datasources.ScopeProvider.GetResourceScope(ac.Parameter(":Recipient"))) case http.MethodGet + "/api/alertmanager/{Recipient}/api/v2/silence/{SilenceId}": eval = ac.EvalPermission(ac.ActionAlertingInstancesExternalRead, datasources.ScopeProvider.GetResourceScope(ac.Parameter(":Recipient"))) case http.MethodGet + "/api/alertmanager/{Recipient}/api/v2/silences": eval = ac.EvalPermission(ac.ActionAlertingInstancesExternalRead, datasources.ScopeProvider.GetResourceScope(ac.Parameter(":Recipient"))) // Alert instances. External AM. case http.MethodGet + "/api/alertmanager/{Recipient}/api/v2/alerts/groups": eval = ac.EvalPermission(ac.ActionAlertingInstancesExternalRead, datasources.ScopeProvider.GetResourceScope(ac.Parameter(":Recipient"))) case http.MethodGet + "/api/alertmanager/{Recipient}/api/v2/alerts": eval = ac.EvalPermission(ac.ActionAlertingInstancesExternalRead, datasources.ScopeProvider.GetResourceScope(ac.Parameter(":Recipient"))) case http.MethodPost + "/api/alertmanager/{Recipient}/api/v2/alerts": eval = ac.EvalPermission(ac.ActionAlertingInstancesExternalWrite, datasources.ScopeProvider.GetResourceScope(ac.Parameter(":Recipient"))) // Prometheus-compatible Paths case http.MethodGet + "/api/prometheus/{Recipient}/api/v1/alerts": eval = ac.EvalPermission(ac.ActionAlertingInstancesExternalRead, datasources.ScopeProvider.GetResourceScope(ac.Parameter(":Recipient"))) // Notification Policies, Contact Points and Templates // Grafana Paths case http.MethodDelete + "/api/alertmanager/grafana/config/api/v1/alerts": // reset alertmanager config to the default eval = ac.EvalPermission(ac.ActionAlertingNotificationsDelete) case http.MethodGet + "/api/alertmanager/grafana/config/api/v1/alerts": eval = ac.EvalPermission(ac.ActionAlertingNotificationsRead) case http.MethodGet + "/api/alertmanager/grafana/api/v2/status": eval = ac.EvalPermission(ac.ActionAlertingNotificationsRead) case http.MethodPost + "/api/alertmanager/grafana/config/api/v1/alerts": // additional authorization is done in the request handler eval = ac.EvalAny(ac.EvalPermission(ac.ActionAlertingNotificationsUpdate), ac.EvalPermission(ac.ActionAlertingNotificationsCreate), ac.EvalPermission(ac.ActionAlertingNotificationsDelete)) case http.MethodPost + "/api/alertmanager/grafana/config/api/v1/receivers/test": eval = ac.EvalPermission(ac.ActionAlertingNotificationsRead) // External Alertmanager Paths case http.MethodDelete + "/api/alertmanager/{Recipient}/config/api/v1/alerts": eval = ac.EvalPermission(ac.ActionAlertingNotificationsDelete, datasources.ScopeProvider.GetResourceScope(ac.Parameter(":Recipient"))) case http.MethodGet + "/api/alertmanager/{Recipient}/api/v2/status": eval = ac.EvalPermission(ac.ActionAlertingNotificationsExternalRead, datasources.ScopeProvider.GetResourceScope(ac.Parameter(":Recipient"))) case http.MethodGet + "/api/alertmanager/{Recipient}/config/api/v1/alerts": eval = ac.EvalPermission(ac.ActionAlertingNotificationsExternalRead, datasources.ScopeProvider.GetResourceScope(ac.Parameter(":Recipient"))) case http.MethodPost + "/api/alertmanager/{Recipient}/config/api/v1/alerts": eval = ac.EvalPermission(ac.ActionAlertingNotificationsExternalWrite, datasources.ScopeProvider.GetResourceScope(ac.Parameter(":Recipient"))) case http.MethodPost + "/api/alertmanager/{Recipient}/config/api/v1/receivers/test": eval = ac.EvalPermission(ac.ActionAlertingNotificationsExternalRead, datasources.ScopeProvider.GetResourceScope(ac.Parameter(":Recipient"))) // Raw Alertmanager Config Paths case http.MethodDelete + "/api/v1/ngalert/admin_config", http.MethodGet + "/api/v1/ngalert/admin_config", http.MethodPost + "/api/v1/ngalert/admin_config", http.MethodGet + "/api/v1/ngalert/alertmanagers": return middleware.ReqOrgAdmin } if eval != nil { return authorize(middleware.ReqSignedIn, eval) } panic(fmt.Sprintf("no authorization handler for method [%s] of endpoint [%s]", method, path)) }