Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 9 additions & 53 deletions lib/client/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ import (
"github.com/gravitational/teleport/lib/shell"
alpncommon "github.com/gravitational/teleport/lib/srv/alpnproxy/common"
"github.com/gravitational/teleport/lib/sshutils"
"github.com/gravitational/teleport/lib/sshutils/scp"
"github.com/gravitational/teleport/lib/sshutils/sftp"
"github.com/gravitational/teleport/lib/tlsca"
"github.com/gravitational/teleport/lib/utils"
Expand Down Expand Up @@ -1854,53 +1853,6 @@ func PlayFile(ctx context.Context, tarFile io.Reader, sid string) error {
return playSession(sessionEvents, stream)
}

// ExecuteSCP executes SCP command. It executes scp.Command using
// lower-level API integrations that mimic SCP CLI command behavior
func (tc *TeleportClient) ExecuteSCP(ctx context.Context, serverAddr string, cmd scp.Command) error {
ctx, span := tc.Tracer.Start(
ctx,
"teleportClient/ExecuteSCP",
oteltrace.WithSpanKind(oteltrace.SpanKindClient),
)
defer span.End()

// connect to proxy first:
if !tc.Config.ProxySpecified() {
return trace.BadParameter("proxy server is not specified")
}

proxyClient, err := tc.ConnectToProxy(ctx)
if err != nil {
return trace.Wrap(err)
}
defer proxyClient.Close()

nodeClient, err := tc.ConnectToNode(
ctx,
proxyClient,
// We append the ":0" to tell the server to figure out the port for us.
NodeDetails{Addr: serverAddr + ":0", Namespace: tc.Namespace, Cluster: tc.SiteName},
tc.Config.HostLogin,
)
if err != nil {
tc.ExitStatus = 1
return trace.Wrap(err)
}

err = nodeClient.ExecuteSCP(ctx, cmd)
if err != nil {
// converts SSH error code to tc.ExitStatus
exitError, _ := trace.Unwrap(err).(*ssh.ExitError)
if exitError != nil {
tc.ExitStatus = exitError.ExitStatus()
}
return err

}

return nil
}

// SFTP securely copies files between Nodes or SSH servers using SFTP
func (tc *TeleportClient) SFTP(ctx context.Context, args []string, port int, opts sftp.Options, quiet bool) (err error) {
ctx, span := tc.Tracer.Start(
Expand Down Expand Up @@ -1958,7 +1910,7 @@ func (tc *TeleportClient) uploadConfig(args []string, port int, opts sftp.Option
// copy everything except the last arg (the destination)
dstPath := args[len(args)-1]

dst, addr, err := getSCPDestination(dstPath, port)
dst, addr, err := getSFTPDestination(dstPath, port)
if err != nil {
return nil, trace.Wrap(err)
}
Expand All @@ -1980,7 +1932,7 @@ func (tc *TeleportClient) downloadConfig(args []string, port int, opts sftp.Opti
}

// args are guaranteed to have len(args) > 1
src, addr, err := getSCPDestination(args[0], port)
src, addr, err := getSFTPDestination(args[0], port)
if err != nil {
return nil, trace.Wrap(err)
}
Expand All @@ -1996,8 +1948,8 @@ func (tc *TeleportClient) downloadConfig(args []string, port int, opts sftp.Opti
}, nil
}

func getSCPDestination(target string, port int) (dest *scp.Destination, addr string, err error) {
dest, err = scp.ParseSCPDestination(target)
func getSFTPDestination(target string, port int) (dest *sftp.Destination, addr string, err error) {
dest, err = sftp.ParseDestination(target)
if err != nil {
return nil, "", trace.Wrap(err)
}
Expand Down Expand Up @@ -2034,7 +1986,11 @@ func (tc *TeleportClient) TransferFiles(ctx context.Context, hostLogin, nodeAddr
client, err := tc.ConnectToNode(
ctx,
proxyClient,
NodeDetails{Addr: nodeAddr, Namespace: tc.Namespace, Cluster: tc.SiteName},
NodeDetails{
Addr: nodeAddr,
Namespace: tc.Namespace,
Cluster: tc.SiteName,
},
hostLogin,
)
if err != nil {
Expand Down
94 changes: 0 additions & 94 deletions lib/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,9 @@ import (
"context"
"crypto/tls"
"encoding/json"
"errors"
"fmt"
"io"
"net"
"os"
"strconv"
"strings"
"time"
Expand All @@ -52,7 +50,6 @@ import (
"github.com/gravitational/teleport/lib/defaults"
"github.com/gravitational/teleport/lib/events"
"github.com/gravitational/teleport/lib/sshutils"
"github.com/gravitational/teleport/lib/sshutils/scp"
"github.com/gravitational/teleport/lib/sshutils/sftp"
"github.com/gravitational/teleport/lib/utils"
"github.com/gravitational/teleport/lib/utils/socks"
Expand Down Expand Up @@ -1711,97 +1708,6 @@ func (proxy *ProxyClient) Close() error {
return trace.NewAggregate(proxy.Client.Close(), proxy.currentCluster.Close())
}

// ExecuteSCP runs remote scp command(shellCmd) on the remote server and
// runs local scp handler using SCP Command
func (c *NodeClient) ExecuteSCP(ctx context.Context, cmd scp.Command) error {
ctx, span := c.Tracer.Start(
ctx,
"nodeClient/ExecuteSCP",
oteltrace.WithSpanKind(oteltrace.SpanKindClient),
)
defer span.End()

shellCmd, err := cmd.GetRemoteShellCmd()
if err != nil {
return trace.Wrap(err)
}

s, err := c.Client.NewSession(ctx)
if err != nil {
return trace.Wrap(err)
}
defer s.Close()

stdin, err := s.StdinPipe()
if err != nil {
return trace.Wrap(err)
}

stdout, err := s.StdoutPipe()
if err != nil {
return trace.Wrap(err)
}

// Stream scp's stderr so tsh gets the verbose remote error
// if the command fails
stderr, err := s.StderrPipe()
if err != nil {
return trace.Wrap(err)
}
go io.Copy(os.Stderr, stderr)

ch := utils.NewPipeNetConn(
stdout,
stdin,
utils.MultiCloser(),
&net.IPAddr{},
&net.IPAddr{},
)

execC := make(chan error, 1)
go func() {
err := cmd.Execute(ch)
if err != nil && !trace.IsEOF(err) {
log.WithError(err).Warn("Failed to execute SCP command.")
}
stdin.Close()
execC <- err
}()

runC := make(chan error, 1)
go func() {
err := s.Run(ctx, shellCmd)
if err != nil && errors.Is(err, &ssh.ExitMissingError{}) {
// TODO(dmitri): currently, if the session is aborted with (*session).Close,
// the remote side cannot send exit-status and this error results.
// To abort the session properly, Teleport needs to support `signal` request
err = nil
}
runC <- err
}()

var runErr error
select {
case <-ctx.Done():
if err := s.Close(); err != nil {
log.WithError(err).Debug("Failed to close the SSH session.")
}
err, runErr = <-execC, <-runC
case err = <-execC:
runErr = <-runC
case runErr = <-runC:
err = <-execC
}

if runErr != nil && (err == nil || trace.IsEOF(err)) {
err = runErr
}
if trace.IsEOF(err) {
err = nil
}
return trace.Wrap(err)
}

// TransferFiles transfers files over SFTP.
func (c *NodeClient) TransferFiles(ctx context.Context, cfg *sftp.Config) error {
ctx, span := c.Tracer.Start(
Expand Down
Loading