RTECO-524 - Add proxy support for OIDC authentication#593
Conversation
f2298dc to
c68c882
Compare
| proxyUrl = parsed.toString(); | ||
| } catch (e) { | ||
| tl.warning('Failed to parse proxy URL: ' + e.message); | ||
| return; |
There was a problem hiding this comment.
If the URL parse fails (malformed proxy URL), the function returns without setting any proxy env vars. That means the user's proxy is silently dropped. Is that correct?
I think better approach: warn and fall through with the original proxyUrl (without credentials), rather than abandoning proxy support entirely. The user gets a degraded experience (unauthenticated proxy) rather than no proxy at all.
@bhanurp any thoughts?
There was a problem hiding this comment.
Fixed. Removed the return on parse failure — the function now warns and falls through with the original proxyUrl (without credentials), so proxy support isn't lost when the URL can't be parsed.
| assert.strictEqual(config.proxy.proxyPassword, 'pass'); | ||
| clearProxyVars(); | ||
| }); | ||
|
|
There was a problem hiding this comment.
I don't see a test for forwardProxyToEnv() when URL parse throws (the return on parse failure path) should be covered.
There was a problem hiding this comment.
Updated the existing forwardProxyToEnv handles invalid proxy URL gracefully test to match the new behavior. It now asserts that HTTP_PROXY and HTTPS_PROXY are set to the original URL when parsing fails (credentials not included).
| assert.strictEqual(config.proxy.proxyUsername, undefined); | ||
| clearProxyVars(); | ||
| }); | ||
|
|
There was a problem hiding this comment.
I don't see any tests for Agent.ProxyUrl set + HTTP_PROXY already in env- we need to check taht don't override kind of guard you wrote right?
There was a problem hiding this comment.
Already covered — check forwardProxyToEnv does not override existing HTTP_PROXY (line 172 in proxyConfigTest.js).
It sets both process.env.HTTP_PROXY = 'http://existing:9090' and Agent.ProxyUrl = 'http://myproxy:8080' and asserts HTTP_PROXY stays unchanged.
| proxyUrl = process.env.HTTPS_PROXY || process.env.https_proxy || process.env.HTTP_PROXY || process.env.http_proxy; | ||
| if (proxyUrl) { | ||
| tl.debug('Using proxy from environment variable: ' + proxyUrl); | ||
| } |
There was a problem hiding this comment.
The fallback here is inside the else branch meaning it only applies when Agent.ProxyUrl is absent. But forwardProxyToEnv() already set HTTP_PROXY/HTTPS_PROXY from Agent.ProxyUrl earlier in executeCliTask.
So if Agent.ProxyUrl is set:
forwardProxyToEnv() sets HTTP_PROXY/HTTPS_PROXY in the environment
getProxyConfiguration() reads Agent.ProxyUrl directly (not the env vars)
But if a user sets HTTP_PROXY manually and Agent.ProxyUrl is also set, getProxyConfiguration() will use Agent.ProxyUrl for the typed-rest-client while HTTP_PROXY might point somewhere different.
This dual-source behavior should be documented right? WTDY?
There was a problem hiding this comment.
Added a JSDoc block on getProxyConfiguration explaining the behavior: when Agent.ProxyUrl is set, typed-rest-client uses it directly via this function, while forwardProxyToEnv separately forwards it into HTTP_PROXY/HTTPS_PROXY for JFrog CLI.
If a user also has a different HTTP_PROXY set manually, the two sources diverge intentionally — forwardProxyToEnv never overrides a pre-existing env var.
| const requestOptions = getProxyConfiguration(); | ||
| const httpClient = new httpm.HttpClient(buildAgent, [new credentialsHandler.BearerCredentialHandler(token, false)], requestOptions); | ||
| tl.debug('Requesting OIDC token from: ' + url); | ||
| const response = await httpClient.post(url, JSON.stringify({}), { |
There was a problem hiding this comment.
If the OIDC endpoint hangs or is unreachable, await httpClient.post(...) will never resolve, leaving the pipeline task stuck indefinitely with no way to recover short of the agent's own job timeout (which is typically 60 minutes based on documentation I read)
So I think requestOptions should have timeout also I feel.
const requestOptions = { ...getProxyConfiguration(), socketTimeout: 30000 };
There was a problem hiding this comment.
Fixed. Added socketTimeout: 30000 to the request options on the fetchAzureOidcToken call so a hung endpoint won't block the pipeline indefinitely.
npm run formatfor formatting the code before submitting the pull request.Add proxy support for OIDC authentication
Summary
The JFrog Azure DevOps extension now supports proxy configurations when retrieving OIDC tokens from Azure DevOps. Previously, the OIDC token request (
POST https://dev.azure.com/.../_apis/distributedtask/hubs/.../oidctoken) used the synchronoussync-requestlibrary, which does not honor proxy settings. This caused OIDC authentication to fail when the Azure DevOps Agent runs behind a proxy.Problem
When an Azure DevOps Agent is deployed within an intranet behind a proxy, the extension's OIDC flow fails silently because:
sync-requestdoes not support proxy configuration.Agent.ProxyUrl,Agent.ProxyUsername,Agent.ProxyPassword,Agent.ProxyBypassList).Solution
sync-requestwith the asynctyped-rest-client/HttpClient(already a project dependency) for the OIDC token fetch. This client natively supports proxy configuration and automatically respectsHTTP_PROXY/HTTPS_PROXYenvironment variables.getProxyConfiguration()to explicitly read Azure DevOps Agent proxy variables and pass them to the HTTP client.configureSpecificCliServer(shared by all connection types) intoconfigureJfrogCliServer(JFrog platform connections only), keeping the async footprint minimal.Async impact
Only the OIDC code path is async. All other connection types (Artifactory, Distribution, Xray) and all other task files remain fully synchronous and unchanged.
Proxy support matrix
HTTP_PROXY/HTTPS_PROXYenv varstyped-rest-client)Agent.ProxyUrl/Agent.ProxyUsername/Agent.ProxyPassword/Agent.ProxyBypassListgetProxyConfiguration())