Add support for authenticated forward HTTP proxies#7306
Conversation
Update all lib-httpx declarations in lockstep to pick up forward proxy support: clients built via a plain HxClient.newBuilder() now resolve the proxy - including user:pass@host:port credentials - from the HTTPS_PROXY, HTTP_PROXY, ALL_PROXY and NO_PROXY environment variables automatically. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VV3ykikhtoSqjpG5gH4J6K Signed-off-by: Phil Ewels <phil.ewels@seqera.io>
Behind an authenticating corporate proxy Nextflow failed with an immediate 407 on HTTPS. Two independent JVM behaviours caused this and both are addressed: 1. java.net.http.HttpClient ignores Authenticator.setDefault(), so proxy credentials must be set on the client builder. Add the HttpClientHelper.applyProxy() helper (backed by lib-httpx HxProxyConfig) and apply it to all sites building a raw HttpClient or passing a pre-built client to HxClient - RepositoryProvider, SraExplorer, WaveClient, TowerXAuth and DataLinksResourceHandler - preserving each site's existing settings and honouring NO_PROXY. The default authenticator is kept for legacy HttpURLConnection paths. 2. jdk.http.auth.tunneling.disabledSchemes=Basic is the JDK default and strips Basic credentials from the HTTPS CONNECT tunnel even when an authenticator is set. When the proxy configuration provides credentials the launcher now defaults this property (and the proxying counterpart) to empty, unless already set by the user. Add an integration test suite based on a local mock authenticating proxy covering the auto-resolve path (plugin registry fetch), the explicit-client paths (helper and Wave transport) and HTTPS CONNECT tunnelling against a local TLS origin, plus launcher unit tests for the disabledSchemes handling. Document credential support and the disabledSchemes behaviour in the environment variables reference. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VV3ykikhtoSqjpG5gH4J6K Signed-off-by: Phil Ewels <phil.ewels@seqera.io>
✅ Deploy Preview for nextflow-docs canceled.
|
Co-authored-by: Chris Hakkaart <chris.hakkaart@seqera.io> Signed-off-by: Phil Ewels <phil.ewels@seqera.io>
Share the proxy environment map via MockAuthProxyServer.proxyEnv() instead of duplicating it across test classes, remove the unused requestLines field, precompute the expected Proxy-Authorization header and cache the EnvHelper reflection lookups. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VV3ykikhtoSqjpG5gH4J6K Signed-off-by: Phil Ewels <phil.ewels@seqera.io>
|
Note on the CI failure: the build fails at dependency resolution because Generated by Claude Code |
christopher-hakkaart
left a comment
There was a problem hiding this comment.
Style suggestions.
Co-authored-by: Christopher Hakkaart <christopher.hakkaart@gmail.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VV3ykikhtoSqjpG5gH4J6K Signed-off-by: Phil Ewels <phil.ewels@seqera.io>
…henticated-proxies-y5jzlo Signed-off-by: Phil Ewels <phil.ewels@seqera.io> # Conflicts: # plugins/nf-seqera/build.gradle
The lib-httpx 2.4.0 release (seqeralabs/libseqera#82) deliberately dropped the environment auto-resolution from an earlier design iteration: as a library it never reaches into ambient global state, so resolving the proxy settings from the environment is the consumer's responsibility. Move the HTTP_PROXY/HTTPS_PROXY/ALL_PROXY/NO_PROXY environment resolution into HttpClientHelper, reusing ProxyConfig - relocated to nf-commons and extended to URL-decode credentials - and building the lib-httpx HxProxyConfig explicitly. Since plain HxClient builders no longer resolve the proxy on their own, wire the remaining HxClient sites (plugin registry repository and client, Platform client and auth command) through the new HttpClientHelper.applyProxy(HxClient.Builder) helper. The proxy tests now drive the environment through SysEnv instead of mutating the process environment reflectively, and account for the built-in loopback bypass of the lib-httpx proxy selector. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VV3ykikhtoSqjpG5gH4J6K Signed-off-by: Phil Ewels <phil.ewels@seqera.io>
|
lib-httpx 2.4.0 is now published, so the dependency-resolution failure blocking CI is gone. The published artifact reflects the final design of seqeralabs/libseqera#82: the environment auto-resolution was dropped during review in favour of an explicit API (
Branch is merged up to current master, and all touched-module test suites pass locally against the real 2.4.0 artifact. PR description updated to match. Watching CI. Generated by Claude Code |
Apply review cleanups: resolve each proxy variable with a single helper that checks both spellings and names the offending variable when the value cannot be parsed; move the protocol default port logic to ProxyConfig; clear the proxy auth schemes also when the credentials are provided only via the ALL_PROXY variable, which is resolved by the HTTP clients but not by the per-qualifier proxy setup; drop the unused request counter, the tunnel join timeout and the byte-by-byte stream copy from the mock proxy fixture; use the Spock TempDir fixture and share the request scaffolding in the client helper test. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VV3ykikhtoSqjpG5gH4J6K Signed-off-by: Phil Ewels <phil.ewels@seqera.io>
|
CI is green ✅ — all build and test matrix jobs (JDK 17 and 25) pass on head 152bbd0, now building against the published lib-httpx 2.4.0. The PR is ready for review/merge. Generated by Claude Code |
|
Hi Phil, my inclination is to close this in favour of #7331 why rely on existing helpers for proxy handling. Let me know if something is missing |
|
No objection to consolidating on #7331 — but a few things it currently misses that shouldn't get lost, whichever PR moves forward:
Conversely, one thing #7331 does better which this PR should adopt if kept: configuring Happy either way — just flagging the pieces above so they land somewhere. Generated by Claude Code |
This comment has been minimized.
This comment has been minimized.
|
Thanks @ewels — all three have now landed on #7331 (branch merged up to current master, one trivial
Also confirmed the "conversely" point is already the case on #7331 — clients are configured on Each item is a separate commit with unit tests (RED→GREEN). Still open, if worth adding: (a) the doc note for |
Closes #7305
Depends on seqeralabs/libseqera#82 (published as lib-httpx 2.4.0)
Problem
Behind an authenticating corporate forward proxy, Nextflow fails immediately with
407 Proxy Authentication Requiredon HTTPS, whilegitand Python tooling on the same host work fine. Two independent JVM behaviours cause this, and either one alone is enough to break proxy authentication, so both must be fixed together:java.net.http.HttpClientignoresAuthenticator.setDefault(...). Proxy credentials only take effect when the authenticator is set on the client builder itself. The launcher previously only set the default authenticator, so everyHxClient/HttpClient-based code path (SCM providers, plugin registry, Wave, Seqera Platform, SRA) never authenticated to the proxy. Fixing this alone is still not enough for HTTPS, because of (2).The JDK strips Basic credentials from the HTTPS
CONNECTtunnel.jdk.http.auth.tunneling.disabledSchemes=Basicis the JDK default (see$JAVA_HOME/conf/net.properties), so even a correctly-wired authenticator is silently dropped when tunnelling HTTPS through the proxy. Fixing this alone is also not enough, because without (1) the authenticator is never consulted in the first place.Routing was already fine: a client with no explicit proxy uses
ProxySelector.getDefault(), which honours the-Dhttps.proxyHostproperties set by the launcher.Design
Per the final design of seqeralabs/libseqera#82, lib-httpx 2.4.0 exposes an explicit proxy API —
HxClient.Builder.proxy(ProxySelector)/.authenticator(Authenticator)/.withProxyConfig(HxProxyConfig)— and deliberately does not read the environment itself: resolvingHTTP_PROXY/HTTPS_PROXYis the consumer's job. Nextflow therefore resolves the environment in one place (HttpClientHelperinnf-commons) and wires it into every HTTP client explicitly.Changes
Bump
io.seqera:lib-httpx2.3.0 → 2.4.0 innf-commons,nf-seqera,nf-wave(compileOnly + testImplementation) andnf-google, keeping the existing scopes and version-override pins in lockstep.Launcher: when the parsed proxy configuration carries credentials, default
jdk.http.auth.tunneling.disabledSchemesandjdk.http.auth.proxying.disabledSchemesto empty — only if the user has not set them (System.getProperty(name) == nullguard, never overridden). This happens insetupEnvironment(), before any HTTP client is created. The existingAuthenticator.setDefault(...)is kept for legacyHttpURLConnectionpaths (e.g. nf-httpfs).New
HttpClientHelperinnf-commons, resolvingHTTPS_PROXY/HTTP_PROXY/ALL_PROXY/NO_PROXY(both cases, URL-encodeduser:pass@host:portcredentials) fromSysEnvand building an explicitHxProxyConfig.ProxyConfigmoved from thenextflowmodule tonf-commons(same package) so its URL parsing can be reused, and extended to URL-decode credentials. Two entry points:applyProxy(HttpClient.Builder)— for raw JDK clients: setstoProxySelector()and, when credentials are present,toAuthenticator()on the builder. Applied inscm/RepositoryProvider.newHttpClient(),datasource/SraExplorer.getHttpClient(), nf-waveWaveClient.newHttpClient0()(used by both the authenticated and plain Wave clients), nf-seqeraTowerXAuthandDataLinksResourceHandler.applyProxy(HxClient.Builder)— for lib-httpx clients: applieswithProxyConfig(...). Applied inplugin/HttpPluginRepository,module/RegistryClientFactory, nf-seqeraTowerClientandAuthCommandImpl.Each site keeps its existing version/redirect/timeout/executor settings, including nf-wave's conditional virtual-threads executor. The lib-httpx proxy selector also bypasses loopback addresses (
localhost,127.*,::1) by design.Docs:
HTTP_PROXY/HTTPS_PROXYentries now document embedded credentials (asFTP_PROXYalready did) and thedisabledSchemesbehaviour, with theNXF_OPTS='-Djdk.http.auth.tunneling.disabledSchemes='fallback for users who prefer to set it themselves.Tests
MockAuthProxyServertest fixture (raw-socket forward proxy in the style of the one in Add authenticated forward-proxy support to HxClient seqeralabs/libseqera#82): returns407withoutProxy-Authorization, answers plain HTTP requests with the correct Basic credentials, and tunnelsCONNECTrequests to the requested target port on loopback.HttpClientHelperTest: env resolution (both cases,ALL_PROXYfallback, URL-decoded credentials); plain HTTP 407→retry-with-credentials→200; wrong credentials fail after the 407 challenge; HTTPSCONNECTtunnelling against a local HTTPS origin with a self-signed certificate, requested via a non-loopback host name so it is only reachable through the proxy (the module test JVM runs with-Djdk.http.auth.tunneling.disabledSchemes=, mirroring what the launcher sets at runtime);NO_PROXYand loopback bypass at the selector level; no-proxy-configured leaves the client untouched. Tests drive the environment viaSysEnv— no process-environment reflection.HttpPluginRepositoryProxyTest: a plugin registry metadata fetch against a registry host only reachable through the authenticating proxy.WaveClientProxyTest: the Wave HTTP transport authenticates through the proxy, resolved from the environment.ProxyConfigTest: URL-decoding of credentials.LauncherTest: thedisabledSchemesproperties default to empty only when the proxy has credentials and the user has not set the property; user-set values are never overridden; untouched when the proxy has no credentials.All of the above verified locally against the published lib-httpx 2.4.0 artifact.
Compatibility
disabledSchemesproperties are only touched when proxy credentials are present).jdk.http.auth.*.disabledSchemesvalues always win.🤖 Generated with Claude Code
https://claude.ai/code/session_01VV3ykikhtoSqjpG5gH4J6K