From bae0d77cb28c65f819aa0aeb30415c4baf743dc2 Mon Sep 17 00:00:00 2001 From: "Han Verstraete (OpenFaaS Ltd)" Date: Tue, 4 Jun 2024 10:27:02 +0200 Subject: [PATCH 1/2] Use cancellable context in token cache example Signed-off-by: Han Verstraete (OpenFaaS Ltd) --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 6f30a58..3f2ce3b 100644 --- a/README.md +++ b/README.md @@ -199,9 +199,12 @@ client := sdk.NewClientWithOpts(gatewayURL, http.DefaultClient, sdk.WithFunction Optionally a `TokenCache` can be configured to cache function access tokens and prevent the client from having to do a token exchange each time a function is invoked. ```go +ctx, cancel := context.WithCancel(context.Background()) +defer cancel() + fnTokenCache := sdk.NewMemoryTokenCache() // Start garbage collection to remove expired tokens from the cache. -go fnTokenCache.StartGC(context.Background(), time.Second*10) +go fnTokenCache.StartGC(ctx, time.Second*10) client := sdk.NewClientWithOpts( gatewayUrl, From 25544af389bb059c3d0b0b8106a9757d07b4c309 Mon Sep 17 00:00:00 2001 From: "Han Verstraete (OpenFaaS Ltd)" Date: Wed, 5 Jun 2024 10:39:50 +0200 Subject: [PATCH 2/2] Use function name as cache key for function access tokens Remove the source token from the cache key. By using the source token as part of the cache key the cache would be invalidated when the original access token had expired which is confusing for users and leads to higher load on the token exchange endpoint if short lived tokens are used. Signed-off-by: Han Verstraete (OpenFaaS Ltd) --- functions.go | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/functions.go b/functions.go index f59ee32..ae14c9e 100644 --- a/functions.go +++ b/functions.go @@ -1,7 +1,6 @@ package sdk import ( - "crypto/sha256" "fmt" "net/http" ) @@ -36,8 +35,7 @@ func (c *Client) InvokeFunction(name, namespace string, async bool, auth bool, r if c.fnTokenCache != nil { // Function access tokens are cached as long as the token is valid // to prevent having to do a token exchange each time the function is invoked. - cacheKey := getFunctionTokenCacheKey(idToken, fmt.Sprintf("%s.%s", name, namespace)) - + cacheKey := fmt.Sprintf("%s.%s", name, namespace) token, ok := c.fnTokenCache.Get(cacheKey) if !ok { token, err = ExchangeIDToken(tokenURL, idToken, WithScope(scope), WithAudience(audience)) @@ -63,17 +61,3 @@ func (c *Client) InvokeFunction(name, namespace string, async bool, auth bool, r return c.do(req) } - -// getFunctionTokenCacheKey computes a cache key for caching a function access token based -// on the original id token that is exchanged for the function access token and the function -// name e.g. figlet.openfaas-fn. -// The original token is included in the hash to avoid cache hits for a function when the -// source token changes. -func getFunctionTokenCacheKey(idToken string, serviceName string) string { - hash := sha256.New() - hash.Write([]byte(idToken)) - hash.Write([]byte(serviceName)) - - sum := hash.Sum(nil) - return fmt.Sprintf("%x", sum) -}