Skip to content

API Implementation of Egress proxy network policy.#144

Open
siddhibhor-56 wants to merge 1 commit into
openshift:mainfrom
siddhibhor-56:feature/ep-1998-e2e-proxy-egress-np
Open

API Implementation of Egress proxy network policy.#144
siddhibhor-56 wants to merge 1 commit into
openshift:mainfrom
siddhibhor-56:feature/ep-1998-e2e-proxy-egress-np

Conversation

@siddhibhor-56
Copy link
Copy Markdown
Contributor

@siddhibhor-56 siddhibhor-56 commented May 7, 2026

Ep Link

Tested using custom workflow workflow link on ambient code platform.

Summary by CodeRabbit

  • New Features

    • Added networkPolicyProvisioning configuration field to proxy settings in both ExternalSecretsConfig and ExternalSecretsManager, allowing users to control automatic operator management of proxy egress NetworkPolicies (defaults to Managed; Unmanaged option available).
  • Tests

    • Comprehensive test coverage for NetworkPolicy provisioning behavior, proxy port detection, and legacy policy cleanup during upgrades.

@openshift-ci openshift-ci Bot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label May 7, 2026
@openshift-ci openshift-ci Bot requested review from TrilokGeer and bharath-b-rh May 7, 2026 15:19
@openshift-ci
Copy link
Copy Markdown

openshift-ci Bot commented May 7, 2026

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: siddhibhor-56
Once this PR has been reviewed and has the lgtm label, please assign swghosh for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 7, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

This PR adds controlled NetworkPolicy provisioning for proxy egress traffic in External Secrets Operator. It introduces a new NetworkPolicyProvisioning field (Managed/Unmanaged) to both ExternalSecretsConfig and ExternalSecretsManager, implements proxy egress NetworkPolicy reconciliation with automatic port extraction from proxy URLs, renames user-defined policies with an eso-user- prefix, and includes migration cleanup for stale policies.

Changes

Proxy Egress NetworkPolicy Provisioning

Layer / File(s) Summary
API contract and configuration schema
api/v1alpha1/meta.go, config/crd/bases/operator.openshift.io_externalsecretsconfigs.yaml, config/crd/bases/operator.openshift.io_externalsecretsmanagers.yaml, pkg/controller/external_secrets/constants.go
New ManagementState type and Managed/Unmanaged constants define provisioning modes. CRD schemas add networkPolicyProvisioning field with Managed default. Constants define proxy egress policy name, skip-cleanup annotation, and user policy naming prefix.
Client interface for bulk deletions
pkg/controller/client/client.go, pkg/controller/client/fakes/fake_ctrl_client.go
CtrlClient interface gains DeleteAllOf method. CtrlClientImpl delegates to controller-runtime. FakeCtrlClient adds full test support including call tracking, argument capture, and configurable returns.
Proxy egress NetworkPolicy reconciliation and cleanup
pkg/controller/external_secrets/networkpolicy.go
createOrApplyNetworkPolicies orchestrates proxy egress reconciliation and stale policy cleanup. User policies gain eso-user- prefix. Proxy egress conditionally creates/updates or deletes eso-sys-proxy-egress-core based on proxy presence and Managed mode, extracting egress port from URLs. Cleanup deletes labeled policies outside desired set and sets migration completion annotation.
API-level field validation tests
api/v1alpha1/tests/externalsecretsconfig.operator.openshift.io/externalsecretsconfig.testsuite.yaml
Validates networkPolicyProvisioning acceptance, defaults to Managed with proxy config, rejects invalid values, preserves with other proxy fields, and supports value transitions.
Unit tests for NetworkPolicy reconciliation
pkg/controller/external_secrets/networkpolicy_test.go
Custom policy tests updated for eso-user- prefix. New tests cover: proxy egress management decisions by proxy presence and mode; proxy port extraction with scheme defaults; proxy egress create/update/delete flows; migration cleanup pruning and annotation handling.
End-to-end NetworkPolicy provisioning tests
test/e2e/e2e_test.go
Validates absence when no proxy, creation under Managed with correct port, deletion under Unmanaged, eso-user- prefixing for user policies, and skip-cleanup annotation presence after first reconcile.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 9 | ❌ 3

❌ Failed checks (3 warnings)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Test Structure And Quality ⚠️ Warning E2e tests fail on error checking and cleanup patterns: assertions use .To(HaveOccurred()) instead of k8serrors.IsNotFound(), and cleanup helper clears values to nil instead of restoring originals. Fix assertions on lines 742-745, 824-827, 870-871 to use k8serrors.IsNotFound(). Update restoreESCProxyConfig() to restore original values instead of nil.
Microshift Test Compatibility ⚠️ Warning e2e tests in Proxy Egress NetworkPolicy Context use operator.openshift.io APIs not available on MicroShift, with no [apigroup:] tag, [Skipped:MicroShift] label, or runtime MicroShift check. Add [apigroup:operator.openshift.io] tag to Context("Proxy Egress NetworkPolicy [apigroup:operator.openshift.io]", func() {...}) to auto-skip on MicroShift CI.
✅ Passed checks (9 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Stable And Deterministic Test Names ✅ Passed All test names added in this PR are static and deterministic with no dynamic data, generated IDs, timestamps, or variables.
Single Node Openshift (Sno) Test Compatibility ✅ Passed Tests verify NetworkPolicy creation/deletion and CRD annotations through standard APIs available on SNO. No multi-node scheduling, node topology, or HA failover assumptions present.
Topology-Aware Scheduling Compatibility ✅ Passed PR adds NetworkPolicy management for proxy egress, not pod scheduling. No affinity rules, topology assumptions, or node constraints affecting deployment scheduling were introduced.
Ote Binary Stdout Contract ✅ Passed No OTE Binary Stdout Contract violations found. All stdout writes in modified code route through GinkgoWriter, Ginkgo v2's managed output mechanism that doesn't corrupt JSON communication.
Ipv6 And Disconnected Network Test Compatibility ✅ Passed New e2e tests contain no IPv4 assumptions or external connectivity. All operations are cluster-internal using Kubernetes APIs. testProxyURL is hostname-based, IPv6-compatible.
Title check ✅ Passed The title clearly describes the main change: API implementation of egress proxy network policy, which aligns with the core functionality added across API types, CRD schema, controller logic, and tests.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
test/e2e/e2e_test.go (1)

869-872: 💤 Low value

Consider using Consistently to verify the unprefixed policy never exists.

The synchronous Get at line 870 might pass spuriously if checked at the exact moment before the controller has fully reconciled. Using Consistently would provide stronger guarantees that the unprefixed policy is never created.

♻️ Suggested improvement
-			By(fmt.Sprintf("Verifying unprefixed name '%s' does not exist as a separate object", userPolicyName))
-			_, err = clientset.NetworkingV1().NetworkPolicies(operandNamespace).Get(ctx, userPolicyName, metav1.GetOptions{})
-			Expect(err).To(HaveOccurred(), "unprefixed '%s' should not exist as a K8s object", userPolicyName)
+			By(fmt.Sprintf("Verifying unprefixed name '%s' does not exist as a separate object", userPolicyName))
+			Consistently(func(g Gomega) {
+				_, err := clientset.NetworkingV1().NetworkPolicies(operandNamespace).Get(ctx, userPolicyName, metav1.GetOptions{})
+				g.Expect(err).To(HaveOccurred(), "unprefixed '%s' should not exist as a K8s object", userPolicyName)
+			}, 10*time.Second, 2*time.Second).Should(Succeed())
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/e2e/e2e_test.go` around lines 869 - 872, Replace the one-off synchronous
Get call that checks for the absence of the unprefixed policy with a Gomega
Consistently assertion so the test verifies the object never appears over time;
specifically, wrap the call to
clientset.NetworkingV1().NetworkPolicies(operandNamespace).Get(ctx,
userPolicyName, metav1.GetOptions{}) (and its returned error) in a Consistently
block (using an appropriate timeout and poll interval) and assert that the error
always occurs (Expect(err).To(HaveOccurred())), referencing userPolicyName,
operandNamespace, ctx and the Get call to locate the code to change.
pkg/controller/external_secrets/networkpolicy.go (1)

248-253: 💤 Low value

Consider handling NotFound error gracefully during deletion.

If the NetworkPolicy is deleted by another actor between the Exists check and the Delete call, this could return an error. While the reconciliation will likely succeed on retry, ignoring NotFound errors during deletion is a common resilience pattern.

♻️ Suggested improvement
 		if exists {
 			r.log.V(1).Info("Proxy egress policy no longer needed, deleting", "name", npName)
 			if err := r.Delete(r.ctx, fetched); err != nil {
+				if k8serrors.IsNotFound(err) {
+					return nil
+				}
 				return common.FromClientError(err, "failed to delete proxy egress network policy %s", npName)
 			}
 			r.eventRecorder.Eventf(esc, corev1.EventTypeNormal, "Reconciled", "NetworkPolicy %s deleted", npName)
 		}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/controller/external_secrets/networkpolicy.go` around lines 248 - 253, The
delete path for the proxy egress NetworkPolicy should treat a NotFound error as
non-fatal: after calling r.Delete(fetched) in the block that logs "Proxy egress
policy no longer needed, deleting" (use symbols r.Delete, fetched, npName,
r.log, r.eventRecorder), check the returned error with apierrors.IsNotFound(err)
(import "k8s.io/apimachinery/pkg/api/errors") and ignore/log it (e.g.,
r.log.V(1).Info("NetworkPolicy already deleted", "name", npName)) instead of
returning; only wrap-and-return other errors via common.FromClientError so
transient races where another actor already deleted the NetworkPolicy do not
cause a reconcile failure.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@api/v1alpha1/tests/externalsecretsconfig.operator.openshift.io/externalsecretsconfig.testsuite.yaml`:
- Around line 1729-1814: The test cases named like "Should accept
networkPolicyAllowProxyEgressAll set to Managed/Unmanaged", "Should default
networkPolicyAllowProxyEgressAll to Managed when proxy is set without the
field", "Should fail with invalid value for networkPolicyAllowProxyEgressAll",
and "Should accept proxy config with all fields including
networkPolicyAllowProxyEgressAll" are currently placed under onUpdate without an
updated manifest; move these create-style cases into onCreate (or add an
explicit updated manifest per case) so they exercise create/default behavior
rather than update behavior—locate the entries with resourceName: cluster and
kind: ExternalSecretsConfig in the test suite and either change their parent
block to onCreate or provide an updated: | YAML payload for each to represent
the post-update state.

In `@pkg/controller/external_secrets/constants.go`:
- Around line 78-80: The code concatenates userNetworkPolicyPrefix ("eso-user-")
to user-provided names in buildNetworkPolicyFromConfig which can exceed
Kubernetes' 253-char DNS-1123 subdomain limit; enforce a max user name length of
244 characters (253 - len("eso-user-")) or apply deterministic
truncation/hashing before concatenation. Update buildNetworkPolicyFromConfig to
validate the incoming name length (or truncate/hash it) and produce a final name
<=253 chars, and align the CRD validation (external_secrets_config_types.go) to
cap the user-provided name to 244 characters so reconcilers never try to create
too-long NetworkPolicy names.

---

Nitpick comments:
In `@pkg/controller/external_secrets/networkpolicy.go`:
- Around line 248-253: The delete path for the proxy egress NetworkPolicy should
treat a NotFound error as non-fatal: after calling r.Delete(fetched) in the
block that logs "Proxy egress policy no longer needed, deleting" (use symbols
r.Delete, fetched, npName, r.log, r.eventRecorder), check the returned error
with apierrors.IsNotFound(err) (import "k8s.io/apimachinery/pkg/api/errors") and
ignore/log it (e.g., r.log.V(1).Info("NetworkPolicy already deleted", "name",
npName)) instead of returning; only wrap-and-return other errors via
common.FromClientError so transient races where another actor already deleted
the NetworkPolicy do not cause a reconcile failure.

In `@test/e2e/e2e_test.go`:
- Around line 869-872: Replace the one-off synchronous Get call that checks for
the absence of the unprefixed policy with a Gomega Consistently assertion so the
test verifies the object never appears over time; specifically, wrap the call to
clientset.NetworkingV1().NetworkPolicies(operandNamespace).Get(ctx,
userPolicyName, metav1.GetOptions{}) (and its returned error) in a Consistently
block (using an appropriate timeout and poll interval) and assert that the error
always occurs (Expect(err).To(HaveOccurred())), referencing userPolicyName,
operandNamespace, ctx and the Get call to locate the code to change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 453d2949-13e2-4cd7-88cb-44c93795a333

📥 Commits

Reviewing files that changed from the base of the PR and between 2a65cb8 and 8789ab8.

📒 Files selected for processing (8)
  • api/v1alpha1/meta.go
  • api/v1alpha1/tests/externalsecretsconfig.operator.openshift.io/externalsecretsconfig.testsuite.yaml
  • config/crd/bases/operator.openshift.io_externalsecretsconfigs.yaml
  • config/crd/bases/operator.openshift.io_externalsecretsmanagers.yaml
  • pkg/controller/external_secrets/constants.go
  • pkg/controller/external_secrets/networkpolicy.go
  • pkg/controller/external_secrets/networkpolicy_test.go
  • test/e2e/e2e_test.go

Comment thread pkg/controller/external_secrets/constants.go Outdated
ambient-code Bot pushed a commit to siddhibhor-56/external-secrets-operator that referenced this pull request May 8, 2026
…etworkPolicyAllowProxyEgressAll

- Move 5 ESC proxy egress tests from onUpdate to onCreate (they lacked
  required 'updated' field, causing 'Object Kind is missing' errors)
- Add logLevel: 1 to expected in ESC onUpdate proxy egress test (API
  server defaults logLevel when appConfig is present)
- Add networkPolicyAllowProxyEgressAll: Managed to 5 ESM test expected
  blocks where proxy is configured (field defaulted by kubebuilder marker)

Fixes 11 CI unit test failures in PR openshift#144.

Ref: openshift/enhancements#1998
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@ambient-code ambient-code Bot force-pushed the feature/ep-1998-e2e-proxy-egress-np branch from 720831b to bd96e90 Compare May 15, 2026 07:31
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@test/e2e/e2e_test.go`:
- Around line 725-738: The helper restoreESCProxyConfig currently force-clears
proxy and NetworkPolicies by setting updatedCR.Spec.ApplicationConfig.Proxy =
nil and updatedCR.Spec.ControllerConfig.NetworkPolicies = nil; change it to
capture the original values before modifying the CR and restore those captured
values in the retry.Update loop (use variables like originalProxy and
originalNetworkPolicies captured from existingCR) and invoke this restore via
defer so the test restores prior state instead of erasing it; update references
in the retry.RetryOnConflict closure (existingCR, updatedCR,
runtimeClient.Update) to assign the captured originals back to
updatedCR.Spec.ApplicationConfig.Proxy and
updatedCR.Spec.ControllerConfig.NetworkPolicies rather than nil.
- Around line 742-745: The test currently treats any error from
clientset.NetworkingV1().NetworkPolicies(...).Get as success; change the
Consistently check (the block referencing ctx, operandNamespace,
proxyEgressNPName) to assert the error is a NotFound error explicitly using
k8serrors.IsNotFound(err) instead of HaveOccurred; import k8serrors
(k8s.io/apimachinery/pkg/api/errors) if missing and replace
g.Expect(err).To(HaveOccurred(), ...) with an assertion like
g.Expect(k8serrors.IsNotFound(err)).To(BeTrue(), "%s should not exist when no
proxy is configured", proxyEgressNPName) and apply the same pattern to the other
occurrences mentioned.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 6163de1d-9774-4ebf-b283-9716a4cc705f

📥 Commits

Reviewing files that changed from the base of the PR and between 720831b and bd96e90.

📒 Files selected for processing (10)
  • api/v1alpha1/meta.go
  • api/v1alpha1/tests/externalsecretsconfig.operator.openshift.io/externalsecretsconfig.testsuite.yaml
  • config/crd/bases/operator.openshift.io_externalsecretsconfigs.yaml
  • config/crd/bases/operator.openshift.io_externalsecretsmanagers.yaml
  • pkg/controller/client/client.go
  • pkg/controller/client/fakes/fake_ctrl_client.go
  • pkg/controller/external_secrets/constants.go
  • pkg/controller/external_secrets/networkpolicy.go
  • pkg/controller/external_secrets/networkpolicy_test.go
  • test/e2e/e2e_test.go
✅ Files skipped from review due to trivial changes (1)
  • pkg/controller/client/fakes/fake_ctrl_client.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • pkg/controller/external_secrets/networkpolicy_test.go
  • pkg/controller/external_secrets/networkpolicy.go

Comment thread test/e2e/e2e_test.go Outdated
Comment thread test/e2e/e2e_test.go Outdated
@ambient-code ambient-code Bot force-pushed the feature/ep-1998-e2e-proxy-egress-np branch from bd96e90 to 5cea3eb Compare May 15, 2026 07:37
@siddhibhor-56 siddhibhor-56 changed the title [WIP]: Feature Implementation of Egress proxy network policy. APi Implementation of Egress proxy network policy. May 15, 2026
@siddhibhor-56
Copy link
Copy Markdown
Contributor Author

/unhold

@siddhibhor-56 siddhibhor-56 changed the title APi Implementation of Egress proxy network policy. API Implementation of Egress proxy network policy. May 15, 2026
Comment thread api/v1alpha1/meta.go Outdated
// +optional
NoProxy string `json:"noProxy,omitempty"`

// networkPolicyProvisioning controls whether the operator automatically creates a NetworkPolicy
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please keep API changes aligned with what's present in EP.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated according to the EP

@siddhibhor-56
Copy link
Copy Markdown
Contributor Author

/ok-to-test

@openshift-ci openshift-ci Bot added the ok-to-test Indicates a non-member PR verified by an org member that is safe to test. label May 15, 2026
@siddhibhor-56 siddhibhor-56 force-pushed the feature/ep-1998-e2e-proxy-egress-np branch 5 times, most recently from 6b314d6 to 5c213ad Compare May 15, 2026 11:44
…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 <cursoragent@cursor.com>
@siddhibhor-56 siddhibhor-56 force-pushed the feature/ep-1998-e2e-proxy-egress-np branch from 5c213ad to bd8d79a Compare May 15, 2026 11:52
@openshift-ci
Copy link
Copy Markdown

openshift-ci Bot commented May 15, 2026

@siddhibhor-56: all tests passed!

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. ok-to-test Indicates a non-member PR verified by an org member that is safe to test.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants