diff --git a/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_apiservers-Default.crd.yaml b/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_apiservers-Default.crd.yaml
index ef855e38741..cd70f4879c7 100644
--- a/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_apiservers-Default.crd.yaml
+++ b/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_apiservers-Default.crd.yaml
@@ -223,6 +223,42 @@ spec:
type: array
x-kubernetes-list-type: atomic
type: object
+ tlsAdherence:
+ description: |-
+ tlsAdherence controls if components in the cluster adhere to the TLS security profile
+ configured on this APIServer resource.
+
+ Valid values are "LegacyAdheringComponentsOnly" and "StrictAllComponents".
+
+ When set to "LegacyAdheringComponentsOnly", components that already honor the
+ cluster-wide TLS profile continue to do so. Components that do not already honor
+ it continue to use their individual TLS configurations.
+
+ When set to "StrictAllComponents", all components must honor the configured TLS
+ profile unless they have a component-specific TLS configuration that overrides
+ it. This mode is recommended for security-conscious deployments and is required
+ for certain compliance frameworks.
+
+ Note: Some components such as Kubelet and IngressController have their own
+ dedicated TLS configuration mechanisms via KubeletConfig and IngressController
+ CRs respectively. When these component-specific TLS configurations are set,
+ they take precedence over the cluster-wide tlsSecurityProfile. When not set,
+ these components fall back to the cluster-wide default.
+
+ Components that encounter an unknown value for tlsAdherence should treat it
+ as "StrictAllComponents" and log a warning to ensure forward compatibility
+ while defaulting to the more secure behavior.
+
+ This field is optional.
+ When omitted, this means the user has no opinion and the platform is left
+ to choose reasonable defaults. These defaults are subject to change over time.
+ The current default is LegacyAdheringComponentsOnly.
+
+ Once set, this field may be changed to a different value, but may not be removed.
+ enum:
+ - LegacyAdheringComponentsOnly
+ - StrictAllComponents
+ type: string
tlsSecurityProfile:
description: |-
tlsSecurityProfile specifies settings for TLS connections for externally exposed servers.
@@ -380,6 +416,9 @@ spec:
type: string
type: object
type: object
+ x-kubernetes-validations:
+ - message: tlsAdherence may not be removed once set
+ rule: 'has(oldSelf.tlsAdherence) ? has(self.tlsAdherence) : true'
status:
description: status holds observed values from the cluster. They may not
be overridden.
diff --git a/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_apiservers-OKD.crd.yaml b/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_apiservers-OKD.crd.yaml
index 99c093b2176..3fcdb34871a 100644
--- a/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_apiservers-OKD.crd.yaml
+++ b/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_apiservers-OKD.crd.yaml
@@ -223,6 +223,42 @@ spec:
type: array
x-kubernetes-list-type: atomic
type: object
+ tlsAdherence:
+ description: |-
+ tlsAdherence controls if components in the cluster adhere to the TLS security profile
+ configured on this APIServer resource.
+
+ Valid values are "LegacyAdheringComponentsOnly" and "StrictAllComponents".
+
+ When set to "LegacyAdheringComponentsOnly", components that already honor the
+ cluster-wide TLS profile continue to do so. Components that do not already honor
+ it continue to use their individual TLS configurations.
+
+ When set to "StrictAllComponents", all components must honor the configured TLS
+ profile unless they have a component-specific TLS configuration that overrides
+ it. This mode is recommended for security-conscious deployments and is required
+ for certain compliance frameworks.
+
+ Note: Some components such as Kubelet and IngressController have their own
+ dedicated TLS configuration mechanisms via KubeletConfig and IngressController
+ CRs respectively. When these component-specific TLS configurations are set,
+ they take precedence over the cluster-wide tlsSecurityProfile. When not set,
+ these components fall back to the cluster-wide default.
+
+ Components that encounter an unknown value for tlsAdherence should treat it
+ as "StrictAllComponents" and log a warning to ensure forward compatibility
+ while defaulting to the more secure behavior.
+
+ This field is optional.
+ When omitted, this means the user has no opinion and the platform is left
+ to choose reasonable defaults. These defaults are subject to change over time.
+ The current default is LegacyAdheringComponentsOnly.
+
+ Once set, this field may be changed to a different value, but may not be removed.
+ enum:
+ - LegacyAdheringComponentsOnly
+ - StrictAllComponents
+ type: string
tlsSecurityProfile:
description: |-
tlsSecurityProfile specifies settings for TLS connections for externally exposed servers.
@@ -380,6 +416,9 @@ spec:
type: string
type: object
type: object
+ x-kubernetes-validations:
+ - message: tlsAdherence may not be removed once set
+ rule: 'has(oldSelf.tlsAdherence) ? has(self.tlsAdherence) : true'
status:
description: status holds observed values from the cluster. They may not
be overridden.
diff --git a/features.md b/features.md
index 5740fc034fb..594e3b3e231 100644
--- a/features.md
+++ b/features.md
@@ -84,7 +84,6 @@
| OnPremDNSRecords| | | Enabled | Enabled | | | Enabled | Enabled |
| SELinuxMount| | | Enabled | Enabled | | | Enabled | Enabled |
| SignatureStores| | | Enabled | Enabled | | | Enabled | Enabled |
-| TLSAdherence| | | Enabled | Enabled | | | Enabled | Enabled |
| TLSGroupPreferences| | | Enabled | Enabled | | | Enabled | Enabled |
| VSphereConfigurableMaxAllowedBlockVolumesPerNode| | | Enabled | Enabled | | | Enabled | Enabled |
| VSphereMultiVCenterDay2| | | Enabled | Enabled | | | Enabled | Enabled |
@@ -120,6 +119,7 @@
| SigstoreImageVerification| Enabled | Enabled | Enabled | Enabled | Enabled | Enabled | Enabled | Enabled |
| SigstoreImageVerificationPKI| Enabled | Enabled | Enabled | Enabled | Enabled | Enabled | Enabled | Enabled |
| StoragePerformantSecurityPolicy| Enabled | Enabled | Enabled | Enabled | Enabled | Enabled | Enabled | Enabled |
+| TLSAdherence| Enabled | Enabled | Enabled | Enabled | Enabled | Enabled | Enabled | Enabled |
| UpgradeStatus| Enabled | Enabled | Enabled | Enabled | Enabled | Enabled | Enabled | Enabled |
| VSphereHostVMGroupZonal| Enabled | Enabled | Enabled | Enabled | Enabled | Enabled | Enabled | Enabled |
| VSphereMixedNodeEnv| Enabled | Enabled | Enabled | Enabled | Enabled | Enabled | Enabled | Enabled |
diff --git a/features/features.go b/features/features.go
index 9e1150f2d6a..da90f92c667 100644
--- a/features/features.go
+++ b/features/features.go
@@ -1010,7 +1010,7 @@ var (
contactPerson("joelanford").
productScope(ocpSpecific).
enhancementPR("https://github.com/openshift/enhancements/pull/1910").
- enable(inDevPreviewNoUpgrade(), inTechPreviewNoUpgrade()).
+ enable(inDefault(), inOKD(), inTechPreviewNoUpgrade(), inDevPreviewNoUpgrade()).
mustRegister()
FeatureGateConfidentialCluster = newFeatureGate("ConfidentialCluster").
diff --git a/payload-manifests/crds/0000_10_config-operator_01_apiservers-Default.crd.yaml b/payload-manifests/crds/0000_10_config-operator_01_apiservers-Default.crd.yaml
index ef855e38741..cd70f4879c7 100644
--- a/payload-manifests/crds/0000_10_config-operator_01_apiservers-Default.crd.yaml
+++ b/payload-manifests/crds/0000_10_config-operator_01_apiservers-Default.crd.yaml
@@ -223,6 +223,42 @@ spec:
type: array
x-kubernetes-list-type: atomic
type: object
+ tlsAdherence:
+ description: |-
+ tlsAdherence controls if components in the cluster adhere to the TLS security profile
+ configured on this APIServer resource.
+
+ Valid values are "LegacyAdheringComponentsOnly" and "StrictAllComponents".
+
+ When set to "LegacyAdheringComponentsOnly", components that already honor the
+ cluster-wide TLS profile continue to do so. Components that do not already honor
+ it continue to use their individual TLS configurations.
+
+ When set to "StrictAllComponents", all components must honor the configured TLS
+ profile unless they have a component-specific TLS configuration that overrides
+ it. This mode is recommended for security-conscious deployments and is required
+ for certain compliance frameworks.
+
+ Note: Some components such as Kubelet and IngressController have their own
+ dedicated TLS configuration mechanisms via KubeletConfig and IngressController
+ CRs respectively. When these component-specific TLS configurations are set,
+ they take precedence over the cluster-wide tlsSecurityProfile. When not set,
+ these components fall back to the cluster-wide default.
+
+ Components that encounter an unknown value for tlsAdherence should treat it
+ as "StrictAllComponents" and log a warning to ensure forward compatibility
+ while defaulting to the more secure behavior.
+
+ This field is optional.
+ When omitted, this means the user has no opinion and the platform is left
+ to choose reasonable defaults. These defaults are subject to change over time.
+ The current default is LegacyAdheringComponentsOnly.
+
+ Once set, this field may be changed to a different value, but may not be removed.
+ enum:
+ - LegacyAdheringComponentsOnly
+ - StrictAllComponents
+ type: string
tlsSecurityProfile:
description: |-
tlsSecurityProfile specifies settings for TLS connections for externally exposed servers.
@@ -380,6 +416,9 @@ spec:
type: string
type: object
type: object
+ x-kubernetes-validations:
+ - message: tlsAdherence may not be removed once set
+ rule: 'has(oldSelf.tlsAdherence) ? has(self.tlsAdherence) : true'
status:
description: status holds observed values from the cluster. They may not
be overridden.
diff --git a/payload-manifests/crds/0000_10_config-operator_01_apiservers-OKD.crd.yaml b/payload-manifests/crds/0000_10_config-operator_01_apiservers-OKD.crd.yaml
index 99c093b2176..3fcdb34871a 100644
--- a/payload-manifests/crds/0000_10_config-operator_01_apiservers-OKD.crd.yaml
+++ b/payload-manifests/crds/0000_10_config-operator_01_apiservers-OKD.crd.yaml
@@ -223,6 +223,42 @@ spec:
type: array
x-kubernetes-list-type: atomic
type: object
+ tlsAdherence:
+ description: |-
+ tlsAdherence controls if components in the cluster adhere to the TLS security profile
+ configured on this APIServer resource.
+
+ Valid values are "LegacyAdheringComponentsOnly" and "StrictAllComponents".
+
+ When set to "LegacyAdheringComponentsOnly", components that already honor the
+ cluster-wide TLS profile continue to do so. Components that do not already honor
+ it continue to use their individual TLS configurations.
+
+ When set to "StrictAllComponents", all components must honor the configured TLS
+ profile unless they have a component-specific TLS configuration that overrides
+ it. This mode is recommended for security-conscious deployments and is required
+ for certain compliance frameworks.
+
+ Note: Some components such as Kubelet and IngressController have their own
+ dedicated TLS configuration mechanisms via KubeletConfig and IngressController
+ CRs respectively. When these component-specific TLS configurations are set,
+ they take precedence over the cluster-wide tlsSecurityProfile. When not set,
+ these components fall back to the cluster-wide default.
+
+ Components that encounter an unknown value for tlsAdherence should treat it
+ as "StrictAllComponents" and log a warning to ensure forward compatibility
+ while defaulting to the more secure behavior.
+
+ This field is optional.
+ When omitted, this means the user has no opinion and the platform is left
+ to choose reasonable defaults. These defaults are subject to change over time.
+ The current default is LegacyAdheringComponentsOnly.
+
+ Once set, this field may be changed to a different value, but may not be removed.
+ enum:
+ - LegacyAdheringComponentsOnly
+ - StrictAllComponents
+ type: string
tlsSecurityProfile:
description: |-
tlsSecurityProfile specifies settings for TLS connections for externally exposed servers.
@@ -380,6 +416,9 @@ spec:
type: string
type: object
type: object
+ x-kubernetes-validations:
+ - message: tlsAdherence may not be removed once set
+ rule: 'has(oldSelf.tlsAdherence) ? has(self.tlsAdherence) : true'
status:
description: status holds observed values from the cluster. They may not
be overridden.
diff --git a/payload-manifests/featuregates/featureGate-4-10-Hypershift-Default.yaml b/payload-manifests/featuregates/featureGate-4-10-Hypershift-Default.yaml
index fc3a3dc3a30..029c29e8f79 100644
--- a/payload-manifests/featuregates/featureGate-4-10-Hypershift-Default.yaml
+++ b/payload-manifests/featuregates/featureGate-4-10-Hypershift-Default.yaml
@@ -263,9 +263,6 @@
{
"name": "SignatureStores"
},
- {
- "name": "TLSAdherence"
- },
{
"name": "TLSGroupPreferences"
},
@@ -376,6 +373,9 @@
{
"name": "StoragePerformantSecurityPolicy"
},
+ {
+ "name": "TLSAdherence"
+ },
{
"name": "UpgradeStatus"
},
diff --git a/payload-manifests/featuregates/featureGate-4-10-Hypershift-OKD.yaml b/payload-manifests/featuregates/featureGate-4-10-Hypershift-OKD.yaml
index 1513fbdf881..7e19c11f20f 100644
--- a/payload-manifests/featuregates/featureGate-4-10-Hypershift-OKD.yaml
+++ b/payload-manifests/featuregates/featureGate-4-10-Hypershift-OKD.yaml
@@ -265,9 +265,6 @@
{
"name": "SignatureStores"
},
- {
- "name": "TLSAdherence"
- },
{
"name": "TLSGroupPreferences"
},
@@ -378,6 +375,9 @@
{
"name": "StoragePerformantSecurityPolicy"
},
+ {
+ "name": "TLSAdherence"
+ },
{
"name": "UpgradeStatus"
},
diff --git a/payload-manifests/featuregates/featureGate-4-10-SelfManagedHA-Default.yaml b/payload-manifests/featuregates/featureGate-4-10-SelfManagedHA-Default.yaml
index 662bcb95df8..1b62636cd19 100644
--- a/payload-manifests/featuregates/featureGate-4-10-SelfManagedHA-Default.yaml
+++ b/payload-manifests/featuregates/featureGate-4-10-SelfManagedHA-Default.yaml
@@ -251,9 +251,6 @@
{
"name": "SignatureStores"
},
- {
- "name": "TLSAdherence"
- },
{
"name": "TLSGroupPreferences"
},
@@ -376,6 +373,9 @@
{
"name": "StoragePerformantSecurityPolicy"
},
+ {
+ "name": "TLSAdherence"
+ },
{
"name": "UpgradeStatus"
},
diff --git a/payload-manifests/featuregates/featureGate-4-10-SelfManagedHA-OKD.yaml b/payload-manifests/featuregates/featureGate-4-10-SelfManagedHA-OKD.yaml
index 1396a78cd0f..e2ed62ea2d3 100644
--- a/payload-manifests/featuregates/featureGate-4-10-SelfManagedHA-OKD.yaml
+++ b/payload-manifests/featuregates/featureGate-4-10-SelfManagedHA-OKD.yaml
@@ -253,9 +253,6 @@
{
"name": "SignatureStores"
},
- {
- "name": "TLSAdherence"
- },
{
"name": "TLSGroupPreferences"
},
@@ -378,6 +375,9 @@
{
"name": "StoragePerformantSecurityPolicy"
},
+ {
+ "name": "TLSAdherence"
+ },
{
"name": "UpgradeStatus"
},
diff --git a/tools/codegen/cmd/featuregate-test-analyzer.go b/tools/codegen/cmd/featuregate-test-analyzer.go
index eb76143a2c6..ae874d54dea 100644
--- a/tools/codegen/cmd/featuregate-test-analyzer.go
+++ b/tools/codegen/cmd/featuregate-test-analyzer.go
@@ -801,6 +801,38 @@ func filterVariants(featureGate string, variantsList ...[]JobVariant) []JobVaria
return filteredVariants
}
+// flexibleDateTime wraps time.Time so that JSON values can be decoded from
+// either an RFC 3339 timestamp (e.g. "2018-07-11T00:00:00Z") or a bare
+// date-only string (e.g. "2018-07-11"). The Sippy /api/releases endpoint
+// switched the development_start and ga fields from RFC 3339 timestamps to
+// bare dates; supporting both keeps this tool compatible with old and new
+// responses.
+type flexibleDateTime struct {
+ time.Time
+}
+
+// UnmarshalJSON decodes the JSON value into the wrapped time.Time, trying the
+// RFC 3339 layout first and falling back to the date-only layout ("2006-01-02").
+func (f *flexibleDateTime) UnmarshalJSON(data []byte) error {
+ s := strings.Trim(string(data), `"`)
+ if s == "" || s == "null" {
+ return nil
+ }
+
+ if t, err := time.Parse(time.RFC3339, s); err == nil {
+ f.Time = t
+ return nil
+ }
+
+ t, err := time.Parse("2006-01-02", s)
+ if err != nil {
+ return fmt.Errorf("cannot parse %q as RFC 3339 or date-only (2006-01-02): %w", s, err)
+ }
+
+ f.Time = t
+ return nil
+}
+
// getLatestRelease returns the latest release from Sippy.
func getLatestRelease() (string, error) {
releaseAPI := "https://sippy.dptools.openshift.org/api/releases"
@@ -821,8 +853,8 @@ func getLatestRelease() (string, error) {
var result struct {
ReleaseAttrs map[string]struct {
- DevelopmentStart *time.Time `json:"development_start,omitempty"`
- Product string `json:"product,omitempty"`
+ DevelopmentStart *flexibleDateTime `json:"development_start,omitempty"`
+ Product string `json:"product,omitempty"`
} `json:"release_attrs,omitempty"`
}
@@ -840,14 +872,14 @@ func getLatestRelease() (string, error) {
continue
}
- if releaseAttrs.DevelopmentStart != nil && !releaseAttrs.DevelopmentStart.IsZero() && time.Now().Before(*releaseAttrs.DevelopmentStart) {
+ if releaseAttrs.DevelopmentStart != nil && !releaseAttrs.DevelopmentStart.Time.IsZero() && time.Now().Before(releaseAttrs.DevelopmentStart.Time) {
// We only want to consider releases that have started development.
continue
}
- if releaseAttrs.DevelopmentStart != nil && !releaseAttrs.DevelopmentStart.IsZero() && releaseAttrs.DevelopmentStart.After(latestReleaseStart) {
+ if releaseAttrs.DevelopmentStart != nil && !releaseAttrs.DevelopmentStart.Time.IsZero() && releaseAttrs.DevelopmentStart.Time.After(latestReleaseStart) {
latestRelease = release
- latestReleaseStart = *releaseAttrs.DevelopmentStart
+ latestReleaseStart = releaseAttrs.DevelopmentStart.Time
}
}
diff --git a/tools/codegen/pkg/sippy/json_types.go b/tools/codegen/pkg/sippy/json_types.go
index ad2012a3ef5..ece3044dea4 100644
--- a/tools/codegen/pkg/sippy/json_types.go
+++ b/tools/codegen/pkg/sippy/json_types.go
@@ -337,7 +337,7 @@ func BuildSippyJobRunsForJobURL(release, jobName string, timestamp time.Time) st
{
ColumnField: "timestamp",
OperatorValue: ">=",
- Value: fmt.Sprintf("%d", timestamp.UnixMilli()),
+ Value: timestamp.UTC().Format(time.RFC3339),
},
}