Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add tsh command to resolve a single host #47689

Merged
merged 1 commit into from
Oct 23, 2024
Merged

Conversation

rosstimothy
Copy link
Contributor

@rosstimothy rosstimothy commented Oct 17, 2024

tsh resolve allows identifying a single host either directly by hostname, or via custom search/predicate expression from a matched proxy template. The main use case is to provide a simple command for users that wish to use Match exec in their SSH config. Today, all matching in SSH config must be done via DNS and requires users to add some Teleport specific suffix/prefix, or use a wildcard entry to invoke a tsh proxy command.

For example, the SSH config generated today via tsh config is the following:

# Common flags for all local.dev hosts
Host *.cluster-name proxy.example.com
    UserKnownHostsFile "/Users/tim/.tsh/known_hosts"
    IdentityFile "/Users/tim/.tsh/keys/proxy.example.com/tim"
    CertificateFile "/Users/tim/.tsh/keys/proxy.example.com/tim-ssh/cluster-name-cert.pub"

# Flags for all local.dev hosts except the proxy
Host *.cluster-name
    Port 3022 !proxy.example.com
    ProxyCommand "tsh" proxy ssh --cluster=cluster-name --proxy=proxy.example.com:443 %r@%h:%p

This allows connections to the Teleport SSH service without using tsh directly via ssh foo.cluster-name. However, when migrating to Teleport, that requires the user to alter their existing workflow to include the cluster-name suffix. To remedy this, users can now augment their SSH config to utilize Match exec instead of globbing on the cluster name suffix with the following:

Match exec "tsh resolve -q %h"
    ProxyCommand "tsh" proxy ssh --cluster=cluster-name --proxy=proxy.example.com:443 %r@%h:%p

By default tsh resolve will output the matching host, if one was found, but if the -q flag provided like in the example above the output will be silenced. If no matches are found, or multiple matches are found, tsh resolve will exit with a non-zero exit code as per the Match exec requirements. If and only if a single host is resolved will tsh resolve exit with a zero exit code.

There are performance concerns that need to be taken into account before users adopt this in their SSH config. First, this may cause tsh resolve to be invoked on any SSH request. For example, even doing git pull/git push may now first require tsh resolve to exit with a non-zero exit code before interacting with the git remote. Additionally, when tsh resolve finds a match, any connections to the node will require two connections to the cluster and two ListUnifiedResourcesRequests to resolve the host since the invocation of tsh resolve and tsh proxy ssh or tbot proxy ssh do not share resources. For the reasons mentioned above, the SSH configuration generated by tsh config was not updated to include this new command. If users want to opt into this behavior they must acknowledge the latency concerns by manually editing the config.

changelog: Add a resolve command to tsh that may be used as the target for a Match exec condition in an SSH config.

@rosstimothy rosstimothy force-pushed the tross/match_exec branch 3 times, most recently from e81e652 to 39d5804 Compare October 18, 2024 14:14
@rosstimothy rosstimothy marked this pull request as ready for review October 18, 2024 14:24
@github-actions github-actions bot added size/md tsh tsh - Teleport's command line tool for logging into nodes running Teleport. labels Oct 18, 2024
tool/tsh/common/tsh.go Outdated Show resolved Hide resolved
@rosstimothy
Copy link
Contributor Author

Friendly ping @hugoShaka

`tsh resolve` allows identifying a single host either directly by
hostname, or via custom search/predicate expression from a matched
proxy template. The main use case is to provide a simple command
for users that wish to use `Match exec` in their SSH config. Today,
all matching in SSH config must be done via DNS and requires users
to add some Teleport specific suffix/prefix, or use a wildcard entry
to invoke a tsh proxy command.

For example, the SSH config generated today via `tsh config` is the
following:

```
# Common flags for all local.dev hosts
Host *.cluster-name proxy.example.com
    UserKnownHostsFile "/Users/tim/.tsh/known_hosts"
    IdentityFile "/Users/tim/.tsh/keys/proxy.example.com/tim"
    CertificateFile "/Users/tim/.tsh/keys/proxy.example.com/tim-ssh/cluster-name-cert.pub"

# Flags for all local.dev hosts except the proxy
Host *.cluster-name
    Port 3022 !proxy.example.com
    ProxyCommand "tsh" proxy ssh --cluster=cluster-name --proxy=proxy.example.com:443 %r@%h:%p
```

This allows connections to the Teleport SSH service without using tsh directly
via `ssh foo.cluster-name`. However, when migrating to Teleport, that requires
the user to alter their existing workflow to include the cluster-name suffix.
To remedy this, users can now augment their SSH config to utilize `Match exec`
instead of globbing on the cluster name suffix with the following:

```
Match exec "tsh resolve -q %h"
    ProxyCommand "tsh" proxy ssh --cluster=cluster-name --proxy=proxy.example.com:443 %r@%h:%p
```

By default tsh resolve will output the matching host, if one was
found, but if the `-q` flag provided like in the example above
the output will be silenced. If no matches are found, or multiple
matches are found, `tsh resolve` will exit with a non-zero exit
code as per the `Match exec` requirements. If and only if a single
host is resolved will `tsh resolve` exit with a zero exit code.

There are performance concerns that need to be taken into account
before users adopt this in their SSH config. First, this may cause
`tsh resolve` to be invoked on any SSH request. For example, even
doing git pull/git push may now first require `tsh resolve` to
exit with a non-zero exit code before interact with the git remote.
Additionally, when `tsh resolve` finds a match, any connections to
the node will require _two_ connections to the cluster and _two_
ListUnifiedResourcesRequests to resolve the host since the
invocation of `tsh resolve` and `tsh proxy ssh` or `tbot proxy ssh`
do not share any resources. For the reasons mentioned above, the
SSH configuration generated by `tsh config` was not updated to
include this new command. If users want to opt into this behavior
they must acknowledge the latency concerns by manually editting
the config.
@rosstimothy rosstimothy enabled auto-merge October 23, 2024 19:04
@rosstimothy rosstimothy added this pull request to the merge queue Oct 23, 2024
Merged via the queue into master with commit c1c1427 Oct 23, 2024
40 of 41 checks passed
@rosstimothy rosstimothy deleted the tross/match_exec branch October 23, 2024 19:40
@public-teleport-github-review-bot

@rosstimothy See the table below for backport results.

Branch Result
branch/v15 Create PR
branch/v16 Create PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backport/branch/v15 backport/branch/v16 size/md tsh tsh - Teleport's command line tool for logging into nodes running Teleport.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants