Rework pkg/rbac with new resource index struct
This commit is contained in:
@@ -82,8 +82,10 @@ func benchmarkMatchResource(b *testing.B, c int) {
|
||||
b.StartTimer()
|
||||
|
||||
for n := 0; n < b.N; n++ {
|
||||
matchResource("corteza::test/a/1/1/1", "corteza::test/a/1/1/1")
|
||||
matchResource("corteza::test/a/*/*/1", "corteza::test/a/1/1/1")
|
||||
for i := 0; i < c; i++ {
|
||||
matchResource("corteza::test/a/1/1/1", "corteza::test/a/1/1/1")
|
||||
matchResource("corteza::test/a/*/*/1", "corteza::test/a/1/1/1")
|
||||
}
|
||||
}
|
||||
|
||||
b.StopTimer()
|
||||
|
||||
+29
-4
@@ -2,6 +2,9 @@ package rbac
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/cortezaproject/corteza-server/pkg/resource"
|
||||
)
|
||||
|
||||
type (
|
||||
@@ -17,10 +20,19 @@ type (
|
||||
|
||||
RuleSet []*Rule
|
||||
|
||||
ruleIndexWrap struct {
|
||||
index *resource.IndexNode
|
||||
rules RuleSet
|
||||
}
|
||||
|
||||
// OptRuleSet RBAC rule index (operation / role ID / rules)
|
||||
OptRuleSet map[string]map[uint64]RuleSet
|
||||
OptRuleSet map[string]map[uint64]*ruleIndexWrap
|
||||
)
|
||||
|
||||
func (r Rule) Clone() *Rule {
|
||||
return &r
|
||||
}
|
||||
|
||||
func (r Rule) String() string {
|
||||
return fmt.Sprintf("%s %d to %s on %s", r.Access, r.RoleID, r.Operation, r.Resource)
|
||||
}
|
||||
@@ -29,19 +41,32 @@ func indexRules(rules []*Rule) OptRuleSet {
|
||||
i := make(OptRuleSet)
|
||||
for _, r := range rules {
|
||||
if i[r.Operation] == nil {
|
||||
i[r.Operation] = make(map[uint64]RuleSet)
|
||||
i[r.Operation] = make(map[uint64]*ruleIndexWrap)
|
||||
}
|
||||
|
||||
if i[r.Operation][r.RoleID] == nil {
|
||||
i[r.Operation][r.RoleID] = RuleSet{}
|
||||
i[r.Operation][r.RoleID] = &ruleIndexWrap{
|
||||
index: resource.NewIndex(),
|
||||
}
|
||||
}
|
||||
|
||||
i[r.Operation][r.RoleID] = append(i[r.Operation][r.RoleID], r)
|
||||
i[r.Operation][r.RoleID].index.Add(r, r.IndexPath()...)
|
||||
i[r.Operation][r.RoleID].rules = append(i[r.Operation][r.RoleID].rules, r)
|
||||
}
|
||||
|
||||
return i
|
||||
}
|
||||
|
||||
func (r Rule) IndexPath() (out [][]string) {
|
||||
pts := strings.Split(r.Resource, pathSep)
|
||||
|
||||
for _, p := range pts {
|
||||
out = append(out, []string{p})
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (set RuleSet) Len() int { return len(set) }
|
||||
func (set RuleSet) Swap(i, j int) { set[i], set[j] = set[j], set[i] }
|
||||
func (set RuleSet) Less(i, j int) bool {
|
||||
|
||||
@@ -2,6 +2,7 @@ package rbac
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func check(indexedRules OptRuleSet, rolesByKind partRoles, op, res string) Access {
|
||||
@@ -44,7 +45,11 @@ func check(indexedRules OptRuleSet, rolesByKind partRoles, op, res string) Acces
|
||||
if !rolesByKind[kind][roleID] {
|
||||
continue
|
||||
}
|
||||
rules = append(rules, r...)
|
||||
|
||||
aux := r.index.Collect(resourceToIndexPath(res)...)
|
||||
for _, a := range aux {
|
||||
rules = append(rules, a.(*Rule))
|
||||
}
|
||||
}
|
||||
|
||||
access := checkRulesByResource(rules, op, res)
|
||||
@@ -89,3 +94,14 @@ func member(r partRoles, k roleKind) bool {
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// utility to get the resource index path from the resource identifier
|
||||
func resourceToIndexPath(r string) (out [][]string) {
|
||||
pts := strings.Split(r, pathSep)
|
||||
|
||||
for _, pt := range pts {
|
||||
out = append(out, []string{pt})
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -105,9 +105,11 @@ func benchmarkCheck(b *testing.B, c int) {
|
||||
|
||||
for i := 0; i < cap(rules); i++ {
|
||||
rules = append(rules, &Rule{
|
||||
RoleID: uint64(rand.Int31n(50)),
|
||||
Resource: fmt.Sprintf("res-%d", rand.Int31n(1000)),
|
||||
Operation: fmt.Sprintf("op-%d", rand.Int31n(100)),
|
||||
// one over because interval is [a, b)
|
||||
// lowered others to make the cases more resource intensive
|
||||
RoleID: uint64(rand.Int31n(10)),
|
||||
Resource: fmt.Sprintf("res-%d", rand.Int31n(10)),
|
||||
Operation: fmt.Sprintf("op-%d", rand.Int31n(5)),
|
||||
Access: Access(rand.Int31n(2)),
|
||||
})
|
||||
}
|
||||
@@ -117,7 +119,7 @@ func benchmarkCheck(b *testing.B, c int) {
|
||||
b.StartTimer()
|
||||
|
||||
for n := 0; n < b.N; n++ {
|
||||
check(iRules, pr, "res-0", "op-0")
|
||||
check(iRules, pr, "op-0", "res-0")
|
||||
}
|
||||
|
||||
b.StopTimer()
|
||||
|
||||
+1
-1
@@ -279,7 +279,7 @@ func (svc service) String() (out string) {
|
||||
|
||||
for _, byRole := range svc.indexed {
|
||||
for _, rr := range byRole {
|
||||
for _, r := range rr {
|
||||
for _, r := range rr.rules {
|
||||
out += fmt.Sprintf(tpl, r.Access, r.Operation, role(r.RoleID), r.Resource)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user