Skip to content

[WIP] CNTRLPLANE-3851: Oauth server proxy config e2e#950

Open
ehearne-redhat wants to merge 10 commits into
openshift:masterfrom
ehearne-redhat:oauth-server-proxy-config-e2e
Open

[WIP] CNTRLPLANE-3851: Oauth server proxy config e2e#950
ehearne-redhat wants to merge 10 commits into
openshift:masterfrom
ehearne-redhat:oauth-server-proxy-config-e2e

Conversation

@ehearne-redhat

@ehearne-redhat ehearne-redhat commented Jul 20, 2026

Copy link
Copy Markdown

Continues work from and closes openshift/origin#31398 . Kept in separate file for now. Plan is to add tests to test/e2e-component-proxy/component_proxy.go into #949 when consensus reached on test status.

Summary by CodeRabbit

  • New Features

    • Added component-scoped proxy support for authentication services, including HTTP/HTTPS proxy and noProxy settings.
    • Added trusted CA support for proxied identity provider and OAuth connections.
    • Proxy settings now apply to identity provider discovery, OAuth route checks, and connectivity validation.
    • Added component proxy end-to-end coverage, including OIDC login, CA rotation, bypass rules, and failure scenarios.
  • Bug Fixes

    • Unreachable identity providers now generate warning events without unnecessarily degrading the operator.

tchap and others added 10 commits July 16, 2026 15:34
Vendor openshift/api with the new AuthenticationProxyConfig and
AuthenticationConfigMapReference types on the Authentication operator
spec, gated behind FeatureGateAuthenticationComponentProxy.
Add TransportForCARefWithProxy for building proxy-aware
transports with optional extra CA data.
Add shared utilities for component-scoped proxy configuration:

- ResolveProxy: reads spec.proxy from the Authentication operator CR
  when the AuthenticationComponentProxy feature gate is enabled and
  returns a ResolvedProxy with the effective proxy strings, falling
  back to the process environment when no component proxy is configured.
- ResolvedProxy.ProxyFunc: returns a func(*http.Request) (*url.URL, error)
  suitable for http.Transport.Proxy.
Wire the component-scoped proxy into every affected controller:

Config observer: builds a proxy-aware HTTP transport for OIDC
discovery and password grant checks. The Listers struct gains
OperatorAuthLister and FeatureGateAccessor. The convertIdentityProviders
signature changes from a ConfigMap lister to a transportForCABuilderFunc,
decoupling transport construction from the IDP conversion logic. Adds an
ObserveProxyTrustedCA observer that injects the proxy CA bundle path into
the observed config when a component proxy with a trustedCA is active.

Deployment controller: resolves the component proxy, injects
HTTP_PROXY/HTTPS_PROXY/NO_PROXY env vars into the OAuth Server pod,
syncs the trustedCA ConfigMap from openshift-config to
openshift-authentication, and adds a volume/mount with Optional=true
for CA hot-reload without redeployment.

Proxy validation controller: validates route reachability through
the component proxy. Tests IdP endpoint connectivity and emits
IdPEndpointUnreachable Warning events for transient failures
(does not set Degraded). Uses hash-based change detection to
avoid redundant validation.

Endpoint accessible controller: gains an optional proxy function
for route health checks. Only the route check controller gets the
proxy because it connects to the external route hostname; service
and endpoint checks connect to cluster-internal addresses and
remain proxy-free.

Custom route controller: resolves the component proxy via
ResolveProxy for the route availability health check. Loads the
proxy trusted CA via LoadCAData and appends it to the root CA pool.
Fixes the routeAvailablity typo (now routeAvailability).

Operator startup: passes operatorAuthLister, featureGateAccessor,
and operatorAuthInformer to all affected controllers.
Extract shared test helpers into pkg/internal/transporttest:
UnwrapTransport, MakeSelfSignedCA, MustParseURL. Replace local
copies in transport, proxy, and observe_idps test files.

Add TestBuildIDPTransport to verify that with the feature gate
enabled and a component proxy with trusted CA configured, the
IDP transport builder wires the proxy function and loads the CA.

Add Test_validateIdPConnectivity_hashDedup to verify hash-based
dedup: successful validation saves the hash and skips redundant
checks; failed validation does not save the hash, allowing retry.

Enable the AuthenticationComponentProxy feature gate in
TestObserveIdentityProviders to exercise the gate-enabled path
with no proxy configured (no-op fallback to environment).
Verify that setting spec.proxy.httpsProxy to an unreachable host on
the operator Authentication CR causes ProxyConfigControllerDegraded
to become True, propagating to ClusterOperator Degraded=True.

The test is gated behind the AuthenticationComponentProxy feature gate
and registered in the OTE serial/operator suite.
Add C2 test: deploy a Squid proxy, configure spec.proxy to point at
it, add a fake OpenID IdP with an unresolvable issuer URL, and verify
the ProxyConfigController emits an IdPEndpointUnreachable Warning
event without going Degraded.

Also add stub helper functions in test/library/proxy.go for future
proxy e2e infrastructure (DeploySquidProxy, DeployProxyNetworkPolicies,
etc.). Use WaitForOperatorToPickUpChanges in both C1 and C2 cleanup
to avoid racing with stale operator status.
…dd A1 test

Move proxy config save/restore logic into a shared test helper in
test/library/proxy.go. Add the A1 test (OIDC IdP validation through
component proxy) and clean up C1/C2 tests to use the shared helper
and exported CheckFeatureGateEnabledOrSkip. Remove redundant nil
check in C1 test.
@openshift-merge-bot

Copy link
Copy Markdown
Contributor

Pipeline controller notification
This repo is configured to use the pipeline controller. Second-stage tests will be triggered either automatically or after lgtm label is added, depending on the repository configuration. The pipeline controller will automatically detect which contexts are required and will utilize /test Prow commands to trigger the second stage.

For optional jobs, comment /test ? to see a list of all defined jobs. To trigger manually all jobs from second stage use /pipeline required command.

This repository is configured in: LGTM mode

@openshift-ci-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label Jul 20, 2026
@openshift-ci-robot

openshift-ci-robot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

@ehearne-redhat: This pull request references CNTRLPLANE-3851 which is a valid jira issue.

Details

In response to this:

Continues work from and closes openshift/origin#31398 . Kept in separate file for now. Plan is to add tests to test/e2e-component-proxy/component_proxy.go into #949 when consensus reached on test status.

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.

@openshift-ci openshift-ci Bot added do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. labels Jul 20, 2026
@openshift-ci

openshift-ci Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

PR needs rebase.

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.

@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown

Walkthrough

Adds feature-gated component proxy resolution across authentication controllers, proxy-aware HTTP transports, trusted CA synchronization for OAuth Server, IdP connectivity validation, controller wiring, and serial end-to-end tests.

Changes

Component proxy foundation

Layer / File(s) Summary
Proxy resolution and transport contracts
pkg/controllers/common/proxy.go, pkg/transport/*, pkg/internal/transporttest/*
Resolves component or environment proxy settings, merges bypass hosts, loads CA references, and builds proxy-aware TLS transports with unit coverage.
Identity-provider and OAuth observation
pkg/controllers/configobservation/...
Passes proxy-aware transport builders through IdP discovery and password-grant checks, and observes the OAuth trusted CA path.
Controller proxy integration
pkg/controllers/customroute/*, pkg/controllers/deployment/*, pkg/controllers/oauthendpoints/*, pkg/libs/endpointaccessible/*
Uses resolved proxy settings for route and endpoint checks, OAuth deployment environment variables, and trusted CA ConfigMap synchronization.
Proxy and IdP connectivity validation
pkg/controllers/proxyconfig/*
Validates proxy reachability and external IdP endpoints, emits warning events, and caches successful validation inputs by hash.
Operator wiring and e2e coverage
pkg/operator/*, cmd/cluster-authentication-operator-tests-ext/*, test/e2e-component-proxy/*, test/library/proxy.go
Wires informers and feature gates, registers serial component-proxy suites, and adds proxy, OIDC, trusted CA, and NoProxy scenarios.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Authentication
  participant ResolveProxy
  participant OAuthDeployment
  participant OAuthServer
  participant IdP
  Authentication->>ResolveProxy: component proxy and trusted CA
  ResolveProxy->>OAuthDeployment: proxy environment and CA mount
  OAuthDeployment->>OAuthServer: configured deployment
  OAuthServer->>IdP: proxied OIDC request
  IdP-->>OAuthServer: discovery or token response
Loading

Possibly related PRs


Important

Pre-merge checks failed

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

❌ Failed checks (1 error, 4 warnings)

Check name Status Explanation Resolution
No-Sensitive-Data-In-Logs ❌ Error FAIL: new GinkgoWriter and klog lines print proxy/issuer URLs and unreachable IdP endpoint errors, exposing internal hostnames in logs. Remove URL/host details from logs; redact endpoint/proxy values and avoid printing event messages or errors that embed hostnames.
Docstring Coverage ⚠️ Warning Docstring coverage is 40.63% 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 testOIDCIdPThroughComponentProxy reuses proxyCleanup for both Squid teardown and proxy restore, so the Squid cleanup closure is overwritten and leaks resources. Use a separate variable for the restore cleanup (e.g. proxyConfigCleanup) so the Squid teardown closure still calls the original cleanup.
Microshift Test Compatibility ⚠️ Warning New serial Ginkgo specs use Authentication/ClusterOperator/FeatureGate APIs and have no [Skipped:MicroShift], [apigroup:], or IsMicroShiftCluster guard. Tag these specs with [Skipped:MicroShift] or the relevant [apigroup:...] labels, or add a runtime MicroShift skip before using unsupported APIs.
Ipv6 And Disconnected Network Test Compatibility ⚠️ Warning New serial e2e tests call AddKeycloakIDP, which deploys quay.io/keycloak/keycloak:25.0; that public-registry pull breaks disconnected compatibility. Use a mirrored/internal Keycloak image or mark the test [Skipped:Disconnected]; verify in the serial IPv6 job.
✅ Passed checks (10 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is clearly related to the PR and identifies the main e2e proxy-config work, even if it does not cover all controller and transport changes.
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 Ginkgo titles in the added e2e files are static string literals; no generated or data-derived test names were found.
Single Node Openshift (Sno) Test Compatibility ✅ Passed The new Ginkgo tests use normal operator/API flows and no node-count, rescheduling, or HA assumptions; no SNO-specific skip is needed.
Topology-Aware Scheduling Compatibility ✅ Passed No new topology-sensitive scheduling rules were introduced; the OAuth deployment still sets maxUnavailable to controlPlaneCount-1 and no new node affinity/spread changes appear in touched files.
Ote Binary Stdout Contract ✅ Passed No new process-level stdout writes were added; main() already routes klog to stderr, and the new component-proxy suite uses GinkgoWriter only.
No-Weak-Crypto ✅ Passed No MD5/SHA1/DES/RC4/3DES/Blowfish/ECB, custom crypto, or secret/token timing comparisons were found; SHA-256 is only used for a reconcile hash.
Container-Privileges ✅ Passed No new privilege flags were introduced in the changed files; searches found none of hostPID/hostNetwork/hostIPC/allowPrivilegeEscalation/SYS_ADMIN, and manifest edits were only annotations.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@openshift-ci

openshift-ci Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign gangwgr 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

@openshift-ci

openshift-ci Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

@ehearne-redhat: The following tests failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
ci/prow/verify-deps 6a54b55 link true /test verify-deps
ci/prow/test-operator-integration 6a54b55 link true /test test-operator-integration
ci/prow/images 6a54b55 link true /test images
ci/prow/verify-bindata 6a54b55 link true /test verify-bindata
ci/prow/unit 6a54b55 link true /test unit
ci/prow/verify 6a54b55 link true /test verify
ci/prow/okd-scos-images 6a54b55 link true /test okd-scos-images

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.

@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: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
pkg/controllers/proxyconfig/proxyconfig_controller.go (1)

260-269: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

No Timeout set on proxy/IdP-validation HTTP clients.

Unlike the comparable clients in custom_route_conditions.go (Timeout: 5 * time.Second) and endpoint_accessible_controller.go, neither http.Client returned here sets a Timeout. If the sync context has no deadline, isEndpointReachable calls against a slow/unreachable proxy or external IdP could block the controller's sync goroutine indefinitely.

As per path instructions, Go code should use "context.Context for cancellation and timeouts" for external calls.

🔧 Proposed fix
 	return &http.Client{
+			Timeout: 5 * time.Second,
 			Transport: &http.Transport{
 				TLSClientConfig: tlsConfig,
 				Proxy:           proxyFn,
 			},
 		}, &http.Client{
+			Timeout: 5 * time.Second,
 			Transport: &http.Transport{
 				TLSClientConfig: tlsConfig,
 			},
 		}, nil
🤖 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/controllers/proxyconfig/proxyconfig_controller.go` around lines 260 -
269, Update the HTTP clients returned by the proxy/IdP validation
client-construction function to enforce cancellation via context.Context and a
bounded timeout, matching the established timeout behavior in
custom_route_conditions.go and endpoint_accessible_controller.go. Ensure both
the proxy-enabled and direct clients used by isEndpointReachable cannot block
indefinitely when the sync context lacks a deadline.

Source: Path instructions

pkg/controllers/configobservation/oauth/idp_conversions.go (1)

318-336: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Add a bounded timeout to outbound OIDC discovery/password-grant requests.

discoverOpenIDURLs and checkOIDCPasswordGrantFlow hit operator-configured issuer/token endpoints with no http.Client.Timeout or request deadline. buildIDPTransport only wires CA/proxy settings, so a slow or hung IdP can block the config-observer sync loop indefinitely.

🤖 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/controllers/configobservation/oauth/idp_conversions.go` around lines 318
- 336, Add a bounded timeout to the outbound HTTP requests in discoverOpenIDURLs
and checkOIDCPasswordGrantFlow, using the existing transport configuration while
ensuring issuer and token endpoint calls cannot block indefinitely. Apply the
timeout via an http.Client or request context/deadline for both discovery and
password-grant flows, and preserve their current response and error handling.
🧹 Nitpick comments (2)
test/e2e-component-proxy/component_proxy_oidc_login.go (1)

254-254: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Drop the no-op fmt.Sprintf.

fmt.Sprintf("ocp-test-proxy-login-group") has no format args; use a plain string literal (staticcheck S1039).

♻️ Proposed fix
-	group := fmt.Sprintf("ocp-test-proxy-login-group")
+	group := "ocp-test-proxy-login-group"
🤖 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-component-proxy/component_proxy_oidc_login.go` at line 254, Replace
the no-op fmt.Sprintf call assigned to group with the plain string literal
"ocp-test-proxy-login-group", and remove the fmt import if it is no longer used
elsewhere in the file.

Source: Linters/SAST tools

test/library/proxy.go (1)

54-93: 🩺 Stability & Availability | 🔵 Trivial

Unimplemented helpers will panic when the e2e suite runs.

DeploySquidProxy, DeployProxyNetworkPolicies, GetOAuthServerProxyEnvVars, GetSquidProxyLogs, WaitForSquidProxyTraffic, VerifyOAuthServerDeploymentProxyConfig, VerifyTrustedCAConfigMapSynced, and CheckFeatureGateEnabledOrSkip are all panic("not implemented"), yet the new [ComponentProxy] specs invoke them — the suite will panic rather than run. Consistent with the WIP status noted in the PR objectives; flagging so it isn't merged into an enabled suite before implementation. Want me to open a tracking issue?

🤖 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/library/proxy.go` around lines 54 - 93, Implement all eight helper
functions currently containing panic("not implemented"): DeploySquidProxy,
DeployProxyNetworkPolicies, GetOAuthServerProxyEnvVars, GetSquidProxyLogs,
WaitForSquidProxyTraffic, VerifyOAuthServerDeploymentProxyConfig,
VerifyTrustedCAConfigMapSynced, and CheckFeatureGateEnabledOrSkip. Use the
existing Kubernetes clients and each function’s documented contract so the
[ComponentProxy] specs execute their deployment, policy, inspection, polling,
verification, and feature-gate behavior without panicking.
🤖 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/controllers/common/proxy.go`:
- Around line 99-105: Update mergeNoProxy to use the set’s sorted-list operation
before joining entries, replacing the nondeterministic UnsortedList call while
preserving deduplication and comma-separated output.

In `@pkg/controllers/customroute/custom_route_conditions.go`:
- Around line 165-171: Check the boolean result of AppendCertsFromPEM after
loading proxy trusted-CA data and return a descriptive parse error when it is
false. Update rootCAs in pkg/controllers/customroute/custom_route_conditions.go
lines 165-171, returning the error from the surrounding condition flow, and
caPool in pkg/controllers/proxyconfig/proxyconfig_controller.go lines 249-255,
returning it from createHTTPClients.

In `@pkg/controllers/deployment/deployment_controller.go`:
- Around line 382-392: Update the proxy trusted CA copy flow around targetCM to
propagate sourceCM.BinaryData as well as sourceCM.Data. Ensure the ConfigMap
applied to openshift-authentication preserves certificate content regardless of
whether the source stores it in Data or BinaryData.

In `@test/e2e-component-proxy/component_proxy_oidc_login.go`:
- Line 377: Update the deferred temporary-directory cleanup near the existing
os.RemoveAll call to explicitly handle its return value, either by intentionally
discarding it or logging cleanup failures, while preserving the best-effort
cleanup behavior and satisfying errcheck.

In `@test/e2e-component-proxy/component_proxy.go`:
- Around line 50-59: Rename the proxy-config cleanup result from
SaveAndRestoreProxyConfig to proxyConfigCleanup in both affected sections of
test/e2e-component-proxy/component_proxy.go: lines 50-59 and 155-177. Register
proxyConfigCleanup directly with DeferCleanup in the first section, and invoke
proxyConfigCleanup() inside the existing cleanup closure in the second,
preserving proxyCleanup exclusively for Squid teardown.

---

Outside diff comments:
In `@pkg/controllers/configobservation/oauth/idp_conversions.go`:
- Around line 318-336: Add a bounded timeout to the outbound HTTP requests in
discoverOpenIDURLs and checkOIDCPasswordGrantFlow, using the existing transport
configuration while ensuring issuer and token endpoint calls cannot block
indefinitely. Apply the timeout via an http.Client or request context/deadline
for both discovery and password-grant flows, and preserve their current response
and error handling.

In `@pkg/controllers/proxyconfig/proxyconfig_controller.go`:
- Around line 260-269: Update the HTTP clients returned by the proxy/IdP
validation client-construction function to enforce cancellation via
context.Context and a bounded timeout, matching the established timeout behavior
in custom_route_conditions.go and endpoint_accessible_controller.go. Ensure both
the proxy-enabled and direct clients used by isEndpointReachable cannot block
indefinitely when the sync context lacks a deadline.

---

Nitpick comments:
In `@test/e2e-component-proxy/component_proxy_oidc_login.go`:
- Line 254: Replace the no-op fmt.Sprintf call assigned to group with the plain
string literal "ocp-test-proxy-login-group", and remove the fmt import if it is
no longer used elsewhere in the file.

In `@test/library/proxy.go`:
- Around line 54-93: Implement all eight helper functions currently containing
panic("not implemented"): DeploySquidProxy, DeployProxyNetworkPolicies,
GetOAuthServerProxyEnvVars, GetSquidProxyLogs, WaitForSquidProxyTraffic,
VerifyOAuthServerDeploymentProxyConfig, VerifyTrustedCAConfigMapSynced, and
CheckFeatureGateEnabledOrSkip. Use the existing Kubernetes clients and each
function’s documented contract so the [ComponentProxy] specs execute their
deployment, policy, inspection, polling, verification, and feature-gate behavior
without panicking.
🪄 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: cb1ed3ca-4797-402c-8f83-5ce5903c255c

📥 Commits

Reviewing files that changed from the base of the PR and between def3591 and 6a54b55.

⛔ Files ignored due to path filters (55)
  • go.sum is excluded by !**/*.sum
  • vendor/github.com/openshift/api/.golangci.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/Makefile is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/apps/.codegen.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/authorization/.codegen.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/build/.codegen.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/cloudnetwork/.codegen.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/register.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/types_cluster_version.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/types_crio_credential_provider_config.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/types_infrastructure.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/types_network.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1/zz_generated.deepcopy.go is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/config/v1/zz_generated.featuregated-crd-manifests.yaml is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/config/v1/zz_generated.model_name.go is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/config/v1/zz_generated.swagger_doc_generated.go is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/config/v1alpha1/types_cluster_monitoring.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/config/v1alpha1/zz_generated.deepcopy.go is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/config/v1alpha1/zz_generated.swagger_doc_generated.go is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/features.md is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/features/features.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/image/.codegen.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/network/.codegen.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/networkoperator/.codegen.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/oauth/.codegen.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/types_authentication.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/types_csi_cluster_driver.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/types_ingresscontroller.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_authentication_01_authentications-CustomNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_authentication_01_authentications-DevPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_authentication_01_authentications-TechPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_csi-driver_01_clustercsidrivers-CustomNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_csi-driver_01_clustercsidrivers-Default.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_csi-driver_01_clustercsidrivers-DevPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_csi-driver_01_clustercsidrivers-OKD.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_csi-driver_01_clustercsidrivers-TechPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_ingress_00_ingresscontrollers-CustomNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_ingress_00_ingresscontrollers-Default.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_ingress_00_ingresscontrollers-DevPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_ingress_00_ingresscontrollers-OKD.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_ingress_00_ingresscontrollers-TechPreviewNoUpgrade.crd.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/operator/v1/zz_generated.deepcopy.go is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/operator/v1/zz_generated.featuregated-crd-manifests.yaml is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/operator/v1/zz_generated.model_name.go is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/operator/v1/zz_generated.swagger_doc_generated.go is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/osin/v1/types.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/osin/v1/zz_generated.swagger_doc_generated.go is excluded by !**/vendor/**, !vendor/**, !**/zz_generated*
  • vendor/github.com/openshift/api/project/.codegen.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/quota/.codegen.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/route/.codegen.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/samples/.codegen.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/security/.codegen.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/template/.codegen.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/openshift/api/user/.codegen.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/modules.txt is excluded by !**/vendor/**, !vendor/**
📒 Files selected for processing (33)
  • cmd/cluster-authentication-operator-tests-ext/main.go
  • go.mod
  • pkg/controllers/common/proxy.go
  • pkg/controllers/common/proxy_test.go
  • pkg/controllers/configobservation/configobservercontroller/observe_config_controller.go
  • pkg/controllers/configobservation/interfaces.go
  • pkg/controllers/configobservation/oauth/idp_conversions.go
  • pkg/controllers/configobservation/oauth/idp_conversions_test.go
  • pkg/controllers/configobservation/oauth/observe_idps.go
  • pkg/controllers/configobservation/oauth/observe_idps_test.go
  • pkg/controllers/configobservation/oauth/observe_proxy_trusted_ca.go
  • pkg/controllers/configobservation/oauth/observe_proxy_trusted_ca_test.go
  • pkg/controllers/customroute/custom_route_conditions.go
  • pkg/controllers/customroute/custom_route_controller.go
  • pkg/controllers/deployment/default_deployment.go
  • pkg/controllers/deployment/deployment_controller.go
  • pkg/controllers/deployment/deployment_controller_test.go
  • pkg/controllers/oauthendpoints/oauth_endpoints_controller.go
  • pkg/controllers/proxyconfig/proxyconfig_controller.go
  • pkg/controllers/proxyconfig/proxyconfig_controller_test.go
  • pkg/internal/transporttest/transporttest.go
  • pkg/libs/endpointaccessible/endpoint_accessible_controller.go
  • pkg/operator/replacement_starter.go
  • pkg/operator/starter.go
  • pkg/transport/transport.go
  • pkg/transport/transport_test.go
  • test-data/apply-configuration/overall/minimal-cluster/expected-output/UserWorkload/Create/cluster-scoped-resources/certificates.k8s.io/certificatesigningrequests/9806-body-system-COLON-openshift-COLON-openshift-authenticator-.yaml
  • test-data/apply-configuration/overall/minimal-cluster/expected-output/UserWorkload/Create/cluster-scoped-resources/certificates.k8s.io/certificatesigningrequests/9806-metadata-system-COLON-openshift-COLON-openshift-authenticator-.yaml
  • test-data/apply-configuration/overall/oauth-server-creation-minimal/expected-output/Management/Create/namespaces/openshift-authentication/apps/deployments/b3b2-body-oauth-openshift.yaml
  • test-data/apply-configuration/overall/oauth-server-creation-minimal/expected-output/Management/Create/namespaces/openshift-authentication/apps/deployments/b3b2-metadata-oauth-openshift.yaml
  • test/e2e-component-proxy/component_proxy.go
  • test/e2e-component-proxy/component_proxy_oidc_login.go
  • test/library/proxy.go

Comment on lines +99 to +105
// mergeNoProxy combines user-provided noProxy entries with static cluster-internal
// defaults. It performs deduplication, but the items are not sorted.
func mergeNoProxy(userNoProxy []string) string {
entries := sets.New[string](staticNoProxyEntries...)
entries.Insert(userNoProxy...)
return strings.Join(entries.UnsortedList(), ",")
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win

Non-deterministic NoProxy ordering will thrash the oauth-server redeploy hash.

UnsortedList() returns entries in random map-iteration order, so mergeNoProxy produces a different comma-joined string on virtually every call even when the underlying set hasn't changed. deployment_controller.go's Sync() feeds this directly into its redeploy-trigger string (fmt.Sprintf("proxy:%s:%s:%s", proxy.HTTPProxy, proxy.HTTPSProxy, proxy.NoProxy)), so this nondeterminism will make that hash change on nearly every reconcile, potentially forcing continual/needless rolling redeployment of the OAuth server. Use a sorted list instead.

🐛 Proposed fix
 func mergeNoProxy(userNoProxy []string) string {
 	entries := sets.New[string](staticNoProxyEntries...)
 	entries.Insert(userNoProxy...)
-	return strings.Join(entries.UnsortedList(), ",")
+	return strings.Join(sets.List(entries), ",")
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// mergeNoProxy combines user-provided noProxy entries with static cluster-internal
// defaults. It performs deduplication, but the items are not sorted.
func mergeNoProxy(userNoProxy []string) string {
entries := sets.New[string](staticNoProxyEntries...)
entries.Insert(userNoProxy...)
return strings.Join(entries.UnsortedList(), ",")
}
// mergeNoProxy combines user-provided noProxy entries with static cluster-internal
// defaults. It performs deduplication, but the items are not sorted.
func mergeNoProxy(userNoProxy []string) string {
entries := sets.New[string](staticNoProxyEntries...)
entries.Insert(userNoProxy...)
return strings.Join(sets.List(entries), ",")
}
🤖 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/controllers/common/proxy.go` around lines 99 - 105, Update mergeNoProxy
to use the set’s sorted-list operation before joining entries, replacing the
nondeterministic UnsortedList call while preserving deduplication and
comma-separated output.

Comment on lines +165 to +171
if len(proxy.TrustedCAName) > 0 {
caData, err := transport.LoadCAData(configMapLister, proxy.TrustedCAName, "ca-bundle.crt")
if err != nil {
return fmt.Errorf("failed to load proxy CA: %w", err)
}
rootCAs.AppendCertsFromPEM(caData)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Ignored AppendCertsFromPEM result when loading proxy trusted CA in two files. Both sites load the proxy's trusted-CA PEM bytes via transport.LoadCAData and then call AppendCertsFromPEM without checking its ok bool return, unlike the existing sibling checks in the same files (e.g., custom_route_conditions.go line 161, proxyconfig_controller.go line 287). Malformed or truncated CA data is silently ignored instead of surfacing a clear error.

  • pkg/controllers/customroute/custom_route_conditions.go#L165-L171: check the ok return of rootCAs.AppendCertsFromPEM(caData) and return an error (e.g. fmt.Errorf("failed to parse proxy CA %q", proxy.TrustedCAName)) when false.
  • pkg/controllers/proxyconfig/proxyconfig_controller.go#L249-L255: check the ok return of caPool.AppendCertsFromPEM(caData) and return an error from createHTTPClients when false.
📍 Affects 2 files
  • pkg/controllers/customroute/custom_route_conditions.go#L165-L171 (this comment)
  • pkg/controllers/proxyconfig/proxyconfig_controller.go#L249-L255
🤖 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/controllers/customroute/custom_route_conditions.go` around lines 165 -
171, Check the boolean result of AppendCertsFromPEM after loading proxy
trusted-CA data and return a descriptive parse error when it is false. Update
rootCAs in pkg/controllers/customroute/custom_route_conditions.go lines 165-171,
returning the error from the surrounding condition flow, and caPool in
pkg/controllers/proxyconfig/proxyconfig_controller.go lines 249-255, returning
it from createHTTPClients.

Source: Path instructions

Comment on lines +382 to +392
sourceCM, err := c.sourceConfigMapLister.ConfigMaps("openshift-config").Get(trustedCAName)
if err != nil {
return fmt.Errorf("failed to get component proxy CA configmap \"%s/%s\": %w", "openshift-config", trustedCAName, err)
}

targetCM := corev1ac.ConfigMap(componentProxyCAConfigMapName, "openshift-authentication").WithData(sourceCM.Data)
if _, err := c.configMaps.ConfigMaps("openshift-authentication").Apply(
ctx, targetCM, metav1.ApplyOptions{FieldManager: c.name, Force: true},
); err != nil {
return fmt.Errorf("failed to apply component proxy CA configmap \"%s/%s\": %w", "openshift-authentication", componentProxyCAConfigMapName, err)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Proxy trusted CA copy drops BinaryData, potentially loses cert content.

targetCM := corev1ac.ConfigMap(...).WithData(sourceCM.Data) only copies sourceCM.Data. transport.LoadCAData (used elsewhere to read this exact kind of CA configmap) explicitly falls back to cm.BinaryData[key] when Data[key] is empty, indicating this configmap's PEM content can legitimately live in BinaryData. If the source openshift-config configmap referenced by TrustedCA.Name stores the bundle there, the copied target configmap mounted into the OAuth server pod will be empty, silently breaking proxy TLS trust for the running server.

🐛 Proposed fix to also propagate BinaryData
-	targetCM := corev1ac.ConfigMap(componentProxyCAConfigMapName, "openshift-authentication").WithData(sourceCM.Data)
+	targetCM := corev1ac.ConfigMap(componentProxyCAConfigMapName, "openshift-authentication").
+		WithData(sourceCM.Data).
+		WithBinaryData(sourceCM.BinaryData)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
sourceCM, err := c.sourceConfigMapLister.ConfigMaps("openshift-config").Get(trustedCAName)
if err != nil {
return fmt.Errorf("failed to get component proxy CA configmap \"%s/%s\": %w", "openshift-config", trustedCAName, err)
}
targetCM := corev1ac.ConfigMap(componentProxyCAConfigMapName, "openshift-authentication").WithData(sourceCM.Data)
if _, err := c.configMaps.ConfigMaps("openshift-authentication").Apply(
ctx, targetCM, metav1.ApplyOptions{FieldManager: c.name, Force: true},
); err != nil {
return fmt.Errorf("failed to apply component proxy CA configmap \"%s/%s\": %w", "openshift-authentication", componentProxyCAConfigMapName, err)
}
sourceCM, err := c.sourceConfigMapLister.ConfigMaps("openshift-config").Get(trustedCAName)
if err != nil {
return fmt.Errorf("failed to get component proxy CA configmap \"%s/%s\": %w", "openshift-config", trustedCAName, err)
}
targetCM := corev1ac.ConfigMap(componentProxyCAConfigMapName, "openshift-authentication").
WithData(sourceCM.Data).
WithBinaryData(sourceCM.BinaryData)
if _, err := c.configMaps.ConfigMaps("openshift-authentication").Apply(
ctx, targetCM, metav1.ApplyOptions{FieldManager: c.name, Force: true},
); err != nil {
return fmt.Errorf("failed to apply component proxy CA configmap \"%s/%s\": %w", "openshift-authentication", componentProxyCAConfigMapName, err)
}
🤖 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/controllers/deployment/deployment_controller.go` around lines 382 - 392,
Update the proxy trusted CA copy flow around targetCM to propagate
sourceCM.BinaryData as well as sourceCM.Data. Ensure the ConfigMap applied to
openshift-authentication preserves certificate content regardless of whether the
source stores it in Data or BinaryData.

g.By("Generating self-signed CA and creating trustedCA ConfigMap")
tempDir, err := os.MkdirTemp("", "testca")
o.Expect(err).NotTo(o.HaveOccurred())
defer os.RemoveAll(tempDir)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Handle the os.RemoveAll error (errcheck).

golangci-lint's errcheck flags the unchecked return. Since it's a best-effort temp-dir cleanup, either explicitly discard or log on failure to satisfy the linter.

🧹 Proposed fix
-	defer os.RemoveAll(tempDir)
+	defer func() {
+		if err := os.RemoveAll(tempDir); err != nil {
+			g.GinkgoWriter.Printf("failed to remove temp dir %s: %v\n", tempDir, err)
+		}
+	}()
🧰 Tools
🪛 golangci-lint (2.12.2)

[error] 377-377: Error return value of os.RemoveAll is not checked

(errcheck)

🤖 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-component-proxy/component_proxy_oidc_login.go` at line 377, Update
the deferred temporary-directory cleanup near the existing os.RemoveAll call to
explicitly handle its return value, either by intentionally discarding it or
logging cleanup failures, while preserving the best-effort cleanup behavior and
satisfying errcheck.

Source: Linters/SAST tools

Comment on lines +50 to +59
proxyURL, proxyNamespace, proxyCleanup := test.DeploySquidProxy(t, clients.KubeClient)
g.DeferCleanup(func() {
g.GinkgoWriter.Println("cleaning up: removing Squid proxy")
proxyCleanup()
})
g.GinkgoWriter.Printf("Squid proxy URL: %s\n", proxyURL)

g.By("Saving original proxy config and setting component-scoped proxy")
operatorAuth, proxyCleanup := test.SaveAndRestoreProxyConfig(t, clients.OperatorClient, clients.ConfigClient)
g.DeferCleanup(proxyCleanup)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift

Reused proxyCleanup variable breaks Squid teardown in two tests. In both functions the Squid teardown is captured in a DeferCleanup closure by variable reference, then proxyCleanup is reassigned by SaveAndRestoreProxyConfig (via := where only operatorAuth is new). At cleanup time every closure invokes the proxy-config restore, leaking the Squid proxy namespace and restoring config twice. Fix by giving the config cleanup its own variable (as in component_proxy_oidc_login.go).

  • test/e2e-component-proxy/component_proxy.go#L50-L59: rename to operatorAuth, proxyConfigCleanup := test.SaveAndRestoreProxyConfig(...) and g.DeferCleanup(proxyConfigCleanup).
  • test/e2e-component-proxy/component_proxy.go#L155-L177: rename the L163 result to proxyConfigCleanup and call proxyConfigCleanup() in the L170-178 cleanup closure instead of reassigning proxyCleanup.
📍 Affects 1 file
  • test/e2e-component-proxy/component_proxy.go#L50-L59 (this comment)
  • test/e2e-component-proxy/component_proxy.go#L155-L177
🤖 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-component-proxy/component_proxy.go` around lines 50 - 59, Rename the
proxy-config cleanup result from SaveAndRestoreProxyConfig to proxyConfigCleanup
in both affected sections of test/e2e-component-proxy/component_proxy.go: lines
50-59 and 155-177. Register proxyConfigCleanup directly with DeferCleanup in the
first section, and invoke proxyConfigCleanup() inside the existing cleanup
closure in the second, preserving proxyCleanup exclusively for Squid teardown.

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. jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants