Reduces latency creating ssh sessions via the web ui by:
1) No longer uses `TeleportClient.SSH` to establish a session
2) Reuses the user auth client for the web session to perform MFA ceremony
3) Ensures that connection attempts follow the flow outlined in RFD 93
The web api server now leverages the `proxy.Router` and `srv.SessionController`
directly, instead of doing so indirectly via `TeleportClient.SSH`. Using
the `TeleportClient` required an ssh connection to be established from the web
api server to the proxy ssh server, which are in the same process. This added
overhead can be avoided now that the routing logic and session control logic
exists in a reusable component. To create an interactive session on the node
once the connection is established, `client.NodeClient` is used. A new constructor
was added to facilitate creating one and remove duplicated creation code and a
`RunInteractiveShell` receiver method was added to allow callers outside of
`lib/client` to spawn a session.
`TerminalHandler.issueSessionMFACerts` used to check if per-session mfa was enabled
and perform the mfa ceremony via the `client.ProxyClient` which was constructed
with the `TeleportClient` established from connecting to the proxy ssh server.
This would dial the Auth server under the hood directly and call `IsMFARequired`
and do the ceremony if required. Each web session established via the web ui
already established an auth client with the credentials of the logged in user.
Again overhead is removed by leveraging the existing auth client and performing
the mfa ceremony manually.
Finally `TerminalHandler.makeClient` always attempted to perform the mfa ceremony
prior to returning the `TeleportClient`. As outlined in [RFD 93](https://github.com/gravitational/teleport/blob/master/rfd/0093-offline-access.md),
this causes additional latency and requires Auth connectivity to connect to nodes.
The connection flow is now modified to attempt connection to the nodes first, and
fall back to the mfa ceremony and reconnecting only if the node denies access.
Partially addresses #15167
* Allow tsh to retrieve cluster details in one request
Prior to connecting to a node via `tsh ssh` we need two bits of
information about the cluster:
1) The session recording mode
2) Whether FIPS is enabled
In order to retrieve the information `tsh` first would send the
global ssh request `RecordingProxyReqType` to determine the
session recording mode. Later on `tsh` would Ping the auth
server to determine if the cluster was running in FIPS mode.
In an effort to reduce the number of round trips to retrieve
this data, a new global ssh request `ClusterDetailsReqType` is
introduced that returns both the session recording mode and
whether FIPS is enabled. This allows `tsh` to leverage the new
request to get all the information it needs, and is extensible
in case more information is needed` in one request which helps
reduce latency for `tsh ssh`.
* Prevent ssh.Session SendRequest from wrapping payload twice
Payloads were inadvertently being wrapped twice by sessions making
the ssh server unable to parse the request payload. This is largely
only an issue for window-change requests, as they are the only request
being sent directly via a session that contains a payload. All window-change
requests now use ssh.Session WindowChange instead or sending the request
manually.
* Add spans to TeleportClient/ProxyClient/NodeSession
* Improve dialer tracing
* Alter default http client span name to include path
* propagate tracing options in NewClientConn
Adds a wrapper around `ssh.Session` which injects tracing context
in a similar manner to the `ssh.Client` wrapper. All usages of
`ssh.Session` have now been replaced and have the appropriate
`context.Context` passed along
Part of #12241
Create spans for all public facing TeleportClient,
ProxyClient, and NodeClient methods. This makes
correlating spans easier to reason about when
looking at `tsh` traces. As a result of creating
spans, some additional context propagation is
required as well to ensure that spans are linked
properly.
This also removes the unused `quiet` argument from
`ConnectToCluster`. It's usage was not consistent
by existing callers, and it was ignored, so in order
to avoid confusion in future calls, it was removed.
#12241
* Remove more deprecated code
In the case where we were using the PostalCode, StreetAddress,
and Province fields rather than ASN.1 extensions we could have
removed more code, but I opted for a phase approach where we stop
populating the fields in v10 (but still accept them), and then
stop reading them entirely in v11.
* Fix lints and remove more unused code
* Restore StreetAddress / PostalCode
We don't yet have dedicated extensions for these
* Add tracing instrumentation for ssh clients/servers
Add tracing context to the existing ProxyHelloSignature to provide
span information across ssh connections. To add span context per
ssh session on top of new connections, the same tracing context is
passed in the first global request of the session.
In order to ensure that tracing context is pulled from and inserted
into the proper context.Context, some interfaces and methods were
changed to take one as the first argument.
This change clears the screen when an ssh session ends (only in FIPS mode). Note: This doesn't currently do anything in `tsh` on Windows since BoringCrypto isn't supported, but once it is supported, the behavior will match Unix and web.
Co-authored-by: Grzegorz <grzegorz.zdunek@goteleport.com>
Co-authored-by: Russell Jones <russjones@users.noreply.github.com>
* Add support for `tsh ssh` on Windows
This adds Windows session support to tsh, taking advantage of ANSI
terminal support and VT emulation added in recent versions Windows
10. On supported Windows versions (Windows 10 1607+), `tsh ssh`
should work as expected in `cmd.exe`, PowerShell, and the new
Windows Terminal app.
* Address a few review comments
* Remove significant chunks of unnecessary tncon code.
Removes the global buffer, `GetVTSeqFromKeyStroke`, and several
ancillary headers and functions that aren't needed for our (current)
use-case. Also removes mouse and focus events.
* Refactor OS-specific terminal handling
This significantly simplifies OS-specific terminal behavior:
* Move OS specific terminal code into a new `terminal` package
* Remove `session_windows.go` in favor of an OS-independent
`session.go`, defer to terminal package for OS specific
functionality.
* Remove ConPTY since it's not needed.
* Always wait for the terminal and ssh session to fully close before
quitting.
* Refactor tncon; ensure the raw reader can be closed and reopened,
remove lots of unnecessary C code.
* Revert dependency changes
* Use WindowsOS constant.
* Fix `tsh play` on Windows
This fixes `tsh play` on Windows by using the new `terminal` module to
initialize the terminal for raw input in a cross-platform way.
Additionally, this simplifies `terminal.New()` since in practice we never
want interactive mode at init time, and fixes a broken unit test.
* Use correct log library
* Fix `tsh play` player controls on Windows
This fixes the console player controls on Windows as well as the timestamp
writer.
* Clean up lints
* Add missing license header
* Fix broken unit test
* Fix cross-compile builds on Linux/Docker
We need windows.h, which is not capitalized in the mingw packages
(and is case insensitive on Windows).
* Address code review feedback
- Rename `Terminal.InitInteractive` to `Terminal.InitRaw`
- Ensure goroutines terminate on close
- Fix outdated godoc comments
- Ensure Terminal event subscribers are cleared (and their channels
are closed)
- Ensure terminal output mode is reset on error in initTerminal
- Bubble up errors in Terminal.Close()
- Add author notice to tncon.c re: our changes
- Add go-ansiterm as a direct dependency
- Run `make update-vendor`
* Add constants and a small player.go TODO.
* Clear linter warning
Prior to this change, `tsh` will only ever forward the internal key
agent managed by `tsh` to a remote machine.
This change allows a user to specify that `tsh` should forward either
the `tsh`-internal keystore, or the system key agent at `$SSH_AUTH_SOCK`.
This change also brings the `-A` command-line option into line with
OpenSSH.
For more info refer to RFD-0022.
See-Also: #1571
* Attempt to isolate and improve state handling of a NodeSession.
* Add terminal close for kube terminal tests
* Address review comments
* Small tweaks
Co-authored-by: Andrew Lytvynov <andrew@goteleport.com>
Only applies to interactive sessions.
Watch the user keyboard input for one of:
- `~?`: print help output for escape sequences
- `~.`: disconnect the current session (for example when stuck due to
traffic getting black-holed)
The full list of OpenSSH sequences is here:
https://man.openbsd.org/ssh#ESCAPE_CHARACTERS
We only support the two mentioned above for now. If the need arises, it
should be easy to add.
The implementation ended up pretty complicated, read the comment on
`escape.NewReader` for some info and reasoning.
Fixes#2555
Before establishing a session, request the server version. If the server
replies false, that means it does not support that request type and is
an older server version which needs UUIDv1 format session IDs.
* Changed import path from github.com/moby/moby to canonical path of
github.com/docker/docker.
* Updated dependency for github.com/docker/docker/pkg/term.
* Updated dependency for github.com/Azure/go-ansiterm.
* Cache services.ClusterConfig within srv.ServerContext for the duration
of a connection.
* Create a single websocket between the browser and the proxy for all
* terminal bytes and events.
This commit adds several improvements to how CLI SSH login works
- Validated keys are added to the SSH agent [1]
- tsh will does not verify host keys twice anymore
- error messages for "access denied" look clean now
[1] This is huge. This means that tsh login can "feed" the keys to the
built-in SSH agents of the OS and OpenSSH can fetch them from there.
QUESTION: why do we even need `tsh agent` option then? ssh-agent is
installed on every Linux/OSX machine.