Alerting: Fix per-receiver RBAC for receivers with long names (#95084)

* Implement uidToResourceID

* add middleware

* Move uidToResourceID to alerting package

* Only hash uid if it's too long

* Use hashed uid in access control

* Move ReceiverUidToResourceId to ScopeProvider

* resolve uid in middleware only if param exists

* Tests

* Linting

---------

Co-authored-by: Yuri Tseretyan <yuriy.tseretyan@grafana.com>
This commit is contained in:
Matthew Jacobson
2024-10-22 10:04:13 -04:00
committed by GitHub
co-authored by Yuri Tseretyan
parent 25e85f8947
commit 4aad44e848
5 changed files with 74 additions and 11 deletions
@@ -5,16 +5,18 @@ import (
"net/http"
"strconv"
"go.opentelemetry.io/otel"
"github.com/grafana/grafana/pkg/api/dtos"
"github.com/grafana/grafana/pkg/api/response"
"github.com/grafana/grafana/pkg/api/routing"
"github.com/grafana/grafana/pkg/services/accesscontrol"
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
alertingac "github.com/grafana/grafana/pkg/services/ngalert/accesscontrol"
"github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/services/team"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/web"
"go.opentelemetry.io/otel"
)
var tracer = otel.Tracer("github.com/grafana/grafana/pkg/accesscontrol/resourcepermissions")
@@ -48,6 +50,9 @@ func (a *api) registerEndpoints() {
if a.service.options.Resource == "teams" {
teamUIDResolverResource = team.MiddlewareTeamUIDResolver(a.service.teamService, ":resourceID")
}
if a.service.options.Resource == "receivers" {
teamUIDResolverResource = MiddlewareReceiverUIDResolver(":resourceID")
}
a.router.Group(fmt.Sprintf("/api/access-control/%s", a.service.options.Resource), func(r routing.RouteRegister) {
actionRead := fmt.Sprintf("%s.permissions:read", a.service.options.Resource)
@@ -430,3 +435,13 @@ func permissionSetResponse(cmd setPermissionCommand) response.Response {
}
return response.Success(message)
}
func MiddlewareReceiverUIDResolver(paramName string) web.Handler {
return func(c *contextmodel.ReqContext) {
gotParams := web.Params(c.Req)
if uid, ok := gotParams[paramName]; ok {
gotParams[paramName] = alertingac.ScopeReceiversProvider.GetResourceIDFromUID(uid)
web.SetURLParams(c.Req, gotParams)
}
}
}