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:-}"