Skip to content

Commit

Permalink
filters/auth: eliminate allocations in tokeninfo scope checks
Browse files Browse the repository at this point in the history
```
goos: linux
goarch: amd64
pkg: github.com/zalando/skipper/filters/auth
cpu: Intel(R) Core(TM) i5-8350U CPU @ 1.70GHz
                                               │   HEAD~1    │                HEAD                 │
                                               │   sec/op    │   sec/op     vs base                │
OAuthTokeninfoRequest/oauthTokeninfoAllScope-8   422.5n ± 4%   246.2n ± 1%  -41.74% (p=0.000 n=10)
OAuthTokeninfoRequest/oauthTokeninfoAnyScope-8   413.5n ± 4%   251.5n ± 0%  -39.19% (p=0.000 n=10)
geomean                                          418.0n        248.8n       -40.48%

                                               │   HEAD~1   │                 HEAD                  │
                                               │    B/op    │   B/op    vs base                     │
OAuthTokeninfoRequest/oauthTokeninfoAllScope-8   112.0 ± 0%   0.0 ± 0%  -100.00% (p=0.000 n=10)
OAuthTokeninfoRequest/oauthTokeninfoAnyScope-8   112.0 ± 0%   0.0 ± 0%  -100.00% (p=0.000 n=10)
geomean                                          112.0                  ?                       ¹ ²
¹ summaries must be >0 to compute geomean
² ratios must be >0 to compute geomean

                                               │   HEAD~1   │                  HEAD                   │
                                               │ allocs/op  │ allocs/op   vs base                     │
OAuthTokeninfoRequest/oauthTokeninfoAllScope-8   3.000 ± 0%   0.000 ± 0%  -100.00% (p=0.000 n=10)
OAuthTokeninfoRequest/oauthTokeninfoAnyScope-8   3.000 ± 0%   0.000 ± 0%  -100.00% (p=0.000 n=10)
geomean                                          3.000                    ?                       ¹ ²
¹ summaries must be >0 to compute geomean
² ratios must be >0 to compute geomean
```

Signed-off-by: Alexander Yastrebov <alexander.yastrebov@zalando.de>
  • Loading branch information
AlexanderYastrebov committed Dec 12, 2023
1 parent daa8a07 commit 92a0856
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 28 deletions.
13 changes: 0 additions & 13 deletions filters/auth/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,16 +174,3 @@ func all(left, right []string) bool {
}
return true
}

// intersect checks that one string in the left is also in the right
func intersect(left, right []string) bool {
for _, l := range left {
for _, r := range right {
if l == r {
return true
}
}
}

return false
}
33 changes: 18 additions & 15 deletions filters/auth/tokeninfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -271,16 +271,13 @@ func (f *tokeninfoFilter) validateAnyScopes(h map[string]interface{}) bool {
if !ok {
return false
}
var a []string
for i := range v {
s, ok := v[i].(string)
if !ok {
return false

for _, scope := range f.scopes {
if contains(v, scope) {
return true
}
a = append(a, s)
}

return intersect(f.scopes, a)
return false
}

func (f *tokeninfoFilter) validateAllScopes(h map[string]interface{}) bool {
Expand All @@ -296,16 +293,13 @@ func (f *tokeninfoFilter) validateAllScopes(h map[string]interface{}) bool {
if !ok {
return false
}
var a []string
for i := range v {
s, ok := v[i].(string)
if !ok {

for _, scope := range f.scopes {
if !contains(v, scope) {
return false
}
a = append(a, s)
}

return all(f.scopes, a)
return true
}

func (f *tokeninfoFilter) validateAnyKV(h map[string]interface{}) bool {
Expand Down Expand Up @@ -336,6 +330,15 @@ func (f *tokeninfoFilter) validateAllKV(h map[string]interface{}) bool {
return true
}

func contains(vals []interface{}, s string) bool {
for _, v := range vals {
if v == s {
return true
}
}
return false
}

// Request handles authentication based on the defined auth type.
func (f *tokeninfoFilter) Request(ctx filters.FilterContext) {
r := ctx.Request()
Expand Down
47 changes: 47 additions & 0 deletions filters/auth/tokeninfo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -528,3 +528,50 @@ func BenchmarkOAuthTokeninfoRequest(b *testing.B) {
}
})
}

func TestOAuthTokeninfoAllocs(t *testing.T) {
tio := TokeninfoOptions{
URL: "https://127.0.0.1:12345/token",
Timeout: 3 * time.Second,
}

fr := make(filters.Registry)
fr.Register(NewOAuthTokeninfoAllScopeWithOptions(tio))
fr.Register(NewOAuthTokeninfoAnyScopeWithOptions(tio))
fr.Register(NewOAuthTokeninfoAllKVWithOptions(tio))
fr.Register(NewOAuthTokeninfoAnyKVWithOptions(tio))

var filters []filters.Filter
for _, def := range eskip.MustParseFilters(`
oauthTokeninfoAnyScope("foobar.read", "foobar.write") ->
oauthTokeninfoAllScope("foobar.read", "foobar.write") ->
oauthTokeninfoAnyKV("k1", "v1", "k2", "v2") ->
oauthTokeninfoAllKV("k1", "v1", "k2", "v2")
`) {
f, err := fr[def.Name].CreateFilter(def.Args)
require.NoError(t, err)

filters = append(filters, f)
}

ctx := &filtertest.Context{
FStateBag: map[string]interface{}{
tokeninfoCacheKey: map[string]interface{}{
scopeKey: []interface{}{"uid", "foobar.read", "foobar.write", "foobar.exec"},
"k1": "v1",
"k2": "v2",
},
},
FResponse: &http.Response{},
}

allocs := testing.AllocsPerRun(100, func() {
for _, f := range filters {
f.Request(ctx)
}
require.False(t, ctx.FServed)
})
if allocs != 0.0 {
t.Errorf("Expected zero allocations, got %f", allocs)
}
}

0 comments on commit 92a0856

Please sign in to comment.