16669: Fix pass-through of cached remote token.
authorTom Clegg <tom@tomclegg.ca>
Wed, 23 Sep 2020 21:37:34 +0000 (17:37 -0400)
committerTom Clegg <tom@tomclegg.ca>
Wed, 21 Oct 2020 13:04:25 +0000 (09:04 -0400)
Arvados-DCO-1.1-Signed-off-by: Tom Clegg <tom@tomclegg.ca>

lib/controller/federation.go
lib/controller/federation/conn.go
lib/controller/localdb/login_oidc.go
services/api/app/models/api_client_authorization.rb

index aceaba8087ad2031413516c2671f75174c457fae..cab5e4c4ca45172edb28f07210b001456f1e11af 100644 (file)
@@ -263,17 +263,20 @@ func (h *Handler) saltAuthToken(req *http.Request, remote string) (updatedReq *h
                return updatedReq, nil
        }
 
+       ctxlog.FromContext(req.Context()).Infof("saltAuthToken: cluster %s token %s remote %s", h.Cluster.ClusterID, creds.Tokens[0], remote)
        token, err := auth.SaltToken(creds.Tokens[0], remote)
 
        if err == auth.ErrObsoleteToken {
-               // If the token exists in our own database, salt it
-               // for the remote. Otherwise, assume it was issued by
-               // the remote, and pass it through unmodified.
+               // If the token exists in our own database for our own
+               // user, salt it for the remote. Otherwise, assume it
+               // was issued by the remote, and pass it through
+               // unmodified.
                currentUser, ok, err := h.validateAPItoken(req, creds.Tokens[0])
                if err != nil {
                        return nil, err
-               } else if !ok {
-                       // Not ours; pass through unmodified.
+               } else if !ok || strings.HasPrefix(currentUser.UUID, remote) {
+                       // Unknown, or cached + belongs to remote;
+                       // pass through unmodified.
                        token = creds.Tokens[0]
                } else {
                        // Found; make V2 version and salt it.
index f07c3b63167d577f722b085ff56de252a73f251f..986faa7b05e33e325a6bc1c15b4283ec6d79d9ed 100644 (file)
@@ -79,6 +79,14 @@ func saltedTokenProvider(local backend, remoteID string) rpc.TokenProvider {
                                } else if err != nil {
                                        return nil, err
                                }
+                               if strings.HasPrefix(aca.UUID, remoteID) {
+                                       // We have it cached here, but
+                                       // the token belongs to the
+                                       // remote target itself, so
+                                       // pass it through unmodified.
+                                       tokens = append(tokens, token)
+                                       continue
+                               }
                                salted, err := auth.SaltToken(aca.TokenV2(), remoteID)
                                if err != nil {
                                        return nil, err
index 8909e0a72ea157028a80915eb51cdfe9ae4dc82b..2da7ca5ccf98e14a6c2cb32d4602ecb81eb68101 100644 (file)
@@ -380,7 +380,7 @@ func (ta *oidcTokenAuthorizer) WrapCalls(origFunc api.RoutableFunc) api.Routable
 // if so, ensures that an api_client_authorizations row exists so that
 // RailsAPI will accept it as an Arvados token.
 func (ta *oidcTokenAuthorizer) registerToken(ctx context.Context, tok string) error {
-       if strings.HasPrefix(tok, "v2/") {
+       if tok == ta.ctrl.Cluster.SystemRootToken || strings.HasPrefix(tok, "v2/") {
                return nil
        }
        if cached, hit := ta.cache.Get(tok); !hit {
index 6a34ed95522f419f88303cc5de3190e833f2d99e..74a4c1efa571b5229825243c98034957e99d4e45 100644 (file)
@@ -206,7 +206,7 @@ class ApiClientAuthorization < ArvadosModel
         # below. If so, we'll stuff the database with hmac instead of
         # the real OIDC token.
         upstream_cluster_id = Rails.configuration.Login.LoginCluster
-        token_uuid = generate_uuid
+        token_uuid = upstream_cluster_id + generate_uuid[5..27]
         secret = hmac
       else
         return nil