15954: Merge branch 'master'
authorTom Clegg <tom@tomclegg.ca>
Thu, 27 Feb 2020 14:25:20 +0000 (09:25 -0500)
committerTom Clegg <tom@tomclegg.ca>
Thu, 27 Feb 2020 14:25:20 +0000 (09:25 -0500)
Arvados-DCO-1.1-Signed-off-by: Tom Clegg <tom@tomclegg.ca>

1  2 
lib/controller/federation/conn.go

index 3909b6cdd5ab5cad8e8e7b2024606811baf248ca,56f117ee781682aeb09119b448494f263d34046f..279b7a51d5d8d4e57f920721db10ace45268b1d2
@@@ -7,6 -7,7 +7,6 @@@ package federatio
  import (
        "bytes"
        "context"
 -      "crypto/md5"
        "encoding/json"
        "errors"
        "fmt"
@@@ -34,7 -35,7 +34,7 @@@ func New(cluster *arvados.Cluster) *Con
        local := localdb.NewConn(cluster)
        remotes := map[string]backend{}
        for id, remote := range cluster.RemoteClusters {
 -              if !remote.Proxy {
 +              if !remote.Proxy || id == cluster.ClusterID {
                        continue
                }
                conn := rpc.NewConn(id, &url.URL{Scheme: remote.Scheme, Host: remote.Host}, remote.Insecure, saltedTokenProvider(local, id))
@@@ -168,6 -169,26 +168,6 @@@ func rewriteManifest(mt, remoteID strin
        })
  }
  
 -// this could be in sdk/go/arvados
 -func portableDataHash(mt string) string {
 -      h := md5.New()
 -      blkRe := regexp.MustCompile(`^ [0-9a-f]{32}\+\d+`)
 -      size := 0
 -      _ = regexp.MustCompile(` ?[^ ]*`).ReplaceAllFunc([]byte(mt), func(tok []byte) []byte {
 -              if m := blkRe.Find(tok); m != nil {
 -                      // write hash+size, ignore remaining block hints
 -                      tok = m
 -              }
 -              n, err := h.Write(tok)
 -              if err != nil {
 -                      panic(err)
 -              }
 -              size += n
 -              return nil
 -      })
 -      return fmt.Sprintf("%x+%d", h.Sum(nil), size)
 -}
 -
  func (conn *Conn) ConfigGet(ctx context.Context) (json.RawMessage, error) {
        var buf bytes.Buffer
        err := config.ExportJSON(&buf, conn.cluster)
@@@ -201,6 -222,32 +201,32 @@@ func (conn *Conn) Login(ctx context.Con
        }
  }
  
+ func (conn *Conn) Logout(ctx context.Context, options arvados.LogoutOptions) (arvados.LogoutResponse, error) {
+       // If the logout request comes with an API token from a known
+       // remote cluster, redirect to that cluster's logout handler
+       // so it has an opportunity to clear sessions, expire tokens,
+       // etc. Otherwise use the local endpoint.
+       reqauth, ok := auth.FromContext(ctx)
+       if !ok || len(reqauth.Tokens) == 0 || len(reqauth.Tokens[0]) < 8 || !strings.HasPrefix(reqauth.Tokens[0], "v2/") {
+               return conn.local.Logout(ctx, options)
+       }
+       id := reqauth.Tokens[0][3:8]
+       if id == conn.cluster.ClusterID {
+               return conn.local.Logout(ctx, options)
+       }
+       remote, ok := conn.remotes[id]
+       if !ok {
+               return conn.local.Logout(ctx, options)
+       }
+       baseURL := remote.BaseURL()
+       target, err := baseURL.Parse(arvados.EndpointLogout.Path)
+       if err != nil {
+               return arvados.LogoutResponse{}, fmt.Errorf("internal error getting redirect target: %s", err)
+       }
+       target.RawQuery = url.Values{"return_to": {options.ReturnTo}}.Encode()
+       return arvados.LogoutResponse{RedirectLocation: target.String()}, nil
+ }
  func (conn *Conn) CollectionGet(ctx context.Context, options arvados.GetOptions) (arvados.Collection, error) {
        if len(options.UUID) == 27 {
                // UUID is really a UUID
                        // options.UUID is either hash+size or
                        // hash+size+hints; only hash+size need to
                        // match the computed PDH.
 -                      if pdh := portableDataHash(c.ManifestText); pdh != options.UUID && !strings.HasPrefix(options.UUID, pdh+"+") {
 +                      if pdh := arvados.PortableDataHash(c.ManifestText); pdh != options.UUID && !strings.HasPrefix(options.UUID, pdh+"+") {
                                err = httpErrorf(http.StatusBadGateway, "bad portable data hash %q received from remote %q (expected %q)", pdh, remoteID, options.UUID)
                                ctxlog.FromContext(ctx).Warn(err)
                                return err