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), }, }