mirror of
https://github.com/gravitational/teleport
synced 2024-10-20 17:23:22 +00:00
desktop playback error handling (#10765)
This commit is contained in:
parent
32457df042
commit
896dbbbc47
4
.github/ISSUE_TEMPLATE/testplan.md
vendored
4
.github/ISSUE_TEMPLATE/testplan.md
vendored
|
@ -938,6 +938,10 @@ and non interactive tsh bench loads.
|
|||
- [ ] Verify async recording (`mode: node` or `mode: proxy`)
|
||||
- [ ] Sessions show up in session recordings UI with desktop icon
|
||||
- [ ] Sessions can be played back, including play/pause functionality
|
||||
- [ ] A session that ends with a TDP error message can be played back, ends by displaying the error message,
|
||||
and the progress bar progresses to the end.
|
||||
- [ ] Attempting to play back a session that doesn't exist (i.e. by entering a non-existing session id in the url) shows
|
||||
a relevant error message.
|
||||
- [ ] RBAC for sessions: ensure users can only see their own recordings when
|
||||
using the RBAC rule from our
|
||||
[docs](../../docs/pages/access-controls/reference.mdx#rbac-for-sessions)
|
||||
|
|
|
@ -872,7 +872,7 @@ func (s *WindowsService) makeTDPSendHandler(ctx context.Context, emitter events.
|
|||
id *tlsca.Identity, sessionID, desktopAddr string) func(m tdp.Message, b []byte) {
|
||||
return func(m tdp.Message, b []byte) {
|
||||
switch b[0] {
|
||||
case byte(tdp.TypePNGFrame):
|
||||
case byte(tdp.TypePNGFrame), byte(tdp.TypeError):
|
||||
e := &events.DesktopRecording{
|
||||
Metadata: events.Metadata{
|
||||
Type: libevents.DesktopRecordingEvent,
|
||||
|
|
|
@ -19,13 +19,16 @@ package desktop
|
|||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
apievents "github.com/gravitational/teleport/api/types/events"
|
||||
"github.com/gravitational/teleport/lib/session"
|
||||
"github.com/gravitational/teleport/lib/utils"
|
||||
"github.com/gravitational/trace"
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/net/websocket"
|
||||
)
|
||||
|
@ -207,6 +210,15 @@ func (pp *Player) streamSessionEvents(ctx context.Context, cancel context.Cancel
|
|||
// otherwise it just sits at the player UI
|
||||
if err != nil && !errors.Is(err, context.Canceled) {
|
||||
pp.log.WithError(err).Errorf("streaming session %v", pp.sID)
|
||||
var errorText string
|
||||
if os.IsNotExist(err) || trace.IsNotFound(err) {
|
||||
errorText = "session not found"
|
||||
} else {
|
||||
errorText = "server error"
|
||||
}
|
||||
if _, err := pp.ws.Write([]byte(fmt.Sprintf(`{"message": "error", "errorText": "%v"}`, errorText))); err != nil {
|
||||
pp.log.WithError(err).Error("failed to write \"error\" message over websocket")
|
||||
}
|
||||
}
|
||||
return
|
||||
case evt := <-eventsC:
|
||||
|
@ -227,6 +239,10 @@ func (pp *Player) streamSessionEvents(ctx context.Context, cancel context.Cancel
|
|||
msg, err := utils.FastMarshal(e)
|
||||
if err != nil {
|
||||
pp.log.WithError(err).Errorf("failed to marshal DesktopRecording event into JSON: %v", e)
|
||||
if _, err := pp.ws.Write([]byte(`{"message":"error","errorText":"server error"}`)); err != nil {
|
||||
pp.log.WithError(err).Error("failed to write \"error\" message over websocket")
|
||||
}
|
||||
return
|
||||
}
|
||||
if _, err := pp.ws.Write(msg); err != nil {
|
||||
// We expect net.ErrClosed to arise when another goroutine returns before
|
||||
|
|
|
@ -65,7 +65,7 @@ func TestStreamsDesktopEvents(t *testing.T) {
|
|||
b := make([]byte, 4096)
|
||||
n, err := ws.Read(b)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, []byte(`{"message":"end"}`), b[:n])
|
||||
require.JSONEq(t, `{"message":"end"}`, string(b[:n]))
|
||||
}
|
||||
|
||||
func newServer(t *testing.T, streamInterval time.Duration, events []apievents.AuditEvent) *httptest.Server {
|
||||
|
|
Loading…
Reference in a new issue