Skip to content

Commit 8f10dbc

Browse files
committed
Add KEP-4872 Harden Kubelet serving cert validation
1 parent e6475c7 commit 8f10dbc

File tree

2 files changed

+426
-0
lines changed

2 files changed

+426
-0
lines changed
Lines changed: 386 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,386 @@
1+
# KEP-4872: Harden Kubelet Serving Certificate Validation in Kube-API server
2+
3+
<!-- toc -->
4+
- [Release Signoff Checklist](#release-signoff-checklist)
5+
- [Summary](#summary)
6+
- [Motivation](#motivation)
7+
- [Impact of node impersonation](#impact-of-node-impersonation)
8+
- [Goals](#goals)
9+
- [Non-Goals](#non-goals)
10+
- [Proposal](#proposal)
11+
- [User Stories (Optional)](#user-stories-optional)
12+
- [Story 1](#story-1)
13+
- [Story 2](#story-2)
14+
- [Notes/Constraints/Caveats (Optional)](#notesconstraintscaveats-optional)
15+
- [Risks and Mitigations](#risks-and-mitigations)
16+
- [Design Details](#design-details)
17+
- [Enabling the feature](#enabling-the-feature)
18+
- [Metrics](#metrics)
19+
- [TLS insecure](#tls-insecure)
20+
- [Test Plan](#test-plan)
21+
- [Prerequisite testing updates](#prerequisite-testing-updates)
22+
- [Unit tests](#unit-tests)
23+
- [Integration tests](#integration-tests)
24+
- [e2e tests](#e2e-tests)
25+
- [Graduation Criteria](#graduation-criteria)
26+
- [Alpha](#alpha)
27+
- [Beta](#beta)
28+
- [GA](#ga)
29+
- [Upgrade / Downgrade Strategy](#upgrade--downgrade-strategy)
30+
- [Version Skew Strategy](#version-skew-strategy)
31+
- [Production Readiness Review Questionnaire](#production-readiness-review-questionnaire)
32+
- [Feature Enablement and Rollback](#feature-enablement-and-rollback)
33+
- [Rollout, Upgrade and Rollback Planning](#rollout-upgrade-and-rollback-planning)
34+
- [Monitoring Requirements](#monitoring-requirements)
35+
- [Dependencies](#dependencies)
36+
- [Scalability](#scalability)
37+
- [Troubleshooting](#troubleshooting)
38+
- [Implementation History](#implementation-history)
39+
- [Drawbacks](#drawbacks)
40+
- [Alternatives](#alternatives)
41+
- [Infrastructure Needed](#infrastructure-needed)
42+
<!-- /toc -->
43+
44+
## Release Signoff Checklist
45+
46+
<!--
47+
**ACTION REQUIRED:** In order to merge code into a release, there must be an
48+
issue in [kubernetes/enhancements] referencing this KEP and targeting a release
49+
milestone **before the [Enhancement Freeze](https://git.k8s.io/sig-release/releases)
50+
of the targeted release**.
51+
52+
For enhancements that make changes to code or processes/procedures in core
53+
Kubernetes—i.e., [kubernetes/kubernetes], we require the following Release
54+
Signoff checklist to be completed.
55+
56+
Check these off as they are completed for the Release Team to track. These
57+
checklist items _must_ be updated for the enhancement to be released.
58+
-->
59+
60+
Items marked with (R) are required *prior to targeting to a milestone / release*.
61+
62+
- [ ] (R) Enhancement issue in release milestone, which links to KEP dir in [kubernetes/enhancements] (not the initial KEP PR)
63+
- [ ] (R) KEP approvers have approved the KEP status as `implementable`
64+
- [ ] (R) Design details are appropriately documented
65+
- [ ] (R) Test plan is in place, giving consideration to SIG Architecture and SIG Testing input (including test refactors)
66+
- [ ] e2e Tests for all Beta API Operations (endpoints)
67+
- [ ] (R) Ensure GA e2e tests meet requirements for [Conformance Tests](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/conformance-tests.md)
68+
- [ ] (R) Minimum Two Week Window for GA e2e tests to prove flake free
69+
- [ ] (R) Graduation criteria is in place
70+
- [ ] (R) [all GA Endpoints](https://github.com/kubernetes/community/pull/1806) must be hit by [Conformance Tests](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/conformance-tests.md)
71+
- [ ] (R) Production readiness review completed
72+
- [ ] (R) Production readiness review approved
73+
- [ ] "Implementation History" section is up-to-date for milestone
74+
- [ ] User-facing documentation has been created in [kubernetes/website], for publication to [kubernetes.io]
75+
- [ ] Supporting documentation—e.g., additional design documents, links to mailing list discussions/SIG meetings, relevant PRs/issues, release notes
76+
77+
[kubernetes.io]: https://kubernetes.io/
78+
[kubernetes/enhancements]: https://git.k8s.io/enhancements
79+
[kubernetes/kubernetes]: https://git.k8s.io/kubernetes
80+
[kubernetes/website]: https://git.k8s.io/website
81+
82+
## Summary
83+
84+
This proposal aims to enhance the security of the Kube API server by validating the Common Name (CN) of the kubelet's serving certificate to ensure it matches the expected node name.
85+
This validation prevents a compromised node that has obtained a certificate for an IP address it does not own from using it to impersonate another node.
86+
87+
## Motivation
88+
89+
In cloud environments, IPs can change rapidly due to the ephemeral nature of the infrastructure.
90+
If IPs or machines rotate faster than the expiration frequency of kubelet serving certificates, a certificate issued to an old node could be used to respond to requests aimed at a new node, provided they share an IP.
91+
92+
In addition, in on-premises environments, verifying that the IP addresses in a Certificate Signing Request (CSR) are owned by the requesting node can be challenging due to the lack of a reliable source of truth for IP ownership.
93+
Even when such a source exists, integration can be complex, leading to unsafe practices like auto-approval of CSRs without a strong guarantee of IP ownership.
94+
This vulnerability can be exploited through ARP poisoning or other routing attacks, allowing a rogue node to obtain a certificate for an IP it does not own and reroute traffic to itself.
95+
96+
When the Kube API server connects to a kubelet, it verifies that the serving certificate is signed by a trusted CA and that the IP or hostname it’s connecting to is included in the certificate's SANs.
97+
If a rogue node obtained a certificate for an IP it does not own and reroute traffic to itself, it would be able to impersonate a Node that reports that IP.
98+
99+
### Impact of node impersonation
100+
101+
Provided an actor with control of a node can impersonate another node, the impact would be:
102+
103+
* Break confidentiality of the requests sent by the Kube-API server to the kubelet (e.g kubectl exec/logs).These are usually user-driven requests. That gives the threat actor the possibility of producing incorrect or mis-leading feedback. In the exec case, it could allow a threat actor to issue prompts for credentials. In addition, the exec commands might contain user secrets.
104+
* Break confidentiality of credentials if the client uses token based authentication. This is probably more common for non Kube-API server clients, given mTLS is common for Kube-API server to kubelet communication.
105+
106+
### Goals
107+
108+
* Ensure the Kube API server validates that the node’s serving certificate's CN matches the expected node name.
109+
* Prevent rogue nodes from using certificates issued for IPs they do not own.
110+
111+
### Non-Goals
112+
113+
* This proposal does not address certificate validation for clients other than the Kube API server, such as metrics scrapers. However, we'll consider an implementation in client-go that could be used by those other clients.
114+
115+
## Proposal
116+
117+
We propose that the Kube API server is modified to validate the Common Name (CN) of the kubelet's serving certificate is equal to `system:node:<nodename>`.
118+
`nodename` is the name of the Node object as reported by the kubelet. When the Kube-API server connects to the kubelet server (e.g. for logs, exec, port-forward), it always knows the Node it's connecting to.
119+
120+
### User Stories (Optional)
121+
122+
#### Story 1
123+
124+
As a cluster administrator, I want to ensure that kubelet serving certificates are validated based on the node name, reducing the risk of IP-based impersonation attacks.
125+
126+
#### Story 2
127+
128+
As a cluster administrator using custom serving certificates for the kubelet server, I want to be able to disable the Subject's CN validation.
129+
130+
### Notes/Constraints/Caveats (Optional)
131+
132+
When the kubelet requests a certificate through a CSR, it sets the CN to `system:node:<nodename>`, enforced by the admission controller as per [PR \#126015](https://github.com/kubernetes/kubernetes/pull/126015).
133+
134+
However, certificates issued manually or through other mechanisms may not follow this convention.
135+
With the new validation, any certificate not following this `system:node:<nodename>` convention will be deemed invalid by the Kube API server.
136+
This will require cluster administrators to reissue any non-conforming certificates before enabling this feature.
137+
138+
### Risks and Mitigations
139+
140+
This could disrupt existing clusters that are using custom kubelet serving certificates.
141+
These clusters will need to reissue their certificates before enabling this feature. We will allow to disable the validation through a command-line flag to allow for a smooth transition.
142+
143+
## Design Details
144+
145+
### Enabling the feature
146+
147+
We will introduce a feature flag `KubeletCertCNValidation` that will gate the usage of the new validation.
148+
This gate will start off by default in Alpha, will be turned on by default in Beta and will be removed in GA.
149+
150+
In addition, we will allow to disable the validation through a command-line flag `--disable-kubelet-cert-cn-validation`.
151+
This flag can only be set if the `KubeletCertCNValidation` feature flag is enabled.
152+
This flag will allow cluster administrators to opt-out of this validation if they are using custom kubelet serving certificates that don't follow the `system:node:<nodename>` convention even after the feature gate is removed.
153+
154+
#### Metrics
155+
156+
In order to help cluster administrators determine if it's safe to enable the feature, we propose to add a new metric `kube_apiserver_validation_kubelet_cert_cn_errors` that will track the number of errors due to the new CN validation.
157+
If the feature gate is disabled, we will still add the validation code to the HTTP transport, however, if the validation fails we won't return an error, we will just increment the metric counter.
158+
In addition, we will log the error including the node name, so cluster administrators can identify which nodes are affected and need to reissue their certificates.
159+
160+
We purposefully don't add the node name to the metric to avoid a high cardinality.
161+
The purpose of the metric is to easily/cheaply tell administrators if they can flip the feature on or not. If the answer is no (counter is greater than 0), the rest of the necessary information to detect the offending nodes will come from logs.
162+
163+
Given that running the validation to feed the metric still has a cost, we won't run it if the validation is explicitly disabled with `--disable-kubelet-cert-cn-validation`.
164+
165+
We will remove the metric once the feature is GA.
166+
167+
> TODO: let's discuss this in the review. We could consider adding the node name to the metric or even keeping the metric post GA if it's valuable.
168+
169+
### TLS insecure
170+
171+
Currently, if the Kube-API server is not configured with a `--kubelet-certificate-authority` the TLS client for kubelet server will skip the server certificate validation.
172+
Additionally, `logs` requests allow to configure `InsecureSkipTLSVerifyBackend` per request to skip the server certificate validation.
173+
174+
To align with this behavior, we won't execute the CN validation if `--kubelet-certificate-authority` is not set or if `InsecureSkipTLSVerifyBackend` is set to true.
175+
176+
### Test Plan
177+
178+
[x] I/we understand the owners of the involved components may require updates to
179+
existing tests to make this code solid enough prior to committing the changes necessary
180+
to implement this enhancement.
181+
182+
##### Prerequisite testing updates
183+
184+
##### Unit tests
185+
186+
Unit tests will be added along with any new code introduced.
187+
188+
Existing test coverage for the packages we anticipate modifying:
189+
190+
- `k8s.io/kubernetes/pkg/kubelet/client`: `2024-10-07` - `28.2`
191+
- `k8s.io/client-go/transport`: `2024-10-07` - `59.4`
192+
193+
##### Integration tests
194+
195+
Integration tests will be added to ensure the following:
196+
* An error is returned if `--disable-kubelet-cert-cn-validation` is set but `KubeletCertCNValidation` feature flag is not enabled.
197+
* Validation for custom certificates works if feature flag is not enabled.
198+
* Validation for custom certificates works if feature flag enabled and `--disable-kubelet-cert-cn-validation` is set to true.
199+
* Validation for custom certificates fails if feature flag enabled and `--disable-kubelet-cert-cn-validation` is set to false or not set.
200+
* Validation for kubernetes issued certificates works if feature flag enabled and `--disable-kubelet-cert-cn-validation` is set to false or not set.
201+
202+
##### e2e tests
203+
204+
End-to-end tests won't be needed as unit and integration tests will cover all the scenarios.
205+
206+
### Graduation Criteria
207+
208+
#### Alpha
209+
210+
* Add feature flag for gating usage, off by default
211+
* Add flag to disable extra validation
212+
* Unit and integration tests
213+
214+
#### Beta
215+
* Address user reviews and iterate if needed
216+
* Feature flag on by default
217+
218+
#### GA
219+
* Remove feature flag
220+
221+
### Upgrade / Downgrade Strategy
222+
223+
Once feature flag is on by default (starting in Beta), administrators using custom serving certs
224+
can use the proposed flag to disable the extra validation and maintain current behavior.
225+
They will be able to use this flag even after the feature flag is removed.
226+
227+
### Version Skew Strategy
228+
229+
Not applicable.
230+
231+
## Production Readiness Review Questionnaire
232+
233+
### Feature Enablement and Rollback
234+
235+
###### How can this feature be enabled / disabled in a live cluster?
236+
237+
- [x] Feature gate
238+
- Feature gate name: `KubeletCertCNValidation`
239+
- Components depending on the feature gate: kube-apiserver
240+
- [x] Other
241+
- Describe the mechanism: kube-apiserver command-line flag `--disable-kubelet-cert-cn-validation`
242+
- Will enabling / disabling the feature require downtime of the control
243+
plane? No. But requires restarting the kube-apiserver.
244+
- Will enabling / disabling the feature require downtime or reprovisioning
245+
of a node? No.
246+
247+
###### Does enabling the feature change any default behavior?
248+
249+
Yes. If a cluster is using custom kubelet serving certificates that don't follow the same convention as kubernetes issued certificates (CN is `system:node:<node-name>`),
250+
enabling this feature will make any connection initiated by the kube-api server fail (logs, exec and port-forwarding).
251+
252+
###### Can the feature be disabled once it has been enabled (i.e. can we roll back the enablement)?
253+
254+
Yes, the feature can be disabled once enabled by just setting the command-line flag to true.
255+
256+
###### What happens if we reenable the feature if it was previously rolled back?
257+
258+
You just get back the new behavior with the extra cert validation, no extra considerations needed.
259+
260+
###### Are there any tests for feature enablement/disablement?
261+
262+
We will add integration tests to validate the enablement/disablement flow. Test cases specified in a previous section.
263+
264+
### Rollout, Upgrade and Rollback Planning
265+
266+
###### How can a rollout or rollback fail? Can it impact already running workloads?
267+
268+
A rollout can fail if the feature flag is not enabled but the command-line flag is set.
269+
270+
Already running workloads won't be impacted but cluster users won't be able to access the control plane if the cluster is single-node.
271+
272+
###### What specific metrics should inform a rollback?
273+
274+
Not applicable.
275+
276+
###### Were upgrade and rollback tested? Was the upgrade->downgrade->upgrade path tested?
277+
278+
No. There is no data stored for this feature which persists between upgrade / downgrade, or between enable / disable.
279+
The feature is purely an API server configuration option.
280+
281+
###### Is the rollout accompanied by any deprecations and/or removals of features, APIs, fields of API types, flags, etc.?
282+
283+
No.
284+
285+
### Monitoring Requirements
286+
287+
###### How can an operator determine if the feature is in use by workloads?
288+
289+
The cluster administrators can check the flags passed to the kube-apiserver if they have access to the control plane nodes.
290+
If the `--disable-kubelet-cert-cn-validation` flag is not set or set to false, the feature is being used.
291+
Alternatively the can check the `kubernetes_feature_enabled` metric.
292+
293+
###### How can someone using this feature know that it is working for their instance?
294+
295+
- [x] Other
296+
- Details: users can create a Node with a kubelet serving certificate that doesn't meet the CN requirements enforced by this validation (something different than `system:node:<node-name>`).Then run `kubectl logs` for any pod running in that node. If it returns an error for an invalid certificate, the feature is working.
297+
298+
###### What are the reasonable SLOs (Service Level Objectives) for the enhancement?
299+
300+
The average `apiserver_request_duration_seconds` for logs/exec/port-forward requests is within reasonable limits.
301+
A raising value after enabling this feature could signal overhead introduced by the extra validation.
302+
303+
> TODO: I expect the overhead to be negligible and probably to fall in within the standard deviation of the current average. Specially for long running requests like port-forward and exec. Is this even valuable to have here?
304+
305+
###### What are the SLIs (Service Level Indicators) an operator can use to determine the health of the service?
306+
307+
- [x] Metrics
308+
- Metric name: `kube_apiserver_pod_logs_backend_tls_failure_total`
309+
- Components exposing the metric: kube-apiserver
310+
311+
> TODO: should `kube_apiserver_pod_logs_backend_tls_failure_total` reflect errors due to the new CN validation?
312+
> It's technically a TLS failure, but it's not part of the base TLS client validations.
313+
314+
###### Are there any missing metrics that would be useful to have to improve observability of this feature?
315+
316+
We could add a metric specific to track the number of requests that failed due to the new CN validation. In addition, we could track the time spent per request on the CN validation.
317+
318+
However, we consider these metrics to not provide enough value to justify the work to maintain them.
319+
320+
### Dependencies
321+
322+
###### Does this feature depend on any specific services running in the cluster?
323+
324+
No.
325+
326+
### Scalability
327+
328+
###### Will enabling / using this feature result in any new API calls?
329+
330+
No.
331+
332+
###### Will enabling / using this feature result in introducing new API types?
333+
334+
No.
335+
336+
###### Will enabling / using this feature result in any new calls to the cloud provider?
337+
338+
No.
339+
340+
###### Will enabling / using this feature result in increasing size or count of the existing API objects?
341+
342+
No.
343+
344+
###### Will enabling / using this feature result in increasing time taken by any operations covered by existing SLIs/SLOs?
345+
346+
No. This only affects streaming APIs and these are not covered by SLIs/SLOs.
347+
348+
###### Will enabling / using this feature result in non-negligible increase of resource usage (CPU, RAM, disk, IO, ...) in any components?
349+
350+
No.
351+
352+
Note: depending on the implementation (caching the client-go transport or not) there might be a slight increase in memory (due to one transport per node being cached) or in CPU usage (due to building the transport on the fly for every request). This should be negligible.
353+
354+
###### Can enabling / using this feature result in resource exhaustion of some node resources (PIDs, sockets, inodes, etc.)?
355+
356+
No.
357+
358+
### Troubleshooting
359+
360+
###### How does this feature react if the API server and/or etcd is unavailable?
361+
362+
It's part of the API server, so the feature will be unavailable.
363+
364+
###### What are other known failure modes?
365+
366+
- [API server can't connect to Nodes with custom kubelet serving certificates that don't follow the `system:node:<node-name>` convention]
367+
- Detection: `kubectl logs` returns a certificate validation error.
368+
- Mitigations: disable the validation with the `--disable-kubelet-cert-cn-validation` flag.
369+
- Diagnostics: error is returned by the API server, no additional logging needed.
370+
- Testing: We will have tests for this, this is basically testing that the feature works.
371+
372+
###### What steps should be taken if SLOs are not being met to determine the problem?
373+
374+
## Implementation History
375+
376+
## Drawbacks
377+
378+
This could disrupt clusters that are using custom kubelet serving certificates. These clusters will need to reissue their certificates before enabling this feature.
379+
380+
## Alternatives
381+
382+
None.
383+
384+
## Infrastructure Needed
385+
386+
None.

0 commit comments

Comments
 (0)