From 3a511ac393527e065b67e35f04d4e9047bfffa2a Mon Sep 17 00:00:00 2001 From: Ingo Oppermann Date: Tue, 30 Apr 2024 14:12:01 +0200 Subject: [PATCH] Add cache for compiled glob patterns --- iam/access/access_test.go | 20 ++++++++++++++++++++ iam/access/functions.go | 38 ++++++++++++++++++++++++++++++++------ 2 files changed, 52 insertions(+), 6 deletions(-) diff --git a/iam/access/access_test.go b/iam/access/access_test.go index 220cfa26..b857dd69 100644 --- a/iam/access/access_test.go +++ b/iam/access/access_test.go @@ -101,3 +101,23 @@ func TestAccessManager(t *testing.T) { ok, _ = am.Enforce("foobar", "group", "blubb", "/", "write") require.True(t, ok) } + +func BenchmarkEnforce(b *testing.B) { + adapter, err := createAdapter() + require.NoError(b, err) + + am, err := New(Config{ + Adapter: adapter, + Logger: nil, + }) + require.NoError(b, err) + + am.AddPolicy("$anon", "$none", []string{"foobar"}, "**", []string{"ANY"}) + + b.ResetTimer() + + for i := 0; i < b.N; i++ { + ok, _ := am.Enforce("$anon", "$none", "foobar", "baz", "read") + require.True(b, ok) + } +} diff --git a/iam/access/functions.go b/iam/access/functions.go index 5cc61b1e..07bc70e9 100644 --- a/iam/access/functions.go +++ b/iam/access/functions.go @@ -2,10 +2,14 @@ package access import ( "strings" + "sync" "github.com/datarhei/core/v16/glob" ) +var globcache = map[string]glob.Glob{} +var globcacheMu = sync.RWMutex{} + func resourceMatch(request, policy string) bool { reqPrefix, reqResource := getPrefix(request) polPrefix, polResource := getPrefix(policy) @@ -31,16 +35,38 @@ func resourceMatch(request, policy string) bool { match = false + key := reqType + polResource + if reqType == "api" || reqType == "fs" || reqType == "rtmp" || reqType == "srt" { - match, err = glob.Match(polResource, reqResource, rune('/')) - if err != nil { - return false + globcacheMu.RLock() + matcher, ok := globcache[key] + globcacheMu.RUnlock() + if !ok { + matcher, err = glob.Compile(polResource, rune('/')) + if err != nil { + return false + } + globcacheMu.Lock() + globcache[key] = matcher + globcacheMu.Unlock() } + + match = matcher.Match(reqResource) } else { - match, err = glob.Match(polResource, reqResource) - if err != nil { - return false + globcacheMu.RLock() + matcher, ok := globcache[key] + globcacheMu.RUnlock() + if !ok { + matcher, err = glob.Compile(polResource) + if err != nil { + return false + } + globcacheMu.Lock() + globcache[key] = matcher + globcacheMu.Unlock() } + + match = matcher.Match(reqResource) } return match