Skip to content

Commit c8b8ebc

Browse files
Add TLSAdherence field to APIServer API
This adds a new TLSAdherence field to the APIServer spec that controls how strictly TLS settings are enforced across cluster components. - Add TLSAdherencePolicy enum with StrictAllComponents and LegacyExternalAPIServerComponentsOnly values - Add CEL validation to prevent removing tlsAdherence once set - Add TLSAdherence feature gate (enabled in DevPreview/TechPreview) - Add integration tests for the new field Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 3239ef4 commit c8b8ebc

22 files changed

+813
-0
lines changed
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
apiVersion: apiextensions.k8s.io/v1
2+
name: "APIServer"
3+
crdName: apiservers.config.openshift.io
4+
featureGates:
5+
- TLSAdherence
6+
tests:
7+
onCreate:
8+
- name: Should be able to create with tlsAdherence set to LegacyExternalAPIServerComponentsOnly
9+
initial: |
10+
apiVersion: config.openshift.io/v1
11+
kind: APIServer
12+
spec:
13+
tlsAdherence: LegacyExternalAPIServerComponentsOnly
14+
expected: |
15+
apiVersion: config.openshift.io/v1
16+
kind: APIServer
17+
spec:
18+
audit:
19+
profile: Default
20+
tlsAdherence: LegacyExternalAPIServerComponentsOnly
21+
- name: Should be able to create with tlsAdherence set to StrictAllComponents
22+
initial: |
23+
apiVersion: config.openshift.io/v1
24+
kind: APIServer
25+
spec:
26+
tlsAdherence: StrictAllComponents
27+
expected: |
28+
apiVersion: config.openshift.io/v1
29+
kind: APIServer
30+
spec:
31+
audit:
32+
profile: Default
33+
tlsAdherence: StrictAllComponents
34+
- name: Should reject invalid tlsAdherence value
35+
initial: |
36+
apiVersion: config.openshift.io/v1
37+
kind: APIServer
38+
spec:
39+
tlsAdherence: InvalidValue
40+
expectedError: 'spec.tlsAdherence: Unsupported value: "InvalidValue": supported values: "LegacyExternalAPIServerComponentsOnly", "StrictAllComponents"'
41+
onUpdate:
42+
- name: Should be able to update tlsAdherence from LegacyExternalAPIServerComponentsOnly to StrictAllComponents
43+
initial: |
44+
apiVersion: config.openshift.io/v1
45+
kind: APIServer
46+
spec:
47+
tlsAdherence: LegacyExternalAPIServerComponentsOnly
48+
updated: |
49+
apiVersion: config.openshift.io/v1
50+
kind: APIServer
51+
spec:
52+
tlsAdherence: StrictAllComponents
53+
expected: |
54+
apiVersion: config.openshift.io/v1
55+
kind: APIServer
56+
spec:
57+
audit:
58+
profile: Default
59+
tlsAdherence: StrictAllComponents
60+
- name: Should be able to update tlsAdherence from StrictAllComponents to LegacyExternalAPIServerComponentsOnly
61+
initial: |
62+
apiVersion: config.openshift.io/v1
63+
kind: APIServer
64+
spec:
65+
tlsAdherence: StrictAllComponents
66+
updated: |
67+
apiVersion: config.openshift.io/v1
68+
kind: APIServer
69+
spec:
70+
tlsAdherence: LegacyExternalAPIServerComponentsOnly
71+
expected: |
72+
apiVersion: config.openshift.io/v1
73+
kind: APIServer
74+
spec:
75+
audit:
76+
profile: Default
77+
tlsAdherence: LegacyExternalAPIServerComponentsOnly
78+
- name: Should not allow removing tlsAdherence once set
79+
initial: |
80+
apiVersion: config.openshift.io/v1
81+
kind: APIServer
82+
spec:
83+
tlsAdherence: StrictAllComponents
84+
updated: |
85+
apiVersion: config.openshift.io/v1
86+
kind: APIServer
87+
spec: {}
88+
expectedError: "tlsAdherence may not be removed once set"

config/v1/types_apiserver.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ type APIServer struct {
3434
Status APIServerStatus `json:"status"`
3535
}
3636

37+
// +openshift:validation:FeatureGateAwareXValidation:featureGate=TLSAdherence,rule="has(oldSelf.tlsAdherence) ? has(self.tlsAdherence) : true",message="tlsAdherence may not be removed once set"
3738
type APIServerSpec struct {
3839
// servingCert is the TLS cert info for serving secure traffic. If not specified, operator managed certificates
3940
// will be used for serving secure traffic.
@@ -62,6 +63,37 @@ type APIServerSpec struct {
6263
// The current default is the Intermediate profile.
6364
// +optional
6465
TLSSecurityProfile *TLSSecurityProfile `json:"tlsSecurityProfile,omitempty"`
66+
// tlsAdherence controls which components in the cluster adhere to the TLS security profile
67+
// configured on this APIServer resource.
68+
//
69+
// Valid values are "LegacyExternalAPIServerComponentsOnly" and "StrictAllComponents".
70+
//
71+
// When set to "LegacyExternalAPIServerComponentsOnly", only the externally exposed
72+
// API server components (kube-apiserver, openshift-apiserver, oauth-apiserver) honor the configured
73+
// TLS profile. Other components continue to use their individual TLS configurations.
74+
//
75+
// When set to "StrictAllComponents", all components must honor the configured TLS profile
76+
// unless they have a component-specific TLS configuration that overrides it.
77+
// This mode is recommended for security-conscious deployments and is required for
78+
// certain compliance frameworks.
79+
//
80+
// Note: Some components such as Kubelet and IngressController have their own dedicated TLS
81+
// configuration mechanisms via KubeletConfig and IngressController CRs respectively. When these
82+
// component-specific TLS configurations are set, they take precedence over the cluster-wide
83+
// tlsSecurityProfile. When not set, these components fall back to the cluster-wide default.
84+
//
85+
// Components that encounter an unknown value for tlsAdherence should treat it as "StrictAllComponents"
86+
// and log a warning to ensure forward compatibility while defaulting to the more secure behavior.
87+
//
88+
// This field is optional.
89+
// When omitted, this means the user has no opinion and the platform is left to choose reasonable defaults.
90+
// These defaults are subject to change over time.
91+
// The current default is LegacyExternalAPIServerComponentsOnly.
92+
//
93+
// Once set, this field may be changed to a different value, but may not be removed.
94+
// +openshift:enable:FeatureGate=TLSAdherence
95+
// +optional
96+
TLSAdherence TLSAdherencePolicy `json:"tlsAdherence,omitempty"`
6597
// audit specifies the settings for audit configuration to be applied to all OpenShift-provided
6698
// API servers in the cluster.
6799
// +optional
@@ -237,6 +269,32 @@ const (
237269
type APIServerStatus struct {
238270
}
239271

272+
// TLSAdherencePolicy defines which components adhere to the TLS security profile.
273+
// Implementors should use the ShouldAllComponentsAdhere helper function from library-go
274+
// rather than checking these values directly.
275+
// +kubebuilder:validation:Enum=LegacyExternalAPIServerComponentsOnly;StrictAllComponents
276+
type TLSAdherencePolicy string
277+
278+
const (
279+
// TLSAdherencePolicyNoOpinion represents an empty/unset value for tlsAdherence.
280+
// This value cannot be explicitly set and is only present when the field is omitted.
281+
// When the field is omitted, the cluster defaults to LegacyExternalAPIServerComponentsOnly
282+
// behavior. Components should treat this the same as LegacyExternalAPIServerComponentsOnly.
283+
TLSAdherencePolicyNoOpinion TLSAdherencePolicy = ""
284+
285+
// TLSAdherencePolicyLegacyExternalAPIServerComponentsOnly means only the externally exposed
286+
// API server components (kube-apiserver, openshift-apiserver, oauth-apiserver) honor
287+
// the configured TLS profile. Other components continue to use their individual TLS
288+
// configurations.
289+
TLSAdherencePolicyLegacyExternalAPIServerComponentsOnly TLSAdherencePolicy = "LegacyExternalAPIServerComponentsOnly"
290+
291+
// TLSAdherencePolicyStrictAllComponents means all components must honor the configured TLS
292+
// profile unless they have a component-specific TLS configuration that overrides it.
293+
// This mode is recommended for security-conscious deployments and is required
294+
// for certain compliance frameworks.
295+
TLSAdherencePolicyStrictAllComponents TLSAdherencePolicy = "StrictAllComponents"
296+
)
297+
240298
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
241299

242300
// Compatibility level 1: Stable within a major release for a minimum of 12 months or 3 minor releases (whichever is longer).

config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_apiservers-CustomNoUpgrade.crd.yaml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,40 @@ spec:
292292
type: array
293293
x-kubernetes-list-type: atomic
294294
type: object
295+
tlsAdherence:
296+
description: |-
297+
tlsAdherence controls which components in the cluster adhere to the TLS security profile
298+
configured on this APIServer resource.
299+
300+
Valid values are "LegacyExternalAPIServerComponentsOnly" and "StrictAllComponents".
301+
302+
When set to "LegacyExternalAPIServerComponentsOnly", only the externally exposed
303+
API server components (kube-apiserver, openshift-apiserver, oauth-apiserver) honor the configured
304+
TLS profile. Other components continue to use their individual TLS configurations.
305+
306+
When set to "StrictAllComponents", all components must honor the configured TLS profile
307+
unless they have a component-specific TLS configuration that overrides it.
308+
This mode is recommended for security-conscious deployments and is required for
309+
certain compliance frameworks.
310+
311+
Note: Some components such as Kubelet and IngressController have their own dedicated TLS
312+
configuration mechanisms via KubeletConfig and IngressController CRs respectively. When these
313+
component-specific TLS configurations are set, they take precedence over the cluster-wide
314+
tlsSecurityProfile. When not set, these components fall back to the cluster-wide default.
315+
316+
Components that encounter an unknown value for tlsAdherence should treat it as "StrictAllComponents"
317+
and log a warning to ensure forward compatibility while defaulting to the more secure behavior.
318+
319+
This field is optional.
320+
When omitted, this means the user has no opinion and the platform is left to choose reasonable defaults.
321+
These defaults are subject to change over time.
322+
The current default is LegacyExternalAPIServerComponentsOnly.
323+
324+
Once set, this field may be changed to a different value, but may not be removed.
325+
enum:
326+
- LegacyExternalAPIServerComponentsOnly
327+
- StrictAllComponents
328+
type: string
295329
tlsSecurityProfile:
296330
description: |-
297331
tlsSecurityProfile specifies settings for TLS connections for externally exposed servers.
@@ -427,6 +461,9 @@ spec:
427461
type: string
428462
type: object
429463
type: object
464+
x-kubernetes-validations:
465+
- message: tlsAdherence may not be removed once set
466+
rule: 'has(oldSelf.tlsAdherence) ? has(self.tlsAdherence) : true'
430467
status:
431468
description: status holds observed values from the cluster. They may not
432469
be overridden.

config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_apiservers-DevPreviewNoUpgrade.crd.yaml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,40 @@ spec:
292292
type: array
293293
x-kubernetes-list-type: atomic
294294
type: object
295+
tlsAdherence:
296+
description: |-
297+
tlsAdherence controls which components in the cluster adhere to the TLS security profile
298+
configured on this APIServer resource.
299+
300+
Valid values are "LegacyExternalAPIServerComponentsOnly" and "StrictAllComponents".
301+
302+
When set to "LegacyExternalAPIServerComponentsOnly", only the externally exposed
303+
API server components (kube-apiserver, openshift-apiserver, oauth-apiserver) honor the configured
304+
TLS profile. Other components continue to use their individual TLS configurations.
305+
306+
When set to "StrictAllComponents", all components must honor the configured TLS profile
307+
unless they have a component-specific TLS configuration that overrides it.
308+
This mode is recommended for security-conscious deployments and is required for
309+
certain compliance frameworks.
310+
311+
Note: Some components such as Kubelet and IngressController have their own dedicated TLS
312+
configuration mechanisms via KubeletConfig and IngressController CRs respectively. When these
313+
component-specific TLS configurations are set, they take precedence over the cluster-wide
314+
tlsSecurityProfile. When not set, these components fall back to the cluster-wide default.
315+
316+
Components that encounter an unknown value for tlsAdherence should treat it as "StrictAllComponents"
317+
and log a warning to ensure forward compatibility while defaulting to the more secure behavior.
318+
319+
This field is optional.
320+
When omitted, this means the user has no opinion and the platform is left to choose reasonable defaults.
321+
These defaults are subject to change over time.
322+
The current default is LegacyExternalAPIServerComponentsOnly.
323+
324+
Once set, this field may be changed to a different value, but may not be removed.
325+
enum:
326+
- LegacyExternalAPIServerComponentsOnly
327+
- StrictAllComponents
328+
type: string
295329
tlsSecurityProfile:
296330
description: |-
297331
tlsSecurityProfile specifies settings for TLS connections for externally exposed servers.
@@ -427,6 +461,9 @@ spec:
427461
type: string
428462
type: object
429463
type: object
464+
x-kubernetes-validations:
465+
- message: tlsAdherence may not be removed once set
466+
rule: 'has(oldSelf.tlsAdherence) ? has(self.tlsAdherence) : true'
430467
status:
431468
description: status holds observed values from the cluster. They may not
432469
be overridden.

config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_apiservers-TechPreviewNoUpgrade.crd.yaml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,40 @@ spec:
224224
type: array
225225
x-kubernetes-list-type: atomic
226226
type: object
227+
tlsAdherence:
228+
description: |-
229+
tlsAdherence controls which components in the cluster adhere to the TLS security profile
230+
configured on this APIServer resource.
231+
232+
Valid values are "LegacyExternalAPIServerComponentsOnly" and "StrictAllComponents".
233+
234+
When set to "LegacyExternalAPIServerComponentsOnly", only the externally exposed
235+
API server components (kube-apiserver, openshift-apiserver, oauth-apiserver) honor the configured
236+
TLS profile. Other components continue to use their individual TLS configurations.
237+
238+
When set to "StrictAllComponents", all components must honor the configured TLS profile
239+
unless they have a component-specific TLS configuration that overrides it.
240+
This mode is recommended for security-conscious deployments and is required for
241+
certain compliance frameworks.
242+
243+
Note: Some components such as Kubelet and IngressController have their own dedicated TLS
244+
configuration mechanisms via KubeletConfig and IngressController CRs respectively. When these
245+
component-specific TLS configurations are set, they take precedence over the cluster-wide
246+
tlsSecurityProfile. When not set, these components fall back to the cluster-wide default.
247+
248+
Components that encounter an unknown value for tlsAdherence should treat it as "StrictAllComponents"
249+
and log a warning to ensure forward compatibility while defaulting to the more secure behavior.
250+
251+
This field is optional.
252+
When omitted, this means the user has no opinion and the platform is left to choose reasonable defaults.
253+
These defaults are subject to change over time.
254+
The current default is LegacyExternalAPIServerComponentsOnly.
255+
256+
Once set, this field may be changed to a different value, but may not be removed.
257+
enum:
258+
- LegacyExternalAPIServerComponentsOnly
259+
- StrictAllComponents
260+
type: string
227261
tlsSecurityProfile:
228262
description: |-
229263
tlsSecurityProfile specifies settings for TLS connections for externally exposed servers.
@@ -359,6 +393,9 @@ spec:
359393
type: string
360394
type: object
361395
type: object
396+
x-kubernetes-validations:
397+
- message: tlsAdherence may not be removed once set
398+
rule: 'has(oldSelf.tlsAdherence) ? has(self.tlsAdherence) : true'
362399
status:
363400
description: status holds observed values from the cluster. They may not
364401
be overridden.

config/v1/zz_generated.featuregated-crd-manifests.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ apiservers.config.openshift.io:
88
FeatureGates:
99
- KMSEncryption
1010
- KMSEncryptionProvider
11+
- TLSAdherence
1112
FilenameOperatorName: config-operator
1213
FilenameOperatorOrdering: "01"
1314
FilenameRunLevel: "0000_10"

0 commit comments

Comments
 (0)