From a5a73a3532d8a7117f68f376ba9840a86aeac10c Mon Sep 17 00:00:00 2001 From: KevFan Date: Wed, 5 Feb 2025 10:50:23 +0000 Subject: [PATCH] refactor: loading all matched api key values Signed-off-by: KevFan --- go.mod | 5 +-- go.sum | 14 +++++---- pkg/evaluators/identity/api_key.go | 49 +++++++++++++++++++++--------- 3 files changed, 46 insertions(+), 22 deletions(-) diff --git a/go.mod b/go.mod index 80ee0f7a..1b93e404 100644 --- a/go.mod +++ b/go.mod @@ -19,6 +19,7 @@ require ( github.com/hashicorp/go-multierror v1.1.1 github.com/open-policy-agent/opa v0.68.0 github.com/prometheus/client_golang v1.20.2 + github.com/samber/lo v1.49.1 github.com/spf13/cobra v1.8.1 github.com/spf13/pflag v1.0.5 github.com/tidwall/gjson v1.14.0 @@ -115,7 +116,7 @@ require ( github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/spf13/cast v1.6.0 // indirect - github.com/stretchr/testify v1.9.0 + github.com/stretchr/testify v1.10.0 github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.0 // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect @@ -127,7 +128,7 @@ require ( golang.org/x/crypto v0.26.0 // indirect golang.org/x/sys v0.23.0 // indirect golang.org/x/term v0.23.0 // indirect - golang.org/x/text v0.17.0 // indirect + golang.org/x/text v0.21.0 // indirect golang.org/x/time v0.6.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect diff --git a/go.sum b/go.sum index d9ef5732..6efbf8fd 100644 --- a/go.sum +++ b/go.sum @@ -483,6 +483,8 @@ github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99 github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/samber/lo v1.49.1 h1:4BIFyVfuQSEpluc7Fua+j1NolZHiEHEpaSEKdsH0tew= +github.com/samber/lo v1.49.1/go.mod h1:dO6KHFzUKXgP8LDhU0oI8d2hekjXnGOu0DB8Jecxd6o= github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= @@ -529,8 +531,8 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/tchap/go-patricia/v2 v2.3.1 h1:6rQp39lgIYZ+MHmdEq4xzuk1t7OdC35z/xm0BGhTkes= github.com/tchap/go-patricia/v2 v2.3.1/go.mod h1:VZRHKAb53DLaG+nA9EaYYiaEx6YztwDlLElMsnSHD4k= github.com/tidwall/gjson v1.14.0 h1:6aeJ0bzojgWLa82gDQHcx3S0Lr/O51I9bJ5nv6JFx5w= @@ -667,8 +669,8 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= -golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= +golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -711,8 +713,8 @@ golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fq golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= -golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U= diff --git a/pkg/evaluators/identity/api_key.go b/pkg/evaluators/identity/api_key.go index 025c70ba..91f78ffc 100644 --- a/pkg/evaluators/identity/api_key.go +++ b/pkg/evaluators/identity/api_key.go @@ -5,6 +5,8 @@ import ( "fmt" "sync" + "github.com/samber/lo" + "github.com/kuadrant/authorino/pkg/auth" "github.com/kuadrant/authorino/pkg/log" @@ -105,18 +107,28 @@ func (a *APIKey) AddK8sSecretBasedIdentity(ctx context.Context, new k8s.Secret) logger := log.FromContext(ctx).WithName("apikey") - // Remove existing entries that match namespace/name, regardless of key value. - // This ensures old key values are removed. - for oldAPIKeyValue, current := range a.secrets { - if current.GetNamespace() == new.GetNamespace() && current.GetName() == new.GetName() { - delete(a.secrets, oldAPIKeyValue) - logger.V(1).Info("api key removed (replaced or updated)") + // Get all current keys in the map that match the new secret name and namespace + currentKeysSecret := lo.PickBy(a.secrets, func(key string, current k8s.Secret) bool { + return current.GetNamespace() == new.GetNamespace() && current.GetName() == new.GetName() + }) + + // get api keys from new secret + newAPIKeys := a.getValuesFromSecret(new) + + for _, newKey := range newAPIKeys { + a.secrets[newKey] = new + if _, ok := currentKeysSecret[newKey]; !ok { + logger.V(1).Info("api key added") + } else { + logger.V(1).Info("api key secret updated") } } - // Add the new secret. - if a.appendK8sSecretBasedIdentity(new) { - logger.V(1).Info("api key added") + // get difference between new and the old + staleKeys, _ := lo.Difference(lo.Keys(currentKeysSecret), newAPIKeys) + for _, newKey := range staleKeys { + delete(a.secrets, newKey) + logger.V(1).Info("stale api key deleted") } } @@ -132,7 +144,6 @@ func (a *APIKey) RevokeK8sSecretBasedIdentity(ctx context.Context, deleted k8s_t if secret.GetNamespace() == deleted.Namespace && secret.GetName() == deleted.Name { delete(a.secrets, key) log.FromContext(ctx).WithName("apikey").V(1).Info("api key deleted") - return } } } @@ -144,15 +155,25 @@ func (a *APIKey) withinScope(namespace string) bool { // Appends the K8s Secret to the cache of API keys // Caution! This function is not thread-safe. Make sure to acquire a lock before calling it. func (a *APIKey) appendK8sSecretBasedIdentity(secret k8s.Secret) bool { - appended := false + values := a.getValuesFromSecret(secret) + for _, value := range values { + a.secrets[value] = secret + } + + // Was appended if length is greater than zero + return len(values) != 0 +} + +// getValuesFromSecret extracts the values from the secret based on APIKey KeySelectors +func (a *APIKey) getValuesFromSecret(secret k8s.Secret) []string { + var keys []string for _, key := range a.KeySelectors { value, isAPIKeySecret := secret.Data[key] if isAPIKeySecret && len(value) > 0 { - a.secrets[string(value)] = secret - appended = true + keys = append(keys, string(value)) } } - return appended + return keys }