From bd8d79af1c7b5196670f01d39aed9d6a01cb901d Mon Sep 17 00:00:00 2001 From: siddhi bhor Date: Fri, 15 May 2026 16:37:31 +0530 Subject: [PATCH] feat(api): add NetworkPolicyProvisioning field to ProxyConfig for EP-1998 Introduce ManagementState type with Managed and Unmanaged values, and add NetworkPolicyProvisioning field to ProxyConfig. When set to Managed (default), the operator will automatically create and maintain a NetworkPolicy allowing ESO pods to reach the configured proxy server. When set to Unmanaged, administrators manage proxy egress NetworkPolicies themselves. The field is defined at spec.appConfig.proxy.networkPolicyProvisioning on ExternalSecretsConfig. CRD YAMLs for both ExternalSecretsConfig and ExternalSecretsManager are updated. Six API test cases cover valid values, default injection, invalid value rejection, and mutability. Ref: openshift/enhancements#1998 Co-authored-by: Cursor --- api/v1alpha1/meta.go | 21 ++++ .../externalsecretsconfig.testsuite.yaml | 117 ++++++++++++++++++ .../externalsecretsmanager.testsuite.yaml | 5 + ...ecrets-operator.clusterserviceversion.yaml | 2 +- ...r.openshift.io_externalsecretsconfigs.yaml | 12 ++ ....openshift.io_externalsecretsmanagers.yaml | 12 ++ ...r.openshift.io_externalsecretsconfigs.yaml | 12 ++ ....openshift.io_externalsecretsmanagers.yaml | 12 ++ docs/api_reference.md | 18 +++ hack/govulncheck.sh | 2 +- 10 files changed, 211 insertions(+), 2 deletions(-) diff --git a/api/v1alpha1/meta.go b/api/v1alpha1/meta.go index 68a882d64..2980a39ce 100644 --- a/api/v1alpha1/meta.go +++ b/api/v1alpha1/meta.go @@ -111,8 +111,29 @@ type ProxyConfig struct { // +kubebuilder:validation:MaxLength:=4096 // +optional NoProxy string `json:"noProxy,omitempty"` + + // NetworkPolicyProvisioning defines the management strategy for the proxy egress rule. + // When set to Managed, the operator automatically provisions and maintains + // a NetworkPolicy allowing traffic to the configured proxy. + // If no proxy is configured, no NetworkPolicy will be created + // regardless of this setting. + // +kubebuilder:validation:Enum=Managed;Unmanaged + // +kubebuilder:default=Managed + // +optional + NetworkPolicyProvisioning ManagementState `json:"networkPolicyProvisioning,omitempty"` } +// ManagementState controls whether the operator manages the resource lifecycle. +type ManagementState string + +const ( + // ManagementStateManaged indicates the Operator is responsible for the resource lifecycle. + ManagementStateManaged ManagementState = "Managed" + + // ManagementStateUnmanaged indicates the User is responsible for the resource lifecycle. + ManagementStateUnmanaged ManagementState = "Unmanaged" +) + // Mode indicates the operational state of the optional features. type Mode string diff --git a/api/v1alpha1/tests/externalsecretsconfig.operator.openshift.io/externalsecretsconfig.testsuite.yaml b/api/v1alpha1/tests/externalsecretsconfig.operator.openshift.io/externalsecretsconfig.testsuite.yaml index 6e20a96df..ca22244bb 100644 --- a/api/v1alpha1/tests/externalsecretsconfig.operator.openshift.io/externalsecretsconfig.testsuite.yaml +++ b/api/v1alpha1/tests/externalsecretsconfig.operator.openshift.io/externalsecretsconfig.testsuite.yaml @@ -1445,6 +1445,96 @@ tests: injectAnnotations: "false" certificateDuration: "8760h" certificateRenewBefore: "30m" + - name: Should accept networkPolicyProvisioning set to Managed (default) + resourceName: cluster + initial: | + apiVersion: operator.openshift.io/v1alpha1 + kind: ExternalSecretsConfig + spec: + appConfig: + proxy: + httpProxy: "http://proxy.example.com:3128" + networkPolicyProvisioning: Managed + expected: | + apiVersion: operator.openshift.io/v1alpha1 + kind: ExternalSecretsConfig + spec: + appConfig: + logLevel: 1 + proxy: + httpProxy: "http://proxy.example.com:3128" + networkPolicyProvisioning: Managed + - name: Should accept networkPolicyProvisioning set to Unmanaged + resourceName: cluster + initial: | + apiVersion: operator.openshift.io/v1alpha1 + kind: ExternalSecretsConfig + spec: + appConfig: + proxy: + httpProxy: "http://proxy.example.com:3128" + networkPolicyProvisioning: Unmanaged + expected: | + apiVersion: operator.openshift.io/v1alpha1 + kind: ExternalSecretsConfig + spec: + appConfig: + logLevel: 1 + proxy: + httpProxy: "http://proxy.example.com:3128" + networkPolicyProvisioning: Unmanaged + - name: Should default networkPolicyProvisioning to Managed when proxy is set without the field + resourceName: cluster + initial: | + apiVersion: operator.openshift.io/v1alpha1 + kind: ExternalSecretsConfig + spec: + appConfig: + proxy: + httpProxy: "http://proxy.example.com:3128" + expected: | + apiVersion: operator.openshift.io/v1alpha1 + kind: ExternalSecretsConfig + spec: + appConfig: + logLevel: 1 + proxy: + httpProxy: "http://proxy.example.com:3128" + networkPolicyProvisioning: Managed + - name: Should fail with invalid value for networkPolicyProvisioning + resourceName: cluster + initial: | + apiVersion: operator.openshift.io/v1alpha1 + kind: ExternalSecretsConfig + spec: + appConfig: + proxy: + httpProxy: "http://proxy.example.com:3128" + networkPolicyProvisioning: Enabled + expectedError: "spec.appConfig.proxy.networkPolicyProvisioning: Unsupported value: \"Enabled\": supported values: \"Managed\", \"Unmanaged\"" + - name: Should accept proxy config with all fields including networkPolicyProvisioning + resourceName: cluster + initial: | + apiVersion: operator.openshift.io/v1alpha1 + kind: ExternalSecretsConfig + spec: + appConfig: + proxy: + httpProxy: "http://proxy.example.com:3128" + httpsProxy: "https://proxy.example.com:3129" + noProxy: "localhost,127.0.0.1,.cluster.local" + networkPolicyProvisioning: Unmanaged + expected: | + apiVersion: operator.openshift.io/v1alpha1 + kind: ExternalSecretsConfig + spec: + appConfig: + logLevel: 1 + proxy: + httpProxy: "http://proxy.example.com:3128" + httpsProxy: "https://proxy.example.com:3129" + noProxy: "localhost,127.0.0.1,.cluster.local" + networkPolicyProvisioning: Unmanaged onUpdate: - name: Should be able to update labels in controller config resourceName: cluster @@ -1726,3 +1816,30 @@ tests: - to: - ipBlock: cidr: 172.16.0.0/12 + - name: Should be able to update networkPolicyProvisioning from Managed to Unmanaged + resourceName: cluster + initial: | + apiVersion: operator.openshift.io/v1alpha1 + kind: ExternalSecretsConfig + spec: + appConfig: + proxy: + httpProxy: "http://proxy.example.com:3128" + networkPolicyProvisioning: Managed + updated: | + apiVersion: operator.openshift.io/v1alpha1 + kind: ExternalSecretsConfig + spec: + appConfig: + proxy: + httpProxy: "http://proxy.example.com:3128" + networkPolicyProvisioning: Unmanaged + expected: | + apiVersion: operator.openshift.io/v1alpha1 + kind: ExternalSecretsConfig + spec: + appConfig: + logLevel: 1 + proxy: + httpProxy: "http://proxy.example.com:3128" + networkPolicyProvisioning: Unmanaged diff --git a/api/v1alpha1/tests/externalsecretsmanager.operator.openshift.io/externalsecretsmanager.testsuite.yaml b/api/v1alpha1/tests/externalsecretsmanager.operator.openshift.io/externalsecretsmanager.testsuite.yaml index 2f88c646a..cc4a78561 100644 --- a/api/v1alpha1/tests/externalsecretsmanager.operator.openshift.io/externalsecretsmanager.testsuite.yaml +++ b/api/v1alpha1/tests/externalsecretsmanager.operator.openshift.io/externalsecretsmanager.testsuite.yaml @@ -88,6 +88,7 @@ tests: proxy: httpProxy: "http://proxy.example.com:8080" httpsProxy: "https://proxy.example.com:8443" + networkPolicyProvisioning: Managed noProxy: "localhost,127.0.0.1,.local" - name: Should fail to create with invalid singleton name resourceName: invalid-name @@ -182,6 +183,7 @@ tests: logLevel: 1 proxy: httpProxy: "http://proxy-url-at-exactly-two-thousand-and-forty-eight-characters-to-test-the-boundary-condition-where-we-want-to-ensure-that-urls-at-the-maximum-allowed-length-are-accepted-properly-by-the-validation-system-while-urls-that-exceed-this-limit-are-rejected-appropriately-which-is-important-for-maintaining-proper-validation-boundaries-in-production-systems-where-configuration-parameters-must-be-validated-correctly-to-prevent-system-failures-or-unexpected-behavior-that-could-impact-application-functionality-and-user-experience-in-various-deployment-environments-including-development-staging-and-production-kubernetes-clusters-running-across-different-cloud-providers-and-on-premises-infrastructure-where-proxy-configurations-are-commonly-used-for-network-security-and-compliance-requirements-that-organizations-need-to-meet-for-their-business-operations-and-regulatory-obligations-in-different-geographical-regions-around-the-world-where-various-network-policies-and-security-measures-are-implemented-to-protect-sensitive-data-and-ensure-proper-access-control-for-applications-and-services-that-handle-confidential-information-and-business-critical-processes-that-must-operate-reliably-and-securely-at-all-times-without-interruption-or-performance-degradation-that-could-affect-end-users-and-customers-who-depend-on-these-systems-for-their-daily-activities-and-business-needs-which-makes-proper-validation-of-configuration-parameters-like-proxy-urls-essential-for-maintaining-system-stability-and-security-in-production-environments-where-any-configuration-error-could-have-significant-consequences-for-business-continuity-and-customer-satisfaction-which-is-why-we-implement-comprehensive-boundary-testing-to-ensure-that-all-validation-rules-work-correctly-at-their-specified-limits-and-provide-clear-error-messages-when-those-limits-are-exceeded-by-user-configurations.example.com:8080" + networkPolicyProvisioning: Managed - name: Should accept HTTPS proxy URL at maximum length boundary resourceName: cluster initial: | @@ -200,6 +202,7 @@ tests: logLevel: 1 proxy: httpsProxy: "https://secure-proxy-url-at-exactly-two-thousand-and-forty-eight-characters-to-test-the-boundary-condition-where-we-want-to-ensure-that-urls-at-the-maximum-allowed-length-are-accepted-properly-by-the-validation-system-while-urls-that-exceed-this-limit-are-rejected-appropriately-which-is-important-for-maintaining-proper-validation-boundaries-in-production-systems-where-configuration-parameters-must-be-validated-correctly-to-prevent-system-failures-or-unexpected-behavior-that-could-impact-application-functionality-and-user-experience-in-various-deployment-environments-including-development-staging-and-production-kubernetes-clusters-running-across-different-cloud-providers-and-on-premises-infrastructure-where-proxy-configurations-are-commonly-used-for-network-security-and-compliance-requirements-that-organizations-need-to-meet-for-their-business-operations-and-regulatory-obligations-in-different-geographical-regions-around-the-world-where-various-network-policies-and-security-measures-are-implemented-to-protect-sensitive-data-and-ensure-proper-access-control-for-applications-and-services-that-handle-confidential-information-and-business-critical-processes-that-must-operate-reliably-and-securely-at-all-times-without-interruption-or-performance-degradation-that-could-affect-end-users-and-customers-who-depend-on-these-systems-for-their-daily-activities-and-business-needs-which-makes-proper-validation-of-configuration-parameters-like-proxy-urls-essential-for-maintaining-system-stability-and-security-in-production-environments-where-any-configuration-error-could-have-significant-consequences-for-business-continuity-and-customer-satisfaction-which-is-why-we-implement-comprehensive-boundary-testing-to-ensure-that-all-validation-rules-work-correctly-at-their-specified-limits-and-provide-clear-error-messages-when-those-limits-are-exceeded.example.com:8443" + networkPolicyProvisioning: Managed - name: Should accept empty proxy configuration resourceName: cluster initial: | @@ -220,6 +223,7 @@ tests: proxy: httpProxy: "" httpsProxy: "" + networkPolicyProvisioning: Managed noProxy: "" onUpdate: - name: Should be able to add global config after creation @@ -337,6 +341,7 @@ tests: proxy: httpProxy: "http://proxy.company.com:3128" httpsProxy: "https://proxy.company.com:3128" + networkPolicyProvisioning: Managed noProxy: "localhost,127.0.0.1,.company.com" - name: Should be able to update node selector and tolerations resourceName: cluster diff --git a/bundle/manifests/openshift-external-secrets-operator.clusterserviceversion.yaml b/bundle/manifests/openshift-external-secrets-operator.clusterserviceversion.yaml index a87455abc..12bcabe19 100644 --- a/bundle/manifests/openshift-external-secrets-operator.clusterserviceversion.yaml +++ b/bundle/manifests/openshift-external-secrets-operator.clusterserviceversion.yaml @@ -220,7 +220,7 @@ metadata: categories: Security console.openshift.io/disable-operand-delete: "true" containerImage: openshift.io/external-secrets-operator:latest - createdAt: "2026-03-06T13:50:37Z" + createdAt: "2026-05-15T11:51:51Z" features.operators.openshift.io/cnf: "false" features.operators.openshift.io/cni: "false" features.operators.openshift.io/csi: "false" diff --git a/bundle/manifests/operator.openshift.io_externalsecretsconfigs.yaml b/bundle/manifests/operator.openshift.io_externalsecretsconfigs.yaml index f27616944..f2dbb80be 100644 --- a/bundle/manifests/operator.openshift.io_externalsecretsconfigs.yaml +++ b/bundle/manifests/operator.openshift.io_externalsecretsconfigs.yaml @@ -1034,6 +1034,18 @@ spec: maxLength: 2048 minLength: 0 type: string + networkPolicyProvisioning: + default: Managed + description: |- + NetworkPolicyProvisioning defines the management strategy for the proxy egress rule. + When set to Managed, the operator automatically provisions and maintains + a NetworkPolicy allowing traffic to the configured proxy. + If no proxy is configured, no NetworkPolicy will be created + regardless of this setting. + enum: + - Managed + - Unmanaged + type: string noProxy: description: |- noProxy is a comma-separated list of hostnames and/or CIDRs and/or IPs for which the proxy should not be used. diff --git a/bundle/manifests/operator.openshift.io_externalsecretsmanagers.yaml b/bundle/manifests/operator.openshift.io_externalsecretsmanagers.yaml index fd26d0632..333156254 100644 --- a/bundle/manifests/operator.openshift.io_externalsecretsmanagers.yaml +++ b/bundle/manifests/operator.openshift.io_externalsecretsmanagers.yaml @@ -1031,6 +1031,18 @@ spec: maxLength: 2048 minLength: 0 type: string + networkPolicyProvisioning: + default: Managed + description: |- + NetworkPolicyProvisioning defines the management strategy for the proxy egress rule. + When set to Managed, the operator automatically provisions and maintains + a NetworkPolicy allowing traffic to the configured proxy. + If no proxy is configured, no NetworkPolicy will be created + regardless of this setting. + enum: + - Managed + - Unmanaged + type: string noProxy: description: |- noProxy is a comma-separated list of hostnames and/or CIDRs and/or IPs for which the proxy should not be used. diff --git a/config/crd/bases/operator.openshift.io_externalsecretsconfigs.yaml b/config/crd/bases/operator.openshift.io_externalsecretsconfigs.yaml index 274ac9416..c615195d1 100644 --- a/config/crd/bases/operator.openshift.io_externalsecretsconfigs.yaml +++ b/config/crd/bases/operator.openshift.io_externalsecretsconfigs.yaml @@ -1034,6 +1034,18 @@ spec: maxLength: 2048 minLength: 0 type: string + networkPolicyProvisioning: + default: Managed + description: |- + NetworkPolicyProvisioning defines the management strategy for the proxy egress rule. + When set to Managed, the operator automatically provisions and maintains + a NetworkPolicy allowing traffic to the configured proxy. + If no proxy is configured, no NetworkPolicy will be created + regardless of this setting. + enum: + - Managed + - Unmanaged + type: string noProxy: description: |- noProxy is a comma-separated list of hostnames and/or CIDRs and/or IPs for which the proxy should not be used. diff --git a/config/crd/bases/operator.openshift.io_externalsecretsmanagers.yaml b/config/crd/bases/operator.openshift.io_externalsecretsmanagers.yaml index c508693b4..cee5f265d 100644 --- a/config/crd/bases/operator.openshift.io_externalsecretsmanagers.yaml +++ b/config/crd/bases/operator.openshift.io_externalsecretsmanagers.yaml @@ -1031,6 +1031,18 @@ spec: maxLength: 2048 minLength: 0 type: string + networkPolicyProvisioning: + default: Managed + description: |- + NetworkPolicyProvisioning defines the management strategy for the proxy egress rule. + When set to Managed, the operator automatically provisions and maintains + a NetworkPolicy allowing traffic to the configured proxy. + If no proxy is configured, no NetworkPolicy will be created + regardless of this setting. + enum: + - Managed + - Unmanaged + type: string noProxy: description: |- noProxy is a comma-separated list of hostnames and/or CIDRs and/or IPs for which the proxy should not be used. diff --git a/docs/api_reference.md b/docs/api_reference.md index 9a5c023ae..8061f4a2c 100644 --- a/docs/api_reference.md +++ b/docs/api_reference.md @@ -414,6 +414,23 @@ _Appears in:_ | `labels` _object (keys:string, values:string)_ | labels to apply to all resources created by the operator.
This field can have a maximum of 20 entries. | | MaxProperties: 20
MinProperties: 0
| +#### ManagementState + +_Underlying type:_ _string_ + +ManagementState controls whether the operator manages the resource lifecycle. + + + +_Appears in:_ +- [ProxyConfig](#proxyconfig) + +| Field | Description | +| --- | --- | +| `Managed` | ManagementStateManaged indicates the Operator is responsible for the resource lifecycle.
| +| `Unmanaged` | ManagementStateUnmanaged indicates the User is responsible for the resource lifecycle.
| + + #### Mode _Underlying type:_ _string_ @@ -498,6 +515,7 @@ _Appears in:_ | `httpProxy` _string_ | httpProxy is the URL of the proxy for HTTP requests.
This field can have a maximum of 2048 characters. | | MaxLength: 2048
MinLength: 0
| | `httpsProxy` _string_ | httpsProxy is the URL of the proxy for HTTPS requests.
This field can have a maximum of 2048 characters. | | MaxLength: 2048
MinLength: 0
| | `noProxy` _string_ | noProxy is a comma-separated list of hostnames and/or CIDRs and/or IPs for which the proxy should not be used.
This field can have a maximum of 4096 characters. | | MaxLength: 4096
MinLength: 0
| +| `networkPolicyProvisioning` _[ManagementState](#managementstate)_ | NetworkPolicyProvisioning defines the management strategy for the proxy egress rule.
When set to Managed, the operator automatically provisions and maintains
a NetworkPolicy allowing traffic to the configured proxy.
If no proxy is configured, no NetworkPolicy will be created
regardless of this setting. | Managed | Enum: [Managed Unmanaged]
| #### SecretReference diff --git a/hack/govulncheck.sh b/hack/govulncheck.sh index 1b138be2b..d185409f6 100755 --- a/hack/govulncheck.sh +++ b/hack/govulncheck.sh @@ -24,7 +24,7 @@ set -o errexit ## Below vulnerabilities are in the go packages, which impacts the operator code and requires the fix to be available downstream. # - https://pkg.go.dev/vuln/GO-2026-4601 - Incorrect parsing of IPv6 host literals in net/url # - https://pkg.go.dev/vuln/GO-2026-4602 - FileInfo can escape from a Root in os -KNOWN_VULNS_PATTERN="GO-2025-3521|GO-2025-3547|GO-2026-4601|GO-2026-4602" +KNOWN_VULNS_PATTERN="GO-2025-3521|GO-2025-3547|GO-2026-4971|GO-2026-4918" GOVULNCHECK_BIN="${1:-}" OUTPUT_DIR="${2:-}"