Skip to content

Commit 536c62b

Browse files
committed
Update kuberc KEP with credential plugin allowlist
Currently, the kubeconfig may specify arbitrary binaries to run as client-go credential plugins. Due to the fact that kubeconfig files are often generated, and because they contain a lot of noise, there is significant friction in manually inspecting the kubeconfig for suspicious binaries after it is generated. To encourage secure behavior, we want to introduce an allowlist to the kuberc, which will describe the conditions under which a binary plugin may be run. Currently the only condition is the name (absolute path or basename of a binary found in `PATH`). * Revise based on feedback - Describe behavior when allowlist is `nil` - Describe behavior when allowlist is empty - Describe future plans for field additions * Add SIG Auth as participating SIG * Update TOC for KEP 3104 * Correct `os.LookPath` to `exec.LookPath` * Add note about when the allowlist will not apply * Avoid confusion between nil list and empty list In the credential plugin allowlist, consider nil and empty lists an error. Jordan Liggitt has pointed out that treating them differently is generally avoided in APIs, as it can confuse users. In order to make the user's intention more explicit, an additional field, `credentialPluginPolicy` has been added. Its value must be one of `EnableAll | DisableAll | Allowlist`. `EnableAll` and `DisableAll` are self-explanatory and do not require an allowlist. `Allowlist` will use the allowlist as defined in the KEP. * Note that this change considers the following cases to be errors: - a policy of `EnableAll` with an allowlist provided - a policy of `DisableAll` with an allowlist provided - a policy of `Allowlist` with no allowlist provided (i.e. a `nil` - allowlist` - a policy of `Allowlist` with an explicitly empty allowlist provided * Clarify v1beta1 and kubectl v1.35 only (allowlist) * Update kep.yaml - Add sig-api-machinery as participating SIG - Add enj as reviewer - Update latest milestone to v1.35 * Allowlist: rename `name` field to `command` * Clarify meaning of "the operation will fail" * Specify appropriate api group and version * Move detail to new section under `Design Details` * Add table showing `command` comparison Signed-off-by: Peter Engelbert <[email protected]>
1 parent 755a89a commit 536c62b

File tree

2 files changed

+76
-2
lines changed

2 files changed

+76
-2
lines changed

keps/sig-cli/3104-introduce-kuberc/README.md

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ tags, and then generate with `hack/update-toc.sh`.
8888
- [Story 2](#story-2)
8989
- [Story 3](#story-3)
9090
- [Story 4](#story-4)
91+
- [Story 5](#story-5)
9192
- [Notes/Constraints/Caveats (Optional)](#notesconstraintscaveats-optional)
9293
- [Open Questions](#open-questions)
9394
- [Risks and Mitigations](#risks-and-mitigations)
@@ -104,6 +105,7 @@ tags, and then generate with `hack/update-toc.sh`.
104105
- [option](#option-1)
105106
- [prependarg](#prependarg)
106107
- [appendarg](#appendarg)
108+
- [Allowlist Design Details](#allowlist-design-details)
107109
- [Test Plan](#test-plan)
108110
- [Prerequisite testing updates](#prerequisite-testing-updates)
109111
- [Unit tests](#unit-tests)
@@ -273,6 +275,10 @@ As a user I would like to be able to opt out of deprecation warnings.
273275

274276
https://github.com/kubernetes/kubectl/issues/1317
275277

278+
#### Story 5
279+
280+
As a user I would like to be able to prevent the execution of untrusted binaries by the client-go credential plugin system.
281+
276282
### Notes/Constraints/Caveats (Optional)
277283

278284
<!--
@@ -331,6 +337,11 @@ fields (`apiVersion`, `kind`):
331337

332338
* `aliases` Allows users to declare their own command aliases, including options and values.
333339
* `defaults` Enables users to set default options to be applied to commands.
340+
* `credentialPluginPolicy` (available in **kubectl.config.k8s.io/v1beta1**)
341+
Allows users to deny all, alow all, or allow some client-go credential plugins.
342+
* `credentialPluginAllowlist` (available in **kubectl.config.k8s.io/v1beta1**)
343+
Enables users to specify criteria for trusting binaries to be executed by
344+
the client-go credential plugin system.
334345

335346
`aliases` will not be permitted to override built-in commands but will take
336347
precedence over plugins (builtins -> aliases -> plugins). Any additional options
@@ -343,6 +354,7 @@ intended behavior and realizing that targeting options effectively addresses the
343354
use cases. During command execution, a merge will be occur, with inline overrides
344355
taking precedence over the defaults.
345356

357+
346358
```
347359
apiVersion: kubectl.config.k8s.io/v1beta1
348360
kind: Preference
@@ -368,6 +380,10 @@ defaults:
368380
- name: interactive
369381
default: "true"
370382
383+
credentialPluginPolicy: Allowlist
384+
credentialPluginAllowlist:
385+
- command: cloudplatform-credential-helper
386+
- command: custom-credential-script
371387
```
372388

373389
### Kubectl Kuberc Management Command (kubectl kuberc)
@@ -441,12 +457,68 @@ This gives us the opportunity to standardize kuberc files.
441457

442458
#### prependarg
443459

444-
`--prependarg` is an arbitrary list of strings that accepts anything in a string array format.
460+
`--prependarg` is an arbitrary list of strings that accepts anything in a string array format.
445461

446462
#### appendarg
447463

448464
`--appendarg` is an arbitrary list of strings that accepts anything in string array format.
449465

466+
### Allowlist Design Details
467+
468+
`credentialPluginAllowlist` allows the end-user to provide an array of objects
469+
describing required conditions for executing a credential plugin binary. The
470+
overall result of a check against the allowlist will be the logical OR of the
471+
individual checks against the allowlist's entries. Each allowlist entry MUST
472+
have at least one nonempty field describing the conditions required for the
473+
plugin's execution. If multiple fields are specified within an entry, the
474+
binary in question must meet all of the required conditions in that entry in
475+
order to be executed (i.e. they are combined with logical AND).
476+
477+
Each element in the allowlist is a set of criteria; if the binary in question
478+
meets all of the criteria in at least one **set** of criteria, the plugin will
479+
be allowed to execute. If no criteria set succeeds after comparing the binary
480+
to all sets of criteria, the operation will be immediately aborted and an error
481+
returned.
482+
483+
At the outset, the entry object will have only one field, `command`. The path of
484+
the binary specified in the kubeconfig will be compared against that named in
485+
the `command` field. This field may contain a basename, or the full path of a
486+
plugin. To ensure an exact match, `exec.LookPath` will be called on both the
487+
`command` field and the binary named in the kubeconfig. The resulting absolute
488+
paths must match. The following table illustrates this:
489+
490+
491+
| Scenario | `PATH=` | Allowlist `command` | `exec.LookPath(allowlist.Command)` | kubeconfig `command` | `exec.LookPath(execConfig.Command)` | success? |
492+
|----------|---------|---------------------|------------------------------------|----------------------|-------------------------------------|----------|
493+
| kubeconfig lists full path; `my-binary` is in both `/usr/local/bin` and `/usr/bin` | `PATH=/usr/local/bin:/usr/bin:<...>` | my-binary | /usr/local/bin/my-binary | /usr/bin/my-binary | /usr/bin/my-binary | false |
494+
| kubeconfig lists full path; `my-binary` is only in `/usr/local/bin` | `PATH=/usr/local/bin:/usr/bin:<...>` | my-binary | /usr/local/bin/my-binary | /usr/bin/my-binary | /usr/bin/my-binary | false |
495+
| kubeconfig lists full path; `my-binary` is only in `/usr/bin` | `PATH=/usr/local/bin:/usr/bin:<...>` | my-binary | /usr/bin/my-binary | /usr/bin/my-binary | /usr/bin/my-binary | true |
496+
| kubeconfig lists full path; `my-binary` is only in `/usr/bin` | `PATH=/usr/local/bin:/usr/bin:<...>` | /usr/bin/my-binary | /usr/bin/my-binary | /usr/bin/my-binary | /usr/bin/my-binary | true |
497+
| kuberc lists full path; `my-binary` is only in `/usr/bin` | `PATH=/usr/local/bin:/usr/bin:<...>` | /usr/bin/my-binary | /usr/bin/my-binary | my-binary | /usr/bin/my-binary | true |
498+
| kuberc lists full path; `my-binary` is in `/usr/local/bin` | `PATH=/usr/local/bin:/usr/bin:<...>` | /usr/bin/my-binary | /usr/bin/my-binary | my-binary | /usr/local/bin/my-binary | false |
499+
| neither lists full path; `my-binary` is in `/usr/bin`; equivalent to basename match | `PATH=/usr/local/bin:/usr/bin:<...>` | my-binary | /usr/bin/my-binary | my-binary | /usr/bin/my-binary | true |
500+
501+
If `credentialPluginPolicy` is set to `Allowlist`, but a
502+
`credentialPluginAllowlist` is not provided, it will be considered an
503+
configuration error. Rather than guess at what the user intended, the operation
504+
will be aborted just before the `exec` call. An error describing the
505+
misconfiguration will be returned. This is because the allowlist is a security
506+
control, and it is likely the user has made a mistake. Since the output may be
507+
long, it would be easy for a security warning to be lost at the beginning of
508+
the output. An explicitly empty allowlist (i.e. `credentialPluginAllowlist: []`),
509+
in combination with `credentialPluginPolicy: Allowlist` will be considered an
510+
error for the same reason. The user should instead use `credentialPluginPolicy:
511+
DisableAll` in this case.
512+
513+
Commands that don't create a client, such as `kubectl config view` will not be
514+
affected by the allowlist. Additionally, commands that create but do not *use*
515+
a client (such as commands run with `--dry-run`) will likewise remain
516+
unaffected.
517+
518+
In future updates, other allowlist entry fields MAY be added. Specifically,
519+
fields allowing for verification by digest or public key have been discussed.
520+
The initial design MUST accommodate such future additions.
521+
450522
### Test Plan
451523

452524
<!--

keps/sig-cli/3104-introduce-kuberc/kep.yaml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,16 @@ authors:
55
- "@soltysh"
66
owning-sig: sig-cli
77
participating-sigs:
8-
- sig-cli
8+
- sig-auth
9+
- sig-api-machinery
910
status: implementable
1011
creation-date: 2022-06-13
1112
reviewers:
1213
- "@liggitt"
1314
- "@eddiezane"
1415
- "@soltysh"
1516
- "@mpuckett159"
17+
- "@enj"
1618
approvers:
1719
- "@ardaguclu"
1820

0 commit comments

Comments
 (0)