Skip to content

ESO-437: Implement NetworkPolicy auto-creation for configured proxy#146

Open
siddhibhor-56 wants to merge 7 commits into
openshift:mainfrom
siddhibhor-56:feature/ep-1834-controller-networkpolicy
Open

ESO-437: Implement NetworkPolicy auto-creation for configured proxy#146
siddhibhor-56 wants to merge 7 commits into
openshift:mainfrom
siddhibhor-56:feature/ep-1834-controller-networkpolicy

Conversation

@siddhibhor-56

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

Copy link
Copy Markdown
Contributor

Implement the controller-side logic for EP-1834 (Network Policies for External Secrets Operator and Operands):

  • Rename all static NetworkPolicy manifests with eso-sys- prefix
  • Prepend eso-user- prefix to user-configured network policies
  • Add conditional proxy egress policy (eso-sys-proxy-egress-core) that extracts port from proxy URL and respects networkPolicyProvisioning
  • Add migration cleanup that builds a desired set of NP names and deletes stale managed policies (both unprefixed legacy and removed eso-user-* policies), gated by skip annotation
  • Update RBAC markers to include delete and deletecollection verbs
  • Add comprehensive tests for all new functions

Ref: openshift/enhancements#1834

Summary by CodeRabbit

  • New Features

    • Automatic cleanup of legacy operator-managed network policies during upgrades.
    • Automatic management of a proxy egress NetworkPolicy when a cluster proxy is configured.
  • Chores

    • Standardized network policy identifiers with system (eso-sys-) and user (eso-user-) prefixes.
    • Expanded operator RBAC to allow deletion of NetworkPolicy resources.

@coderabbitai

coderabbitai Bot commented May 25, 2026

Copy link
Copy Markdown

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 prefixes operator-managed static NetworkPolicies with eso-sys-, prefixes user-provided policies with eso-user-, adds proxy egress policy reconciliation and proxy-port extraction, implements a one-time cleanup of stale unprefixed policies (marked by an annotation), and grants the operator delete RBAC for networkpolicies.

Changes

Network Policy Naming and Migration System

Layer / File(s) Summary
Network policy naming constants and configuration
pkg/controller/external_secrets/constants.go
Introduces constants for system (eso-sys-) and user (eso-user-) policy prefixes, proxy egress policy name, and cleanup annotation; fixes DNS asset constant name.
RBAC permissions for network policy deletion
pkg/controller/external_secrets/controller.go, config/rbac/role.yaml, bundle/manifests/openshift-external-secrets-operator.clusterserviceversion.yaml
Adds the delete verb to operator RBAC for networking.k8s.io/networkpolicies (kubebuilder annotation, ClusterRole, and CSV).
Static network policy YAML manifests with new names
bindata/external-secrets/networkpolicy_*.yaml
Six NetworkPolicy YAMLs renamed to eso-sys-* (API server/webhook, Bitwarden, cert-controller, main-controller, DNS rule, deny-all).
Embedded bindata assets synchronized with policy names
pkg/operator/assets/bindata.go
Updates embedded YAML asset strings for the six NetworkPolicy resources to match eso-sys- prefixed names.
Core network policy controller logic with naming, proxy reconciliation, and cleanup
pkg/controller/external_secrets/networkpolicy.go
Custom policies are generated with userNetworkPolicyPrefix; adds reconcileProxyEgressPolicy and extractProxyPort; computes desired operator-managed names; deletes stale managed policies and patches the CR annotation to mark cleanup.
Test suite for naming, proxy logic, and cleanup
pkg/controller/external_secrets/networkpolicy_test.go
Updates tests to expect eso-sys-* and eso-user-* names; adds tests for proxy port extraction, proxy egress reconciliation, and migration cleanup behaviors.
Vulnerability allowlist script
hack/govulncheck.sh
Updates the comment justification text for GO-2026-5026 in the govulncheck script.

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested labels: jira/valid-reference, approved, qe-approved, lgtm

Suggested reviewers:

  • TrilokGeer

Important

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

❌ Failed checks (1 error, 1 warning, 1 inconclusive)

Check name Status Explanation Resolution
No-Sensitive-Data-In-Logs ❌ Error extractProxyPort() logs proxy URLs in error messages via fmt.Errorf, exposing internal network infrastructure hostnames/ports in operator logs. Sanitize the error message by removing the raw proxy URL from the error. Use "failed to parse configured proxy URL" instead of "failed to parse proxy URL %q".
Docstring Coverage ⚠️ Warning Docstring coverage is 40.00% 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 ❓ Inconclusive Custom check specifies Ginkgo test patterns, but networkpolicy_test.go uses standard Go testing (*testing.T). Ginkgo is only used in test/ e2e tests, not controller unit tests. Clarify whether check applies to standard Go tests (*testing.T) or only Ginkgo tests (Describe/It/BeforeEach).
✅ Passed checks (12 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 33 test cases in networkpolicy_test.go use stable, deterministic names as static string literals with t.Run(tt.name). No dynamic values, UUIDs, timestamps, IPs, or generated suffixes found.
Microshift Test Compatibility ✅ Passed No new Ginkgo e2e tests were added in this PR. The tests added are standard Go unit tests in networkpolicy_test.go, not Ginkgo e2e tests. The check does not apply.
Single Node Openshift (Sno) Test Compatibility ✅ Passed No Ginkgo e2e tests were added. The PR only modifies unit tests in pkg/controller/external_secrets/networkpolicy_test.go using Go's standard testing.T, not Ginkgo framework. The check does not apply.
Topology-Aware Scheduling Compatibility ✅ Passed PR only modifies NetworkPolicies (network traffic control) with no scheduling constraints; no affinity, topology, nodeSelector, tolerations, or topology-aware logic added across any modified files.
Ote Binary Stdout Contract ✅ Passed No stdout violations found. PR modifies only controller library code with structured logging. No process-level functions changed. Constants are compile-time string literals.
Ipv6 And Disconnected Network Test Compatibility ✅ Passed No Ginkgo e2e tests (It(), Describe(), etc.) were added. PR only modified unit tests in pkg/controller/external_secrets/networkpolicy_test.go using standard testing.T; e2e test files unchanged.
No-Weak-Crypto ✅ Passed No weak cryptographic algorithms, custom crypto implementations, or non-constant-time secret comparisons detected. PR only modifies Kubernetes NetworkPolicy naming and reconciliation logic.
Container-Privileges ✅ Passed PR does not flag privileged: true, hostPID, hostNetwork, hostIPC, SYS_ADMIN, or allowPrivilegeEscalation: true in any container/K8s manifests; all security contexts remain secure.
Title check ✅ Passed The title directly and clearly describes the main change: implementing NetworkPolicy auto-creation for configured proxy, which aligns with the primary objective of adding conditional proxy egress policy reconciliation.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@openshift-ci openshift-ci Bot requested review from TrilokGeer and bharath-b-rh May 25, 2026 10:14

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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)
pkg/controller/external_secrets/networkpolicy_test.go (2)

691-699: ⚡ Quick win

Strengthen cleanup test assertions for side effects.

The "delete unprefixed policies and set annotation" case captures deletedNames but does not assert what was deleted or that patching occurred, so false positives are possible.

Also applies to: 738-747

🤖 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_test.go` around lines 691 -
699, The test case "delete unprefixed policies and set annotation" registers
m.DeleteCalls and m.PatchCalls but only captures deletedNames without asserting
results; update the test to assert that deletedNames contains the expected
policy names (e.g., the unprefixed policy) and that a patch was performed by
counting PatchCalls or setting a flag in the PatchCalls handler (similarly add
assertions for the other case around the existing handlers at lines ~738-747).
Specifically, modify the m.DeleteCalls handler to record names (already done)
and add an assertion that deletedNames equals the expected slice, and enhance
m.PatchCalls to increment a patchCount or set patched=true and assert
patchCount>0 (or patched==true) to verify patch side effects for both test
cases.

779-781: ⚡ Quick win

Assert the created proxy egress port value, not only list sizes.

The create-path test should verify the actual port (e.g., 3128) to fully validate extractProxyPort + policy construction integration.

🤖 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_test.go` around lines 779 -
781, The test currently only checks lengths of np.Spec.Egress and its Ports;
instead assert the actual proxy port value produced by extractProxyPort and used
in the policy. After the existing length checks, access the port via
np.Spec.Egress[0].Ports[0].Port and compare its int value to the expected port
(e.g., 3128) — for Kubernetes intstr.IntOrString values check Port.IntVal (or
Port.StrVal if using string form) and fail the test if it does not equal the
expected port. This ensures extractProxyPort + policy construction are
validated.
🤖 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 `@pkg/controller/external_secrets/networkpolicy.go`:
- Around line 355-362: The switch on parsed.Scheme currently defaults to
returning 443 for unknown schemes, which hides invalid proxy URLs; update the
logic that handles parsed.Scheme (the switch block) to return an explicit error
for unsupported schemes instead of silently returning 443, including the invalid
scheme in the error message so callers can fail fast and surface misconfigured
proxy URLs. Ensure the function signature is adjusted to propagate the error (or
wrap/return an error alongside the port) and update call sites accordingly to
handle the error return.
- Around line 205-207: Validate the final Kubernetes resource name length before
concatenating esoUserPrefix with npConfig.Name in the NetworkPolicy ObjectMeta
construction (where Name: esoUserPrefix + npConfig.Name is set). Specifically,
ensure len(esoUserPrefix)+len(npConfig.Name) meets Kubernetes DNS-1123 label
limits (max 63 chars) and contains valid characters; if it would exceed the
limit or be invalid, either truncate npConfig.Name safely to fit or return an
actionable error so reconcile fails fast. Implement this check in the function
that builds the NetworkPolicy (reference esoUserPrefix and npConfig.Name) and
centralize name validation using existing DNS-1123 helpers or a small validator
helper to avoid creating invalid resource names at runtime.

---

Nitpick comments:
In `@pkg/controller/external_secrets/networkpolicy_test.go`:
- Around line 691-699: The test case "delete unprefixed policies and set
annotation" registers m.DeleteCalls and m.PatchCalls but only captures
deletedNames without asserting results; update the test to assert that
deletedNames contains the expected policy names (e.g., the unprefixed policy)
and that a patch was performed by counting PatchCalls or setting a flag in the
PatchCalls handler (similarly add assertions for the other case around the
existing handlers at lines ~738-747). Specifically, modify the m.DeleteCalls
handler to record names (already done) and add an assertion that deletedNames
equals the expected slice, and enhance m.PatchCalls to increment a patchCount or
set patched=true and assert patchCount>0 (or patched==true) to verify patch side
effects for both test cases.
- Around line 779-781: The test currently only checks lengths of np.Spec.Egress
and its Ports; instead assert the actual proxy port value produced by
extractProxyPort and used in the policy. After the existing length checks,
access the port via np.Spec.Egress[0].Ports[0].Port and compare its int value to
the expected port (e.g., 3128) — for Kubernetes intstr.IntOrString values check
Port.IntVal (or Port.StrVal if using string form) and fail the test if it does
not equal the expected port. This ensures extractProxyPort + policy construction
are validated.
🪄 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: fc416023-3158-4aa1-bd18-fe93b6d5dc75

📥 Commits

Reviewing files that changed from the base of the PR and between f418404 and c3a5469.

📒 Files selected for processing (10)
  • bindata/external-secrets/networkpolicy_allow-api-server-and-webhook-traffic.yaml
  • bindata/external-secrets/networkpolicy_allow-api-server-egress-for-bitwarden-sever.yaml
  • bindata/external-secrets/networkpolicy_allow-api-server-egress-for-cert-controller-traffic.yaml
  • bindata/external-secrets/networkpolicy_allow-api-server-egress-for-main-controller-traffic.yaml
  • bindata/external-secrets/networkpolicy_allow-dns.yaml
  • bindata/external-secrets/networkpolicy_deny-all.yaml
  • pkg/controller/external_secrets/controller.go
  • pkg/controller/external_secrets/networkpolicy.go
  • pkg/controller/external_secrets/networkpolicy_test.go
  • pkg/operator/assets/bindata.go

Comment on lines 205 to 207
ObjectMeta: metav1.ObjectMeta{
Name: npConfig.Name,
Name: esoUserPrefix + npConfig.Name,
Namespace: namespace,

@coderabbitai coderabbitai Bot May 25, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Validate custom policy name length before adding eso-user- prefix.

At Line 206, a long user-provided name can become invalid after prefixing, causing reconcile-time create/update failures.

💡 Proposed fix
 func (r *Reconciler) buildNetworkPolicyFromConfig(esc *operatorv1alpha1.ExternalSecretsConfig, npConfig operatorv1alpha1.NetworkPolicy, resourceMetadata common.ResourceMetadata) (*networkingv1.NetworkPolicy, error) {
+	maxUserPolicyNameLen := 253 - len(esoUserPrefix)
+	if len(npConfig.Name) > maxUserPolicyNameLen {
+		return nil, fmt.Errorf("network policy name %q is too long; max allowed is %d characters", npConfig.Name, maxUserPolicyNameLen)
+	}
+
 	namespace := getNamespace(esc)
🤖 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 205 - 207,
Validate the final Kubernetes resource name length before concatenating
esoUserPrefix with npConfig.Name in the NetworkPolicy ObjectMeta construction
(where Name: esoUserPrefix + npConfig.Name is set). Specifically, ensure
len(esoUserPrefix)+len(npConfig.Name) meets Kubernetes DNS-1123 label limits
(max 63 chars) and contains valid characters; if it would exceed the limit or be
invalid, either truncate npConfig.Name safely to fit or return an actionable
error so reconcile fails fast. Implement this check in the function that builds
the NetworkPolicy (reference esoUserPrefix and npConfig.Name) and centralize
name validation using existing DNS-1123 helpers or a small validator helper to
avoid creating invalid resource names at runtime.

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.

@siddhibhor-56 This is a valid point. And I think we should instead change in the API to update kubebuilder:validation:MaxLength from 253 to 243 and update the godoc there as well.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

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.

Done

Comment thread pkg/controller/external_secrets/networkpolicy.go Outdated
@siddhibhor-56 siddhibhor-56 force-pushed the feature/ep-1834-controller-networkpolicy branch from c3a5469 to 0da61f2 Compare May 28, 2026 10:25
@openshift-ci openshift-ci Bot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label May 28, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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 (1)
pkg/controller/external_secrets/networkpolicy_test.go (1)

551-621: ⚡ Quick win

Add explicit malformed-proxy URL coverage in TestExtractProxyPort.

The table tests happy/default paths only, but extractProxyPort has a parse-error branch that isn’t exercised. Add at least one invalid URL case (e.g., bad escape/invalid host:port) and assert wantErr=true so this path is protected.

🤖 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_test.go` around lines 551 -
621, TestExtractProxyPort currently covers only valid/default proxy URLs; add a
table case that triggers the parse-error branch in extractProxyPort. Insert a
test case in TestExtractProxyPort with a malformed URL (for example HTTPSProxy:
"http://%41:bad" or similar invalid host:port) and set wantErr: true, then
assert the returned error is non-nil (and ignore port). This will exercise the
parse-error path in extractProxyPort and ensure the test suite protects that
branch.
🤖 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 `@hack/govulncheck.sh`:
- Line 27: KNOWN_VULNS_PATTERN was extended to include GO-2026-4971 and
GO-2026-4918 but the rationale/comments do not explain why these IDs are being
suppressed; update the justification block that documents ignored
vulnerabilities to add concise, auditable reasons for each new ID (e.g., why
they are not exploitable in our context, mitigated by configuration X, or
scheduled for a library upgrade) and include references (ticket/PR numbers or
CVE details) so future reviewers can trace the exception; ensure the text format
and location match the existing rationale block that accompanies
KNOWN_VULNS_PATTERN so it stays consistent and discoverable.

In `@pkg/controller/external_secrets/networkpolicy_test.go`:
- Around line 738-747: Test lacks an assertion for the negative delete case:
inside the table-driven test after checking the positive delete case
(wantDeleted && mock.DeleteCallCount() == 0), add the inverse assertion for when
wantDeleted is false by asserting mock.DeleteCallCount() == 0 and failing the
test if it is > 0; update the same test block that checks Create calls (uses
tt.wantDeleted, mock.DeleteCallCount(), mock.CreateCallCount()) so both create
and delete behaviors are asserted for true and false scenarios.

---

Nitpick comments:
In `@pkg/controller/external_secrets/networkpolicy_test.go`:
- Around line 551-621: TestExtractProxyPort currently covers only valid/default
proxy URLs; add a table case that triggers the parse-error branch in
extractProxyPort. Insert a test case in TestExtractProxyPort with a malformed
URL (for example HTTPSProxy: "http://%41:bad" or similar invalid host:port) and
set wantErr: true, then assert the returned error is non-nil (and ignore port).
This will exercise the parse-error path in extractProxyPort and ensure the test
suite protects that branch.
🪄 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: b88fb920-63ae-4a72-9b3e-74006d1a495e

📥 Commits

Reviewing files that changed from the base of the PR and between c3a5469 and 0da61f2.

📒 Files selected for processing (23)
  • api/v1alpha1/external_secrets_config_types.go
  • api/v1alpha1/meta.go
  • api/v1alpha1/tests/externalsecretsconfig.operator.openshift.io/externalsecretsconfig.testsuite.yaml
  • api/v1alpha1/tests/externalsecretsmanager.operator.openshift.io/externalsecretsmanager.testsuite.yaml
  • bindata/external-secrets/networkpolicy_allow-api-server-and-webhook-traffic.yaml
  • bindata/external-secrets/networkpolicy_allow-api-server-egress-for-bitwarden-sever.yaml
  • bindata/external-secrets/networkpolicy_allow-api-server-egress-for-cert-controller-traffic.yaml
  • bindata/external-secrets/networkpolicy_allow-api-server-egress-for-main-controller-traffic.yaml
  • bindata/external-secrets/networkpolicy_allow-dns.yaml
  • bindata/external-secrets/networkpolicy_deny-all.yaml
  • bundle/manifests/openshift-external-secrets-operator.clusterserviceversion.yaml
  • bundle/manifests/operator.openshift.io_externalsecretsconfigs.yaml
  • bundle/manifests/operator.openshift.io_externalsecretsmanagers.yaml
  • config/crd/bases/operator.openshift.io_externalsecretsconfigs.yaml
  • config/crd/bases/operator.openshift.io_externalsecretsmanagers.yaml
  • config/rbac/role.yaml
  • docs/api_reference.md
  • hack/govulncheck.sh
  • pkg/controller/external_secrets/constants.go
  • pkg/controller/external_secrets/controller.go
  • pkg/controller/external_secrets/networkpolicy.go
  • pkg/controller/external_secrets/networkpolicy_test.go
  • pkg/operator/assets/bindata.go
✅ Files skipped from review due to trivial changes (8)
  • bindata/external-secrets/networkpolicy_allow-api-server-egress-for-cert-controller-traffic.yaml
  • api/v1alpha1/external_secrets_config_types.go
  • bindata/external-secrets/networkpolicy_allow-api-server-egress-for-bitwarden-sever.yaml
  • bindata/external-secrets/networkpolicy_allow-dns.yaml
  • bindata/external-secrets/networkpolicy_deny-all.yaml
  • bindata/external-secrets/networkpolicy_allow-api-server-egress-for-main-controller-traffic.yaml
  • config/crd/bases/operator.openshift.io_externalsecretsconfigs.yaml
  • pkg/operator/assets/bindata.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • bindata/external-secrets/networkpolicy_allow-api-server-and-webhook-traffic.yaml
  • pkg/controller/external_secrets/networkpolicy.go

Comment thread hack/govulncheck.sh Outdated
Comment thread pkg/controller/external_secrets/networkpolicy_test.go
@siddhibhor-56 siddhibhor-56 force-pushed the feature/ep-1834-controller-networkpolicy branch from 0da61f2 to 0829f28 Compare May 28, 2026 12:31
@openshift-ci openshift-ci Bot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label May 28, 2026
@coderabbitai

coderabbitai Bot commented May 28, 2026

Copy link
Copy Markdown

Actionable comments posted: 0

@siddhibhor-56 siddhibhor-56 force-pushed the feature/ep-1834-controller-networkpolicy branch from 0829f28 to 86de1be Compare May 28, 2026 12:58
@coderabbitai

coderabbitai Bot commented May 28, 2026

Copy link
Copy Markdown

Actionable comments posted: 0

@codecov-commenter

codecov-commenter commented May 28, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 28.94737% with 162 lines in your changes missing coverage. Please review.
✅ Project coverage is 46.58%. Comparing base (96b0684) to head (c61fff5).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
pkg/controller/external_secrets/networkpolicy.go 31.63% 126 Missing and 8 partials ⚠️
pkg/controller/external_secrets/utils.go 9.52% 18 Missing and 1 partial ⚠️
pkg/controller/external_secrets/deployments.go 14.28% 5 Missing and 1 partial ⚠️
pkg/controller/external_secrets/configmap.go 25.00% 2 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #146      +/-   ##
==========================================
- Coverage   47.94%   46.58%   -1.37%     
==========================================
  Files          29       29              
  Lines        4207     4416     +209     
==========================================
+ Hits         2017     2057      +40     
- Misses       1902     2056     +154     
- Partials      288      303      +15     
Flag Coverage Δ
e2e 46.58% <28.94%> (-1.37%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@openshift-ci openshift-ci Bot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label May 30, 2026
@siddhibhor-56 siddhibhor-56 force-pushed the feature/ep-1834-controller-networkpolicy branch from 86de1be to 6bc1338 Compare June 1, 2026 06:14
@openshift-ci openshift-ci Bot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Jun 1, 2026
@siddhibhor-56 siddhibhor-56 force-pushed the feature/ep-1834-controller-networkpolicy branch from 60bd91a to 6bc1338 Compare June 1, 2026 07:45
@swghosh swghosh force-pushed the feature/ep-1834-controller-networkpolicy branch from 6bc1338 to 43195d2 Compare June 2, 2026 17:51
@ambient-code ambient-code Bot force-pushed the feature/ep-1834-controller-networkpolicy branch from 43195d2 to 83866c1 Compare June 2, 2026 18:49
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: Ambient Code Bot <bot@ambient-code.local>
Co-Authored-By: openshift-app-platform-shift-bot <267347085+openshift-app-platform-shift-bot@users.noreply.github.com>
@ambient-code ambient-code Bot force-pushed the feature/ep-1834-controller-networkpolicy branch from 83866c1 to d24b528 Compare June 2, 2026 18:53
@bharath-b-rh

bharath-b-rh commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

/retitle ESO-437: Implement NetworkPolicy auto-creation for configured proxy

@openshift-ci openshift-ci Bot changed the title feat(controller): implement NetworkPolicy reconciler for EP-1834 ESO-437: Implement NetworkPolicy auto-creation for configured proxy Jun 5, 2026
@openshift-ci-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label Jun 5, 2026
@openshift-ci-robot

openshift-ci-robot commented Jun 5, 2026

Copy link
Copy Markdown

@siddhibhor-56: This pull request references ESO-437 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the task to target the "5.0.0" version, but no target version was set.

Details

In response to this:

Implement the controller-side logic for EP-1834 (Network Policies for External Secrets Operator and Operands):

  • Rename all static NetworkPolicy manifests with eso-sys- prefix
  • Prepend eso-user- prefix to user-configured network policies
  • Add conditional proxy egress policy (eso-sys-proxy-egress-core) that extracts port from proxy URL and respects networkPolicyProvisioning
  • Add migration cleanup that builds a desired set of NP names and deletes stale managed policies (both unprefixed legacy and removed eso-user-* policies), gated by skip annotation
  • Update RBAC markers to include delete and deletecollection verbs
  • Add comprehensive tests for all new functions

Ref: openshift/enhancements#1834

Summary by CodeRabbit

  • New Features

  • Automatic cleanup of legacy operator-managed network policies during upgrades.

  • Automatic management of a proxy egress NetworkPolicy when a cluster proxy is configured.

  • Chores

  • Standardized network policy identifiers with system (eso-sys-) and user (eso-user-) prefixes.

  • Expanded operator RBAC to allow deletion of NetworkPolicy resources.

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 openshift-eng/jira-lifecycle-plugin repository.

// userNetworkPolicyPrefix is prepended to user-defined network policy names from the CR spec.
userNetworkPolicyPrefix = "eso-user-"

// TODO(siddhibhor-56,ESO-v1.4.0): Remove after 3 releases once the migration from

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.

Suggested change
// TODO(siddhibhor-56,ESO-v1.4.0): Remove after 3 releases once the migration from
// TODO Remove after 3 releases(in v1.5.0) once the migration from

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.

Done

skipNPCleanupAnnotation = "externalsecretsconfig.operator.openshift.io/skip-np-cleanup-check"

// proxyEgressPolicyName is the Kubernetes object name for the automatic proxy egress policy.
proxyEgressPolicyName = systemNetworkPolicyPrefix + "proxy-egress-core"

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.

Should we follow the same naming pattern as other operator created NPs.

Suggested change
proxyEgressPolicyName = systemNetworkPolicyPrefix + "proxy-egress-core"
proxyEgressPolicyName = systemNetworkPolicyPrefix + "allow-proxy-egress"

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.

Done

allowCertControllerTrafficAssetName = "external-secrets/networkpolicy_allow-api-server-egress-for-cert-controller-traffic.yaml"
allowBitwardenServerTrafficAssetName = "external-secrets/networkpolicy_allow-api-server-egress-for-bitwarden-sever.yaml"
allowDnsTrafficAsserName = "external-secrets/networkpolicy_allow-dns.yaml"
allowDnsTrafficAssetName = "external-secrets/networkpolicy_allow-dns.yaml"

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.

Suggested change
allowDnsTrafficAssetName = "external-secrets/networkpolicy_allow-dns.yaml"
allowDNSTrafficAssetName = "external-secrets/networkpolicy_allow-dns.yaml"

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.

Done

return err
}

// TODO(siddhibhor-56,ESO-v1.4.0): Remove after 3 releases once the migration from

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.

Suggested change
// TODO(siddhibhor-56,ESO-v1.4.0): Remove after 3 releases once the migration from
// TODO: Remove after 3 releases(in v1.5.0) once the migration from

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.

Done

Comment on lines 205 to 207
ObjectMeta: metav1.ObjectMeta{
Name: npConfig.Name,
Name: esoUserPrefix + npConfig.Name,
Namespace: namespace,

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.

@siddhibhor-56 This is a valid point. And I think we should instead change in the API to update kubebuilder:validation:MaxLength from 253 to 243 and update the godoc there as well.

},
{
name: "valid BitwardenSDKServer network policy",
name: "valid BitwardenSDKServer network policy with eso-user prefix",

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.

Don't we need any new test cases for proxy?

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.

Added a test case for proxy

Comment thread test/e2e/e2e_test.go Outdated
Context("Static Network Policy Naming", func() {
listManagedNetworkPolicies := func(ctx context.Context, namespace string) ([]networkingv1.NetworkPolicy, error) {
npList, err := clientset.NetworkingV1().NetworkPolicies(namespace).List(ctx, metav1.ListOptions{
LabelSelector: fmt.Sprintf("%s=%s", managedByLabel, managedByValue),

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.

nit: Should we keep it aligned with the implementation where two labels are used for filtering

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.

Done

Comment thread test/e2e/e2e_test.go Outdated
}, 2*time.Minute, 5*time.Second).Should(Succeed())
})

// TODO(siddhibhor-56,ESO-v1.4.0): Remove this test case after 3 releases once the migration from

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.

Suggested change
// TODO(siddhibhor-56,ESO-v1.4.0): Remove this test case after 3 releases once the migration from
// TODO: Remove this test case after 3 releases(in v1.5.0) once the migration from

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.

Done


for i := range npList.Items {
np := &npList.Items[i]
if _, ok := desired[np.GetName()]; ok {

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.

IIUC, are we deleting everyother NP not in the desired slice? What if user has created few NPs by himself without using ExternalSecretsConfig and could contain the same labels added by operator?

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.

`If the annotation is absent, list all NetworkPolicy resources in the namespace by label (`app.kubernetes.io/managed-by: external-secrets-operator` and `app.kubernetes.io/part-of: external-secrets-operator`) and by name, and delete any whose name is not in the desired set. The unprefixed policies from operator versions prior to 1.2.0 - `deny-all-traffic`, `allow-to-dns`, `allow-api-server-egress-for-main-controller`, etc. - carry the operator labels but are no longer in the desired set, so they get cleaned up. Stale user NPs are also removed by the same diff to avoid the duplicate NPs.
`

referring to the EP openshift/enhancements#1998, any network policy that is not contained in the desired set of Network Policies and contain the necessary labels, should be removed right? It removes any stale network policies that could cause network traffic issues.

If that approach looks wrong, then we need to remove only by name and drop the label based listing altogether. WDYT

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.

My query is not related to how we create the desired list, but more on negated deletion logic. A manually created NP with the exact same two labels and a name not in the desired set will be deleted here is it not?

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.

yes, it will get deleted.

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.

My understanding of what's mentioned in the EP is, only those managed by the operator will be deleted using the mentioned filtering.
We should only delete what's created and managed by operator.

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.

Done

Comment thread test/e2e/e2e_test.go
})

// Cluster-wide proxy configuration consumed via OLM env vars.
It("should create proxy egress policy when configured with Managed provisioning", Label("Proxy:HTTP"), func() {

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 assert the created policy’s egress port matches the cluster proxy URL (explicit or scheme default), not only that the policy exists.

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.

Done

@siddhibhor-56 siddhibhor-56 force-pushed the feature/ep-1834-controller-networkpolicy branch from 992c811 to 0ee2c82 Compare June 10, 2026 06:50
Comment on lines +365 to +369
if p := u.Port(); p != "" {
if _, err := fmt.Sscanf(p, "%d", &port); err != nil || port <= 0 {
port = 0
}
}

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.

Sscanf is not stringent parser for ints, even "8080abc" is considered as valid.

Suggested change
if p := u.Port(); p != "" {
if _, err := fmt.Sscanf(p, "%d", &port); err != nil || port <= 0 {
port = 0
}
}
if p := u.Port(); p != "" {
port, err := strconv.Atoi(p)
if err != nil {
return nil, fmt.Errorf("invalid port %q in proxy URL %q: %w", p, raw, err)
}
if port < 1 || port > 65535 {
return nil, fmt.Errorf("port %d out of range in proxy URL %q", port, raw)
}
}

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.

Done

Comment on lines +386 to +388
if len(ports) == 0 {
return nil, fmt.Errorf("unable to determine proxy port: no valid proxy URL with a recognized scheme (http/https) found in proxyConfig")
}

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.

I don't think we should be returning an error, considering when just no_proxy is configured. We should just skip creating the policy.

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.

Done

@siddhibhor-56 siddhibhor-56 force-pushed the feature/ep-1834-controller-networkpolicy branch from a9f0a86 to 81026de Compare June 11, 2026 10:40
@openshift-ci

openshift-ci Bot commented Jun 11, 2026

Copy link
Copy Markdown

@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.

@bharath-b-rh

Copy link
Copy Markdown
Contributor

/lgtm
/approve

Please refer comment for pre-merge results.

/label qe-approved
/label px-approved

cc; @snarayan-redhat for docs approval. Please help update the release notes with this new feature.

Operator NetworkPolicies use eso-sys- (static) and eso-user- (CR-defined) prefixes. A one-time upgrade migration deletes legacy unprefixed policies from an explicit allowlist only.

When spec.applicationConfig.proxy.networkPolicyProvisioning is Managed (default) and HTTP/HTTPS proxy URLs are set, the operator creates eso-sys-allow-proxy-egress for the configured proxy port(s). With Unmanaged, proxy egress NetworkPolicies are your responsibility; the operator does not create or reconcile that policy. NO_PROXY alone does not trigger proxy egress policy creation.

Do not use operator labels app.kubernetes.io/managed-by and app.kubernetes.io/part-of set to external-secrets-operator on manually managed NetworkPolicies unless they are intended to be operator-owned.

/hold for @mytreya-rh's review

@openshift-ci openshift-ci Bot added do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. qe-approved Signifies that QE has signed off on this PR px-approved Signifies that Product Support has signed off on this PR labels Jun 11, 2026
@openshift-ci openshift-ci Bot added the lgtm Indicates that a PR is ready to be merged. label Jun 11, 2026
@openshift-ci

openshift-ci Bot commented Jun 11, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: bharath-b-rh, siddhibhor-56

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

The pull request process is described 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

@openshift-ci openshift-ci Bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Jun 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. lgtm Indicates that a PR is ready to be merged. px-approved Signifies that Product Support has signed off on this PR qe-approved Signifies that QE has signed off on this PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants