Skip to content

Commit 755a89a

Browse files
authored
Merge pull request #5524 from seans3/kep-to-ga
KEP-4006: Updated KEP for 1.35
2 parents bed6973 + f8d92d3 commit 755a89a

File tree

3 files changed

+71
-22
lines changed

3 files changed

+71
-22
lines changed

keps/prod-readiness/sig-api-machinery/4006.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,5 @@ alpha:
33
approver: "@deads2k"
44
beta:
55
approver: "@jpbetz"
6+
stable:
7+
approver: "@jpbetz"

keps/sig-api-machinery/4006-transition-spdy-to-websockets/README.md

Lines changed: 64 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,8 @@ tags, and then generate with `hack/update-toc.sh`.
9696
- [Background: <code>PortForward</code> Subprotocol](#background-portforward-subprotocol)
9797
- [Proposal: New <code>PortForward</code> Tunneling Subprotocol Version - <code>v2.portforward.k8s.io</code>](#proposal-new-portforward-tunneling-subprotocol-version---v2portforwardk8sio)
9898
- [Proposal: API Server PortForward -- Stream Tunnel Proxy](#proposal-api-server-portforward----stream-tunnel-proxy)
99-
- [Pre-GA: Kubelet <code>StreamTranslatorProxy</code>](#pre-ga-kubelet-streamtranslatorproxy)
99+
- [Proposal: Synthetic RBAC CREATE Authorization Check](#proposal-synthetic-rbac-create-authorization-check)
100+
- [Proposal: Transitioning the API Server-to-Kubelet Connection](#proposal-transitioning-the-api-server-to-kubelet-connection)
100101
- [Test Plan](#test-plan)
101102
- [Prerequisite testing updates](#prerequisite-testing-updates)
102103
- [Unit tests](#unit-tests)
@@ -109,6 +110,7 @@ tags, and then generate with `hack/update-toc.sh`.
109110
- [Beta](#beta)
110111
- [v1.30 RemoteCommand Subprotocol (exec, cp, and attach)](#v130-remotecommand-subprotocol-exec-cp-and-attach)
111112
- [v1.31 PortForward Subprotocol (port-forward)](#v131-portforward-subprotocol-port-forward)
113+
- [v1.35 Synthetic RBAC CREATE Authorization Check](#v135-synthetic-rbac-create-authorization-check)
112114
- [GA](#ga)
113115
- [Upgrade / Downgrade Strategy](#upgrade--downgrade-strategy)
114116
- [Version Skew Strategy](#version-skew-strategy)
@@ -236,7 +238,7 @@ communication leg between `kubectl` and the API Server.
236238

237239
2. Extend the WebSockets communication leg from the API Server to Kubelet. After this
238240
extension, WebSockets streaming will occur between `kubectl` and Kubelet (proxied
239-
through the API Server). This plan is described at [Pre-GA: Kubelet](#pre-ga-kubelet-).
241+
through the API Server).
240242

241243
### Non-Goals
242244

@@ -247,6 +249,10 @@ and make progress.
247249

248250
1. We will not make *any* changes to current WebSocket based browser/javascript clients.
249251

252+
2. We will not transition the streaming protocol for the communication leg on the
253+
Node between the Kubelet and the container runtime. This leg will continue to stream
254+
the SPDY protocol.
255+
250256
## Proposal
251257

252258
<!--
@@ -510,22 +516,36 @@ as the downstream connection within the dual concurrent `io.Copy` proxying gorou
510516
The upstream connection is the same SPDY connection to the container (through the
511517
Kubelet and CRI).
512518

513-
### Pre-GA: Kubelet `StreamTranslatorProxy`
514-
515-
The eventual plan is to incrementally transition all SPDY communication legs to WebSockets.
516-
After the WebSocket communication leg from `kubectl` to the API Server is proven
517-
to work, the next communication leg to transition is the one from the API Server to
518-
the Kubelet. Both the API Server and the Kubelet stream data messages using the
519-
`UpgradeAwareProxy`. Since the initial plan is to modify the `UpgradeAwareProxy`
520-
in the API Server to delegate to the `StreamTranslatorProxy`, it will be straightforward
521-
to transition this next communication leg by moving the integrated `StreamTranslatorProxy`
522-
from the API Server to the Kubelet.
523-
524-
The final communication leg to transition from SPDY to WebSockets will be the one
525-
from Kubelet to the Container Runtimes. Since this communication happens within a
526-
node (using Unix domain sockets), this path is not as critical. But this effort
527-
will be more work, since it will require modifying not just Kubelet, but **all**
528-
Container Runtimes.
519+
### Proposal: Synthetic RBAC CREATE Authorization Check
520+
521+
The transition to WebSockets requires changing the initial streaming upgrade request
522+
from a POST to a GET, as the WebSocket protocol specification
523+
([RFC 6455](https://www.rfc-editor.org/rfc/rfc6455#section-4.1)) mandates that the
524+
opening handshake must be an HTTP GET request. This has an unintended security
525+
consequence: RBAC policies that only grant the get verb, such as a typical read-only
526+
"viewer" role, now unexpectedly allow users to run kubectl exec, attach, and port-forward.
527+
To close this privilege escalation vector and restore the principle of least privilege,
528+
this proposal introduces a secondary, synthetic authorization check performed within the
529+
API Server. When a WebSocket upgrade request is received for the pods/exec, pods/attach,
530+
or pods/portforward subresources, the handler will perform an additional check to ensure
531+
the user also has the create verb permission for that specific subresource. This new
532+
authorization check will be controlled by a feature gate,
533+
`AuthorizePodWebsocketUpgradeCreatePermission`, which will be enabled by default to
534+
ensure clusters are secure while allowing operators to temporarily disable it as
535+
they update their RBAC policies.
536+
537+
### Proposal: Transitioning the API Server-to-Kubelet Connection
538+
539+
The long-term goal of this KEP is to replace SPDY with WebSockets for the entire
540+
communication path from the client to the Kubelet. After the initial
541+
kubectl-to-API-Server leg is stable, this proposal outlines the next phase:
542+
transitioning the communication between the API Server and the Kubelet. This is
543+
achieved by replicating the translation logic currently in the API Server—specifically
544+
the `StreamTranslatorProxy` (for exec/attach) and the `StreamTunnelingProxy`
545+
(for port-forward)—into the Kubelet's `UpgradeAwareProxy`. Once implemented, WebSocket
546+
streaming will extend end-to-end from the client to the Node, with the Kubelet then
547+
translating the stream to SPDY for the final, intra-node communication leg to the
548+
container runtime.
529549

530550
### Test Plan
531551

@@ -735,6 +755,8 @@ in back-to-back releases.
735755

736756
##### v1.30 RemoteCommand Subprotocol (exec, cp, and attach)
737757

758+
- `kubectl` environment variable KUBECTL_REMOTE_COMMAND_WEBSOCKETS is **ON** by default.
759+
- API Server feature flag `TranslateStreamCloseWebsocketRequests` is **ON** by default.
738760
- Additional `exec`, `cp`, and `attach` unit tests completed and enabled.
739761
- Additional `exec`, `cp`, and `attach` integration tests completed and enabled.
740762
- Additional `exec`, `cp`, and `attach` e2e tests completed and enabled.
@@ -752,8 +774,17 @@ in back-to-back releases.
752774
- Additional `port-forward` integration tests completed and enabled.
753775
- Additional `port-forward` e2e tests completed and enabled.
754776

777+
##### v1.35 Synthetic RBAC CREATE Authorization Check
778+
779+
- Force synthetic RBAC `CREATE` authorization check for WebSocket upgrades on the following
780+
subresources: `pods/exec`, `pods/attach`, and `pods/portforward`. This additional check
781+
will be gated by the API Server `AuthorizePodWebsocketUpgradeCreatePermission` feature flag,
782+
which defaults to **TRUE**.
783+
755784
#### GA
756785

786+
- `kubectl` environment variables and API Server feature gates are locked to on by default.
787+
- Deprecate `kubectl` environment variables and API Server feature gates for future removal.
757788
- Add WebSocket support for HTTPS proxies.
758789
- See (https://github.com/kubernetes/kubernetes/issues/126134)
759790
- Conformance tests for `RemoteCommand` completed and enabled.
@@ -892,6 +923,8 @@ well as the [existing list] of feature gates.
892923
KUBECTL_REMOTE_COMMAND_WEBSOCKETS, TranslateStreamCloseWebsocketRequests
893924
- Feature gate name(s) for PortForward Subprotocol:
894925
KUBECTL_PORT_FORWARD_WEBSOCKETS, PortForwardWebsockets
926+
- Feature gate name(s) for subresource endpoints `pods/exec`, `pods/attach`,
927+
and `pods/portforward`: AuthorizePodWebsocketUpgradeCreatePermission
895928
- Components depending on the feature gate: kubectl, API Server
896929

897930
###### Does enabling the feature change any default behavior?
@@ -910,7 +943,11 @@ variable set to **ON** for `exec`, `cp`, and `attach` commands. While the
910943
KUBECTL_PORT_FORWARD_WEBSOCKETS environment variable must be set to **ON** for
911944
`port-forward` command. These modifications, however, will be transparent to the
912945
user unless the `kubectl`/API Server communication is communicating through an
913-
intermediary such as a proxy (which is the whole reason for the feature).
946+
intermediary such as a proxy (which is the whole reason for the feature). The API Server
947+
feature flag `AuthorizePodWebsocketUpgradeCreatePermission` forces a synthetic, secondary
948+
RBAC check for the `CREATE` verb permission on WebSocket upgrade requests. When this
949+
feature gate is **TRUE**, the additional permission check will apply to endpoints
950+
`pods/exec`, `pods/attach`, and `pods/portforward`.
914951

915952
###### Can the feature be disabled once it has been enabled (i.e. can we roll back the enablement)?
916953

@@ -928,7 +965,9 @@ NOTE: Also set `disable-supported` to `true` or `false` in `kep.yaml`.
928965
The features can be disabled for a single user by setting the `kubectl` environment
929966
variable associated with the feature to **OFF**. Or the features can be turned off
930967
for all `kubectl` users communicating with a cluster by turning off the feature flags
931-
for the API Server.
968+
for the API Server. A cluster operator can temporarily disable the more stringent permissions for
969+
subresources `pods/exec`, `pods/attach`, and `pods/portforward` by setting the
970+
`AuthorizePodWebsocketUpgradeCreatePermission` feature flag to **FALSE**.
932971

933972
###### What happens if we reenable the feature if it was previously rolled back?
934973

@@ -957,6 +996,9 @@ https://github.com/kubernetes/kubernetes/pull/97058/files#diff-7826f7adbc1996a05
957996
- There are unit tests in the API Server which exercise the feature gate within
958997
the `UpgradeAwareProxy`, which conditionally delegates to the `StreamTunneling`
959998
proxy for the PortForward subprotocol.
999+
- There will be unit tests in the API Server to verify the feature gate
1000+
forcing more stringent RBAC checks for `pods/exec`, `pods/attach`, and
1001+
`pods/portforward`.
9601002

9611003
### Rollout, Upgrade and Rollback Planning
9621004

@@ -1455,6 +1497,8 @@ Major milestones might include:
14551497
- First Kubernetes release where PortForward over WebSockets described in KEP: v1.30
14561498
- PortForward over WebSockets shipped as alpha: v1.30
14571499
- PortForward over WebSockets shipped as beta: v1.31
1500+
- WebSocket HTTPS Proxy functionality shipped: v1.33
1501+
- Synthetic RBAC `CREATE` authz check for WebSocket upgrade requests: v1.35
14581502

14591503
## Drawbacks
14601504

keps/sig-api-machinery/4006-transition-spdy-to-websockets/kep.yaml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,13 @@ stage: beta
2222
# The most recent milestone for which work toward delivery of this KEP has been
2323
# done. This can be the current (upcoming) milestone, if it is being actively
2424
# worked on.
25-
latest-milestone: "v1.31"
25+
latest-milestone: "v1.35"
2626

2727
# The milestone at which this feature was, or is targeted to be, at each stage.
2828
milestone:
2929
alpha: "v1.29"
3030
beta: "v1.31"
31-
stable: "v1.32"
31+
stable: "v1.36"
3232

3333
# The following PRR answers are required at alpha release
3434
# List the feature gate name and the components for which it must be enabled
@@ -45,6 +45,9 @@ feature-gates:
4545
- name: PortForwardWebsockets
4646
components:
4747
- kube-apiserver
48+
- name: AuthorizePodWebsocketUpgradeCreatePermission
49+
components:
50+
- kube-apiserver
4851
disable-supported: true
4952

5053
# The following PRR answers are required at beta release.

0 commit comments

Comments
 (0)