Add web terminal handlers for file transfer requests#24581
Conversation
| if err != nil { | ||
| return trace.Wrap(err) | ||
| } | ||
| t.SessionRegistry.NotifyFileTransferRequest(req, FileTransferApproved, scx) |
There was a problem hiding this comment.
why this notify is missing?
There was a problem hiding this comment.
This is just some base branch shenanigans. Both of the Notifys happen inside the approve/deny methods now but it'll be updated here when I get the base branch updated/merged. Ignore for now!
| if err != nil { | ||
| return 0, trace.Wrap(err) | ||
| } | ||
| approved, ok := e["approved"].(bool) |
There was a problem hiding this comment.
i haven't seen that part in RFD. Some audit event will be extended to have this field or does it already have it? can you link it?
There was a problem hiding this comment.
This approved is handling the file transfer response. Is the response "Approved" or "Denied" basically.
| } | ||
|
|
||
| return 0, nil | ||
| case defaults.WebsocketFileTransferRequestResponse: |
There was a problem hiding this comment.
i saw that in resizeC we check for nil channel at top, do we need it here as well?
| select { | ||
| case <-t.terminalContext.Done(): | ||
| return | ||
| case transferRequest := <-fileTransferC: |
There was a problem hiding this comment.
Don't we have to handle the channel getting closed, just as handleWindowResize does?
Lines 894 to 898 in 959073c
There was a problem hiding this comment.
Shouldn't the new version of handleFileTransfer account for individual channels getting closed?
| return | ||
| case transferRequest := <-fileTransferC: | ||
| // if not response, this is a new file transfer request | ||
| if !transferRequest.Response { |
There was a problem hiding this comment.
Did you consider representing those two different request types as two separate structs or something akin to a discriminated union in TypeScript?
Packing every possible field in a single type and then differentiating between them based on the assumed shape doesn't sound like a sound long-term strategy to me. I can't help here much unfortunately without doing a deeper dive into the code. I'd ask someone who knows Go better than me if it'd be possible to represent those two different types of requests as different structs.
There was a problem hiding this comment.
Yeah, this grew from "eh only 1 field is needed" to a few, and I didn't cut them apart. It's best to do that now and make it more clear.
There was a problem hiding this comment.
After splitting the structs, I made a new chan, one to handle the requests, and one to handle the responses. The original reason to have this struct be the same was to reuse the same chan and just make decisions based on what info came through but I think thats a bit lazy now. Although I have a separate channel, I kept the "setting" of the channels in the same method (just with the two channels now instead of one) and also, have both cases in the same handler as well. Came out cleaner and easier to parse around throughout the app. Thanks for keeping me accountable
| EnvsJSON []byte `json:"envs"` | ||
| } | ||
|
|
||
| type FileTransferReq struct { |
There was a problem hiding this comment.
Looking at other definitions in this file, shouldn't these two have a godoc as well?
| func (s *Session) FileTransferRequestResponse(ctx context.Context, req FileTransferResponseReq) error { | ||
| const request = "file-transfer-request-response" | ||
| config := tracing.NewConfig(s.wrapper.opts) | ||
| ctx, span := config.TracerProvider.Tracer(instrumentationName).Start( |
There was a problem hiding this comment.
Do we need to set up all of this tracing stuff even though in the end we end up just calling s.Session.SendRequest which does that again? I don't really know much about how we do tracing, I'm looking at SetEnv which ends up calling SendRequest too, but SetEnv actually does some extra stuff.
There was a problem hiding this comment.
s.Session.SendRequest doesn't have the tracing as that uses the wrapped ssh.Session, but if I instead just used s.SendRequest, then yeah, I can ignore the tracing as that SendRequest does set it up. Good call
There was a problem hiding this comment.
Ah, I didn't notice the difference between the two. Still, I'd recommend asking on #dev-teleport if one way of doing this is preferred over the other.
There was a problem hiding this comment.
If you want any custom attributes to be included in the span you will need to create one explicitly. The underlying ssh request tracing will simply tell you that a request named foo was sent.
959073c to
8521b0d
Compare
|
Didn't mean to rebase this early and didn't realize after I pushed, sorry! |
…chaelmyers/web_terminal_file_request_handlers
…chaelmyers/web_terminal_file_request_handlers
…chaelmyers/web_terminal_file_request_handlers
…chaelmyers/web_terminal_file_request_handlers
ravicious
left a comment
There was a problem hiding this comment.
Some minor adjustments are needed but looks ok otherwise.
| download, ok := e["download"].(bool) | ||
| if !ok { | ||
| return 0, trace.BadParameter("Unable to find approved status on response") |
There was a problem hiding this comment.
The error message doesn't match the check that's being performed here.
|
|
||
| // WebsocketFileTransferRequestResponse is received when a response (approve/deny) has been | ||
| // made for an existing file transfer request | ||
| WebsocketFileTransferRequestResponse = "t" |
There was a problem hiding this comment.
It'd be nice to add some tests for that based on TestResizeTerminal.
There was a problem hiding this comment.
@avatus can we add some test coverage for this?
|
|
||
| // FileTransferRequestApprove sends a "file-transfer-request-response" ssh request | ||
| // The response will contain an Approve bool which will approve or deny a requested file transfer | ||
| func (s *Session) FileTransferRequestResponse(ctx context.Context, req FileTransferResponseReq) error { |
There was a problem hiding this comment.
When I was reviewing the web PR, I realized that this might need a better name. The other method names are verb based while this one feels a bit odd compared to them.
There was a problem hiding this comment.
I tried thinking of something that would make sense for both like ResponseToFileTransferRequest but, idk I didn't like it. So I just split them into to, ApproveFileTransferRequest and DenyFileTransferRequest. They both take just the requestID now as a string, and the req is created inside the method and sets Approved appropriately. Maybe a bit verbose but much more readable and understandable
| func (s *Session) FileTransferRequestResponse(ctx context.Context, req FileTransferResponseReq) error { | ||
| const request = "file-transfer-request-response" | ||
| config := tracing.NewConfig(s.wrapper.opts) | ||
| ctx, span := config.TracerProvider.Tracer(instrumentationName).Start( |
There was a problem hiding this comment.
If you want any custom attributes to be included in the span you will need to create one explicitly. The underlying ssh request tracing will simply tell you that a request named foo was sent.
…chaelmyers/web_terminal_file_request_handlers
|
|
||
| // WebsocketFileTransferRequestResponse is received when a response (approve/deny) has been | ||
| // made for an existing file transfer request | ||
| WebsocketFileTransferRequestResponse = "t" |
…chaelmyers/web_terminal_file_request_handlers
…chaelmyers/web_terminal_file_request_handlers
* Add file transfer handlers to web terminal * remove unused keys * Add FileTransferContainer This PR separates the absolute positioned container from the FileTransfer component. We will be adding FileTransferRequests in the same spot, and this will allow them to be visible together without css shenanigans trying to absolutely place them together. FileTransferRequests are separate from FileTransfers in that they interact with the tty. * Add useFileTransfer hook * Use useFileTransfer hook inside useSshSession * Add tty handlers * Update getScpUrl to add optional moderated params * Use FileTransferContainer in Connect * Update DocumentSSH * remove fmt * remove unused shellcmd key * lint fixes * remove pending file after get * remove pending file after get * Clean up console log * Update filetransfererquest to use download bool * Fix upload/download flow * Fix typecheck and FileTransfer tests * Fix UI display bugs and add license * Change filetransferresponse to filetransferdecision * Refactor useFileTransfer up to DocumentSsh * Add license * Fix lint error * update pending transfer text * use handleUpload/handleDownload, move FileTransferRequests to prop * Review feedback * Add usecallback to scpurls and useattempt * Apply patch * Update optional params
Add web terminal handlers for file transfer requests (#24581)
Add web terminal handlers for file transfer requests (#24581)
Part of #23546
Relies on #24580
web buddy: #24583
This PR adds the
fileTransferCchannel to our web terminal to listen to websocket events dealing with file transfer requests. The two events added are for requesting a new file transfer, and responding to an existing file transfer.