This code is not caught by linters because it's exported and they assume
there's some external users.
Since teleport is relatively self-contained, we can tell for sure
whether something is called or not.
There are two new ways you can generate a kubeconfig:
- `tctl auth sign --user=foo --format=kubernetes --out=kubeconfig` for
admins
- `tsh login --format=kubernetes -o kubeconfig` for users
This allows admins to generate long-lived kubeconfigs for e.g. CI
systems.
A tricky part is getting the kubernetes endpoint for a proxy in `tctl`.
It does its best to guess the address, but falls back to asking user to
pass `--proxy` flag.
It looks like right now, the proxy info available via the auth server's
API doesn't have kubernetes public_addr for proxies.
Fixes#2825
Fixed regressions in how the cluster name was set in the profile when
doing "tsh login <clusterName>". The following examples illustrate
expected behavior.
Suppose root cluster is example.com and the leaf cluster is
leaf.example.com.
* "tsh login" will update profile to example.com.
* "tsh login example.com" will update profile to example.com.
* "tsh login leaf.example.com" will update profile to
leaf.example.com.
* "tsh login invalid.example.com" will return an error.
Note: The profile is only updated when a identity flag is NOT provided.
This means the following command will NOT update the profile:
tsh --proxy=example.com login --out=certs.pem leaf.example.com
Fixed findings:
```
lib/sshutils/server_test.go:163:2: SA4006: this value of `clt` is never used (staticcheck)
clt, err := ssh.Dial("tcp", srv.Addr(), &cc)
^
lib/sshutils/server_test.go:91:3: SA5001: should check returned error before deferring ch.Close() (staticcheck)
defer ch.Close()
^
lib/shell/shell_test.go:33:2: SA4006: this value of `shell` is never used (staticcheck)
shell, err = GetLoginShell("non-existent-user")
^
lib/cgroup/cgroup_test.go:111:2: SA9003: empty branch (staticcheck)
if err != nil {
^
lib/cgroup/cgroup_test.go:119:2: SA5001: should check returned error before deferring service.Close() (staticcheck)
defer service.Close()
^
lib/client/keystore_test.go:138:2: SA4006: this value of `keyCopy` is never used (staticcheck)
keyCopy, err = s.store.GetKey("host.a", "bob")
^
lib/client/api.go:1604:3: SA4004: the surrounding loop is unconditionally terminated (staticcheck)
return makeProxyClient(sshClient, m), nil
^
lib/backend/test/suite.go:156:2: SA4006: this value of `err` is never used (staticcheck)
result, err = s.B.GetRange(ctx, prefix("/prefix/c/c1"), backend.RangeEnd(prefix("/prefix/c/cz")), backend.NoLimit)
^
lib/utils/timeout_test.go:84:2: SA1019: t.Dial is deprecated: Use DialContext instead, which allows the transport to cancel dials as soon as they are no longer needed. If both are set, DialContext takes priority. (staticcheck)
t.Dial = func(network string, addr string) (net.Conn, error) {
^
lib/utils/websocketwriter.go:83:3: SA4006: this value of `err` is never used (staticcheck)
utf8, err = w.encoder.String(string(data))
^
lib/utils/loadbalancer_test.go:134:2: SA4006: this value of `out` is never used (staticcheck)
out, err = Roundtrip(frontend.String())
^
lib/utils/loadbalancer_test.go:209:2: SA4006: this value of `out` is never used (staticcheck)
out, err = RoundtripWithConn(conn)
^
lib/srv/forward/sshserver.go:582:3: SA4004: the surrounding loop is unconditionally terminated (staticcheck)
return
^
lib/service/service.go:347:4: SA4006: this value of `err` is never used (staticcheck)
i, err = auth.GenerateIdentity(process.localAuth, id, principals, dnsNames)
^
lib/service/signals.go:60:3: SA1016: syscall.SIGKILL cannot be trapped (did you mean syscall.SIGTERM?) (staticcheck)
syscall.SIGKILL, // fast shutdown
^
lib/config/configuration_test.go:184:2: SA4006: this value of `conf` is never used (staticcheck)
conf, err = ReadFromFile(s.configFileBadContent)
^
lib/config/configuration.go:129:2: SA5001: should check returned error before deferring reader.Close() (staticcheck)
defer reader.Close()
^
lib/kube/kubeconfig/kubeconfig_test.go:227:2: SA4006: this value of `err` is never used (staticcheck)
tlsCert, err := ca.GenerateCertificate(tlsca.CertificateRequest{
^
lib/srv/sess.go:720:3: SA4006: this value of `err` is never used (staticcheck)
result, err := s.term.Wait()
^
lib/multiplexer/multiplexer_test.go:169:11: SA1006: printf-style function with dynamic format string and no further arguments should use print-style function instead (staticcheck)
_, err = fmt.Fprintf(conn, proxyLine.String())
^
lib/multiplexer/multiplexer_test.go:221:11: SA1006: printf-style function with dynamic format string and no further arguments should use print-style function instead (staticcheck)
_, err = fmt.Fprintf(conn, proxyLine.String())
^
```
`localAgent` can be nil if `Config.SkipLocalAuth` was set (such as when
passing `-i` flag to `tsh`). Several places in client code didn't handle
missing `localAgent` causing nil pointer panics.
Fixes#3032
Local keystore records trusted TLS CA certs in `<host>/certs.pem`.
When loading client.Key, also load the TLS CA cert for
`key.TrustedCertificates` field.
Without this field, `kubeconfig.Update` called by tsh can't populate the
CA cert in kubeconfig, which causes x509 validation errors with kubectl.
Identity file formatting (former `client.MakeIdentityFile`) will soon
support writing a `kubeconfig` file.
`lib/kube/kubeconfig` depends on `lib/client`, if calls to
`kubeconfig.Update` were added to `client.MakeIdentityFile`, we'd have
an import cycle:
tool/tctl -> lib/client -> lib/kube/kubeconfig -> lib/client
To break the cycle, I extract the identity file formatting (and parsing)
code into a standalone package. It's logically isolated functionality
anyway.
Now the imports will be:
tool/tctl┬─> lib/client
├─> lib/kube/kubeconfig ─> lib/client
╰─> lib/client/identity ┬─> lib/client
╰─> lib/kube/kubeconfig -> lib/client
The path passed in is used as a base, different output formats generate
different file sets based on it. To make things less confusing, return
the list of filepaths written and report it to the user.
Spring cleaning!
A very mechanical cleanup using several linters (unused, deadcode,
structcheck). Build and tests still pass so no behavior should be
affected.
This commit fixes#3252
Security patches 4.2 introduced a regression - leaf clusters ignore role mapping
and attempt to use role names coming from identity of the root cluster
whenever GetNodes method was used.
This commit reverts back the logic, however it ensures that the original
fix is preserved - traits and groups are updated on the user object.
Integration test has been extended to avoid the regression in the future.
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.
If an attacker can force a username change at an IdP, upon second login,
the services.User object of the original user can be updated with new
roles and traits. If these new roles and traits differ, the original
user can have their privileges raised (or lowered).
To mitigate this, encode roles and traits within the certificate and use
these when fetching roles to make RBAC decisions. If roles and traits are
not encoded within an certificate (for example for old style SSH
certificates then fallback to using the services.User object and log a
warning.
Upon calling "tsh login <clusterName>", Teleport will save the cluster
name in ~/.tsh/profile. This value will then be used similar to the
--cluster flag to select which cluster to run a tsh subcommand on.
Update utils.CertChecker to only check key and certificate algorithms
when in FIPS mode. Otherwise accept keys and certificates generated with
any algorithm.
This commit implements #2543
In SSH terms ProxyJump is a shortcut for SSH client
connecting the proxy/jumphost and requesting .port forwarding to the
target node.
This commit adds support for direct-tcpip request support
in teleport proxy service that is an alias to the existing proxy
subsystem and reuses most of the code.
This commit also adds support to "route to cluster" metadata
encoded in SSH certificate making it possible to have client
SSH certificates to include the metadata that will cause the proxy
to route the client requests to a specific cluster.
`tsh ssh -J proxy:port ` is supported in a limited way:
Only one jump host is supported (-J supports chaining
that teleport does not utilise) and tsh will return with error
in case of two jumphosts: -J a,b will not work.
In case if `tsh ssh -J user@proxy` is used, it overrides
the SSH proxy coming from the tsh profile and port-forwarding
is used instead of the existing teleport proxy subsystem
This commit fixes issue #2766.
The prior logic in Kubernetes module used
SNI to route requests to the target kubernetes cluster.
This approach created problems with long cluster names
exceeding 61 character DNS label limit and
required setting up DNS wildcard records.
This commit changes the routing to use the metadata
encoded in client's x509 certificate to route the
request to the target cluster.
SNI approach will be supported for several versions
to preserve backwards compatibility.
- Updates the identity files exported by `tctl auth sign` to include the
user's TLS certificate, as well as the set of available TLS root CA
certs.
- Adds a new GRPC-based auth server method, `GenerateUserCerts`, which
exports both SSH and TLS based certs.
In case of IOT (whenever teleport nodes are
connecting to the proxy), there is no need
to create ReverseTunnel objects in the backend,
as there is always one reverse tunnel per node.
This commit removes the logic that created
reverse tunnel object in the backed in IOT cases
and refactors some other parts of the code.
Whenever many IOT style nodes are connecting
back to the web proxy server, they all
call /find endpoint to discover the configuration.
This new endpoint is designed to be fast and not
hit the database.
In addition to that every proxy reverse tunnel
connection handler was fetching auth servers and
this commit adds caching for the auth servers
on the proxy side.
Updated services.ReverseTunnel to support type (proxy or node). For
proxy types, which represent trusted cluster connections, when a
services.ReverseTunnel is created, it's created on the remote side with
name /reverseTunnels/example.com. For node types, services.ReverseTunnel
is created on the main side as /reverseTunnels/{nodeUUID}.clusterName.
Updated services.TunnelConn to support type (proxy or node). For proxy
types, which represent trusted cluster connections, tunnel connections
are created on the main side under
/tunnelConnections/remote.example.com/{proxyUUID}-remote.example.com.
For nodes, tunnel connections are created on the main side under
/tunnelConnections/example.com/{proxyUUID}-example.com. This allows
searching for tunnel connections by cluster then allows easily creating
a set of proxies that are missing matching services.TunnelConn.
The reverse tunnel server has been updated to handle heartbeats from
proxies as well as nodes. Proxy heartbeat behavior has not changed.
Heartbeats from nodes now add remote connections to the matching local
site. In addition, the reverse tunnel server now proxies connection to
the Auth Server for requests that are already authenticated (a second
authentication to the Auth Server is required).
For registration, nodes try and connect to the Auth Server to fetch host
credentials. Upon failure, nodes now try and fallback to fetching host
credentials from the web proxy.
To establish a connection to an Auth Server, nodes first try and connect
directly, and if the connection fails, fallback to obtaining a
connection to the Auth Server through the reverse tunnel. If a
connection is established directly, node startup behavior has not
changed. If a node establishes a connection through the reverse tunnel,
it creates an AgentPool that attempts to dial back to the cluster and
establish a reverse tunnel.
When nodes heartbeat, they also heartbeat if they are connected directly
to the cluster or through a reverse tunnel. For nodes that are connected
through a reverse tunnel, the proxy subsystem now directs the reverse
tunnel server to establish a connection through the reverse tunnel
instead of directly.
When sending discovery requests, the domain field has been replaced with
tunnelID. The tunnelID field is either the cluster name (same as before)
for proxies, or {nodeUUID}.example.com for nodes.
Previous Login code path was calling itself recursively.
In some cases that lead to endless loops with browser
opening up forever.
This commit factors out retry logic to RetryWithLogin
decorator handler that is used by CLI explicitly.
Client code became better as a result as there are no
hidden side effects.
Login could change the SSH proxy address based
on the information from "ping" endpoint
The function ConnectToProxy was saving
old version of the variable and kept using
it during login procedure.
This commit fixes that so the relevant
variable is always referenced.
This commit adds `--bind-addr` flag to tsh login
and TELEPORT_LOGIN_BIND_ADDR environment variable
to set up login bind address for SSO redirect flows.
Usage examples:
```
tsh login --bind-addr=localhost:3333
tsh login --bind-addr=:3333
tsh login --bind-addr=[::1]:3333
TELEPORT_LOGIN_BIND_ADDR=localhost:7777 tsh login
```
Refactor redirect flow and fix URLs for --bind-addr
This commit expands the usage of the caching layer
for auth server API:
* Introduces in-memory cache that is used to serve all
Auth server API requests. This is done to achieve scalability
on 10K+ node clusters, where each node fetches certificate authorities,
roles, users and join tokens. It is not possible to scale
DynamoDB backend or other backends on 10K reads per seconds
on a single shard or partition. The solution is to introduce
an in-memory cache of the backend state that is always used
for reads.
* In-memory cache has been expanded to support all resources
required by the auth server.
* Experimental `tctl top` command has been introduced to display
common single node metrics.
Replace SQLite Memory Backend with BTree
SQLite in memory backend was suffering from
high tail latencies under load (up to 8 seconds
in 99.9%-ile on load configurations).
This commit replaces the SQLite memory caching
backend with in-memory BTree backend that
brought down tail latencies to 2 seconds (99.9%-ile)
and brought overall performance improvement.
Added utils.CertChecker that wraps a ssh.CertChecker. The new
certificate checker first checks if the certificate is a valid
certificate for Teleport. At the moment that is 2048-bit RSA then calls
the underlying certificate checker to perform the requested validation.
Added github.com/gravitational/teleport/lib/secret package to replace
github.com/mailgun/lemma to move from NaCl to AES-GCM. NaCl is still
supported for legacy clients.
On the client side, make sure directory mode is requested when sending
multiple files. On the server side, when in directory mode, validate
that the target is a directory.