166 lines
4.5 KiB
Go
166 lines
4.5 KiB
Go
package common
|
|
|
|
import (
|
|
"slices"
|
|
|
|
authlib "github.com/grafana/authlib/types"
|
|
|
|
dashboards "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v1beta1"
|
|
folders "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1"
|
|
)
|
|
|
|
const (
|
|
roleGrafanaAdmin = "Grafana Admin"
|
|
roleAdmin = "Admin"
|
|
roleEditor = "Editor"
|
|
roleViewer = "Viewer"
|
|
roleNone = "None"
|
|
)
|
|
|
|
var basicRolesTranslations = map[string]string{
|
|
roleGrafanaAdmin: "basic_grafana_admin",
|
|
roleAdmin: "basic_admin",
|
|
roleEditor: "basic_editor",
|
|
roleViewer: "basic_viewer",
|
|
roleNone: "basic_none",
|
|
}
|
|
|
|
var basicRolesUIDs = []string{
|
|
"basic_grafana_admin",
|
|
"basic_admin",
|
|
"basic_editor",
|
|
"basic_viewer",
|
|
"basic_none",
|
|
}
|
|
|
|
type resourceTranslation struct {
|
|
typ string
|
|
group string
|
|
resource string
|
|
mapping map[string]actionMappig
|
|
}
|
|
|
|
type actionMappig struct {
|
|
relation string
|
|
group string
|
|
resource string
|
|
subresource string
|
|
}
|
|
|
|
func newMapping(relation, subresource string) actionMappig {
|
|
return newScopedMapping(relation, "", "", subresource)
|
|
}
|
|
|
|
func newScopedMapping(relation, group, resource, subresource string) actionMappig {
|
|
return actionMappig{relation, group, resource, subresource}
|
|
}
|
|
|
|
var (
|
|
folderGroup = folders.FolderResourceInfo.GroupResource().Group
|
|
folderResource = folders.FolderResourceInfo.GroupResource().Resource
|
|
|
|
dashboardGroup = dashboards.DashboardResourceInfo.GroupResource().Group
|
|
dashboardResource = dashboards.DashboardResourceInfo.GroupResource().Resource
|
|
)
|
|
|
|
var resourceTranslations = map[string]resourceTranslation{
|
|
KindFolders: {
|
|
typ: TypeFolder,
|
|
group: folderGroup,
|
|
resource: folderResource,
|
|
mapping: map[string]actionMappig{
|
|
"folders:read": newMapping(RelationGet, ""),
|
|
"folders:write": newMapping(RelationUpdate, ""),
|
|
"folders:create": newMapping(RelationCreate, ""),
|
|
"folders:delete": newMapping(RelationDelete, ""),
|
|
"dashboards:read": newScopedMapping(RelationGet, dashboardGroup, dashboardResource, ""),
|
|
"dashboards:write": newScopedMapping(RelationUpdate, dashboardGroup, dashboardResource, ""),
|
|
"dashboards:create": newScopedMapping(RelationCreate, dashboardGroup, dashboardResource, ""),
|
|
"dashboards:delete": newScopedMapping(RelationDelete, dashboardGroup, dashboardResource, ""),
|
|
// Action sets
|
|
"folders:view": newMapping(RelationSetView, ""),
|
|
"folders:edit": newMapping(RelationSetEdit, ""),
|
|
"folders:admin": newMapping(RelationSetAdmin, ""),
|
|
"dashboards:view": newScopedMapping(RelationSetView, dashboardGroup, dashboardResource, ""),
|
|
"dashboards:edit": newScopedMapping(RelationSetEdit, dashboardGroup, dashboardResource, ""),
|
|
"dashboards:admin": newScopedMapping(RelationSetAdmin, dashboardGroup, dashboardResource, ""),
|
|
},
|
|
},
|
|
KindDashboards: {
|
|
typ: TypeResource,
|
|
group: dashboardGroup,
|
|
resource: dashboardResource,
|
|
mapping: map[string]actionMappig{
|
|
"dashboards:read": newMapping(RelationGet, ""),
|
|
"dashboards:write": newMapping(RelationUpdate, ""),
|
|
"dashboards:create": newMapping(RelationCreate, ""),
|
|
"dashboards:delete": newMapping(RelationDelete, ""),
|
|
// Action sets
|
|
"dashboards:view": newMapping(RelationSetView, ""),
|
|
"dashboards:edit": newMapping(RelationSetEdit, ""),
|
|
"dashboards:admin": newMapping(RelationSetAdmin, ""),
|
|
},
|
|
},
|
|
}
|
|
|
|
func TranslateToCheckRequest(namespace, action, kind, name string) (*authlib.CheckRequest, bool) {
|
|
translation, ok := resourceTranslations[kind]
|
|
|
|
if !ok {
|
|
return nil, false
|
|
}
|
|
|
|
m, ok := translation.mapping[action]
|
|
if !ok {
|
|
return nil, false
|
|
}
|
|
|
|
verb, ok := RelationToVerbMapping[m.relation]
|
|
if !ok {
|
|
return nil, false
|
|
}
|
|
|
|
req := &authlib.CheckRequest{
|
|
Namespace: namespace,
|
|
Verb: verb,
|
|
Group: translation.group,
|
|
Resource: translation.resource,
|
|
Name: name,
|
|
}
|
|
|
|
return req, true
|
|
}
|
|
|
|
func TranslateToListRequest(namespace, action, kind string) (*authlib.ListRequest, bool) {
|
|
translation, ok := resourceTranslations[kind]
|
|
|
|
if !ok {
|
|
return nil, false
|
|
}
|
|
|
|
// FIXME: support different verbs
|
|
req := &authlib.ListRequest{
|
|
Namespace: namespace,
|
|
Group: translation.group,
|
|
Resource: translation.resource,
|
|
}
|
|
|
|
return req, true
|
|
}
|
|
|
|
func TranslateToGroupResource(kind string) string {
|
|
translation, ok := resourceTranslations[kind]
|
|
if !ok {
|
|
return ""
|
|
}
|
|
return FormatGroupResource(translation.group, translation.resource, "")
|
|
}
|
|
|
|
func TranslateBasicRole(name string) string {
|
|
return basicRolesTranslations[name]
|
|
}
|
|
|
|
func IsBasicRole(name string) bool {
|
|
return slices.Contains(basicRolesUIDs, name)
|
|
}
|