Skip to content

Commit

Permalink
fix: matchPerm and add more test cases
Browse files Browse the repository at this point in the history
[skip ci]
  • Loading branch information
adityathebe committed Nov 27, 2024
1 parent f4b6a9d commit 3c31ea6
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 29 deletions.
47 changes: 25 additions & 22 deletions rbac/custom_functions.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,24 @@ import (

"github.com/casbin/govaluate"
"github.com/flanksource/commons/collections"
"github.com/samber/lo"
)

func matchPerm(obj any, _agents any, tagsEncoded string) (bool, error) {
var rObj map[string]any
switch v := obj.(type) {
case string:
return true, nil
// an object is required to satisfy the agents & tags requirement.
return false, nil

case map[string]any:
rObj = v
}

var rAgents []any
var rAgents []string
switch v := _agents.(type) {
case []any:
rAgents = v
rAgents = lo.Map(v, func(item any, _ int) string { return item.(string) })
case string:
if v != "" {
rAgents = append(rAgents, v)
Expand All @@ -30,30 +32,20 @@ func matchPerm(obj any, _agents any, tagsEncoded string) (bool, error) {

rTags := collections.SelectorToMap(tagsEncoded)
if config, ok := rObj["config"]; ok {
var tagsmatch = len(rTags) == 0
var agentsMatch = len(rAgents) == 0
var (
tagsmatch = true
agentsMatch = true
)

// All tags must match
tagsRaw := config.(map[string]any)["tags"]
if tags, ok := tagsRaw.(map[string]any); ok {
for k, v := range rTags {
if tags[k] != v {
tagsmatch = false
break
}
}

tagsmatch = true
tagsmatch = mapContains(rTags, tags)
}

// Any agent must match
agentIDRaw := config.(map[string]any)["agent_id"]
if agentID, ok := agentIDRaw.(string); ok {
for _, id := range rAgents {
if agentID == id {
agentsMatch = true
break
}
if len(rAgents) > 0 {
agentIDRaw := config.(map[string]any)["agent_id"]
if agentID, ok := agentIDRaw.(string); ok {
agentsMatch = lo.Contains(rAgents, agentID)
}
}

Expand Down Expand Up @@ -85,3 +77,14 @@ func addCustomFunctions(enforcer addableEnforcer) {
return matchPerm(obj, agents, tagsEncoded)
})
}

// mapContains returns true if `request` fully contains `want`.
func mapContains(want map[string]string, request map[string]any) bool {
for k, v := range want {
if request[k] != v {
return false
}
}

return true
}
76 changes: 69 additions & 7 deletions rbac/custom_functions_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"testing"

"github.com/flanksource/duty/models"
"github.com/google/uuid"
)

func Test_matchPerm(t *testing.T) {
Expand All @@ -12,6 +13,7 @@ func Test_matchPerm(t *testing.T) {
_agents any
_tags string
}

tests := []struct {
name string
args args
Expand All @@ -21,10 +23,10 @@ func Test_matchPerm(t *testing.T) {
{
name: "string object",
args: args{obj: "catalog", _agents: "()", _tags: "namespace=default"},
want: true,
want: false,
},
{
name: "json object",
name: "tag only match",
args: args{
obj: map[string]any{
"config": models.ConfigItem{Tags: map[string]string{
Expand All @@ -37,7 +39,23 @@ func Test_matchPerm(t *testing.T) {
want: true,
},
{
name: "json object tags fully not match",
name: "multiple tags match",
args: args{
obj: map[string]any{
"config": models.ConfigItem{
Tags: map[string]string{
"namespace": "default",
"cluster": "homelab",
},
}.AsMap(),
},
_agents: "",
_tags: "namespace=default,cluster=homelab",
},
want: true,
},
{
name: "multiple tags no match",
args: args{
obj: map[string]any{
"config": models.ConfigItem{Tags: map[string]string{
Expand All @@ -49,13 +67,57 @@ func Test_matchPerm(t *testing.T) {
},
want: false,
},
{
name: "tags & agents match",
args: args{
obj: map[string]any{
"config": models.ConfigItem{
Tags: map[string]string{
"namespace": "default",
},
AgentID: uuid.MustParse("66eda456-315f-455a-95d4-6ef059fc13a8"),
}.AsMap(),
},
_agents: "66eda456-315f-455a-95d4-6ef059fc13a8",
_tags: "namespace=default",
},
want: true,
},
{
name: "tags match & agent no match",
args: args{
obj: map[string]any{
"config": models.ConfigItem{
Tags: map[string]string{
"namespace": "default",
},
AgentID: uuid.MustParse("66eda456-315f-455a-95d4-6ef059fc13a8"),
}.AsMap(),
},
_agents: "",
_tags: "namespace=default,cluster=homelab",
},
want: false,
},
{
name: "tags no match & agent match",
args: args{
obj: map[string]any{
"config": models.ConfigItem{
Tags: map[string]string{
"namespace": "default",
},
AgentID: uuid.MustParse("66eda456-315f-455a-95d4-6ef059fc13a8"),
}.AsMap(),
},
_agents: "66eda456-315f-455a-95d4-6ef059fc13a8",
_tags: "namespace=mc",
},
want: false,
},
}

for _, tt := range tests {
if tt.name != "son object tags fully not match" {
continue
}

t.Run(tt.name, func(t *testing.T) {
got, err := matchPerm(tt.args.obj, tt.args._agents, tt.args._tags)
if (err != nil) != tt.wantErr {
Expand Down

0 comments on commit 3c31ea6

Please sign in to comment.