11 Commits
Author SHA1 Message Date
Noah Stride dce19fa553 Deprecate recording of join metadata into bot instance record (#69571)
* Deprecate recording of join metadata into bot instance record

* update docs

* Store bound keyapir data

* regen docs
2026-08-13 08:15:04 +00:00
Noah Stride f7aef78a96 MWI: Bot Scope Namespacing (#68253)
* MWI: Bot Scope Namespacing (#68253)

* Properly handle scope namespaced bots in tctl

Squash of:
- Properly handle scope namespaced bots in tctl
- tdy

* tidy up todo/lint failure

* Add audit log events

* various tidying

* adjust for consistency

* remove botRef

* Simplify by removing checkBotRefMatches

* Avoid testify in authtest.go

* address review feedback

* defensive checks against name collisions
2026-08-06 09:55:16 +00:00
Noah Stride 9fe6985113 Adjust provision.Token interface to unsplit Bot accessors in preparation for SQN (#67746)
* Adjust `provision.Token` interface to unsplit Bot accessors in preparation for SQN (variant b)

* add todo godocs
2026-06-16 08:28:45 +00:00
Tim Buckley edabc9f89c MWI Scopes[4]: Scoped bot joining and bound keypair support (#65366)
* MWI: Support scoped join tokens in the bound keypair join method

* Bot fields for scoped tokens

* Check bot scope

* Allow bound keypair tokens to pass scope validation

* Support bots

* Fix outstanding references to ProvisionTokenV2

* Zero check on MustRegisterBefore due to proto impl differences

* Properly pass through nil must_register_before

* Also fix nil timestamps in bound keypair status

* And fix rotate_after

* Add BotInternal certificate field

* Add 'bot' TokenUsageMode value and require for bot joins

* Fix mutator execution for scoped bound keypair joining

* Implement more ScopedToken StrongValidateToken checks for bots

Adds a few more of the bot-specific RFD validation checks for bots.

* Improve bot join checks for scoped joining

* Fix build after rebase and add additional RFD checks

This fixes builds after upstream updates and implements a few more
validations required by the RFD:
- AssignedScope field for bots must be empty
- Moved original AssignedScope check to validateNonBot() since it was
  checked unconditionally before.
- BotScope must be a presumably-valid scope at creation time

* Use scope-aware access checker for initial bot certs

* Fix WeakValidateToken() for scoped tokens for bots

WeakValidateToken() was not updated to match the new checks in
StrongValidateToken(); this adds minimal bot-related exemptions
around `assigned_scope` for bots to allow it to be read without
error.

* Add tests for scoped bot tokens, fix role bug

This adds a set of additional token tests for scoped bot tokens, and
fixes an issue where WeakValidateToken() was erroneously rejecting
invalid system roles.

* Properly initialize bound keypair scoped tokens on creation/upsert

We weren't applying the same initialization logic for scoped tokens
that we did for ProvisionTokenV2; this is required for registration
secrets to work properly.

* Update CRDs

* Fix failing test

* Specify types for bound keypair timestamp fields

* Update terraform resources

* Fix lint

* Include bot scope in BotJoin audit events

This includes the bot scope in audit events. It includes the user
label bot scope for successful joins where the user has been fetched,
and otherwise includes the bot scope configured on the token.

* Reject `token` join method for scoped bot tokens

Bot joining should use `bound_keypair`, so reject scoped bot tokens
that attempt to join with the traditional `token` join method.

* Fix failing test due to BotInternal cert parameter

TestRegisterBotInstance wasn't updated to include the BotInternal
flag on initial identity, so this includes it.

* Actually include Scope in bot audit events

* Mutate correct token status in `patchToken`

The mutate result was discarded because the wrong status object was
passed to `mutateScopedToken`.

* Use ScopedAuthorizer in join/Server.authenticate()

`authenticate()` currently rejects scoped identities which prevented
clients from reauthenticating with an existing identity, which is
important for bot renewal and bound keypair joining.

* Pass `BoundHostID` through properly in `GetBoundKeypairStatus()`

* Add basic TestJoinBoundKeypair_ScopedToken test

* Fix lint

* Update join server comments, add note about feature flag edge case

* Target correct provision token for standard token mutations

* Return correct mutated token in patchToken()

* Hide bound keypair registration secrets when `WithSecrets` is unset

* Avoid possible nil pointer dereference

* Address proto comment suggestion from review

* Deduplicate bound keypair mutator validation logic

Validation logic has been pulled out into a `validate()` interface
function and unified for both token types; scoped token bound keypair
fields are converted to their equivalent ProvisionTokenV2 variant
using existing helper logic.

* Nil check in consumeRecoveryMutator.validate()

* Simplify lastRotatedAtMutator

This removes the confusing switch with fallthroughs in favor of 2
simple ifs and a helper function.

* Ensure bound keypair status is non-nil before mutating

* Note non-nil requirement for new lastRotatedAt value

* Update generated operator resources

* Also nil-check status for standard tokens

* Mirror secret censoring for bound keypair secrets in tctl

This mirrors the existing secret censoring in tctl. It doesn't
actually work since the conditional can never be true.

* Use StrongValidate() on BotScope in token StrongValidate()

`validateBotToken()` was incorrectly calling `scopes.WeakValidate()`
on the bot scope. This changes it to call `scopes.StrongValidate()`
instead.

* Mark scoped token bound keypair registration_secret field as sensitive

* Make lastRotatedAtMutator's `mutateScopedToken` nil-safe

* Tag mutator validation errors with a unique name of the mutator

Errors are tagged with the primary field that mutator modifies to
help identify the failing mutator without necessarily identifying
the specific failing check.

* Address code review feedback

* Wait for ScopedRoleAssignment to become available

SRAs don't always propagate immediately, so adds a
`require.EventuallyWithT()` check to ensure it exists before
continuing.

* Add test for scoped bot joining via kubernetes

* Fix formatting
2026-04-16 02:06:24 +00:00
Tim Buckley daf95c1595 Support verifying standard agent UUIDs for bound keypair joining (#64351)
* MWI: Adapt bound keypair verification logic to account for standard hosts

This adds support for verifying host UUIDs (rather than bot instance
UUIDs) to the bound keypair join method.

Note that as hosts only have a trustworthy UUID when joining via the
new join service, bound keypair joining for agents via the legacy join
service is not allowed and will result in an error.

* Test coverage and small fixes for legacy joining

Agents cannot join via the legacy join service, however the bound
keypair implementation depends on having a trustworthy HostID that
is unset for bots. The impl passed it through before since it wasn't
used, so we now clear it.

* Add unit test coverage for node joining

Also includes missing bound keypair case in HostID generation,
fixes a leaky error string in HandleBoundKeypair, and adds additional
checks for identity misuse with presenting HostIDs to a token with
a bot ID and vice versa.

* Address review feedback

- Use `t.Context()` in tests
- Remove unnecessary params for mutator functions that were always
  an empty string.
2026-04-02 01:48:29 +00:00
Tim Buckley bec78b14c8 MWI: Default to creating bound keypair tokens for bots in tctl (#63422)
* MWI: Default to creating bound keypair tokens for bots in `tctl`

This adjusts the default behavior in `tctl` to create bound keypair
tokens when creating new bot tokens in `tctl bots add` and
`tctl bots instances add`.

This adds a new "V2" message template intended for use with joining
URIs and bound keypair tokens, and defaults to that. The existing
template is still available, with minor additive changes, using the
`--legacy` flag. Additional flags to manage bound keypair token
parameters (recovery mode, etc) were also added and are specific to
this join method.

Additionally, joining URI parsing utilities were moved into their
own package to be importable from `tctl` without importing all of
`lib/tbot`.

* Fix broken TestAddAndListBotInstancesJSON

A slight control flow change introduced a dependency on a working
proxy, which isn't enabled by tctl's test harness. This enables the
proxy for this test, with a new test flag to support this.

* Fix imports

* Fix regression in TestTokens

The new helper unconditionally overrode cfg.Proxy.Enabled, which
broke other tests that overrode the parameter in other ways. It
now only toggles it on explicitly.

* Add test coverage for new bot templates

* Fix lint

* Deflake AddBot* tests with ugly static plumbing

There's a lot of random parameters in the rendered token templates
which caused failures in the golden-style tests. This plumbs through
a few static parameters along with adding a template parameter mutator
to override some parameters to ensure test consistency.

* Dedupe bot token flags

Moves bot token flag initialization into a shared
`initSharedBotTokenFlags()` helper.

* Add removal TODO for v20

* Add 'configure' instructions to the bot template
2026-02-09 23:32:04 +00:00
Tim Buckley 4501ac7bc8 MWI: Remove bound keypair experiment flag (#56592)
This removes the environment variable gating use of the bound keypair
experiment.
2025-07-09 23:01:29 +00:00
Zac Bergquist a12def583a Apply remaining modernize changes. (#56037)
This is the last of this series of updates.
2025-06-25 21:25:29 +00:00
Tim Buckley 31c7278206 MWI: Add audit events for bound keypair joining (#55701)
* MWI: Add audit events for bound keypair joining

This adds 3 new audit events for bound keypair joining:
- `join_token.bound_keypair.recovery` - emitted when a join triggers
  a recovery (first join, or join with expired certs)
- `join_token.bound_keypair.rotation` - emitted when a keypair
  rotation takes place
- `join_token.bound_keypair.join_state_verification_failed` - emitted
  when the client provides an invalid join state document

* Fix UI lint

* Fix more UI lints

* Remove outdated TODO

* Fix tests broken by error message changes
2025-06-24 01:50:32 +00:00
Tim Buckley 0756c34c8e MWI: Issue and verify join state documents (#54940)
* MWI: Issue and verify join state documents

This adds join state document issuance and verification to the bound
keypair joining process. This is described in more detail in the
[RFD], but in short, this adds a mechanism similar to the generation
counter to verify bound keypair recovery events.

Each time a recovery is performed, the join counter (stored in the
token's status field) is incremented. This value is embedded in a JWT
and signed by Auth, and the result is passed to the client alongside
their cert bundle. This document effectively gives clients permission
to lock themselves out in the future: if another client attempts to
use their credentials, the original client will eventually present an
outdated join state document, and trigger a lockout.

[RFD]: https://github.com/gravitational/teleport/blob/rfd/0205-improved-onprem-joining/rfd/0205-improved-onprem-joining.md

* Allow selecting all recovery modes

* Remove TODO and debug log

* Add tests for join state issuance and verification

* Add join state tests for RegisterUsingBoundKeypairMethod

Adds some minor error message and comment fixes caught while writing
tests.

* Fix imports

* Fix lints

* Fix failing unit test

* Add notes about lack of expiry field in join state JWTs
2025-05-24 01:32:28 +00:00
Tim Buckley 37d28d0ab1 MWI: Add lib/boundkeypair for bound keypair backend implementation (#54766)
* MWI: Add lib/boundkeypair for bound keypair backend implementation

This splits the backend implementation of lib/boundkeypair out from
the main bound keypair joining PR in #54371. It makes no changes
beyond those already reviewed in that PR.

* Apply code review suggestions

- Renames the experiment package
- Fixes missing test helper flags
- Renames the experiment env var
- Uses strconv.ParseBool()

* Simplify experiment flag
2025-05-13 21:55:49 +00:00