From d2cc89b0268afe0a4890cc3460a2d8618cb22dda Mon Sep 17 00:00:00 2001 From: Cory Johns Date: Mon, 2 Dec 2024 10:54:00 -0800 Subject: [PATCH 1/2] fix(api-gateway): support proxy when fetching jwk for token validation When fetching the JWK data needed to validate the auth token, the environment proxy settings are not honored. --- packages/cubejs-api-gateway/package.json | 1 + packages/cubejs-api-gateway/src/jwk.ts | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/cubejs-api-gateway/package.json b/packages/cubejs-api-gateway/package.json index 743b05142bfa3..e6dac9a46637f 100644 --- a/packages/cubejs-api-gateway/package.json +++ b/packages/cubejs-api-gateway/package.json @@ -45,6 +45,7 @@ "moment-timezone": "^0.5.27", "nexus": "^1.1.0", "node-fetch": "^2.6.1", + "proxy-agent": "^6.4.0", "ramda": "^0.27.0", "uuid": "^8.3.2" }, diff --git a/packages/cubejs-api-gateway/src/jwk.ts b/packages/cubejs-api-gateway/src/jwk.ts index 06ae30ed6150a..9518b0b42a74a 100644 --- a/packages/cubejs-api-gateway/src/jwk.ts +++ b/packages/cubejs-api-gateway/src/jwk.ts @@ -3,6 +3,7 @@ import crypto from 'crypto'; import { asyncMemoizeBackground, asyncRetry, BackgroundMemoizeOptions } from '@cubejs-backend/shared'; import fetch from 'node-fetch'; import jwkToPem from 'jwk-to-pem'; +import { ProxyAgent } from 'proxy-agent'; import { JWTOptions } from './interfaces'; const HEADER_REGEXP = /([a-zA-Z][a-zA-Z_-]*)\s*(?:=(?:"([^"]*)"|([^ \t",;]*)))?/g; @@ -51,7 +52,7 @@ export type JWKsFetcherOptions = Pick, 'onBac export const createJWKsFetcher = (jwtOptions: JWTOptions, options: JWKsFetcherOptions) => { const fetchJwkUrl = asyncMemoizeBackground(async (url: string) => { - const response = await asyncRetry(() => fetch(url), { + const response = await asyncRetry(() => fetch(url, { agent: new ProxyAgent() }), { times: jwtOptions.jwkRetry || 3, }); const json = await response.json(); From ec9bafb4fed42ee72bbf1995e7cff1e5ddac2d5f Mon Sep 17 00:00:00 2001 From: Cory Johns Date: Mon, 27 Jan 2025 14:52:12 -0500 Subject: [PATCH 2/2] Move proxy fix to cubejs-backend-shared instead and use that --- packages/cubejs-api-gateway/package.json | 1 - packages/cubejs-api-gateway/src/jwk.ts | 5 ++--- packages/cubejs-backend-shared/package.json | 2 +- packages/cubejs-backend-shared/src/proxy.ts | 7 +++---- 4 files changed, 6 insertions(+), 9 deletions(-) diff --git a/packages/cubejs-api-gateway/package.json b/packages/cubejs-api-gateway/package.json index c440807239d9f..ab4e6eb91ee1d 100644 --- a/packages/cubejs-api-gateway/package.json +++ b/packages/cubejs-api-gateway/package.json @@ -46,7 +46,6 @@ "moment-timezone": "^0.5.27", "nexus": "^1.1.0", "node-fetch": "^2.6.1", - "proxy-agent": "^6.4.0", "ramda": "^0.27.0", "uuid": "^8.3.2" }, diff --git a/packages/cubejs-api-gateway/src/jwk.ts b/packages/cubejs-api-gateway/src/jwk.ts index 9518b0b42a74a..84f31aca63063 100644 --- a/packages/cubejs-api-gateway/src/jwk.ts +++ b/packages/cubejs-api-gateway/src/jwk.ts @@ -1,9 +1,8 @@ /* eslint-disable no-restricted-syntax */ import crypto from 'crypto'; -import { asyncMemoizeBackground, asyncRetry, BackgroundMemoizeOptions } from '@cubejs-backend/shared'; +import { asyncMemoizeBackground, asyncRetry, BackgroundMemoizeOptions, getHttpAgentForProxySettings } from '@cubejs-backend/shared'; import fetch from 'node-fetch'; import jwkToPem from 'jwk-to-pem'; -import { ProxyAgent } from 'proxy-agent'; import { JWTOptions } from './interfaces'; const HEADER_REGEXP = /([a-zA-Z][a-zA-Z_-]*)\s*(?:=(?:"([^"]*)"|([^ \t",;]*)))?/g; @@ -52,7 +51,7 @@ export type JWKsFetcherOptions = Pick, 'onBac export const createJWKsFetcher = (jwtOptions: JWTOptions, options: JWKsFetcherOptions) => { const fetchJwkUrl = asyncMemoizeBackground(async (url: string) => { - const response = await asyncRetry(() => fetch(url, { agent: new ProxyAgent() }), { + const response = await asyncRetry(() => fetch(url, { agent: await getHttpAgentForProxySettings() }), { times: jwtOptions.jwkRetry || 3, }); const json = await response.json(); diff --git a/packages/cubejs-backend-shared/package.json b/packages/cubejs-backend-shared/package.json index d0a59c6b98f42..1055c72177902 100644 --- a/packages/cubejs-backend-shared/package.json +++ b/packages/cubejs-backend-shared/package.json @@ -42,7 +42,7 @@ "decompress": "^4.2.1", "env-var": "^6.3.0", "fs-extra": "^9.1.0", - "http-proxy-agent": "^4.0.1", + "proxy-agent": "^6.4.0", "moment-range": "^4.0.1", "moment-timezone": "^0.5.33", "node-fetch": "^2.6.1", diff --git a/packages/cubejs-backend-shared/src/proxy.ts b/packages/cubejs-backend-shared/src/proxy.ts index 5f7ace5a654ad..923d41b6cf847 100644 --- a/packages/cubejs-backend-shared/src/proxy.ts +++ b/packages/cubejs-backend-shared/src/proxy.ts @@ -1,5 +1,5 @@ import { exec } from 'child_process'; -import HttpsProxyAgent from 'http-proxy-agent'; +import { ProxyAgent } from 'proxy-agent'; function getCommandOutput(command: string) { return new Promise((resolve, reject) => { @@ -14,6 +14,7 @@ function getCommandOutput(command: string) { }); } +// deprecated, use ProxyAgent instead export async function getProxySettings() { const [proxy] = ( await Promise.all([getCommandOutput('npm config -g get https-proxy'), getCommandOutput('npm config -g get proxy')]) @@ -25,7 +26,5 @@ export async function getProxySettings() { } export async function getHttpAgentForProxySettings() { - const proxy = await getProxySettings(); - - return proxy ? HttpsProxyAgent(proxy) : undefined; + return new ProxyAgent(); }