This change adds the --all/-R flag to tsh ls, tsh apps ls, tsh db ls, and tsh kube ls, which lets tsh list resources from across all clusters and logged in proxies.
* Add CSRF mitigations
This commit includes two fixes:
1. Enforce an application/json Content-Type server-side.
2. When checking the bearer token, verify that the user
associated with the token matches the user associated
with the cookie.
* Fix TEL-Q122-13: Access Requests Denial Of Service Via Request Reason (#125) (#127)
* Ignore input when data flow is off in TermManager
When data flow is disabled in TermManager (at the beginning or when TermManager.Off was called) we should ignore all input we receive (currently we buffer it)
* Agent forwarding socket security fix.
Co-authored-by: Lisa Kim <lisa@goteleport.com>
Co-authored-by: Joel <jwejdenstal@icloud.com>
Co-authored-by: Przemko Robakowski <przemko@przemko-robakowski.pl>
* Add support for automatic user provisioning
* Add UID parker to reexec
* Add a `teleport park` subcommand that does nothing
Co-authored-by: Edoardo Spadolini <edoardo.spadolini@goteleport.com>
This adds proxy peering support. A configurable setting that allows for agents
to connect to a subset of proxies and be reachable through any proxy in the
cluster. This is achieved by creating grpc connections between each proxy
server. Client connections can then be passed between proxies to the desired
agent.
* Optionally provide ca_pin as a file path
* Fix lint errors
* Test CA pin reads from file and from string
* Simplify ApplyCAPins
* Update lib/service/cfg.go
Co-authored-by: Alan Parra <alan.parra@goteleport.com>
* Update lib/utils/utils_test.go
Co-authored-by: Alan Parra <alan.parra@goteleport.com>
* Move length check into ApplyCAPins
* Rename token.go to config.go
* Add test for statictoken parsing
* Refactor token parsing test
* Error on empty ca_pin file
* Warn if config value is a path to an empty file
* Update lib/config/fileconf_test.go
Co-authored-by: Alan Parra <alan.parra@goteleport.com>
* Log empty file warning instead of printing
* Allow multiple entries in files referenced by config values
* Update static token parsing test
* Test reading multiple tokens/pins from a file referenced by a config
* Update lib/config/fileconf.go
Co-authored-by: Alan Parra <alan.parra@goteleport.com>
Co-authored-by: Alan Parra <alan.parra@goteleport.com>
* FnCache context improvements
Modifies the FnCache to be constructed with a context.Context
which is passed to all loadfn provided to Get. This removes
the burden placed on callers to ensure loadfn are not request
context scoped.
* 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 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.
Adding a "marker" to Keychain labels lets us detect unexpected entries (which I
did see happen) and gives us flexibility to change formats in the future.
A marker in the "label" field seems to be enough to achieve the purposes above,
so I stopped at that. Added a couple minor UX tweaks as well.
#9160
* Use a marker for Keychain labels
* Tweak: Rename "Key Handle" to "Credential ID" for consistency
* Tweak: Do not prompt MFA/OTP if doing Touch ID
* Use trace errors
* add hostlogin to proxy config for windows
* Set ProxyClient's HostLogin to the Windows username
Also convert a few TLS handshakes to a context-aware version
for better timeout/cancelation behavior.
Co-authored-by: Zac Bergquist <zac.bergquist@goteleport.com>
Co-authored-by: Zac Bergquist <zmb3@users.noreply.github.com>
* Respect timeout in `(directDial).DialTimeout`
* Add a Timeout to the api/client/webclient calls
* Respect timeout in (proxyDial).DialTimeout
* Applied suggestion
Co-authored-by: Alan Parra <alan.parra@goteleport.com>
Co-authored-by: Alan Parra <alan.parra@goteleport.com>
* Remove unused backend wrapper from Cache
* Remove double printShutdownStatus
* Fix readyz race condition
* Test coverage for the readyz.monitor fix
* Close listeners immediately in proxy.shutdown
* Use and handle net.ErrClosed correctly
This adapts utils.IsUseOfClosedNetworkError to check for net.ErrClosed
even inside trace.Aggregate errors, makes it so that we always return
something that would pass errors.Is(err, net.ErrClosed) when returning
from a (net.Listener).Accept(), and handles closed listeners within our
various Serve() loops so that we don't hit spurious backoff waits while
shutting down.
* Close listeners early and emitters late
* Test coverage for the proxy listener changes
* Revert some errors back to trace.ConnectionProblem
* Reduce PR scope to just the proxy, add comments
* Improve error logging.
* Revert "Make `PortList.Pop()` thread-safe (#11799)"
This reverts commit a17337d1a1.
* Revert "Ensure stateOK is reported only when all components have sent updates (#11249)"
This reverts commit b749302e2c.
* Revert "Throw startup error if `TeleportReadyEvent` is not emitted (#11725)"
This reverts commit 933e247287.
* Revert "Fix ProxyKube not reporting its readiness (#12150)"
This reverts commit 6cdcfe7721.
* Prevent relative expiry from emitting more events than can be processed
This alters relative expiry in four ways:
1) Relative expiry is no longer exclusively run by the auth cache
2) Relative expiry no longer emits delete events
3) There is now a limit to the number of nodes removed per interval
4) Relative expiry now runs more frequently
We can remove the need to emit any fake delete events during relative
expiry by not running it exclusively in the auth cache. All caches
will now run relative expiry themselves, even the components that
don't watch for nodes - this is effectively a noop for them. To
prevent the individual caches from getting too far out of sync, the
expiry interval is set to a much smaller value and we limit the
number of nodes being deleted per interval.
This deprecation was kind of a pain, because x509.CertPool becomes
a black box - there is no public API to determine how many certs
have been added to the pool. To account for this, some of our method
signatures needed to be updated to report the number of certs that
were added.
As of Go 1.18, certificates are verified with the platform verifier
instead of via the Go verifier on macOS. The mac verifier enforces
a maximum validity period of 825 days. Our default of 10 years is too
long, resulting in an error:
x509: certificate is not standards compliant
Introduce Database Certificate Authority. New CA is used by Database Access to sign database certificates making them independent from Host CA.
Co-authored-by: Marek Smoliński <marek@goteleport.com>
This change updates NO_PROXY handling to allow blocking specific host:port combinations, rather than just the host. It also adds a special case for downgrading requests to plain HTTP when --insecure is true and the request goes through a plain HTTP proxy at localhost (i.e. HTTP_PROXY=http://localhost).
Introduce the prompt.Password function and use it consistently whenever we read
a password, OTP or PIN.
The PR makes it easy to support PINs during MFA authentication, so now we do so.
It also adds the capability to mock prompt.Stdin() for tests, adding a uniform
way to fake user input in tests without having to swap functions.
Complements #10953 and #9160.
* Prompt for OTPs as passwords (take 1), read PINs on MFA authentication
* Add the prompt.Password method
* Add Stdin mocking capabilities to the prompt package
* Delegate password reads to prompt.Stdin().ReadPassword()
* Remove stdinHijack from PromptMFAChallenge
* Change api_login_test.go to FakeReader
* Change tsh_test.go to FakeReader
* Retire client.ReadPassword in favor of prompt.Password
* Provider error info on data dir rights
* Added similar message for appropiate access when trying to use a Teleport configuration file (/etc/teleport.yaml) and it fails to load due to permission error.
This changes prompt.ContextReader in the following ways:
Reads only happen as a response to Read methods being called. This allows
ContextReader to coexist with other readers as long as no reads are abandoned.
ReadPassword is now available, the underlying implementation being
term.ReadPassword. An abandoned password read may be turned into a clean read.
This gives us some UX flexibility when callers abandon password reads (looking
at you, PromptMFAChallenge). Turning clean reads into password reads is not
supported. It's tricky and I have a few ideas, but it's not paramount at this
moment.
This solves the woes caused by abandoned OTP reads followed by PIN reads in
different packages, such as client.PromptMFAChallenge followed by tsh mfa add's
implementation.
#9160
* Move ContextReader to its own file
* Refactor ContextReader and implement ReadPassword
* Test ReadPassword
* Fix typos
* Remove prompt.StdinSync()
prompt.Stdin() has the same behavior for non-abandoned reads.
* Group /x/term methods under a type
Seamlessly change the public API of lib/auth/webauthncli to use the
libfido2-backed implementation, as long as the binary was compiled with the
libfido2 build tag.
A few adjustments are necessary to "wancli" methods to allow users to provide
prompt callbacks and to return the credential user (not applicable here, but
will be in following PRs).
Additional changes are made to tsh mfa add in order to avoid stdin hijacking by
ContextReader, since we now may require PIN reads for authenticators.
#9160
* Move U2F logic to u2f_* files
* Split U2F API from general l/a/webauthncli API
* Move FIDO2 public API to fido2_common.go, introduce IsFIDO2Available
* Introduce prompt.SyncReader
Sync reads allow prompt calls to be mixed with term.ReadPassword calls.
* Wire FIDO2 into MFA login
* Wire FIDO2 into MFA registration
* 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 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.
Increase tolerance on expected reads.
This should prevent failures where due to our approximation, we estimate
a fractional number of reads that exceed our tolerance of 1.
Sample error: Max difference between 10.461059975 and 9 allowed is 1, but difference was 1.4610599749999995
Updates #9492