16133: Don't take multiple hops when getting collections.
[arvados.git] / lib / controller / federation / conn.go
index 174ece134ff95cc5eeb78fa8153eaaad917929c0..2aebc0e9707496807f96fa809fc24e111e5950e2 100644 (file)
@@ -38,7 +38,11 @@ func New(cluster *arvados.Cluster) *Conn {
                if !remote.Proxy {
                        continue
                }
-               remotes[id] = rpc.NewConn(id, &url.URL{Scheme: remote.Scheme, Host: remote.Host}, remote.Insecure, saltedTokenProvider(local, id))
+               conn := rpc.NewConn(id, &url.URL{Scheme: remote.Scheme, Host: remote.Host}, remote.Insecure, saltedTokenProvider(local, id))
+               // Older versions of controller rely on the Via header
+               // to detect loops.
+               conn.SendHeader = http.Header{"Via": {"HTTP/1.1 arvados-controller"}}
+               remotes[id] = conn
        }
 
        return &Conn{
@@ -214,6 +218,8 @@ func (conn *Conn) Login(ctx context.Context, options arvados.LoginOptions) (arva
 }
 
 func (conn *Conn) CollectionGet(ctx context.Context, options arvados.GetOptions) (arvados.Collection, error) {
+       downstream := options.ForwardedFor
+       options.ForwardedFor = conn.cluster.ClusterID + "-" + downstream
        if len(options.UUID) == 27 {
                // UUID is really a UUID
                c, err := conn.chooseBackend(options.UUID).CollectionGet(ctx, options)
@@ -225,6 +231,15 @@ func (conn *Conn) CollectionGet(ctx context.Context, options arvados.GetOptions)
                // UUID is a PDH
                first := make(chan arvados.Collection, 1)
                err := conn.tryLocalThenRemotes(ctx, func(ctx context.Context, remoteID string, be backend) error {
+                       if remoteID != "" && downstream != "" {
+                               // If remoteID isn't in downstream, we
+                               // might find the collection by taking
+                               // another hop, but we don't bother:
+                               // token salting and blob signature
+                               // rewriting don't work over multiple
+                               // hops.
+                               return notFoundError{}
+                       }
                        c, err := be.CollectionGet(ctx, options)
                        if err != nil {
                                return err
@@ -340,11 +355,13 @@ var userAttrsCachedFromLoginCluster = map[string]bool{
        "prefs":                   true,
        "username":                true,
 
+       "etag":         false,
        "full_name":    false,
        "identity_url": false,
        "is_invited":   false,
        "owner_uuid":   false,
        "uuid":         false,
+       "writable_by":  false,
 }
 
 func (conn *Conn) UserList(ctx context.Context, options arvados.ListOptions) (arvados.UserList, error) {