Skip to content

Commit 701e9ac

Browse files
authored
Merge pull request #4791 from stlaz/cluster_trust_bundles
KEP-3257: cluster trust bundles: add a new in-tree signer and its CTB
2 parents 4a7f28a + fd8ca84 commit 701e9ac

File tree

2 files changed

+120
-21
lines changed

2 files changed

+120
-21
lines changed

keps/sig-auth/3257-cluster-trust-bundles/README.md

Lines changed: 118 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,9 @@ tags, and then generate with `hack/update-toc.sh`.
8989
- [Configuration Object Definition](#configuration-object-definition)
9090
- [Volume Content Generation and Refresh](#volume-content-generation-and-refresh)
9191
- [Canarying Changes to a ClusterTrustBundle](#canarying-changes-to-a-clustertrustbundle)
92+
- [Publishing the kube-apiserver-serving Trust Bundle](#publishing-the-kube-apiserver-serving-trust-bundle)
93+
- [The kube-apiserver-serving signer](#the-kube-apiserver-serving-signer)
94+
- [Kubelet and KCM API discovery](#kubelet-and-kcm-api-discovery)
9295
- [Test Plan](#test-plan)
9396
- [Prerequisite testing updates](#prerequisite-testing-updates)
9497
- [Unit tests](#unit-tests)
@@ -179,6 +182,10 @@ Additionally, this KEP introduces a new `clusterTrustBundle` kubelet projected
179182
volume source that gives workloads easy filesystem-based access to trust anchor
180183
sets that they might need.
181184

185+
A new ClusterTrustBundle with a new signer `kubernetes.io/kube-apiserver-serving` also gets created
186+
for all clusters. In combination with the new projected volume source,
187+
this trust bundle can be eventually used to replace the use of `kube-root-ca.crt` configMaps
188+
that nowadays live in all namespaces.
182189
## Motivation
183190

184191
In the absence of a standard mechanism for trust distribution, a few different
@@ -228,12 +235,17 @@ distributing trust anchor sets.
228235
* Handle trust anchors expressed in other forms than PEM-wrapped, DER-formatted
229236
X.509.
230237

238+
* Have the kube-apiserver consume ClusterTrustBundles as a part of service/webhook APIs.
239+
This enhancement does not specify a revocation mechanism for a trust represented
240+
by a ClusterTrustBundle. Having this mechanism would be a natural follow-up
241+
candidate to this KEP.
242+
231243
## Proposal
232244

233245
This proposal is centered around a new cluster-scoped ClusterTrustBundle
234246
resource, initially in the certificates/v1alpha1 API group. The
235247
ClusterTrustBundle object can be thought of as a specialized configmap tailored
236-
to the X.509 trust anchor use case. Introducing a dedicated type allows us to
248+
to the X.509 trust anchor use case. Introducing a dedicated type allows us to
237249
attach different RBAC policies to ClusterTrustBundle objects, which will
238250
typically be wide-open for reading, but locked-down for writing.
239251

@@ -253,6 +265,10 @@ projected volume source writes the certificates from a ClusterTrustBundle into
253265
the container filesystem, with the contents of the projected files updating as
254266
the corresponding trust anchor sets are updated.
255267

268+
Finally, the ClusterTrustBundle API is exercised to create an object for
269+
distributing the serving trust to the kube-apiserver, currently represented by
270+
the `kube-root-ca.crt`configMap that's synced into every namespace.
271+
256272
### User Stories
257273

258274
#### Trust Anchor Distribution for Private CAs
@@ -330,10 +346,6 @@ Kubelet in the cluster. When they are updated, workloads will need to receive
330346
the updates fairly quickly (within 5 minutes across the whole cluster), to
331347
accommodate emergency rotation of trust anchors for a private CA.
332348

333-
Security: Should individual trust anchor set entries designate an OCSP endpoint
334-
to check for certificate revociation? Or should we require the URL to be
335-
embedded in the issued certificates? Note: This question is deferred from the 1.30 beta scope, and will be discussed as an addition to the beta scope in 1.31.
336-
337349
## Design Details
338350

339351
### ClusterTrustBundle Object
@@ -359,18 +371,16 @@ as long as their name does not contain a colon.
359371
Multiple ClusterTrustBundle objects may be associated with a single signer.
360372
While each object is independent at the API level, consumers (mostly Kubelet)
361373
will select trust anchors by a combination of field selector on signer name, and
362-
a label selector. Signer controllers may follow the convention of making the
363-
label selector `kubernetes.io/cluster-trust-bundle-version=live` correspond to a
364-
meaningful set of trust anchors. In general, users are expected to read the documentation for their signer controller implementation in order to determine which label selectors to use for their needs, including [canarying](#canarying-changes-to-a-clustertrustbundle).
374+
a label selector. In general, users are expected to read the documentation for their signer controller implementation in order to determine which label selectors to use for their needs, including [canarying](#canarying-changes-to-a-clustertrustbundle).
365375

366376
ClusterTrustBundle objects support `.metadata.generation`.
367377

368378
ClusterTrustBundle creates and updates that result in an empty
369-
`.spec.pemTrustAnchors` will be rejected during validation.
379+
`.spec.trustBundle` will be rejected during validation.
370380

371381
All of the new objects and fields described in this section are gated by the
372382
ClusterTrustBundle kube-apiserver feature gate. Unless the feature gate is
373-
enabled, usage of these alpha objects and fields will be rejected by
383+
enabled, usage of these objects and fields will be rejected by
374384
kube-apiserver.
375385

376386
#### API Object Definition
@@ -563,6 +573,65 @@ For example, if I maintain `example.com/my-signer`, I can use the following stra
563573
canary object first, and assess the health of the canary workloads.
564574
* Once I am satisfied that the change is safe, I edit the live object.
565575

576+
### Publishing the kube-apiserver-serving Trust Bundle
577+
578+
Today, the trust bundle that allows verifying kube-apiserver serving certificate(s)
579+
at its internal endpoints is distributed into every namespace using a configMap.
580+
This is so that it can be mounted along with the ServiceAccount token in order
581+
for the workloads to be able to communicate with the kube-apiserver.
582+
583+
In the future, we should be able to replace mounting these configMaps in pods for
584+
for kube-apiserver trust with the projected volume from this feature, and so a
585+
ClusterTrustBundle API object will be created for all clusters:
586+
587+
```yaml
588+
apiVersion: v1beta1
589+
kind: ClusterTrustBundle
590+
metadata:
591+
generateName: kubernetes.io:kube-apiserver-serving:
592+
spec:
593+
signerName: kubernetes.io/kube-apiserver-serving
594+
trustBundle: "<... PEM CA ...>"
595+
```
596+
597+
This object is managed by the Kubernetes Controller Manager in the existing
598+
`root-ca-certificate-publisher-controller`. It serves the same purpose
599+
and contains the same content as the `ca.crt` data in the `kube-root-ca.crt` configMap - to verify internal kube-apiserver
600+
endpoints. There is currently no in-tree signer designated for these purposes,
601+
and so the signer with name `kubernetes.io/kube-apiserver-serving` is introduced
602+
along with this bundle.
603+
604+
This behavior is feature-gated by the `ClusterTrustBundle` KCM feature gate.
605+
606+
#### The kube-apiserver-serving signer
607+
608+
The signer signs certificates that can be used to verify kube-apiserver serving
609+
certificates. Signing and approval are handled outside kube-controller-manager.
610+
611+
**Trust distribution** - signed certificates are used by the kube-apiserver for TLS
612+
server authentication. The CA bundle is distributed using a ClusterTrustBundle object
613+
identifiable by the `kubernetes.io/kube-apiserver-serving` signer name.
614+
**Permitted subjects** - "Subject" itself is deprecated for TLS server authentication. However,
615+
it should still follow the same rules on DNS/IP SANs from the "Permitted x509 extensions" section
616+
below.
617+
**Permitted x509 extensions** - honors subjectAltName and key usage extensions. At
618+
least one DNS or IP subjectAltName must be present. The SAN DNS/IP of the certificates
619+
must resolve/point to kube-apiserver's hostname/IP.
620+
**Permitted key usages** - ["key encipherment", "digital signature", "server auth"] or ["digital signature", "server auth"].
621+
**Expiration/certificate lifetime** - The recommended maximum lifetime is 30 days.
622+
**CA bit allowed/disallowed** - not recommended.
623+
624+
#### Kubelet and KCM API discovery
625+
626+
Functionalities in both the kubelet and KCM depend on the presence of the ClusterTrustBundle
627+
API. If the `ClusterTrustBundleProjection` (kubelet) and `ClusterTrustBundle` (KCM) feature
628+
gates are enabled, the kubelet and the KCM perform API discovery at startup to check for the
629+
API presence at the version they need. If the API is not present, neither kubelet nor KCM
630+
will enable the new behavior, and the check won't be performed until they restart again.
631+
632+
If the API gets disabled on the kube-apiserver side, both the kubelet and KCM must be
633+
restarted in order for the feature to be disabled there, too.
634+
566635
### Test Plan
567636

568637
[x] I/we understand the owners of the involved components may require updates to
@@ -739,15 +808,44 @@ in back-to-back releases.
739808

740809
### Upgrade / Downgrade Strategy
741810

742-
At present, there are no upgrade / downgrade concerns. The ClusterTrustBundle
743-
feature gate controls overall availability of the feature.
811+
The feature is gated by these feature flags:
812+
- kube-apiserver
813+
- `ClusterTrustBundle` controls availability of the ClusterTrustBundle API and
814+
presence of the relevant rules in cluster roles for the kubelet and KCM.
815+
- `ClusterTrustBundleProjection` controls availability of the `ClusterTrustBundle`
816+
projected volume source in the Pod API.
817+
- kubelet
818+
- `ClusterTrustBundleProjection` controls the availability of the kubelet being
819+
able to mount the volumes. If disabled, kubelet will error out on any attempt to
820+
mount a ClusterTrustBundle projected volume.
821+
- KCM - `ClusterTrustBundle` controls the availability of the kube-apiserver-serving's
822+
signer ClusterTrustBundle.
823+
824+
The proper order at which the feature should be enabled is to start with the
825+
kube-apiserver's feature flags. Aside from enabling the API, the `ClusterTrustBundle`
826+
feature gate also creates the necessary rules in the `system:node` cluster role.
827+
828+
Once the kube-apiserver feature gates are enabled, the order of enabling the feature
829+
at kubelet or KCM does not matter.
744830

745831
### Version Skew Strategy
746832

747-
Both kubelet and kube-apiserver will need to be at 1.29 for the full featureset
748-
to be present. If only kube-apiserver is at 1.29 and kubelet is lower, then the
749-
the pod mounting feature will be cleanly unavailable, but all other aspects of
750-
the feature will work.
833+
The ClusterTrustBundle volume projection was implemented in 1.29 and kubelet would fail to mount CTB
834+
volumes if it was requested via the Pod API while the feature gate is disabled on
835+
kubelet side. This means that pods will fail to become ready in version-skewed environments where the
836+
`ClusterTrustBundleProjection` kubelet feature gate is disabled, independently of the
837+
API version.
838+
839+
If the `ClusterTrustBundleProjection` kubelet feature gate is enabled but the API is at a different
840+
version than the kubelet expects, the kubelet will behave as if the feature gate was disabled.
841+
This will cause pods trying to mount a ClusterTrustBundle to fail to become ready as kubelet
842+
won't be able to create the mount. If the API eventually appears at the desired version, the kubelet
843+
must be restarted in order to enable the new behavior.
844+
845+
Enabling the `ClusterTrustBundle` feature gate at KCM while a different-than-KCM-expected
846+
API version is being served will make the KCM to act as if the feature gate was disabled.
847+
If the API eventually appears at the desired version, the KCM must be restarted in order
848+
to enable the new behavior.
751849

752850
## Production Readiness Review Questionnaire
753851

@@ -887,6 +985,7 @@ Recall that end users cannot usually observe component logs or access metrics.
887985
- [x] Other (treat as last resort)
888986
- Users can see that pods that use ClusterTrustBundle projected volume sources are able to begin running.
889987
- This doesn't cover showing that running pods are having their mounted trust bundles updated properly, so we need to think about how to cover them with events or conditions.
988+
- Users can see that a ClusterTrustBundle for the signer `kubernetes.io/kube-apiserver-serving` exists in the cluster
890989

891990
###### What are the reasonable SLOs (Service Level Objectives) for the enhancement?
892991

@@ -935,7 +1034,7 @@ None beyond kube-apiserver.
9351034
Yes.
9361035

9371036
Kubelet will open a watch on ClusterTrustBundle objects. This watch will be
938-
low-throughput.
1037+
low-throughput. A similar watch is also opened from the KCM side.
9391038

9401039
###### Will enabling / using this feature result in introducing new API types?
9411040

@@ -947,8 +1046,8 @@ No.
9471046

9481047
###### Will enabling / using this feature result in increasing size or count of the existing API objects?
9491048

950-
No, except for the additional pod fields that the user sets to make use of the
951-
feature.
1049+
A new API ClusterTrustBundle API object is created for the new `kubernetes.io/kube-apiserver-serving` signer, and there are
1050+
additional pod fields that the user sets to make use of the feature.
9521051

9531052
###### Will enabling / using this feature result in increasing time taken by any operations covered by existing SLIs/SLOs?
9541053

keps/sig-auth/3257-cluster-trust-bundles/kep.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,12 @@ stage: beta
2727
# The most recent milestone for which work toward delivery of this KEP has been
2828
# done. This can be the current (upcoming) milestone, if it is being actively
2929
# worked on.
30-
latest-milestone: "v1.30"
30+
latest-milestone: "v1.32"
3131

3232
# The milestone at which this feature was, or is targeted to be, at each stage.
3333
milestone:
3434
alpha: "v1.29"
35-
beta: "v1.30"
35+
beta: "v1.32"
3636
stable: ""
3737

3838
# The following PRR answers are required at alpha release

0 commit comments

Comments
 (0)