Skip to content

Commit 9f3ab87

Browse files
authored
MWI: Documentation for Bound Keypair static keys (#59854)
* MWI: Documentation for Bound Keypair static keys This adds documentation and a guide for bound keypair static keys, added in #59620. * Fill in remaining sections * Tweak warning message * Address review comments * Fix excessive whitespace * Address review feedback * Further tweak private key storage wording * Fix broken link to bound keypair guide
1 parent 17aa257 commit 9f3ab87

File tree

7 files changed

+437
-14
lines changed

7 files changed

+437
-14
lines changed

docs/pages/machine-workload-identity/machine-id/deployment/deployment.mdx

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ authentication methods:
4242

4343
## Deployment guides
4444

45-
The guides in this section show you how to deploy Machine ID and join it to your cluster.
45+
The guides in this section show you how to deploy Machine ID and join it to your cluster.
4646
Choose a guide based on the platform where you intend to run Machine ID.
4747

4848
If a specific guide does not exist for your platform, the [Linux
@@ -114,9 +114,9 @@ and [Architecture](../../../reference/architecture/machine-id-architecture.mdx)
114114
},
115115
{
116116
icon: <Icon name="lock" size="xl" />,
117-
to: "../../reference/machine-workload-identity/machine-id/bound-keypair/getting-started",
117+
to: "../../../reference/machine-workload-identity/machine-id/bound-keypair/getting-started",
118118
name: "Bound Keypair Joining",
119-
}
119+
}
120120
]}
121121
/>
122122

@@ -165,6 +165,18 @@ Read the following guides for how to deploy Machine ID on a continuous integrati
165165
icon: <Icon name="terraform" size="xl" />,
166166
to: "../../zero-trust-access/infrastructure-as-code/terraform-provider/terraform-cloud",
167167
name: "Terraform Cloud",
168+
},
169+
{
170+
icon: <Icon name="lock" size="xl" />,
171+
to: "../../../reference/machine-workload-identity/machine-id/bound-keypair/static-keys",
172+
name: "Bound Keypair static keys (Generic)",
168173
}
169174
]}
170175
/>
176+
177+
<Admonition type="tip" title="Unsupported Provider?">
178+
If your CI/CD provider does not have a dedicated join method listed above,
179+
consider using [Bound Keypair static keys][bound-keypair-static] as a fallback.
180+
</Admonition>
181+
182+
[bound-keypair-static]: ../../../reference/machine-workload-identity/machine-id/bound-keypair/static-keys.mdx

docs/pages/reference/cli/tbot.mdx

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,9 @@ specific section for details when using a YAML config file or legacy output.
288288
| `--[no-]oneshot` | If set, quit after the first renewal. |
289289
| `--diag-addr` | If set and the bot is in debug mode, a diagnostics service will listen on specified address. |
290290
| `--storage` | A destination URI for tbot's internal storage, e.g. `file:///foo/bar`. See [Destination URIs](#destination-uris) for more info. |
291-
| `--registration-secret` | An optional joining secret to use on first join with the `bound_keypair` join method. |
291+
| `--registration-secret` | An optional joining secret to use on first join with the `bound_keypair` join method. This can also be provided via the `TBOT_REGISTRATION_SECRET` environment variable. |
292+
| `--registration-secret-path` | An optional path to a file containing a joining secret to use on first join with the `bound_keypair` join method. |
293+
| `--static-key-path` | An optional path to a file containing a static private key for use with the `bound_keypair` join method. A base64-encoded key can also be provided via the `TBOT_BOUND_KEYPAIR_STATIC_KEY` environment variable. |
292294

293295
## tbot start legacy
294296

@@ -727,9 +729,12 @@ new keypair.
727729

728730
| Flag | Description |
729731
|------|-------------|
730-
| `--storage` | A destination URI to be used for bot internal storage. Required. |
731-
| `--proxy-server` | A Teleport Proxy Service address. Required. |
732-
| `--overwrite` | If set, always generate a new key. If unset, the existing public key will be printed if one already exists in the destination specified by `--storage` |
732+
| `--storage` | A destination URI to be used for bot internal storage. Required. |
733+
| `--proxy-server` | A Teleport Proxy Service address. Required. |
734+
| `--overwrite` | If set, always generate a new key. If unset, the existing public key will be printed if one already exists in the destination specified by `--storage`. |
735+
| `--static` | If set, generates a static keypair. For more information, see [the static key guide](../machine-workload-identity/machine-id/bound-keypair/static-keys.mdx). |
736+
| `--static-key-path` | If set with `--static`, writes the static keypair to a file. |
737+
| `--format` | Override the output format, supported values: `text`, `json`. |
733738

734739
### Examples
735740

docs/pages/reference/machine-workload-identity/machine-id/bound-keypair/admin-guide.mdx

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -274,10 +274,65 @@ its previous value.
274274

275275
If [bot keypairs were rotated](#requesting-a-keypair-rotation) between the
276276
snapshot and restore of the Teleport cluster, note that bots only keep a record
277-
of the previous 10 keypairs. This means server-side recovery may impossible if
278-
the keypair expected by the restored Teleport cluster has been rotated out of
277+
of the previous 10 keypairs. This means server-side recovery may be impossible
278+
if the keypair expected by the restored Teleport cluster has been rotated out of
279279
the client-side history, or if the client-side history has been lost or deleted.
280280

281+
## Manually rotating static keys
282+
283+
Static keys prevent automatic key rotation as the `tbot` client cannot update
284+
keys in an arbitrary keystore. However, it may still possible to automate
285+
rotation if your environment or secret store allows you to update secrets
286+
through an API.
287+
288+
The specific steps needed to automate these will vary based on your environment,
289+
but the general steps are:
290+
291+
1. Generate a new keypair on any node using the tbot client:
292+
293+
```code
294+
$ tbot keypair create --proxy-server example.teleport.sh:443 --static --format json
295+
```
296+
297+
2. Parse the `.public_key` and `.private_key` values using your tool of choice,
298+
like `jq` or any other JSON parser.
299+
300+
3. Replace the token in Teleport to trust the new public key, using the value in
301+
the `.public_key` field:
302+
```code
303+
$ cat my-token.yaml
304+
version: v2
305+
kind: token
306+
metadata:
307+
name: my-token
308+
spec:
309+
bot_name: example-bot
310+
bound_keypair:
311+
onboarding:
312+
initial_public_key: <insert .public_key value here>
313+
recovery:
314+
mode: insecure
315+
join_method: bound_keypair
316+
roles:
317+
- Bot
318+
$ tctl create -f my-token.yaml
319+
```
320+
321+
3. Insert the new private key into your keystore. This will vary depending on
322+
which keystore or provider you are using.
323+
* If passing the private key via an environment variable, copy the value directly
324+
* If passing the private key via file, decode the base64-encoded private key first:
325+
```code
326+
$ tbot keypair create --proxy-server example.teleport.sh:443 --static --format json | jq -r .private_key | base64 -d
327+
```
328+
...and store the result as needed.
329+
330+
4. Future jobs should now use the new keypair.
331+
332+
Frequently rotating static keys can help to mitigate the security tradeoffs of
333+
`insecure` recovery. See the [concepts page](concepts.mdx#static-keys) for more
334+
information about static keys.
335+
281336
[rbac]: ../../../access-controls/roles.mdx
282337
[ephemeral]: ../../../architecture/machine-id-architecture.mdx#ephemeral-token
283338
[delegated]: ../../../deployment/join-methods.mdx#delegated-join-methods

docs/pages/reference/machine-workload-identity/machine-id/bound-keypair/bound-keypair.mdx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,10 @@ a bot initially. When ready to deploy to production, it's trivial to adjust
4545
onboarding and recovery settings to select your desired balance between
4646
resiliency and security.
4747

48-
Additionally, with [`insecure` recovery](admin-guide.mdx#disabling-join-state-verification)
49-
and in situations that can accommodate the security complications, Bound Keypair
50-
Joining can be used to join bots in otherwise unsupported CI/CD providers by
51-
persisting the bot's keypair in the platform keystore.
48+
Additionally, with [static keys](static-keys.mdx) and in situations that can
49+
accommodate the security complications, Bound Keypair Joining can be used to
50+
join bots in otherwise unsupported CI/CD providers by persisting the bot's
51+
keypair in a platform keystore.
5252

5353
## Limitations
5454

@@ -75,6 +75,9 @@ You can read step-by-step guides on using Bound Keypair Joining with Machine ID:
7575

7676
- [Using Machine ID with Bound Keypair Joining](./getting-started.mdx):
7777
How to install and configure Machine ID with Bound Keypair Joining
78+
- [Using Machine ID with Bound Keypair static keys](./static-keys.mdx): How to
79+
use Bound Keypair static keys with stateless hosts, like otherwise
80+
unsupported CI/CD providers
7881
- [Bound Keypair Joining Concepts](./concepts.mdx): Learn more about the
7982
components and architecture of Bound Keypair Joining
8083
- [Bound Keypair Joining Admin Guide](./admin-guide.mdx): Learn how to deploy

docs/pages/reference/machine-workload-identity/machine-id/bound-keypair/concepts.mdx

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,10 @@ values:
118118
[See the admin guide](admin-guide.mdx#disabling-join-state-verification) for
119119
more information on using `insecure` mode in practice.
120120

121+
Static key joining (`tbot keypair create --static ...`) requires use of
122+
`insecure` mode as it disables client-side credential storage, meaning bots
123+
cannot complete [join state verification](#join-state-verification).
124+
121125
## Join state verification
122126

123127
A **join state document** is an additional piece of information provided to
@@ -145,5 +149,42 @@ credentials in use by the attacker.
145149
Note that join state verification is disabled when the token's
146150
`spec.bound_keypair.recovery.mode` is set to `insecure`.
147151

152+
## Static Keys
153+
154+
Static keys trade some security guarantees for flexibility, and can help enable
155+
use of `tbot` in environments where bots otherwise could not authenticate, such
156+
as:
157+
- CI/CD providers for which Teleport has no dedicated join method
158+
- Ephemeral bare-metal nodes without TPMs
159+
- Any other environment where persistent storage is not available
160+
- Any environment where an arbitrary number of instances may join, like
161+
ephemeral CI runners.
162+
163+
However, static keys have disadvantages:
164+
- `insecure` mode means any client with the private key can join without
165+
restrictions. If the key is stolen, the attacker will have access to Teleport
166+
and any resources the bot is allowed to access.
167+
- `insecure` mode additionally means you cannot limit the number of uses of the
168+
bound keypair token (`spec.bound_keypair.recovery.limit`).
169+
- Keypair rotation is not supported, as client storage is not writable, and
170+
attempting to require a rotation will prevent bots from joining.
171+
172+
When using static keys, a keypair is generated ahead of time and [preregistered
173+
with Teleport](#onboarding). You can then provide the keypair to the `tbot`
174+
client using a file or the `TBOT_BOUND_KEYPAIR_STATIC_KEY` environment variable.
175+
176+
The `insecure` recovery mode is required when using static keys (with
177+
`tbot keypair create --static ...`) as this mode disables client-side storage
178+
for join state documents. With no previous state, bots will not be able to
179+
complete join state verification, and will be unable to recover after their
180+
first authentication attempt; as such, join state verification must be disabled.
181+
182+
With this context in mind, when using static keys, be aware that any client with
183+
knowledge of the private key can authenticate to Teleport with no additional
184+
restrictions. Before deploying a bot with static keys, take additional care to
185+
fully understand your environment's threat model and security needs, and reduce
186+
access using [Teleport's RBAC](../../../access-controls/roles.mdx) to ensure the
187+
minimum possible blast radius in the event the keypair is compromised.
188+
148189
[renewable]: ../../../deployment/join-methods.mdx#renewable-vs-non-renewable
149190
[token]: ../../../deployment/join-methods.mdx#ephemeral-tokens

0 commit comments

Comments
 (0)