* Enable nolintlint linter
* Fix nolint comments in the api package
* Fix RDP client comment
* Address review comment
Co-authored-by: Alan Parra <alan.parra@goteleport.com>
* Allow unused for nolintlint linter
* Remove redundant casting
* Add comment on why allowed unused is enabled
Co-authored-by: Alan Parra <alan.parra@goteleport.com>
Co-authored-by: Alan Parra <alan.parra@goteleport.com>
We were inconsistent throughout the codebase and would sometimes
use the slices package and other times use our own equivalents
in api/.
This removes our versions in favor of the golang.org/x package that
does the same, which has the added benefit of reducing the surface
area of the public API module.
Note: despite existing uses of the slices package, for some reason
it didn't show up in go.mod or go.sum. Fixed that too.
* Introduce Github Actions join support
* Go mod tidy
* run goimports on source files
* Address PR comments
* More PR review comments
* Changes to tests based on PR feedback
* Improve error message in github rule validation
* Add support for SHA
* Add short message describing which fields shouldb be included
Fix the `test-go-root` target in the `Makefile`, adding a missing
backslash at the end of the first line of the recipe.
Use `User.Username` instead of `User.Name` in the tbot
`TestInitMaybeACLs` test as that value ultimately is passed to
`user.Lookup`, which requires a username. I assume tests on CI were
running where Username == Name.
* Add Yubikey PrivateKey implementation for use by Teleport clients.
- Add yubikey login logic, reusing previously stored private keys.
- Fix identity file decoding with PIV keys, which sign ecdsa certificates.
- Add libpcsclite-dev pre-req for building on linux.
- Remove unnecessary keys.Signer interface and move its functionality to keys.PrivateKey.
- Move retry and jitter utils to new api/utils/retryutils package.
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/
* Add Kubernetes Access support to Machine ID
This adds support for Kubernetes Access to Machine ID. Users can now
request access to a Kubernetes cluster with the new
`kubernetes_cluster` config field. When a request is configured, a
`kubeconfig.yaml` is generated which can be used to access the given
cluster.
As part of this, we also refactor a few parts of the bot code to help
cache various requests that config templates make frequently by
passing a new trivial `bot.B` interface to the `Render()` function.
For good measure, we also fix the `destination.Destination` stutter
by moving the interface to `bot.Destination`.
* Remove unused CLI param and fix docstring typo
* Cache cert authority requests
We now cache most cert authority requests from config templates and
purge the cache after each cert renewal.
* Move bot.B to config.Bot
* Add a matching marshaller for the KubernetesCluster type.
* configure golangci-lint misspell to check for anglicized spellings
* Americanize spellings
* fix aws constant value with british spelling 🇬🇧
* update api types with americanized spellings
* use american spellings .cloudbuild/scripts
* start hashing out machine id CA rotation
* filter out incoming ca events by type
* support multiple trusted certificate authorities in known_hosts
* remove redundant trace.Debug from `tbot` `main()`
* filter to only recieve relevant CA events
* add exponential backoff to renewal
* remove unnecessary `.Ping()` check with new client
* add unit test for filtering CA events
* debounce reloads
* add retry limit and backoff for CA watching
* add integration test for CA rotation
* modify CA rotation watcher loop to retry forever
Co-authored-by: Tim Buckley <tim@goteleport.com>
`tctl version`, just as `tsh version`,
prints out the version of the binary itself,
not the version of the cluster it's connected to.
The cluster version can be discovered by running
`tctl status`.
* start refactoring tbot to have a core struct
* refactor tbot into lib/
* move `tbot` subpackages to `lib/tbot`
* remove mutex pointer
* move `tshwrap` to `lib/` from `/tool/tbot/`
* move new template ssh client render test to lib/
* address pr feedback
* add request changed
`tshwrap` performs a tsh version check to ensure it has the
functionality we need. Unfortunately, during a final refactoring
before merging, we changed the function signature of `capture()` to
require an explicit path to a `tsh` binary but in a way that was
unfortunately not caught by the compiler. The previous syntax meant
we just tried to execute the first argument, i.e. `version`, which
is never what we want.
This PR correctly passes the tsh path to `capture()` to fix the
version check.
* Re-add `kinds` config field with a deprecation warning
This re-adds the `kinds` config field with a deprecation warning. We
removed the field in #11596 but due to strict YAML parsing this
causes existing otherwise compatible configs to error out.
* Update tool/tbot/config/config_destination.go
Co-authored-by: Zac Bergquist <zmb3@users.noreply.github.com>
* Use standardized deprecation comment formatting
Co-authored-by: Zac Bergquist <zmb3@users.noreply.github.com>
This fixes a bug where the SSH HostCA is missing in impersonated
identities. We only include it in primary identities via the
server-side `includeHostCA` flag which can't be directly set by
clients. Without this CA, impersonated identities can't successfully
connect to the auth server via an SSH tunnel, so database requests
fail when using IoT joining.
We fix this by instead copying SSH CAs from the primary identity.
* Extend support for identity files in tsh
This enhances support for identity files in tsh, which previously only
worked for regular SSH access. The largest blocker for support is that
tsh uses profiles for all non-SSH resource access, and profiles have a
direct mapping to some on-disk resources. This patch works around this
in a few ways:
* Virtual profiles: When an identity file is specified with `-i`, we
use it to create an in-memory virtual profile using the cert as the
root identity _and_ for every `RouteToDatabase` (and in the future,
app) field contained in the cert.
* Virtual profile paths: Certain profile operations require paths to
valid certificates and other resources on disk, which may not exist
inside the identity file.
As the driving use-case for this change is integration with Machine
ID, we can "cheat" and pass the correct paths to tsh via
environment variables. A cooperating wrapper in `tbot` will execute
`tsh` with appropriate flags and environment variables, which
override tsh's usual certifiate paths. This allows commands like
`tsh db connect ...` to work as expected.
* Key stores: previously we used a `noLocalKeyStore{}` with which all
lookups fail. This patch replaces it with an in-memory keystore if
a client key is available.
* Profile status: lastly, we add a new `StatusCurrentWithIdentity()`
function to load virtual profiles where supported. Some commands
are not supported in this PR (like `tsh app ...`), but others
don't make sense to support (like cert reissuing).
We might consider merging everything into the traditional
`StatusCurrent()` when adding app support.
App access is still broken and will be addressed in a later change.
Partially fixes#11770
* Fix failing lint
* Add `tbot proxy` and `tbot db` wrapper commands
This adds new wrapper commands that leverage tsh for proxy and
database access.
It also adds a new `tshwrap` helper package which contains utilities
for locating the tsh executable, checking its version, and loading
all necessary data (certificates, destinations, etc) that will need
to be passed to tsh for wrapped commands to function.
* Fix failing unit test due to incorrect default IsVirtual profile flag
* Combine `StatusCurrentWithIdentity()` into `StatusCurrent()`
Additionally, log a warning when environment variable paths aren't
found.
* Fix virtual profile flag always being true
* Update lib/client/api.go
Co-authored-by: Krzysztof Skrzętnicki <krzysztof.skrzetnicki@goteleport.com>
* Address review feedback
* Use `tbot proxy` in generated `ssh_config`
* Add tests for mockable parts of our tsh integration
* Fix lints
* Clarify docstrings in CLIConf
* Tweak comment for clarity; fix typo in `onProxyCommand`
* Add missing copyright header
* Fix failing unit test and pass destination to `Describe()`
This fixes a failing unit test by making the description for
`ssh_config` match its behavior in practice. This necessitated
passing the destination to all templates, unfortunately.
* Add a few extra tests
* Apply suggestions from code review
Co-authored-by: Alan Parra <alan.parra@goteleport.com>
* Address another batch of review comments
* Comment tweaks
* Refactor tshwrap to remove the Runner interface.
* Apply suggestions from code review
Co-authored-by: Alan Parra <alan.parra@goteleport.com>
* Address review comments
Co-authored-by: Krzysztof Skrzętnicki <krzysztof.skrzetnicki@goteleport.com>
Co-authored-by: Alan Parra <alan.parra@goteleport.com>
* 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>
* Allow users to request database certificates in Machine ID
This adds a new destination-level config option to `tbot.yaml` that
allows users to request database access for a particular destination
certificate. Behind the scenes, this triggers generates two
impersonated certs: the first identity is generated to request the
specified roles and resolve the database config, then is replaced
with a new identity using those roles plus a fully-formed
`RouteToDatabase` request.
Database requests are made by adding a destination entry like the
following to `tbot.yaml`:
```yaml
destinations:
- directory: /foo/bar
database:
service: <teleport database name>
username: <database username>
database: <database name>
# The certs won't be very useful without TLS
kinds: [tls]
```
We currently don't support proxying or generating db-specific config
files. See #11596 for an `identityfile` implementation that can help.
Additionally, we don't currently have a `tsh proxy` equivalent so the
legacy MySQL handlers need to be enabled, which is not the case by
default in Teleport 9. However, that same PR can export a
tsh-compatible identity file for the datbase identity which can be
passed along to `tsh -i ...` and presumably used with its proxy
commands. We plan to follow-up with another PR to improve this UX.
* Try to fix flaky test
* Address review feedback
* Update tool/tbot/renew.go
Co-authored-by: Roman Tkachenko <roman@goteleport.com>
* Add special username checks for MongoDB and Redis
Co-authored-by: Roman Tkachenko <roman@goteleport.com>
* Improve error handling in `tbot start`
This attempts to improve a number of error handling issues while
loading the bot identity from storage in `tbot start`:
1. Identity loading errors are silently ignored and the bot
always attempts to generate a new identity from token. This isn't
always correct and is impossible to debug as the true error is
never logged. We now debug log these errors.
2. `LoadIdentity()` doesn't properly account for existing-but-empty
identity files and happily tries to load empty identities from
`tbot init`. This isn't hugely harmful, but produces nonsensical
error logs once #1 is fixed.
* Use `O_RDWR` instead of `O_WRONLY` in `botfs.openStandard()`
This behaves the same as the fs_linux secure implementation in
all cases, and moves the open mode to a shared constant for good
measure.
* Add a small unit test for symlinks mode read/write.
* Fail on non-NotFound errors while reading an Identity.
* Add small unit test for empty identities.
* Remove outdated TODO comment
* Apply suggestions from code review
Co-authored-by: Zac Bergquist <zmb3@users.noreply.github.com>
* Address review feedback
Co-authored-by: Zac Bergquist <zmb3@users.noreply.github.com>
The default `join_method` value was improperly assumed to be "" which
caused any onboarding config from the config file to be overwritten.
This uses the correct default and allows bots to be fully onboarded
via config file.
Fixes#11099
The inferred default was changed without updating the flag's help
message. This updates the help message to explain the new default
value of `--owner`.
`staticcheck` does not seem to appreciate our nop implementations for
non-Linux OSes and produces several noisy warnings about it. This
disables the lints as precisely as possible.
* UX improvements for tbot
A last batch of UX tweaks for 9.0:
- rename --renew-interval -> renewal-interval
- add `--oneshot` mode to fetch one set of certs and exit (client
side only, no server enforcement yet)
- add `tbot version`
- add unix signal handling: graceful exit on SIGINT, reload on
SIGHUP/SIGUSR1
- make auth server an optional config option and check it only when
needed (i.e. `tbot start`)
* Remove `--auth-server` flag from `tbot init` example
* Add `cut` workaround to allow connecting to nodes without DNS
* Update product name in tbot CLI help
* Add `--format=json` support to `tctl bots add`
* Detect OpenSSH version and conditionally remove the RSA deprecation workaround
* Fix failing unit test after rename
* Update tool/tbot/config/configtemplate_ssh.go
Co-authored-by: Zac Bergquist <zmb3@users.noreply.github.com>
* Address review feedback
* Apply suggestions from code review
Co-authored-by: Alan Parra <alan.parra@goteleport.com>
* Document IncludeRSAWorkaround and address review comments
Co-authored-by: Zac Bergquist <zmb3@users.noreply.github.com>
Co-authored-by: Alan Parra <alan.parra@goteleport.com>
* Fix goroutine and memory leak in watchCertAuthorities
The CA Watcher was blocking both on writing to a channel when the watcher
was closed and on HTTP calls that had no request timeout or context passed
to cause cancellation.
All resourceWatcher implementations that had a bug which may cause them to block
on writing to a channel forever were fixed by selecting on the write and ctx.Done.
Adding context.Context to all Get/Put/Post/Delete methods on the auth HTTPClient to
force callers to propagate context. Prior all calls used context.TODO which
prevents requests from being properly cancelled.
Add context propagation to RotateCertAuthority, RotateExternalCertAuthority,
GetCertAuthority, GetCertAuthorities. This is needed to get the correct ctx
from the CertAtuhorityWatcher all the way down to the HTTPClient that makes
the call.
Closes#10648
* Add certificate renewal bot
This adds a new `tbot` tool to continuously renew a set of
certificates after registering with a Teleport cluster using a
similar process to standard node joining.
This makes some modifications to user certificate generation to allow
for certificates that can be renewed beyond their original TTL, and
exposes new gRPC endpoints:
* `CreateBotJoinToken` creates a join token for a bot user
* `GenerateInitialRenewableUserCerts` exchanges a token for a set of
certificates with a new `renewable` flag set
A new `tctl` command, `tctl bots add`, creates a bot user and calls
`CreateBotJoinToken` to issue a token. A bot instance can then be
started using a provided command.
* Cert bot refactoring pass
* Use role requests to split renewable certs from end-user certs
* Add bot configuration file
* Use `teleport.dev/bot` label
* Remove `impersonator` flag on initial bot certs
* Remove unnecessary `renew` package
* Misc other cleanup
* Do not pass through `renewable` flag when role requests are set
This adds additional restrictions on when a certificate's `renewable`
flag is carried over to a new certificate. In particular, it now also
denies the flag when either role requests are present, or the
`disallowReissue` flag has been previously set.
In practice `disallow-reissue` would have prevented any undesired
behavior but this improves consistency and resolves a TODO.
* Various tbot UX improvements; render SSH config
* Fully flesh out config template rendering
* Fix rendering for SSH configuration templates
* Added `String()` impls for destination types
* Improve certificate renewal logging; show more detail
* Properly fall back to default (all) roles
* Add mode hints for files
* Add/update copyright headers
* Add stubs for tbot init and watch commands
* Add gRPC endpoints for managing bots
* Add `CreateBot`, `DeleteBot`, and `GetBotUsers` gRPC endpoints
* Replace `tctl bot (add|rm|ls)` implementations with gRPC calls
* Define a few new constants, `DefaultBotJoinTTL`, `BotLabel`,
`BotGenerationLabel`
* Fix outdated destination flag in example tbot command
* Bugfix pass for demo
* Fixed a few nil pointer derefs when using config from CLI args
* Properly create destination if `--destination-dir` flag is used
* Remove improper default on CLI flag
* `DestinationConfig` is now a list of pointers
* Address first wave of review feedback
Fixes the majority of smaller issues caught by reviewers, thanks all!
* Add doc comments for bot.go functions
* Return the token TTL from CreateBot
* Split initial user cert issuance from `generateUserCerts()`
Issuing initial renewable certificate ended up requiring a lot of
hacks to skip checks that prevented anonymous bots from getting
certs even though we'd verified their identity elsewhere (via token).
This reverts all those hacks and splits initial bot cert logic into a
dedicated `generateInitialRenewableUserCerts()` function which should
make the whole process much easier to follow.
* Set bot traits to silence log messages
* tbot log message consistency pass
* Implement `tbot init` subcommand
This adds a new CLI subcommand to initialize a tbot destination
directory by creating required files ahead of time and assigning
proper permissions (and ACLs, where possible).
* Resolve lints
* Add config tests
* Remove CreateBotJoinToken endpoint
Users should instead use the CreateBot/DeleteBot endpoints.
* Create a fresh private key for every impersonated identity renewal
* Hide `config` subcommand
* Rename bot label prefix to `teleport.internal/`
* Use types.NewRole() to create bot roles
* Clean up error handling in custom YAML unmarshallers
Also, add notes about the supported YAML shapes.
* Fetch proxy host via gRPC Ping() instead of GetProxies()
* Update lib/auth/bot.go
Co-authored-by: Zac Bergquist <zmb3@users.noreply.github.com>
* Fix some review comments
* Add renewable certificate generation checks (#10098)
* Add renewable certificate generation checks
This adds a new validation check for renewable certificates that
maintains a renewal counter as both a certificate extension and a
user label. This counter is used to ensure only a single certificate
lineage can exist: for example, if a renewable certificate is stolen,
only one copy of the certificate can be renewed as the generation
counter will not match
When renewing a certificate, first the generation counter presented
by the user (via their TLS identity) is compared to a value stored
with the associated user (in a new `teleport.dev/bot-generation`
label field). If they aren't equal, the renewal attempt fails.
Otherwise, the generation counter is incremented by 1, stored to the
database using a `CompareAndSwap()` to ensure atomicity, and set on
the generated certificate for use in future renewals.
* Add unit tests for the generation counter
This adds new unit tests to exercise the generation counter checks.
Additionally, it fixes two other renewable cert tests that were
failing.
* Remove certRequestGeneration() function
* Emit audit event when cert generations don't match
* Fully implement `tctl bots lock`
* Show bot name in `tctl bots ls`
* Lock bots when a cert generation mismatch is found
* Make CompareFailed respones from validateGenerationLabel() more actionable
* Update lib/services/local/users.go
Co-authored-by: Nic Klaassen <nic@goteleport.com>
* Backend changes for tbot IoT and AWS joining (#10360)
* backend changes
* add token permission check
* pass ctx from caller
Co-authored-by: Roman Tkachenko <roman@goteleport.com>
* fix comment typo
Co-authored-by: Roman Tkachenko <roman@goteleport.com>
* use UserMetadata instead of Identity in RenewableCertificateGenerationMismatch event
* Client changes for tbot IoT joining (#10397)
* client changes
* delete replaced APIs
* delete unused tbot/auth.go
* add license header
* don't unecessarily fetch host CA
* log fixes
* s/tunnelling/tunneling/
Co-authored-by: Zac Bergquist <zmb3@users.noreply.github.com>
* auth server addresses may be proxies
Co-authored-by: Zac Bergquist <zmb3@users.noreply.github.com>
* comment typo fix
Co-authored-by: Zac Bergquist <zmb3@users.noreply.github.com>
* move *Server methods out of auth_with_roles.go (#10416)
Co-authored-by: Tim Buckley <tim@goteleport.com>
Co-authored-by: Zac Bergquist <zmb3@users.noreply.github.com>
Co-authored-by: Tim Buckley <tim@goteleport.com>
Co-authored-by: Roman Tkachenko <roman@goteleport.com>
Co-authored-by: Tim Buckley <tim@goteleport.com>
Co-authored-by: Zac Bergquist <zmb3@users.noreply.github.com>
Co-authored-by: Nic Klaassen <nic@goteleport.com>
Co-authored-by: Roman Tkachenko <roman@goteleport.com>
Co-authored-by: Zac Bergquist <zmb3@users.noreply.github.com>
* Address another batch of review feedback
* Addres another batch of review feedback
Add `Role.SetMetadata()`, simplify more `trace.WrapWithMessage()`
calls, clear some TODOs and lints, and address other misc feedback
items.
* Fix lint
* Add missing doc comments to SaveIdentity / LoadIdentity
* Remove pam tag from tbot build
* Update note about bot lock deletion
* Another pass of review feedback
Ensure all requestable roles exist when creating a bot, adjust the
default renewable cert TTL down to 1 hour, and check types during
`CompareAndSwapUser()`
* Remove ModeHint
* Rename Identity.Cert and Identity.XCert
* Add `symlinks` flag to tbot config
The optional symlinks flag for directory destinations allows users to
opt in / out of whichever symlink attack hardening mode is selected
by default.
* Add mostly-working secure implementation of botfs.Create/Write
This adds symlink mode selection (secure, try-secure, insecure) and
Linux `Create()`/`Write()` implementations to open files safely.
* Add configurable ACL modes and verify ACL support in tbot init
* Initialize destinations at startup and test before renewal
This initializes destinations at startup (to create directories if
not using `tbot init`) and tests them to ensure the bot can write
_before_ attempting to renew certificates; this should prevent most
accidental generation counter locks.
* Hide watch for now
* Issue a new identity if a token change is detected
* Warn if identity appears to be expired on startup
* Fully implement ACL Verify and Configure
- Fully implements ACL support for Linux
- Adds bot-side verification support to ensure ACLs are configured
properly at runtime.
- Gracefully falls back to no ACLs if the platform / filesystem
doesn't support them
- Clear up outstanding lints
* Make `tbot init` work without a config file
* Show init instructions in tctl bots add
Also:
- Make --bot-user a flag in init (the tctl instructions were
confusing otherwise)
- Handle IsOwnedBy sanely on unsupported platforms
- Add Bold colorizing support
* Clear some TODOs and rephrase tctl help
* Fix typo
* Fix token hash detection bug
* Actually read and write certs with symlink enforcement
Also, fix a config loading bug where CheckAndSetDefaults() wasn't
being called in all cases with CLI destinations.
* Add workaround for OpenSSH permissions check with ACLs
OpenSSH has an overly-paranoid permissions check that forces key
files to be exclusively owner-readable. Unfortunately, for POSIX
compatibility purposes, when ACLs are set, the ACL mask is set as
the group permissions. This effectively makes any ACL incompatible
with OpenSSH.
However, OpenSSH's check does have an escape hatch: it only applies
if the current user is the owner of the file. Therefore, this change
tweaks the `tbot init` flow to create files as root, owned by a
separate user (either `nobody` or even the bot user), with ACL
permissions granting both the bot and reader user access to the
certificates. This effectively bypasses OpenSSH's permissions check
and should preserve our security boundaries.
* Fix lints
* Fix an improper directory chmod to 0600 if ACL test fails
* First pass of tbot init unit tests
* Add symlink tests and fix bug with resolving the default owner
* Fix err misuse
* Fix an ACL error if the bot or reader user is the owner.
* Fix typo
* Fix missing error case in VerifyACL causing unreadable directories
* Address review feedback
- Rename ACLOn -> ACLRequired
- Simplify fs_linux.Read()
- Add missing fs_other.Read()
- Hoist renewal loop logic into its own function
- A few misc bugfixes
* Apply suggestions from code review
Co-authored-by: rosstimothy <39066650+rosstimothy@users.noreply.github.com>
* Address review feedback
- Only log syscall warning once
- Formatting and wording changes
- Improve error handling for `--clean`
* Fix lint error
* Fix imports in fs_other
* Fix possible nil pointer deref if storage is unset
* Use the bot user as default owner
This is more likely to be a safe owner choice than `nobody:nobody`.
* Apply suggestions from code review
Co-authored-by: Roman Tkachenko <roman@goteleport.com>
* Code review fixes
Co-authored-by: Zac Bergquist <zmb3@users.noreply.github.com>
Co-authored-by: Nic Klaassen <nic@goteleport.com>
Co-authored-by: Roman Tkachenko <roman@goteleport.com>
Co-authored-by: rosstimothy <39066650+rosstimothy@users.noreply.github.com>
* Add certificate renewal bot
This adds a new `tbot` tool to continuously renew a set of
certificates after registering with a Teleport cluster using a
similar process to standard node joining.
This makes some modifications to user certificate generation to allow
for certificates that can be renewed beyond their original TTL, and
exposes new gRPC endpoints:
* `CreateBotJoinToken` creates a join token for a bot user
* `GenerateInitialRenewableUserCerts` exchanges a token for a set of
certificates with a new `renewable` flag set
A new `tctl` command, `tctl bots add`, creates a bot user and calls
`CreateBotJoinToken` to issue a token. A bot instance can then be
started using a provided command.
* Cert bot refactoring pass
* Use role requests to split renewable certs from end-user certs
* Add bot configuration file
* Use `teleport.dev/bot` label
* Remove `impersonator` flag on initial bot certs
* Remove unnecessary `renew` package
* Misc other cleanup
* Do not pass through `renewable` flag when role requests are set
This adds additional restrictions on when a certificate's `renewable`
flag is carried over to a new certificate. In particular, it now also
denies the flag when either role requests are present, or the
`disallowReissue` flag has been previously set.
In practice `disallow-reissue` would have prevented any undesired
behavior but this improves consistency and resolves a TODO.
* Various tbot UX improvements; render SSH config
* Fully flesh out config template rendering
* Fix rendering for SSH configuration templates
* Added `String()` impls for destination types
* Improve certificate renewal logging; show more detail
* Properly fall back to default (all) roles
* Add mode hints for files
* Add/update copyright headers
* Add stubs for tbot init and watch commands
* Add gRPC endpoints for managing bots
* Add `CreateBot`, `DeleteBot`, and `GetBotUsers` gRPC endpoints
* Replace `tctl bot (add|rm|ls)` implementations with gRPC calls
* Define a few new constants, `DefaultBotJoinTTL`, `BotLabel`,
`BotGenerationLabel`
* Fix outdated destination flag in example tbot command
* Bugfix pass for demo
* Fixed a few nil pointer derefs when using config from CLI args
* Properly create destination if `--destination-dir` flag is used
* Remove improper default on CLI flag
* `DestinationConfig` is now a list of pointers
* Address first wave of review feedback
Fixes the majority of smaller issues caught by reviewers, thanks all!
* Add doc comments for bot.go functions
* Return the token TTL from CreateBot
* Split initial user cert issuance from `generateUserCerts()`
Issuing initial renewable certificate ended up requiring a lot of
hacks to skip checks that prevented anonymous bots from getting
certs even though we'd verified their identity elsewhere (via token).
This reverts all those hacks and splits initial bot cert logic into a
dedicated `generateInitialRenewableUserCerts()` function which should
make the whole process much easier to follow.
* Set bot traits to silence log messages
* tbot log message consistency pass
* Resolve lints
* Add config tests
* Remove CreateBotJoinToken endpoint
Users should instead use the CreateBot/DeleteBot endpoints.
* Create a fresh private key for every impersonated identity renewal
* Hide `config` subcommand
* Rename bot label prefix to `teleport.internal/`
* Use types.NewRole() to create bot roles
* Clean up error handling in custom YAML unmarshallers
Also, add notes about the supported YAML shapes.
* Fetch proxy host via gRPC Ping() instead of GetProxies()
* Update lib/auth/bot.go
Co-authored-by: Zac Bergquist <zmb3@users.noreply.github.com>
* Fix some review comments
* Add renewable certificate generation checks (#10098)
* Add renewable certificate generation checks
This adds a new validation check for renewable certificates that
maintains a renewal counter as both a certificate extension and a
user label. This counter is used to ensure only a single certificate
lineage can exist: for example, if a renewable certificate is stolen,
only one copy of the certificate can be renewed as the generation
counter will not match
When renewing a certificate, first the generation counter presented
by the user (via their TLS identity) is compared to a value stored
with the associated user (in a new `teleport.dev/bot-generation`
label field). If they aren't equal, the renewal attempt fails.
Otherwise, the generation counter is incremented by 1, stored to the
database using a `CompareAndSwap()` to ensure atomicity, and set on
the generated certificate for use in future renewals.
* Add unit tests for the generation counter
This adds new unit tests to exercise the generation counter checks.
Additionally, it fixes two other renewable cert tests that were
failing.
* Remove certRequestGeneration() function
* Emit audit event when cert generations don't match
* Fully implement `tctl bots lock`
* Show bot name in `tctl bots ls`
* Lock bots when a cert generation mismatch is found
* Make CompareFailed respones from validateGenerationLabel() more actionable
* Update lib/services/local/users.go
Co-authored-by: Nic Klaassen <nic@goteleport.com>
* Backend changes for tbot IoT and AWS joining (#10360)
* backend changes
* add token permission check
* pass ctx from caller
Co-authored-by: Roman Tkachenko <roman@goteleport.com>
* fix comment typo
Co-authored-by: Roman Tkachenko <roman@goteleport.com>
* use UserMetadata instead of Identity in RenewableCertificateGenerationMismatch event
* Client changes for tbot IoT joining (#10397)
* client changes
* delete replaced APIs
* delete unused tbot/auth.go
* add license header
* don't unecessarily fetch host CA
* log fixes
* s/tunnelling/tunneling/
Co-authored-by: Zac Bergquist <zmb3@users.noreply.github.com>
* auth server addresses may be proxies
Co-authored-by: Zac Bergquist <zmb3@users.noreply.github.com>
* comment typo fix
Co-authored-by: Zac Bergquist <zmb3@users.noreply.github.com>
* move *Server methods out of auth_with_roles.go (#10416)
Co-authored-by: Tim Buckley <tim@goteleport.com>
Co-authored-by: Zac Bergquist <zmb3@users.noreply.github.com>
Co-authored-by: Tim Buckley <tim@goteleport.com>
Co-authored-by: Roman Tkachenko <roman@goteleport.com>
Co-authored-by: Tim Buckley <tim@goteleport.com>
Co-authored-by: Zac Bergquist <zmb3@users.noreply.github.com>
Co-authored-by: Nic Klaassen <nic@goteleport.com>
Co-authored-by: Roman Tkachenko <roman@goteleport.com>
Co-authored-by: Zac Bergquist <zmb3@users.noreply.github.com>
* Address another batch of review feedback
* Addres another batch of review feedback
Add `Role.SetMetadata()`, simplify more `trace.WrapWithMessage()`
calls, clear some TODOs and lints, and address other misc feedback
items.
* Fix lint
* Add missing doc comments to SaveIdentity / LoadIdentity
* Remove pam tag from tbot build
* Update note about bot lock deletion
* Another pass of review feedback
Ensure all requestable roles exist when creating a bot, adjust the
default renewable cert TTL down to 1 hour, and check types during
`CompareAndSwapUser()`
Co-authored-by: Zac Bergquist <zmb3@users.noreply.github.com>
Co-authored-by: Nic Klaassen <nic@goteleport.com>
Co-authored-by: Roman Tkachenko <roman@goteleport.com>