@@ -28,15 +28,21 @@ import (
28
28
"github.com/julienschmidt/httprouter"
29
29
"golang.org/x/crypto/ssh"
30
30
31
+ "github.com/gravitational/teleport"
31
32
"github.com/gravitational/teleport/api/client/proto"
32
33
"github.com/gravitational/teleport/api/defaults"
34
+ apidefaults "github.com/gravitational/teleport/api/defaults"
33
35
"github.com/gravitational/teleport/api/utils/keys"
34
36
"github.com/gravitational/teleport/api/utils/sshutils"
37
+ "github.com/gravitational/teleport/lib/agentless"
35
38
"github.com/gravitational/teleport/lib/auth/authclient"
36
39
"github.com/gravitational/teleport/lib/client"
40
+ "github.com/gravitational/teleport/lib/modules"
37
41
"github.com/gravitational/teleport/lib/multiplexer"
38
42
"github.com/gravitational/teleport/lib/reversetunnelclient"
39
43
"github.com/gravitational/teleport/lib/sshutils/sftp"
44
+ "github.com/gravitational/teleport/lib/teleagent"
45
+ "github.com/gravitational/teleport/lib/utils"
40
46
)
41
47
42
48
// fileTransferRequest describes HTTP file transfer request
@@ -144,8 +150,7 @@ func (h *Handler) transferFile(w http.ResponseWriter, r *http.Request, p httprou
144
150
}
145
151
146
152
if req .mfaResponse != "" {
147
- err = ft .issueSingleUseCert (mfaResponse , r , tc )
148
- if err != nil {
153
+ if err = ft .issueSingleUseCert (mfaResponse , r , tc ); err != nil {
149
154
return nil , trace .Wrap (err )
150
155
}
151
156
}
@@ -155,17 +160,84 @@ func (h *Handler) transferFile(w http.ResponseWriter, r *http.Request, p httprou
155
160
ctx = context .WithValue (ctx , sftp .ModeratedSessionID , req .moderatedSessionID )
156
161
}
157
162
158
- cl , err := tc . ConnectToCluster ( ctx )
163
+ accessPoint , err := site . CachingAccessPoint ( )
159
164
if err != nil {
165
+ h .logger .DebugContext (r .Context (), "Unable to get auth access point" , "error" , err )
160
166
return nil , trace .Wrap (err )
161
167
}
162
- defer cl .Close ()
163
168
164
- err = tc . TransferFiles ( ctx , cl , req . login , req . serverID + ":0" , cfg )
169
+ accessChecker , err := sctx . GetUserAccessChecker ( )
165
170
if err != nil {
171
+ return nil , trace .Wrap (err )
172
+ }
173
+
174
+ getAgent := func () (teleagent.Agent , error ) {
175
+ return teleagent .NopCloser (tc .LocalAgent ()), nil
176
+ }
177
+ cert , err := sctx .GetSSHCertificate ()
178
+ if err != nil {
179
+ return nil , trace .Wrap (err )
180
+ }
181
+ signer := agentless .SignerFromSSHCertificate (cert , h .auth .accessPoint , tc .SiteName , tc .Username )
182
+
183
+ conn , err := h .cfg .Router .DialHost (
184
+ ctx ,
185
+ & utils.NetAddr {Addr : r .RemoteAddr },
186
+ & h .cfg .ProxyWebAddr ,
187
+ req .serverID ,
188
+ "0" ,
189
+ tc .SiteName ,
190
+ accessChecker ,
191
+ getAgent ,
192
+ signer ,
193
+ )
194
+ if err != nil {
195
+ if errors .Is (err , teleport .ErrNodeIsAmbiguous ) {
196
+ const message = "error: ambiguous host could match multiple nodes\n \n Hint: try addressing the node by unique id (ex: user@node-id)\n "
197
+ return nil , trace .NotFound (message )
198
+ }
199
+
200
+ return nil , trace .Wrap (err )
201
+ }
202
+
203
+ dialTimeout := apidefaults .DefaultIOTimeout
204
+ if netConfig , err := accessPoint .GetClusterNetworkingConfig (ctx ); err != nil {
205
+ h .logger .DebugContext (r .Context (), "Unable to fetch cluster networking config" , "error" , err )
206
+ } else {
207
+ dialTimeout = netConfig .GetSSHDialTimeout ()
208
+ }
209
+
210
+ sshConfig := & ssh.ClientConfig {
211
+ User : tc .HostLogin ,
212
+ Auth : tc .AuthMethods ,
213
+ HostKeyCallback : tc .HostKeyCallback ,
214
+ Timeout : dialTimeout ,
215
+ }
216
+
217
+ nodeClient , err := client .NewNodeClient (
218
+ ctx ,
219
+ sshConfig ,
220
+ conn ,
221
+ req .serverID + ":0" ,
222
+ req .serverID ,
223
+ tc ,
224
+ modules .GetModules ().IsBoringBinary (),
225
+ )
226
+ if err != nil {
227
+ // The close error is ignored instead of using [trace.NewAggregate] because
228
+ // aggregate errors do not allow error inspection with things like [trace.IsAccessDenied].
229
+ _ = conn .Close ()
230
+
231
+ return nil , trace .Wrap (err )
232
+ }
233
+
234
+ defer nodeClient .Close ()
235
+
236
+ if err := nodeClient .TransferFiles (ctx , cfg ); err != nil {
166
237
if errors .As (err , new (* sftp.NonRecursiveDirectoryTransferError )) {
167
238
return nil , trace .Errorf ("transferring directories through the Web UI is not supported at the moment, please use tsh scp -r" )
168
239
}
240
+
169
241
return nil , trace .Wrap (err )
170
242
}
171
243
0 commit comments