diff --git a/pkg/infra/usagestats/service/accesscontrol.go b/pkg/infra/usagestats/service/accesscontrol.go new file mode 100644 index 00000000000..380380ff802 --- /dev/null +++ b/pkg/infra/usagestats/service/accesscontrol.go @@ -0,0 +1,30 @@ +package service + +import ( + "github.com/grafana/grafana/pkg/services/accesscontrol" +) + +const ( + ActionRead = "server.usagestats.report:read" +) + +var ( + usagestatsReaderRole = accesscontrol.RoleDTO{ + Name: "fixed:usagestats:reader", + DisplayName: "Usage stats report reader", + Description: "View usage statistics report", + Group: "Statistics", + Permissions: []accesscontrol.Permission{ + {Action: ActionRead}, + }, + } +) + +func declareFixedRoles(ac accesscontrol.Service) error { + usagestatsReader := accesscontrol.RoleRegistration{ + Role: usagestatsReaderRole, + Grants: []string{string(accesscontrol.RoleGrafanaAdmin)}, + } + + return ac.DeclareFixedRoles(usagestatsReader) +} diff --git a/pkg/infra/usagestats/service/api.go b/pkg/infra/usagestats/service/api.go index be27e79c394..836f73d3202 100644 --- a/pkg/infra/usagestats/service/api.go +++ b/pkg/infra/usagestats/service/api.go @@ -7,13 +7,16 @@ import ( "github.com/grafana/grafana/pkg/api/routing" "github.com/grafana/grafana/pkg/middleware" "github.com/grafana/grafana/pkg/models" + "github.com/grafana/grafana/pkg/services/accesscontrol" ) const rootUrl = "/api/admin" func (uss *UsageStats) registerAPIEndpoints() { + authorize := accesscontrol.Middleware(uss.accesscontrol) + uss.RouteRegister.Group(rootUrl, func(subrouter routing.RouteRegister) { - subrouter.Get("/usage-report-preview", middleware.ReqGrafanaAdmin, routing.Wrap(uss.getUsageReportPreview)) + subrouter.Get("/usage-report-preview", authorize(middleware.ReqGrafanaAdmin, accesscontrol.EvalPermission(ActionRead)), routing.Wrap(uss.getUsageReportPreview)) }) } diff --git a/pkg/infra/usagestats/service/service.go b/pkg/infra/usagestats/service/service.go index 36ad25d29cd..6ab6551c867 100644 --- a/pkg/infra/usagestats/service/service.go +++ b/pkg/infra/usagestats/service/service.go @@ -10,6 +10,7 @@ import ( "github.com/grafana/grafana/pkg/infra/tracing" "github.com/grafana/grafana/pkg/infra/usagestats" "github.com/grafana/grafana/pkg/plugins" + ac "github.com/grafana/grafana/pkg/services/accesscontrol" "github.com/grafana/grafana/pkg/setting" ) @@ -18,6 +19,7 @@ type UsageStats struct { kvStore *kvstore.NamespacedKVStore RouteRegister routing.RouteRegister pluginStore plugins.Store + accesscontrol ac.AccessControl log log.Logger tracer tracing.Tracer @@ -26,7 +28,13 @@ type UsageStats struct { sendReportCallbacks []usagestats.SendReportCallbackFunc } -func ProvideService(cfg *setting.Cfg, pluginStore plugins.Store, kvStore kvstore.KVStore, routeRegister routing.RouteRegister, tracer tracing.Tracer) *UsageStats { +func ProvideService(cfg *setting.Cfg, + pluginStore plugins.Store, + kvStore kvstore.KVStore, + routeRegister routing.RouteRegister, + tracer tracing.Tracer, + accesscontrol ac.AccessControl, + accesscontrolService ac.Service) (*UsageStats, error) { s := &UsageStats{ Cfg: cfg, RouteRegister: routeRegister, @@ -34,11 +42,18 @@ func ProvideService(cfg *setting.Cfg, pluginStore plugins.Store, kvStore kvstore kvStore: kvstore.WithNamespace(kvStore, 0, "infra.usagestats"), log: log.New("infra.usagestats"), tracer: tracer, + accesscontrol: accesscontrol, + } + + if !accesscontrol.IsDisabled() { + if err := declareFixedRoles(accesscontrolService); err != nil { + return nil, err + } } s.registerAPIEndpoints() - return s + return s, nil } func (uss *UsageStats) Run(ctx context.Context) error { diff --git a/pkg/infra/usagestats/service/usage_stats_test.go b/pkg/infra/usagestats/service/usage_stats_test.go index 3bb4c79c9b3..31ad226729f 100644 --- a/pkg/infra/usagestats/service/usage_stats_test.go +++ b/pkg/infra/usagestats/service/usage_stats_test.go @@ -22,6 +22,7 @@ import ( "github.com/grafana/grafana/pkg/infra/tracing" "github.com/grafana/grafana/pkg/infra/usagestats" "github.com/grafana/grafana/pkg/plugins" + "github.com/grafana/grafana/pkg/services/accesscontrol/actest" "github.com/grafana/grafana/pkg/setting" ) @@ -214,11 +215,15 @@ func createService(t *testing.T, cfg setting.Cfg, sqlStore db.DB, withDB bool) * sqlStore = db.InitTestDB(t) } - return ProvideService( + service, _ := ProvideService( &cfg, &plugins.FakePluginStore{}, kvstore.ProvideService(sqlStore), routing.NewRouteRegister(), tracing.InitializeTracerForTest(), + actest.FakeAccessControl{ExpectedDisabled: true}, + actest.FakeService{}, ) + + return service }