[ARVADOS] updated: 2.1.0-965-gfe92cee1d
Git user
git at public.arvados.org
Fri Jun 18 16:48:27 UTC 2021
Summary of changes:
services/keepproxy/keepproxy.go | 69 +++++++++++++++++++++---------------
services/keepproxy/keepproxy_test.go | 4 +--
2 files changed, 42 insertions(+), 31 deletions(-)
via fe92cee1dd48aca3ee1f2e9465eba4abb2c5b433 (commit)
from 10afc7ae2f95aad09937465702be7c44d07920d4 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
commit fe92cee1dd48aca3ee1f2e9465eba4abb2c5b433
Author: Peter Amstutz <peter.amstutz at curii.com>
Date: Fri Jun 18 12:35:38 2021 -0400
17464: Replace cache with LRU cache
Error out if API error from users.current
Arvados-DCO-1.1-Signed-off-by: Peter Amstutz <peter.amstutz at curii.com>
diff --git a/services/keepproxy/keepproxy.go b/services/keepproxy/keepproxy.go
index df6e06a74..04c95cfee 100644
--- a/services/keepproxy/keepproxy.go
+++ b/services/keepproxy/keepproxy.go
@@ -16,7 +16,6 @@ import (
"os/signal"
"regexp"
"strings"
- "sync"
"syscall"
"time"
@@ -29,6 +28,7 @@ import (
"github.com/coreos/go-systemd/daemon"
"github.com/ghodss/yaml"
"github.com/gorilla/mux"
+ lru "github.com/hashicorp/golang-lru"
log "github.com/sirupsen/logrus"
)
@@ -167,42 +167,45 @@ func run(logger log.FieldLogger, cluster *arvados.Cluster) error {
return http.Serve(listener, httpserver.AddRequestIDs(httpserver.LogRequests(router)))
}
+type TokenCacheEntry struct {
+ expire int64
+ user *arvados.User
+}
+
type APITokenCache struct {
- tokens map[string]int64
- tokenUser map[string]*arvados.User
- lock sync.Mutex
+ tokens *lru.TwoQueueCache
expireTime int64
}
-// RememberToken caches the token and set an expire time. If we already have
-// an expire time on the token, it is not updated.
+// RememberToken caches the token and set an expire time. If the
+// token is already in the cache, it is not updated.
func (cache *APITokenCache) RememberToken(token string, user *arvados.User) {
- cache.lock.Lock()
- defer cache.lock.Unlock()
-
now := time.Now().Unix()
- if cache.tokens[token] == 0 {
- cache.tokens[token] = now + cache.expireTime
+ _, ok := cache.tokens.Get(token)
+ if !ok {
+ cache.tokens.Add(token, TokenCacheEntry{
+ expire: now + cache.expireTime,
+ user: user,
+ })
}
- cache.tokenUser[token] = user
}
// RecallToken checks if the cached token is known and still believed to be
// valid.
func (cache *APITokenCache) RecallToken(token string) (bool, *arvados.User) {
- cache.lock.Lock()
- defer cache.lock.Unlock()
+ val, ok := cache.tokens.Get(token)
+ if !ok {
+ return false, nil
+ }
+ cacheEntry := val.(TokenCacheEntry)
now := time.Now().Unix()
- if cache.tokens[token] == 0 {
- // Unknown token
- return false, nil
- } else if now < cache.tokens[token] {
+ if now < cacheEntry.expire {
// Token is known and still valid
- return true, cache.tokenUser[token]
+ return true, cacheEntry.user
} else {
// Token is expired
- cache.tokens[token] = 0
+ cache.tokens.Remove(token)
return false, nil
}
}
@@ -247,13 +250,17 @@ func (h *proxyHandler) CheckAuthorizationHeader(req *http.Request) (pass bool, t
arv.RequestID = req.Header.Get("X-Request-Id")
user = &arvados.User{}
userCurrentError := arv.Call("GET", "users", "", "current", nil, user)
- if op == "read" {
- // scoped token this will fail the user current check,
- // but if it is a download operation and they can read
- // the keep_services table, it's okay.
- err = arv.Call("HEAD", "keep_services", "", "accessible", nil, nil)
- } else {
- err = userCurrentError
+ err = userCurrentError
+ if err != nil && op == "read" {
+ apiError, ok := err.(arvadosclient.APIServerError)
+ if ok && apiError.HttpStatusCode == http.StatusForbidden {
+ // If it was a scoped "sharing" token it will
+ // return 403 instead of 401 for the current
+ // user check. If it is a download operation
+ // and they have permission to read the
+ // keep_services table, we can allow it.
+ err = arv.Call("HEAD", "keep_services", "", "accessible", nil, nil)
+ }
}
if err != nil {
log.Printf("%s: CheckAuthorizationHeader error: %v", GetRemoteAddress(req), err)
@@ -316,14 +323,18 @@ func MakeRESTRouter(kc *keepclient.KeepClient, timeout time.Duration, cluster *a
transport.TLSClientConfig = arvadosclient.MakeTLSConfig(kc.Arvados.ApiInsecure)
transport.TLSHandshakeTimeout = keepclient.DefaultTLSHandshakeTimeout
+ cacheQ, err := lru.New2Q(500)
+ if err != nil {
+ panic("Could not create 2Q")
+ }
+
h := &proxyHandler{
Handler: rest,
KeepClient: kc,
timeout: timeout,
transport: &transport,
APITokenCache: &APITokenCache{
- tokens: make(map[string]int64),
- tokenUser: make(map[string]*arvados.User),
+ tokens: cacheQ,
expireTime: 300,
},
logger: logger,
diff --git a/services/keepproxy/keepproxy_test.go b/services/keepproxy/keepproxy_test.go
index c5d94f9ac..67018f93c 100644
--- a/services/keepproxy/keepproxy_test.go
+++ b/services/keepproxy/keepproxy_test.go
@@ -418,12 +418,12 @@ func (s *ServerRequiredSuite) TestPutAskGetForbidden(c *C) {
blocklen, _, err := kc.Ask(hash)
c.Check(err, FitsTypeOf, &keepclient.ErrNotFound{})
- c.Check(err, ErrorMatches, ".*not found.*")
+ c.Check(err, ErrorMatches, ".*HTTP 403.*")
c.Check(blocklen, Equals, int64(0))
_, blocklen, _, err = kc.Get(hash)
c.Check(err, FitsTypeOf, &keepclient.ErrNotFound{})
- c.Check(err, ErrorMatches, ".*not found.*")
+ c.Check(err, ErrorMatches, ".*HTTP 403.*")
c.Check(blocklen, Equals, int64(0))
}
-----------------------------------------------------------------------
hooks/post-receive
--
More information about the arvados-commits
mailing list