Skip to content

Commit da6efde

Browse files
committed
cluster trust bundles: add a new in-tree signer and its CTB
1 parent ed5d0b1 commit da6efde

File tree

1 file changed

+115
-10
lines changed
  • keps/sig-auth/3257-cluster-trust-bundles

1 file changed

+115
-10
lines changed

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

Lines changed: 115 additions & 10 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
@@ -563,6 +579,65 @@ For example, if I maintain `example.com/my-signer`, I can use the following stra
563579
canary object first, and assess the health of the canary workloads.
564580
* Once I am satisfied that the change is safe, I edit the live object.
565581

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

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

740815
### Upgrade / Downgrade Strategy
741816

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

745837
### Version Skew Strategy
746838

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.
839+
The ClusterTrustBundle volume projection was implemented in 1.29 and kubelet would fail to mount CTB
840+
volumes if it was requested via the Pod API while the feature gate is disabled on
841+
kubelet side. This means that pods will fail to become ready in version-skewed environments where the
842+
`ClusterTrustBundleProjection` kubelet feature gate is disabled, independently of the
843+
API version.
844+
845+
If the `ClusterTrustBundleProjection` kubelet feature gate is enabled but the API is at a different
846+
version than the kubelet expects, the kubelet will behave as if the feature gate was disabled.
847+
This will cause pods trying to mount a ClusterTrustBundle to fail to become ready as kubelet
848+
won't be able to create the mount. If the API eventually appears at the desired version, the kubelet
849+
must be restarted in order to enable the new behavior.
850+
851+
Enabling the `ClusterTrustBundle` feature gate at KCM while a different-than-KCM-expected
852+
API version is being served will make the KCM to act as if the feature gate was disabled.
853+
If the API eventually appears at the desired version, the KCM must be restarted in order
854+
to enable the new behavior.
751855

752856
## Production Readiness Review Questionnaire
753857

@@ -887,6 +991,7 @@ Recall that end users cannot usually observe component logs or access metrics.
887991
- [x] Other (treat as last resort)
888992
- Users can see that pods that use ClusterTrustBundle projected volume sources are able to begin running.
889993
- 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.
994+
- Users can see that a ClusterTrustBundle for the signer `kubernetes.io/kube-apiserver-serving` exists in the cluster
890995

891996
###### What are the reasonable SLOs (Service Level Objectives) for the enhancement?
892997

@@ -935,7 +1040,7 @@ None beyond kube-apiserver.
9351040
Yes.
9361041

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

9401045
###### Will enabling / using this feature result in introducing new API types?
9411046

@@ -947,8 +1052,8 @@ No.
9471052

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

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

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

0 commit comments

Comments
 (0)