Keepproxy use client-supplied token when forwarding GET and PUT requests.
authorPeter Amstutz <peter.amstutz@curoverse.com>
Tue, 8 Jul 2014 13:18:07 +0000 (09:18 -0400)
committerPeter Amstutz <peter.amstutz@curoverse.com>
Tue, 8 Jul 2014 13:18:07 +0000 (09:18 -0400)
services/keep/src/arvados.org/keepproxy/keepproxy.go

index e3a2ce91945f511b10cfa697c0dd5f07c9ea409d..367854bed382ec1b17589c825126d5e31a9bf6a6 100644 (file)
@@ -193,35 +193,34 @@ func GetRemoteAddress(req *http.Request) string {
        return req.RemoteAddr
 }
 
-func CheckAuthorizationHeader(kc keepclient.KeepClient, cache *ApiTokenCache, req *http.Request) bool {
+func CheckAuthorizationHeader(kc keepclient.KeepClient, cache *ApiTokenCache, req *http.Request) (pass bool, tok string) {
        var auth string
        if auth = req.Header.Get("Authorization"); auth == "" {
-               return false
+               return false, ""
        }
 
-       var tok string
        _, err := fmt.Sscanf(auth, "OAuth2 %s", &tok)
        if err != nil {
                // Scanning error
-               return false
+               return false, ""
        }
 
        if cache.RecallToken(tok) {
                // Valid in the cache, short circut
-               return true
+               return true, tok
        }
 
        arv := *kc.Arvados
        arv.ApiToken = tok
        if err := arv.Call("HEAD", "users", "", "current", nil, nil); err != nil {
                log.Printf("%s: CheckAuthorizationHeader error: %v", GetRemoteAddress(req), err)
-               return false
+               return false, ""
        }
 
        // Success!  Update cache
        cache.RememberToken(tok)
 
-       return true
+       return true, tok
 }
 
 type GetBlockHandler struct {
@@ -281,11 +280,18 @@ func (this GetBlockHandler) ServeHTTP(resp http.ResponseWriter, req *http.Reques
 
        log.Printf("%s: %s %s", GetRemoteAddress(req), req.Method, hash)
 
-       if !CheckAuthorizationHeader(kc, this.ApiTokenCache, req) {
+       var pass bool
+       var tok string
+       if pass, tok = CheckAuthorizationHeader(kc, this.ApiTokenCache, req); !pass {
                http.Error(resp, "Missing or invalid Authorization header", http.StatusForbidden)
                return
        }
 
+       // Copy ArvadosClient struct and use the client's API token
+       arvclient := *kc.Arvados
+       arvclient.ApiToken = tok
+       kc.Arvados = &arvclient
+
        var reader io.ReadCloser
        var err error
        var blocklen int64
@@ -356,11 +362,18 @@ func (this PutBlockHandler) ServeHTTP(resp http.ResponseWriter, req *http.Reques
                return
        }
 
-       if !CheckAuthorizationHeader(kc, this.ApiTokenCache, req) {
+       var pass bool
+       var tok string
+       if pass, tok = CheckAuthorizationHeader(kc, this.ApiTokenCache, req); !pass {
                http.Error(resp, "Missing or invalid Authorization header", http.StatusForbidden)
                return
        }
 
+       // Copy ArvadosClient struct and use the client's API token
+       arvclient := *kc.Arvados
+       arvclient.ApiToken = tok
+       kc.Arvados = &arvclient
+
        // Check if the client specified the number of replicas
        if req.Header.Get("X-Keep-Desired-Replicas") != "" {
                var r int