Fixes#19293
The error message "missing parameter hostname" wasn't very clear what hostname
was missing. Fail faster further up the stack and print a better error message
explaining what is happening.
This applies some checks aroung argument parsing while also adding some
belt-and-suspenders validation into `NewClientStoreFromIdentityFile`
* Set SkipLocalAuth on identity file use; Simplify logic for SkipLocalAuth.
* Fix TrustedCertsFromCACerts to work with known hosts without proxy host set in host name; Fix HostKeyCallback for keys.
* Add regression test where known hosts are not written with proxy host.
* Fix client key default host key callback.
* Return empty list, not not found error, when there are no trusted certs.
* Restore option to filter trusted host keys in host key callback.
* Update lib/client/identityfile/identity_test.go
Co-authored-by: Jakub Nyckowski <jakub.nyckowski@goteleport.com>
---------
Co-authored-by: Jakub Nyckowski <jakub.nyckowski@goteleport.com>
User certs for desktop access are only valid for a few minutes
and are never written to disk. This can make it difficult to
troubleshoot cert validity.
This commit adds support for generating Windows user certificates
which can be exported to the Windows environment for validation.
Note: at this time, we only write the certificate and not the
corresponding private key, making it impossible to use the generated
cert for any real purpose.
- Add a generalized client store made up of a key, profile, and trusted certs store. Each sub store can support different backends (~/.tsh, identity_file, in-memory).
- Replace custom identity file handling with in-memory client store.
- Fix issues with trusted certs handling.
A few of our tests that run certificate rotation fail with an error similar to this:
```
can only switch to phase update_clients from init, the current phase is
```
This happens when a duplicated private key is returned and set as a new key during CA rotation. During the CA rotation, we look for duplicated keys https://github.com/gravitational/teleport/blob/962e5a25bc56b5aad05528867182a43cd53cb551/lib/auth/rotate.go#L218 and try to rotate all of them at one. Because some of our tests use still use `testauthority` that only has 4 keys there is a huge chance that the same key will be returned twice, which causes the issue.
I swapped the logic to use a bigger pool with keys introduced in https://github.com/gravitational/teleport/pull/18750. I also removed the randomization part that, after some testing, I discovered was also causing some problems.
We could probably refactor the code in many tests now to make it simpler, but I want to keep this change as simple as possible. Otherwise, backporting bigger changes to older branches takes a long time.
When using `tctl auth sign --format kubernetes`, `tctl` only allowed a single cluster per `kubeconfig`.
This PR allows `tctl` to multiple calls of `tctl auth sign --format kubernetes` to be written to the same file without destroying previously introduced changes.
Fixes#18080
Update metalinter, fix a few lint warnings and replace deprecated linters.
`deadcode`, `structcheck` and `varcheck` are abandoned and now replaced by [`unused`][1].
Since 1.19, `go fmt` reformats godocs according to https://go.dev/doc/comment. I've done a bulk-reformatting of the codebase to keep the linter happy. Backporting is mostly harmless (the exception being `lib/services/role_test.go`, that for some reason breaks the _old_ linter using the new format).
[1]: https://golangci-lint.run/usage/linters/
* Bump golangci-lint version
* Replace abandoned linters
* Fix bodyclose on lib/auth/github.com
* Fix bodyclose on lib/kube/proxy/streamproto/proto_test.go
* Fix bodyclose on lib/srv/alpnproxy/proxy_test.go
* Fix bodyclose on lib/web/conn_upgrade_test.go
* Silence staticcheck on lib/kube/proxy/forwarder_test.go
* Silence staticcheck on lib/utils/certs_test.go
* Address BuildNameToCertificate deprecation warnings
* Run `go fmt ./...`
* Run `go fmt ./...` on api/
* Ignore formatting in role_test.go
* Remove redundant initializers in lib/srv/uacc/
* Update e/
Primary Changes:
- Remove reliance on Private Key PEM:
- Update native and keygen packages to return PrivateKey instead of PEM key
- Add new PrivateKey interface which implements crypto.Signer
- Replace PEM encoded private key usage where possible
- Replace calls to tls.(Load)X509KeyPair with keys.(Load)X509KeyPair in
client packages
Minor Changes:
- Remove unused agent.AddedKey return from LoadKey
- Simplify sshutils and removed unused code paths
- Add ecdsa and ed25519 key support
* Make tctl write out kube tls server name if tls routing is enabled
Fixes#14489
* Extract kube TLS name generation function to shareable location
We want tctl to be able to use this function as well, so we're locating it
in a place where both tctl and tsh can use it.
Also changing input parameter to k8s host, since it doesn't really care
about port number.
In the context of Teleport Discover we are trying to ease the usage of Teleport for the user's first interaction.
When adding a new database resource the user must, among other things, generate the mTLS files
Examples:
https://goteleport.com/docs/database-access/guides/postgres-self-hosted/#step-25-create-a-certificatekey-pairhttps://goteleport.com/docs/database-access/guides/mysql-self-hosted/#step-24-create-a-certificatekey-pair
This PR aims to reduce this friction: the user should be able to setup the resource without prior setup of local tools (`tsh login`)
We're doing this by providing an endpoint that will return those exact files
Demo
```shell
marco@lenix ~/p/downloadmtls> curl --silent --insecure 'https://127.0.0.1.nip.io:3080/v1/webapi/sites/lenix/sign' --dat
a '{"hostname":"discover.example.com", "ttl":"9999h", "format": "db"}' --header 'Authorization: Bearer 308bf3dd3019ddc4
2cff44a48e028480' --header 'Content-Type: application/json' -OJ
marco@lenix ~/p/downloadmtls> tar -xvf teleport_mTLS_discover.example.com.tar.gz
server.key
server.crt
server.cas
marco@lenix ~/p/downloadmtls> head -1 server.*
==> server.cas <==
-----BEGIN CERTIFICATE-----
==> server.crt <==
-----BEGIN CERTIFICATE-----
==> server.key <==
-----BEGIN RSA PRIVATE KEY-----
```
Fixes https://github.com/gravitational/teleport/issues/14049
After the merge of https://github.com/gravitational/teleport/pull/12674 we no longer use the following configuration:
```yaml
teleport:
ca_signature_algo: "rsa-sha2-512"
```
As we now rely upon the `x/crypto` package to choose the signing algorithm (it defaults to `rsa-sha2-512`)
**Demo**
If we set `ca_signature_algo` (the value is irrelevant) and start `teleport` we get:
```shell
root@marco:/workspace# teleport start --debug
2022-06-02T09:33:58Z WARN ca_signing_algo config option is deprecated and will be ignored, we'll always default to rsa-sha2-512. config/configuration.go:348
2022-06-02T09:33:58Z INFO Generating new host UUID: b001159a-10e0-49a7-b4dc-61c73fbe9e42. service/service.go:726
...
```
Fixes#12905
* Add new `identityfile` config template to `tbot`
This adds a new `identityfile` config template to tbot which
generates an identity file from any of the formats supported by
`tctl auth sign`.
It can be used by specifying one or more formats in the configuration
like so:
```yaml
destinations:
- directory: /foo
kinds: [ssh, tls]
configs:
- identityfile:
formats: [file]
```
It requires both SSH and TLS certificates to work properly. App,
Kubernetes, and Database certs are unlikely to work as they have
additional cert requirements that will be added in separate PRs.
Multiple formats can be specified, and each will be written to its
own subdirectory within the destination using the name of the format.
The particular files written inside this directory depend on the
particular format selected, but n the above example, this means a
file named `/foo/file/identity` is written.
The files all have an `identity` prefix at the moment. This could be
made configurable if desired.
The `file` format can be used in conjunction with `tsh -i` and
`tctl -i` to use those tools with a tbot-generated identity.
Fixes#10812
* Make identityfile formats first-class config templates
This promotes most of the important identityfile formats to proper
config templates. User-facing `kinds` are removed to reduce confusion
and several config templates are now required.
* The `ssh_client` template is now required and will be added
automatically in all cases if not specified.
* A new required `tls_cas` template is added to always export
the current Teleport server CAs in a usable format.
* A new required `identity` template is added to always export an
identity file usable with tsh/tctl.
* New optional `cockroach`, `mongo`, and `tls` templates can export
specifically-formatted TLS certs for various databases and apps.
Additionally some other changes were caught during testing:
* `botfs` now allows users to specify if files should be opened for
reading or for writing; previously, written files were never
truncated when opened for writing leading to garbage at the end of
files if the length changed. Truncation isn't sane for reading so
the two use-cases are now split.
* Update lib/client/identityfile/identity.go
Co-authored-by: Jakub Nyckowski <jakub.nyckowski@goteleport.com>
* Address first batch of review comments
Tweaked the `botfs.openStandard` and `botfs.openSecure` functions to
accept a plain file mode, and removed a ton of boilerplate in
`configtemplate.go`.
* Fix problematic nil interface check in configtemplate
* Clarify comment about `client.Key` DB certs
* Address review feedback
- Use `DatabaseCA` for database specific templates; make the `tls`
template's CA configurable; write the database CA alongside the
others.
- Simplify nil interface check
* Fix outdated var names
Co-authored-by: Jakub Nyckowski <jakub.nyckowski@goteleport.com>
Add support for Database Access for Redis for standalone and cluster self-hosted instances. Teleport requires mTLS in order to connect to Redis instance which is only supported in Redis 6.0+. RESP2 is currently the only supported protocol.
Introduce new make targets to check and add license headers to files
("make lint-license" and "make fix-license"). License checking is now a part of
"make lint" as well.
Initial attempts used goheader, but it caused "make lint-go" to become about 9x
slower (if not more), plus it only targets go files. Google's addlicense is fast
enough and targets however many file types we want.
Existing files that were missing licenses got the header added, using the
current year as the license date.
* Introduce lint-license and fix-license make targets
* Ignore generated files
* Add license to go files
* Replace irregular licenses with standard copyright/license
* Add license to proto files
* Install addlicense in build.assets Dockerfile
Implement context-based cancellation in `/lib/utils/prompt`, for MFA
prompts.
This fixes the following scenario:
```sh
User has both OTP and U2F devices registered.
$ tsh mfa ls
Name Type Added at Last used
----- ---- ----------------------------- -----------------------------
otp TOTP Wed, 21 Apr 2021 19:41:44 UTC Wed, 21 Apr 2021 19:44:32 UTC
usb-a U2F Wed, 21 Apr 2021 19:44:34 UTC Wed, 21 Apr 2021 19:44:34 UTC
Add a new OTP device, using existing U2F device:
$ tsh mfa add
Choose device type [TOTP, U2F]: totp
Enter device name: otp2
Tap any *registered* security key or enter a code from a *registered* OTP device: <tap> # <- First OTP prompt here
Open your TOTP app and create a new manual entry with these fields:
Name: awly@localhost:3080
Issuer: Teleport
Algorithm: SHA1
Number of digits: 6
Period: 30s
Secret: 3UD42X2NN7EEZ6LUPG6NFMNOLDY6AJTS
Once created, enter an OTP code generated by the app: 607738 # <- Second OTP prompt here
MFA device "otp2" added.
```
Before this PR, the first OTP prompt (for `*registered* device`) would
hang in the background. The OTP code from the newly-registered device is
prompted later, but any text written ends up going to the first prompt.
After this PR, the first prompt is canceled and the code from a new
device goes to the second prompt as intended.
Note: this is implemented using pure Go code (background goroutine
consuming `os.Stdin`) rather than syscalls (e.g. `poll` or `select`)
for portability.
```diff
~/.tsh/
└── keys
├── one.example.com --> Proxy hostname
│ ├── certs.pem --> TLS CA certs for the Teleport CA
│ ├── foo --> RSA Private Key for user "foo"
│ ├── foo.pub --> Public Key
- │ ├── foo-cert.pub --> SSH certificate for proxies and nodes
│ ├── foo-x509.pem --> TLS client certificate for Auth Server
+ │ ├── foo-ssh --> SSH certs for user "foo"
+ │ │ ├── root-cert.pub --> SSH cert for Teleport cluster "root"
+ │ │ └── leaf-cert.pub --> SSH cert for Teleport cluster "leaf"
```
When `-J` is provided, this also loads/reissues the SSH cert for the cluster associated with the jumphost's certificate. Fixes#5637.
* Added support for connecting API client through tunnel proxy and web proxy addresses (with identity file).
* Added concurrent dialing logic to dial several possible dialing combinations and seamlessly return the first client to connect.
* When exporting a kubeconfig, optionally overwrite the target file
Running `tctl auth sign ---out=filepath` or `tsh login --out=filepath`
might overwrite the target `filepath` regardless of its existing
contents.
Make the tools prompt the user before overwriting (by default) and
provide a flag to always force the overwrite (for automation).
Without overwrites, writing kubeconfig could fail if parsing the
existing file as a kubeconfig fails.
1. `tsh kube clusters` - lists registered kubernetes clusters
note: this only includes clusters connected via `kubernetes_service`
2. `tsh kube credentials` - returns TLS credentials for a specific kube
cluster; this is a hidden command used as an exec plugin for kubectl
3. `tsh kube login` - switches the kubectl context to one of the
registered clusters; roughly equivalent to `kubectl config
use-context`
When updating kubeconfigs, tsh now uses the exec plugin mode:
https://kubernetes.io/docs/reference/access-authn-authz/authentication/#client-go-credential-plugins
This means that on each kubectl run, kubectl will execute tsh with
special arguments to get the TLS credentials.
Using tsh as exec plugin allows us to put a login prompt when certs
expire. It also lets us lazy-initialize TLS certs for kubernetes
clusters.
`identityfile.Write` assumes that `key.TrustedCA` is populated when
writing a kubeconfig. It's where it takes the CA cert from.
`identityfile.Write` also, confusingly, had a separate `certAuthorities`
argument carrying the same information.
On `tctl auth sign --format=kubernetes --user=foo` we only populated the
`certAuthorities` argument, but not `key.TrustedCA`.
To fix this, and avoid future confusion, remote `certAuthorities`
arugment entirely and always pass CA certs via `key.TrustedCA`. Add a
happy path unit test to make sure it doesn't break in the future.
Also, improve error output a bit and make `--out` a required flag.
Caught by `ineffassign` linter.
Note the change in lib/srv/regular/sshserver.go - looks like we
advertised the custom listening port (`aport`), if it differed from
regular listening port (`port`).
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
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