mirror of https://github.com/grafana/grafana
[release-12.0.1] K8s: Dashboards: Add fine grained access control checks to /apis (#104419)
K8s: Dashboards: Add fine grained access control checks to /apis (#104347) --------- 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>pull/104422/head
parent
835516f832
commit
b0d42f432a
@ -0,0 +1,79 @@ |
||||
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 |
||||
}) |
||||
} |
File diff suppressed because it is too large
Load Diff
Loading…
Reference in new issue