X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/a78762353971ea3707bcf92960a12557d66fb9af..09cbdc3074b3f1e69c9c537875146f6da0a6ed8f:/lib/controller/federation/conn.go diff --git a/lib/controller/federation/conn.go b/lib/controller/federation/conn.go index d1bf473d76..03690af026 100644 --- a/lib/controller/federation/conn.go +++ b/lib/controller/federation/conn.go @@ -69,14 +69,17 @@ func saltedTokenProvider(cluster *arvados.Cluster, local backend, remoteID strin return nil, errors.New("no token provided") } for _, token := range incoming.Tokens { - if strings.HasPrefix(token, "v2/"+cluster.ClusterID+"-") && remoteID == cluster.Login.LoginCluster { - // If we did this, the login cluster - // would call back to us and then - // reject our response because the - // user UUID prefix (i.e., the - // LoginCluster prefix) won't match - // the token UUID prefix (i.e., our - // prefix). + if strings.HasPrefix(token, "v2/"+cluster.ClusterID+"-") && + !strings.HasPrefix(token, "v2/"+cluster.ClusterID+"-gj3su-anonymouspublic/") && + remoteID == cluster.Login.LoginCluster { + // If we did this, the login cluster would call back to us and then + // reject our response because the user UUID prefix (i.e., the + // LoginCluster prefix) won't match the token UUID prefix (i.e., our + // prefix). The anonymous token is OK to forward, because (unlike other + // local tokens for real users) the validation callback will return the + // locally issued anonymous user ID instead of a login-cluster user ID. + // That anonymous user ID gets mapped to the local anonymous user + // automatically on the login cluster. return nil, httpErrorf(http.StatusUnauthorized, "cannot use a locally issued token to forward a request to our login cluster (%s)", remoteID) } salted, err := auth.SaltToken(token, remoteID) @@ -273,6 +276,9 @@ func (conn *Conn) CollectionGet(ctx context.Context, options arvados.GetOptions) } return c, err } + if len(options.UUID) < 34 || options.UUID[32] != '+' { + return arvados.Collection{}, httpErrorf(http.StatusNotFound, "invalid UUID or PDH %q", options.UUID) + } // UUID is a PDH first := make(chan arvados.Collection, 1) err := conn.tryLocalThenRemotes(ctx, options.ForwardedFor, func(ctx context.Context, remoteID string, be backend) error { @@ -372,10 +378,14 @@ func (conn *Conn) ContainerUnlock(ctx context.Context, options arvados.GetOption return conn.chooseBackend(options.UUID).ContainerUnlock(ctx, options) } -func (conn *Conn) ContainerSSH(ctx context.Context, options arvados.ContainerSSHOptions) (arvados.ContainerSSHConnection, error) { +func (conn *Conn) ContainerSSH(ctx context.Context, options arvados.ContainerSSHOptions) (arvados.ConnectionResponse, error) { return conn.chooseBackend(options.UUID).ContainerSSH(ctx, options) } +func (conn *Conn) ContainerGatewayTunnel(ctx context.Context, options arvados.ContainerGatewayTunnelOptions) (arvados.ConnectionResponse, error) { + return conn.chooseBackend(options.UUID).ContainerGatewayTunnel(ctx, options) +} + func (conn *Conn) ContainerRequestList(ctx context.Context, options arvados.ListOptions) (arvados.ContainerRequestList, error) { return conn.generated_ContainerRequestList(ctx, options) } @@ -505,6 +515,26 @@ func (conn *Conn) LinkDelete(ctx context.Context, options arvados.DeleteOptions) return conn.chooseBackend(options.UUID).LinkDelete(ctx, options) } +func (conn *Conn) LogCreate(ctx context.Context, options arvados.CreateOptions) (arvados.Log, error) { + return conn.chooseBackend(options.ClusterID).LogCreate(ctx, options) +} + +func (conn *Conn) LogUpdate(ctx context.Context, options arvados.UpdateOptions) (arvados.Log, error) { + return conn.chooseBackend(options.UUID).LogUpdate(ctx, options) +} + +func (conn *Conn) LogGet(ctx context.Context, options arvados.GetOptions) (arvados.Log, error) { + return conn.chooseBackend(options.UUID).LogGet(ctx, options) +} + +func (conn *Conn) LogList(ctx context.Context, options arvados.ListOptions) (arvados.LogList, error) { + return conn.generated_LogList(ctx, options) +} + +func (conn *Conn) LogDelete(ctx context.Context, options arvados.DeleteOptions) (arvados.Log, error) { + return conn.chooseBackend(options.UUID).LogDelete(ctx, options) +} + func (conn *Conn) SpecimenList(ctx context.Context, options arvados.ListOptions) (arvados.SpecimenList, error) { return conn.generated_SpecimenList(ctx, options) } @@ -525,6 +555,10 @@ func (conn *Conn) SpecimenDelete(ctx context.Context, options arvados.DeleteOpti return conn.chooseBackend(options.UUID).SpecimenDelete(ctx, options) } +func (conn *Conn) SysTrashSweep(ctx context.Context, options struct{}) (struct{}, error) { + return conn.local.SysTrashSweep(ctx, options) +} + var userAttrsCachedFromLoginCluster = map[string]bool{ "created_at": true, "email": true, @@ -546,6 +580,8 @@ var userAttrsCachedFromLoginCluster = map[string]bool{ "owner_uuid": false, "uuid": false, "writable_by": false, + "can_write": false, + "can_manage": false, } func (conn *Conn) batchUpdateUsers(ctx context.Context, @@ -725,6 +761,39 @@ func (conn *Conn) APIClientAuthorizationCurrent(ctx context.Context, options arv return conn.chooseBackend(options.UUID).APIClientAuthorizationCurrent(ctx, options) } +func (conn *Conn) APIClientAuthorizationCreate(ctx context.Context, options arvados.CreateOptions) (arvados.APIClientAuthorization, error) { + if conn.cluster.Login.LoginCluster != "" { + return conn.chooseBackend(conn.cluster.Login.LoginCluster).APIClientAuthorizationCreate(ctx, options) + } + ownerUUID, ok := options.Attrs["owner_uuid"].(string) + if ok && ownerUUID != "" { + return conn.chooseBackend(ownerUUID).APIClientAuthorizationCreate(ctx, options) + } + return conn.local.APIClientAuthorizationCreate(ctx, options) +} + +func (conn *Conn) APIClientAuthorizationUpdate(ctx context.Context, options arvados.UpdateOptions) (arvados.APIClientAuthorization, error) { + if options.BypassFederation { + return conn.local.APIClientAuthorizationUpdate(ctx, options) + } + return conn.chooseBackend(options.UUID).APIClientAuthorizationUpdate(ctx, options) +} + +func (conn *Conn) APIClientAuthorizationDelete(ctx context.Context, options arvados.DeleteOptions) (arvados.APIClientAuthorization, error) { + return conn.chooseBackend(options.UUID).APIClientAuthorizationDelete(ctx, options) +} + +func (conn *Conn) APIClientAuthorizationList(ctx context.Context, options arvados.ListOptions) (arvados.APIClientAuthorizationList, error) { + if id := conn.cluster.Login.LoginCluster; id != "" && id != conn.cluster.ClusterID && !options.BypassFederation { + return conn.chooseBackend(conn.cluster.Login.LoginCluster).APIClientAuthorizationList(ctx, options) + } + return conn.generated_APIClientAuthorizationList(ctx, options) +} + +func (conn *Conn) APIClientAuthorizationGet(ctx context.Context, options arvados.GetOptions) (arvados.APIClientAuthorization, error) { + return conn.chooseBackend(options.UUID).APIClientAuthorizationGet(ctx, options) +} + type backend interface { arvados.API BaseURL() url.URL