mirror of
https://github.com/grafana/grafana.git
synced 2025-07-29 17:02:20 +08:00

--------- Co-authored-by: Ieva <ieva.vasiljeva@grafana.com> Co-authored-by: Gabriel MABILLE <gabriel.mabille@grafana.com> Co-authored-by: Marco de Abreu <marco.deabreu@grafana.com> Co-authored-by: Georges Chaudy <chaudyg@gmail.com>
80 lines
3.2 KiB
Go
80 lines
3.2 KiB
Go
package dashboard
|
|
|
|
import (
|
|
"context"
|
|
|
|
"k8s.io/apiserver/pkg/authorization/authorizer"
|
|
|
|
"github.com/grafana/authlib/types"
|
|
"github.com/grafana/grafana/pkg/apimachinery/identity"
|
|
"github.com/grafana/grafana/pkg/infra/log"
|
|
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
|
"github.com/grafana/grafana/pkg/services/dashboards"
|
|
)
|
|
|
|
func GetAuthorizer(ac accesscontrol.AccessControl, l log.Logger) authorizer.Authorizer {
|
|
return authorizer.AuthorizerFunc(
|
|
func(ctx context.Context, attr authorizer.Attributes) (authorized authorizer.Decision, reason string, err error) {
|
|
// Note that we will return Allow more than expected.
|
|
// This is because we do NOT want to hit the RoleAuthorizer that would be evaluated afterwards.
|
|
|
|
if !attr.IsResourceRequest() {
|
|
return authorizer.DecisionDeny, "unexpected non-resource request", nil
|
|
}
|
|
|
|
user, err := identity.GetRequester(ctx)
|
|
if err != nil {
|
|
return authorizer.DecisionDeny, "error getting requester", err
|
|
}
|
|
|
|
ns := attr.GetNamespace()
|
|
if ns == "" {
|
|
return authorizer.DecisionDeny, "expected namespace", nil
|
|
}
|
|
|
|
info, err := types.ParseNamespace(attr.GetNamespace())
|
|
if err != nil {
|
|
return authorizer.DecisionDeny, "error reading org from namespace", err
|
|
}
|
|
|
|
// Validate organization access before we possibly step out here.
|
|
if user.GetOrgID() != info.OrgID {
|
|
return authorizer.DecisionDeny, "org mismatch", dashboards.ErrUserIsNotSignedInToOrg
|
|
}
|
|
|
|
switch attr.GetVerb() {
|
|
case "list", "search":
|
|
// Detailed read permissions are handled by authz, this just checks whether the user can ready *any* dashboard
|
|
ok, err := ac.Evaluate(ctx, user, accesscontrol.EvalPermission(dashboards.ActionDashboardsRead))
|
|
if !ok || err != nil {
|
|
return authorizer.DecisionDeny, "can not read any dashboards", err
|
|
}
|
|
case "create":
|
|
// Detailed create permissions are handled by authz, this just checks whether the user can create *any* dashboard
|
|
ok, err := ac.Evaluate(ctx, user, accesscontrol.EvalPermission(dashboards.ActionDashboardsCreate))
|
|
if !ok || err != nil {
|
|
return authorizer.DecisionDeny, "can not create any dashboards", err
|
|
}
|
|
case "get":
|
|
ok, err := ac.Evaluate(ctx, user, accesscontrol.EvalPermission(dashboards.ActionDashboardsRead, dashboards.ScopeDashboardsProvider.GetResourceScopeUID(attr.GetName())))
|
|
if !ok || err != nil {
|
|
return authorizer.DecisionDeny, "can not view dashboard", err
|
|
}
|
|
case "update", "patch":
|
|
ok, err := ac.Evaluate(ctx, user, accesscontrol.EvalPermission(dashboards.ActionDashboardsWrite, dashboards.ScopeDashboardsProvider.GetResourceScopeUID(attr.GetName())))
|
|
if !ok || err != nil {
|
|
return authorizer.DecisionDeny, "can not edit dashboard", err
|
|
}
|
|
case "delete":
|
|
ok, err := ac.Evaluate(ctx, user, accesscontrol.EvalPermission(dashboards.ActionDashboardsDelete, dashboards.ScopeDashboardsProvider.GetResourceScopeUID(attr.GetName())))
|
|
if !ok || err != nil {
|
|
return authorizer.DecisionDeny, "can not delete dashboard", err
|
|
}
|
|
default:
|
|
l.Info("unknown verb", "verb", attr.GetVerb())
|
|
return authorizer.DecisionDeny, "unsupported verb", nil // Unknown verb
|
|
}
|
|
return authorizer.DecisionAllow, "", nil
|
|
})
|
|
}
|