3
0
corteza/server/pkg/envoyx/rbacutils.go
Tomaž Jerman 22a70f61a8 Fix invalid matchup when importing resources
Matchups were not scoped which caused them to get matched
to any matched ident, regardles of scope.

This caused NS duplication to "move" original resources to the
cloned one instead of copying them.
2023-03-20 16:07:49 +01:00

145 lines
3.1 KiB
Go

package envoyx
import (
"fmt"
"strings"
"github.com/cortezaproject/corteza/server/pkg/rbac"
"github.com/cortezaproject/corteza/server/system/types"
)
type (
rbacer interface {
RbacResource() string
}
)
func RBACRulesForNodes(rr rbac.RuleSet, nn ...*Node) (rules NodeSet, err error) {
rules = make(NodeSet, 0, len(rr)/2)
dups := make(map[uint64]map[string]map[string]bool)
for _, n := range nn {
if n.Placeholder {
continue
}
c, ok := n.Resource.(rbacer)
if !ok {
continue
}
// Split up the path of this resource
//
// @todo move over to those generated functions
resPath := splitResourcePath(c.RbacResource())
// Find all of the rules that fall under this resource
for _, r := range rr {
if r.RoleID == 0 {
// Can't exist; skip to avoid edge cases
continue
}
// Split up the path of the rule
//
// @todo move over to that generated function
rulePath := splitResourcePath(r.Resource)
// Don't handle rules that are not a subset of the resource
// @todo this should be handled by the parent probably
if len(rulePath) > 0 && rulePath[0] == "*" || rulePath[0] == "" {
continue
}
if !isPathSubset(rulePath, resPath, true) {
// Mismatch; skip
continue
}
// Check if this rule has already been seen
if dups[r.RoleID] != nil && dups[r.RoleID][r.Resource] != nil && dups[r.RoleID][r.Resource][r.Operation] {
continue
}
// Parse the path so we can process it further
ruleRt, res, path, err := ParseRule(r.Resource)
if err != nil {
return nil, err
}
if ruleRt != n.ResourceType {
// Type missmatch; skip
continue
}
// Get the refs
rf := make(map[string]Ref, 2)
for i, ref := range append(path, res) {
// Whenever you'd use a wildcard, it will produce a nil so it
// needs to be skipped
if ref == nil {
continue
}
ref.Scope = n.Scope
// @todo make the thing not a pointer
rf[fmt.Sprintf("Path.%d", i)] = *ref
}
// Ref to the rule
rf["RoleID"] = Ref{
ResourceType: types.RoleResourceType,
Identifiers: MakeIdentifiers(r.RoleID),
}
rules = append(rules, &Node{
Resource: r,
ResourceType: rbac.RuleResourceType,
References: rf,
Scope: n.Scope,
})
// Update the dup checking index
if dups[r.RoleID] == nil {
dups[r.RoleID] = make(map[string]map[string]bool)
}
if dups[r.RoleID][r.Resource] == nil {
dups[r.RoleID][r.Resource] = make(map[string]bool)
}
dups[r.RoleID][r.Resource][r.Operation] = true
}
}
return
}
func splitResourcePath(p string) []string {
return strings.Split(p, "/")[1:]
}
func isPathSubset(rulePath, resPath []string, wildcards bool) bool {
if len(rulePath) == 0 && len(resPath) == 0 {
return true
}
// The lengths must match since missing bits are replaced with wildcards
if len(rulePath) != len(resPath) {
return false
}
for i := 0; i < len(resPath); i++ {
if wildcards && rulePath[i] == "*" {
// Rule matches everything from now on; if we got this far, we're good
return true
}
if rulePath[i] != resPath[i] {
return false
}
}
return true
}