183 lines
5.2 KiB
Go
183 lines
5.2 KiB
Go
package zanzana
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
openfgav1 "github.com/openfga/api/proto/openfga/v1"
|
|
|
|
authlib "github.com/grafana/authlib/types"
|
|
|
|
"github.com/grafana/grafana/pkg/services/authz/zanzana/common"
|
|
)
|
|
|
|
const (
|
|
TypeUser = common.TypeUser
|
|
TypeServiceAccount = common.TypeServiceAccount
|
|
TypeRenderService = common.TypeRenderService
|
|
TypeAnonymous = common.TypeAnonymous
|
|
TypeTeam = common.TypeTeam
|
|
TypeRole = common.TypeRole
|
|
TypeFolder = common.TypeFolder
|
|
TypeResource = common.TypeResource
|
|
TypeNamespace = common.TypeGroupResouce
|
|
)
|
|
|
|
const (
|
|
RelationTeamMember = common.RelationTeamMember
|
|
RelationTeamAdmin = common.RelationTeamAdmin
|
|
RelationParent = common.RelationParent
|
|
RelationAssignee = common.RelationAssignee
|
|
|
|
RelationSetView = common.RelationSetView
|
|
RelationSetEdit = common.RelationSetEdit
|
|
RelationSetAdmin = common.RelationSetAdmin
|
|
|
|
RelationGet = common.RelationGet
|
|
RelationUpdate = common.RelationUpdate
|
|
RelationCreate = common.RelationCreate
|
|
RelationDelete = common.RelationDelete
|
|
|
|
RelationFolderResourceSetView = common.RelationFolderResourceSetView
|
|
RelationFolderResourceSetEdit = common.RelationFolderResourceSetEdit
|
|
RelationFolderResourceSetAdmin = common.RelationFolderResourceSetAdmin
|
|
|
|
RelationFolderResourceRead = common.RelationFolderResourceGet
|
|
RelationFolderResourceWrite = common.RelationFolderResourceUpdate
|
|
RelationFolderResourceCreate = common.RelationFolderResourceCreate
|
|
RelationFolderResourceDelete = common.RelationFolderResourceDelete
|
|
)
|
|
|
|
var (
|
|
RelationsFolder = common.RelationsFolder
|
|
RelationsResouce = common.RelationsResource
|
|
RelationsFolderResource = common.RelationsFolderResource
|
|
)
|
|
|
|
const (
|
|
KindDashboards string = "dashboards"
|
|
KindFolders string = "folders"
|
|
)
|
|
|
|
var (
|
|
ToAuthzExtTupleKey = common.ToAuthzExtTupleKey
|
|
ToAuthzExtTupleKeys = common.ToAuthzExtTupleKeys
|
|
ToAuthzExtTupleKeyWithoutCondition = common.ToAuthzExtTupleKeyWithoutCondition
|
|
ToAuthzExtTupleKeysWithoutCondition = common.ToAuthzExtTupleKeysWithoutCondition
|
|
|
|
ToOpenFGATuple = common.ToOpenFGATuple
|
|
ToOpenFGATuples = common.ToOpenFGATuples
|
|
ToOpenFGATupleKey = common.ToOpenFGATupleKey
|
|
ToOpenFGATupleKeyWithoutCondition = common.ToOpenFGATupleKeyWithoutCondition
|
|
)
|
|
|
|
// NewTupleEntry constructs new openfga entry type:name[#relation].
|
|
// Relation allows to specify group of users (subjects) related to type:name
|
|
// (for example, team:devs#member refers to users which are members of team devs)
|
|
func NewTupleEntry(objectType, name, relation string) string {
|
|
obj := fmt.Sprintf("%s:%s", objectType, name)
|
|
if relation != "" {
|
|
obj = fmt.Sprintf("%s#%s", obj, relation)
|
|
}
|
|
return obj
|
|
}
|
|
|
|
func TranslateToResourceTuple(subject string, action, kind, name string) (*openfgav1.TupleKey, bool) {
|
|
translation, ok := resourceTranslations[kind]
|
|
|
|
if !ok {
|
|
return nil, false
|
|
}
|
|
|
|
m, ok := translation.mapping[action]
|
|
if !ok {
|
|
return nil, false
|
|
}
|
|
|
|
if name == "*" {
|
|
return common.NewGroupResourceTuple(subject, m.relation, translation.group, translation.resource, m.subresource), true
|
|
}
|
|
|
|
if translation.typ == TypeResource {
|
|
return common.NewResourceTuple(subject, m.relation, translation.group, translation.resource, m.subresource, name), true
|
|
}
|
|
|
|
if translation.typ == TypeFolder {
|
|
if m.group != "" && m.resource != "" {
|
|
return common.NewFolderResourceTuple(subject, m.relation, m.group, m.resource, m.subresource, name), true
|
|
}
|
|
|
|
return common.NewFolderTuple(subject, m.relation, name), true
|
|
}
|
|
|
|
return common.NewTypedTuple(translation.typ, subject, m.relation, name), true
|
|
}
|
|
|
|
func IsFolderResourceTuple(t *openfgav1.TupleKey) bool {
|
|
return strings.HasPrefix(t.Object, TypeFolder) && strings.HasPrefix(t.Relation, "resource_")
|
|
}
|
|
|
|
func MergeFolderResourceTuples(a, b *openfgav1.TupleKey) {
|
|
va := a.Condition.Context.Fields["group_resources"]
|
|
vb := b.Condition.Context.Fields["group_resources"]
|
|
va.GetListValue().Values = append(va.GetListValue().Values, vb.GetListValue().Values...)
|
|
}
|
|
|
|
func TranslateToCheckRequest(namespace, action, kind, folder, 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 := common.RelationToVerbMapping[m.relation]
|
|
if !ok {
|
|
return nil, false
|
|
}
|
|
|
|
req := &authlib.CheckRequest{
|
|
Namespace: namespace,
|
|
Verb: verb,
|
|
Group: translation.group,
|
|
Resource: translation.resource,
|
|
Name: name,
|
|
Folder: folder,
|
|
}
|
|
|
|
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 common.FormatGroupResource(translation.group, translation.resource, "")
|
|
}
|
|
|
|
func TranslateBasicRole(name string) string {
|
|
return basicRolesTranslations[name]
|
|
}
|