The open and composable observability and data visualization platform. Visualize metrics, logs, and traces from multiple sources like Prometheus, Loki, Elasticsearch, InfluxDB, Postgres and many more.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
grafana/pkg/registry/apis/dashboard/authorizer.go

95 lines
2.8 KiB

package dashboard
import (
"context"
"k8s.io/apiserver/pkg/authorization/authorizer"
"github.com/grafana/authlib/claims"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/grafana/pkg/apis/dashboard/v0alpha1"
"github.com/grafana/grafana/pkg/services/dashboards"
"github.com/grafana/grafana/pkg/services/guardian"
)
func (b *DashboardsAPIBuilder) GetAuthorizer() authorizer.Authorizer {
return authorizer.AuthorizerFunc(
func(ctx context.Context, attr authorizer.Attributes) (authorized authorizer.Decision, reason string, err error) {
if !attr.IsResourceRequest() {
return authorizer.DecisionNoOpinion, "", nil
}
user, err := identity.GetRequester(ctx)
if err != nil {
return authorizer.DecisionDeny, "", err
}
if attr.GetName() == "" {
// Discourage use of the "list" command for non super admin users
if attr.GetVerb() == "list" && attr.GetResource() == v0alpha1.DashboardResourceInfo.GroupResource().Resource {
if !user.GetIsGrafanaAdmin() {
return authorizer.DecisionDeny, "list summary objects (or connect as GrafanaAdmin)", err
}
}
return authorizer.DecisionNoOpinion, "", nil
}
ns := attr.GetNamespace()
if ns == "" {
return authorizer.DecisionDeny, "expected namespace", nil
}
info, err := claims.ParseNamespace(attr.GetNamespace())
if err != nil {
return authorizer.DecisionDeny, "error reading org from namespace", err
}
// expensive path to lookup permissions for a single dashboard
dto, err := b.dashboardService.GetDashboard(ctx, &dashboards.GetDashboardQuery{
UID: attr.GetName(),
OrgID: info.OrgID,
})
if err != nil {
return authorizer.DecisionDeny, "error loading dashboard", err
}
ok := false
guardian, err := guardian.NewByDashboard(ctx, dto, info.OrgID, user)
if err != nil {
return authorizer.DecisionDeny, "", err
}
switch attr.GetVerb() {
case "get":
ok, err = guardian.CanView()
if !ok || err != nil {
return authorizer.DecisionDeny, "can not view dashboard", err
}
case "create":
fallthrough
case "post":
ok, err = guardian.CanSave() // vs Edit?
if !ok || err != nil {
return authorizer.DecisionDeny, "can not save dashboard", err
}
case "update":
fallthrough
case "patch":
fallthrough
case "put":
ok, err = guardian.CanEdit() // vs Save
if !ok || err != nil {
return authorizer.DecisionDeny, "can not edit dashboard", err
}
case "delete":
ok, err = guardian.CanDelete()
if !ok || err != nil {
return authorizer.DecisionDeny, "can not delete dashboard", err
}
default:
b.log.Info("unknown verb", "verb", attr.GetVerb())
return authorizer.DecisionNoOpinion, "unsupported verb", nil // Unknown verb
}
return authorizer.DecisionAllow, "", nil
})
}