mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Update DS Proxy to use RBAC action (#87517)
iam-team: Update DS Proxy to use RBAC action
This commit is contained in:
parent
410e3b17e9
commit
0072e4a92d
@ -189,4 +189,5 @@ export interface FeatureToggles {
|
|||||||
newDashboardSharingComponent?: boolean;
|
newDashboardSharingComponent?: boolean;
|
||||||
notificationBanner?: boolean;
|
notificationBanner?: boolean;
|
||||||
dashboardRestore?: boolean;
|
dashboardRestore?: boolean;
|
||||||
|
datasourceProxyDisableRBAC?: boolean;
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ import (
|
|||||||
glog "github.com/grafana/grafana/pkg/infra/log"
|
glog "github.com/grafana/grafana/pkg/infra/log"
|
||||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||||
"github.com/grafana/grafana/pkg/plugins"
|
"github.com/grafana/grafana/pkg/plugins"
|
||||||
|
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||||
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
|
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
|
||||||
"github.com/grafana/grafana/pkg/services/datasources"
|
"github.com/grafana/grafana/pkg/services/datasources"
|
||||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||||
@ -304,8 +305,14 @@ func (proxy *DataSourceProxy) validateRequest() error {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if route.ReqRole.IsValid() {
|
if proxy.features.IsEnabled(proxy.ctx.Req.Context(), featuremgmt.FlagDatasourceProxyDisableRBAC) {
|
||||||
if !proxy.ctx.HasUserRole(route.ReqRole) {
|
// TODO(aarongodin): following logic can be removed with FlagDatasourceProxyDisableRBAC as it is covered by
|
||||||
|
// proxy.hasAccessToRoute(..)
|
||||||
|
if route.ReqRole.IsValid() && !proxy.ctx.HasUserRole(route.ReqRole) {
|
||||||
|
return errors.New("plugin proxy route access denied")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if !proxy.hasAccessToRoute(route) {
|
||||||
return errors.New("plugin proxy route access denied")
|
return errors.New("plugin proxy route access denied")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -330,6 +337,26 @@ func (proxy *DataSourceProxy) validateRequest() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (proxy *DataSourceProxy) hasAccessToRoute(route *plugins.Route) bool {
|
||||||
|
ctxLogger := logger.FromContext(proxy.ctx.Req.Context())
|
||||||
|
useRBAC := proxy.features.IsEnabled(proxy.ctx.Req.Context(), featuremgmt.FlagAccessControlOnCall) && route.ReqAction != ""
|
||||||
|
if useRBAC {
|
||||||
|
routeEval := accesscontrol.EvalPermission(route.ReqAction)
|
||||||
|
ok := routeEval.Evaluate(proxy.ctx.GetPermissions())
|
||||||
|
if !ok {
|
||||||
|
ctxLogger.Debug("plugin route is covered by RBAC, user doesn't have access", "route", proxy.ctx.Req.URL.Path, "action", route.ReqAction, "path", route.Path, "method", route.Method)
|
||||||
|
}
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
if route.ReqRole.IsValid() {
|
||||||
|
if hasUserRole := proxy.ctx.HasUserRole(route.ReqRole); !hasUserRole {
|
||||||
|
ctxLogger.Debug("plugin route is covered by org role, user doesn't have access", "route", proxy.ctx.Req.URL.Path, "role", route.ReqRole, "path", route.Path, "method", route.Method)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func (proxy *DataSourceProxy) logRequest() {
|
func (proxy *DataSourceProxy) logRequest() {
|
||||||
if !proxy.cfg.DataProxyLogging {
|
if !proxy.cfg.DataProxyLogging {
|
||||||
return
|
return
|
||||||
|
@ -122,7 +122,7 @@ func (proxy *PluginProxy) HandleRequest() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (proxy *PluginProxy) hasAccessToRoute(route *plugins.Route) bool {
|
func (proxy *PluginProxy) hasAccessToRoute(route *plugins.Route) bool {
|
||||||
useRBAC := proxy.features.IsEnabled(proxy.ctx.Req.Context(), featuremgmt.FlagAccessControlOnCall) && route.RequiresRBACAction()
|
useRBAC := proxy.features.IsEnabled(proxy.ctx.Req.Context(), featuremgmt.FlagAccessControlOnCall) && route.ReqAction != ""
|
||||||
if useRBAC {
|
if useRBAC {
|
||||||
hasAccess := ac.HasAccess(proxy.accessControl, proxy.ctx)(ac.EvalPermission(route.ReqAction))
|
hasAccess := ac.HasAccess(proxy.accessControl, proxy.ctx)(ac.EvalPermission(route.ReqAction))
|
||||||
if !hasAccess {
|
if !hasAccess {
|
||||||
|
@ -207,10 +207,6 @@ type Route struct {
|
|||||||
Body json.RawMessage `json:"body"`
|
Body json.RawMessage `json:"body"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Route) RequiresRBACAction() bool {
|
|
||||||
return r.ReqAction != ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// Header describes an HTTP header that is forwarded with
|
// Header describes an HTTP header that is forwarded with
|
||||||
// the proxied request for a plugin route
|
// the proxied request for a plugin route
|
||||||
type Header struct {
|
type Header struct {
|
||||||
|
@ -1275,6 +1275,13 @@ var (
|
|||||||
HideFromDocs: true,
|
HideFromDocs: true,
|
||||||
HideFromAdminPage: true,
|
HideFromAdminPage: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Name: "datasourceProxyDisableRBAC",
|
||||||
|
Description: "Disables applying a plugin route's ReqAction field to authorization",
|
||||||
|
Stage: FeatureStageGeneralAvailability,
|
||||||
|
Owner: identityAccessTeam,
|
||||||
|
HideFromDocs: true,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -170,3 +170,4 @@ logsExploreTableDefaultVisualization,experimental,@grafana/observability-logs,fa
|
|||||||
newDashboardSharingComponent,experimental,@grafana/sharing-squad,false,false,true
|
newDashboardSharingComponent,experimental,@grafana/sharing-squad,false,false,true
|
||||||
notificationBanner,experimental,@grafana/grafana-frontend-platform,false,false,false
|
notificationBanner,experimental,@grafana/grafana-frontend-platform,false,false,false
|
||||||
dashboardRestore,experimental,@grafana/grafana-frontend-platform,false,false,false
|
dashboardRestore,experimental,@grafana/grafana-frontend-platform,false,false,false
|
||||||
|
datasourceProxyDisableRBAC,GA,@grafana/identity-access-team,false,false,false
|
||||||
|
|
@ -690,4 +690,8 @@ const (
|
|||||||
// FlagDashboardRestore
|
// FlagDashboardRestore
|
||||||
// Enables deleted dashboard restore feature
|
// Enables deleted dashboard restore feature
|
||||||
FlagDashboardRestore = "dashboardRestore"
|
FlagDashboardRestore = "dashboardRestore"
|
||||||
|
|
||||||
|
// FlagDatasourceProxyDisableRBAC
|
||||||
|
// Disables applying a plugin route's ReqAction field to authorization
|
||||||
|
FlagDatasourceProxyDisableRBAC = "datasourceProxyDisableRBAC"
|
||||||
)
|
)
|
||||||
|
@ -2222,6 +2222,19 @@
|
|||||||
"hideFromAdminPage": true,
|
"hideFromAdminPage": true,
|
||||||
"hideFromDocs": true
|
"hideFromDocs": true
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"metadata": {
|
||||||
|
"name": "datasourceProxyDisableRBAC",
|
||||||
|
"resourceVersion": "1715889033198",
|
||||||
|
"creationTimestamp": "2024-05-16T19:50:33Z"
|
||||||
|
},
|
||||||
|
"spec": {
|
||||||
|
"description": "Disables applying a plugin route's ReqAction field to authorization",
|
||||||
|
"stage": "GA",
|
||||||
|
"codeowner": "@grafana/identity-access-team",
|
||||||
|
"hideFromDocs": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user