X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/8c283c6262809df6f9db1aa176a1a8a5e95a717b..8858d25844dc2591e7465466de540c8a62ee4945:/lib/controller/localdb/container_gateway.go diff --git a/lib/controller/localdb/container_gateway.go b/lib/controller/localdb/container_gateway.go index f255bff842..3b40eccaff 100644 --- a/lib/controller/localdb/container_gateway.go +++ b/lib/controller/localdb/container_gateway.go @@ -38,29 +38,40 @@ func (conn *Conn) ContainerSSH(ctx context.Context, opts arvados.ContainerSSHOpt if err != nil { return } - ctxRoot := auth.NewContext(ctx, &auth.Credentials{Tokens: []string{conn.cluster.SystemRootToken}}) - crs, err := conn.railsProxy.ContainerRequestList(ctxRoot, arvados.ListOptions{Limit: -1, Filters: []arvados.Filter{{"container_uuid", "=", opts.UUID}}}) - if err != nil { - return - } - for _, cr := range crs.Items { - if cr.ModifiedByUserUUID != user.UUID { - err = httpserver.ErrorWithStatus(errors.New("permission denied: container is associated with requests submitted by other users"), http.StatusForbidden) + if !user.IsAdmin || !conn.cluster.Containers.ShellAccess.Admin { + if !conn.cluster.Containers.ShellAccess.User { + err = httpserver.ErrorWithStatus(errors.New("shell access is disabled in config"), http.StatusServiceUnavailable) + return + } + var crs arvados.ContainerRequestList + crs, err = conn.railsProxy.ContainerRequestList(ctxRoot, arvados.ListOptions{Limit: -1, Filters: []arvados.Filter{{"container_uuid", "=", opts.UUID}}}) + if err != nil { + return + } + for _, cr := range crs.Items { + if cr.ModifiedByUserUUID != user.UUID { + err = httpserver.ErrorWithStatus(errors.New("permission denied: container is associated with requests submitted by other users"), http.StatusForbidden) + return + } + } + if crs.ItemsAvailable != len(crs.Items) { + err = httpserver.ErrorWithStatus(errors.New("incomplete response while checking permission"), http.StatusInternalServerError) return } - } - if crs.ItemsAvailable != len(crs.Items) { - err = httpserver.ErrorWithStatus(errors.New("incomplete response while checking permission"), http.StatusInternalServerError) - return } - ctr, err := conn.railsProxy.ContainerGet(ctx, arvados.GetOptions{UUID: opts.UUID}) - if err != nil { + switch ctr.State { + case arvados.ContainerStateQueued, arvados.ContainerStateLocked: + err = httpserver.ErrorWithStatus(fmt.Errorf("container is not running yet (state is %q)", ctr.State), http.StatusServiceUnavailable) return - } - if ctr.GatewayAddress == "" || ctr.State != arvados.ContainerStateRunning { - err = httpserver.ErrorWithStatus(fmt.Errorf("gateway is not available, container is %s", strings.ToLower(string(ctr.State))), http.StatusBadGateway) + case arvados.ContainerStateRunning: + if ctr.GatewayAddress == "" { + err = httpserver.ErrorWithStatus(errors.New("container is running but gateway is not available -- installation problem or feature not supported"), http.StatusServiceUnavailable) + return + } + default: + err = httpserver.ErrorWithStatus(fmt.Errorf("container has ended (state is %q)", ctr.State), http.StatusGone) return } // crunch-run uses a self-signed / unverifiable TLS @@ -101,6 +112,7 @@ func (conn *Conn) ContainerSSH(ctx context.Context, opts arvados.ContainerSSHOpt }, }) if err != nil { + err = httpserver.ErrorWithStatus(err, http.StatusBadGateway) return } if respondAuth == "" { @@ -141,6 +153,20 @@ func (conn *Conn) ContainerSSH(ctx context.Context, opts arvados.ContainerSSHOpt netconn.Close() return } + + if !ctr.InteractiveSessionStarted { + _, err = conn.railsProxy.ContainerUpdate(ctxRoot, arvados.UpdateOptions{ + UUID: opts.UUID, + Attrs: map[string]interface{}{ + "interactive_session_started": true, + }, + }) + if err != nil { + netconn.Close() + return + } + } + sshconn.Conn = netconn sshconn.Bufrw = &bufio.ReadWriter{Reader: bufr, Writer: bufw} sshconn.Logger = ctxlog.FromContext(ctx)