Skip to content

Commit

Permalink
[v9] backport #10765 and #10766 (#10855)
Browse files Browse the repository at this point in the history
  • Loading branch information
Isaiah Becker-Mayer authored Mar 7, 2022
1 parent 8fa670b commit a2b8fd5
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 9 deletions.
83 changes: 83 additions & 0 deletions docs/testplan.md
Original file line number Diff line number Diff line change
Expand Up @@ -895,3 +895,86 @@ and non interactive tsh bench loads.
- [ ] Multiple sessions as different users on the same desktop are allowed.
- [ ] Connect multiple `windows_desktop_service`s to the same Teleport cluster,
verify that connections to desktops on different AD domains works.
verify that connections to desktops on different AD domains works. (Attempt to
connect several times to verify that you are routed to the correct
`windows_desktop_service`)
- Verify user input
- [ ] Download [Keyboard Key Info](https://dennisbabkin.com/kbdkeyinfo/) and
verify all keys are processed correctly in each supported browser. Known
issues: F11 cannot be captured by the browser without
[special configuration](https://social.technet.microsoft.com/Forums/en-US/784b2bbe-353f-412e-ac9a-193d81f306b6/remote-desktop-for-mac-f11-key-not-working-on-macbook-pro-touchbar?forum=winRDc)
on MacOS.
- [ ] Left click and right click register as Windows clicks. (Right click on
the desktop should show a Windows menu, not a browser context menu)
- [ ] Vertical and horizontal scroll work.
[Horizontal Scroll Test](https://codepen.io/jaemskyle/pen/inbmB)
- Locking
- [ ] Verify that placing a user lock terminates an active desktop session.
- [ ] Verify that placing a desktop lock terminates an active desktop session.
- [ ] Verify that placing a role lock terminates an active desktop session.
- Labeling
- [ ] Set `client_idle_timeout` to a small value and verify that idle sessions
are terminated (the session should end and an audit event will confirm it
was due to idle connection)
- [ ] All desktops have `teleport.dev/origin` label.
- [ ] Dynamic desktops have additional `teleport.dev` labels for OS, OS
Version, DNS hostname.
- [ ] Regexp-based host labeling applies across all desktops, regardless of
origin.
- RBAC
- [ ] RBAC denies access to a Windows desktop due to labels
- [ ] RBAC denies access to a Windows desktop with the wrong OS-login.
- Clipboard Support
- When a user has a role with clipboard sharing enabled and is using a chromium based browser
- [ ] Going to a desktop when clipboard permissions are in "Ask" mode (aka "prompt") causes the browser to show a prompt while the UI shows a spinner
- [ ] X-ing out of the prompt (causing the clipboard permission to remain in "Ask" mode) causes the prompt to show up again
- [ ] Denying clibpoard permissions brings up a relevant error alert (with "Clipboard Sharing Disabled" in the top bar)
- [ ] Allowing clipboard permissions allows you to see the desktop session, with "Clipboard Sharing Enabled" highlighted in the top bar
- [ ] Copy text from local workstation, paste into remote desktop
- [ ] Copy text from remote desktop, paste into local workstation
- When a user has a role with clipboard sharing enabled and is *not* using a chromium based browser
- [ ] The UI shows a relevant alert and "Clipboard Sharing Disabled" is highlighted in the top bar
- When a user has a role with clipboard sharing *disabled* and is using a chromium and non-chromium based browser (confirm both)
- [ ] The live session should show disabled in the top bar and copy/paste should not work between your workstation and the remote desktop.
- Per-Session MFA (try webauthn on each of Chrome, Safari, and Firefox; u2f only works with Firefox)
- [ ] Attempting to start a session no keys registered shows an error message
- [ ] Attempting to start a session with a u2f key registered shows an error message
- [ ] Attempting to start a session with a webauthn registered pops up the "Verify Your Identity" dialog
- [ ] Hitting "Cancel" shows an error message
- [ ] Hitting "Verify" causes your browser to prompt you for MFA
- [ ] Cancelling that browser MFA prompt shows an error
- [ ] Successful MFA verification allows you to connect
- Session Recording
- [ ] Verify sessions are not recorded if *all* of a user's roles disable recording
- [ ] Verify sync recording (`mode: node-sync` or `mode: proy-sync`)
- [ ] 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)
- Audit Events (check these after performing the above tests)
- [ ] `windows.desktop.session.start` (`TDP00I`) emitted on start
- [ ] `windows.desktop.session.start` (`TDP00W`) emitted when session fails to
start (due to RBAC, for example)
- [ ] `windows.desktop.session.end` (`TDP01I`) emitted on end
- [ ] `desktop.clipboard.send` (`TDP02I`) emitted for local copy -> remote
paste
- [ ] `desktop.clipboard.receive` (`TDP03I`) emitted for remote copy -> local
paste
## Binaries compatibility
- Verify that teleport/tsh/tctl/tbot run on:
- [ ] CentOS 7
- [ ] CentOS 8
- [ ] Ubuntu 18.04
- [ ] Ubuntu 20.04
- [ ] Debian 9
- Verify tsh runs on:
- [ ] Windows 10
- [ ] MacOS
18 changes: 11 additions & 7 deletions lib/srv/desktop/rdp/rdpclient/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -362,13 +362,17 @@ func (c *Client) start() {
return
}
case tdp.ClipboardData:
if err := cgoError(C.update_clipboard(
c.rustClient,
(*C.uint8_t)(unsafe.Pointer(&m[0])),
C.uint32_t(len(m)),
)); err != nil {
c.cfg.Log.Warningf("Failed forwarding RDP clipboard data: %v", err)
return
if len(m) > 0 {
if err := cgoError(C.update_clipboard(
c.rustClient,
(*C.uint8_t)(unsafe.Pointer(&m[0])),
C.uint32_t(len(m)),
)); err != nil {
c.cfg.Log.Warningf("Failed forwarding RDP clipboard data: %v", err)
return
}
} else {
c.cfg.Log.Warning("Recieved an empty clipboard message")
}
default:
c.cfg.Log.Warningf("Skipping unimplemented TDP message type %T", msg)
Expand Down
2 changes: 1 addition & 1 deletion lib/srv/desktop/windows_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
16 changes: 16 additions & 0 deletions lib/web/desktop/playback.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)
Expand Down Expand Up @@ -205,6 +208,15 @@ func (pp *Player) streamSessionEvents(ctx context.Context, cancel context.Cancel
case err := <-errC:
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:
Expand All @@ -225,6 +237,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
Expand Down
2 changes: 1 addition & 1 deletion lib/web/desktop/playback_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down

0 comments on commit a2b8fd5

Please sign in to comment.