diff --git a/packages/automl/frontend/config/webpack.dev.js b/packages/automl/frontend/config/webpack.dev.js index 6dacbc8066..f192651d04 100644 --- a/packages/automl/frontend/config/webpack.dev.js +++ b/packages/automl/frontend/config/webpack.dev.js @@ -28,35 +28,56 @@ const DEPLOYMENT_MODE = process.env._DEPLOYMENT_MODE; const AUTH_METHOD = process.env._AUTH_METHOD; const BASE_PATH = DEPLOYMENT_MODE === 'kubeflow' ? '/automl/' : PUBLIC_PATH; +// Get the kubeconfig token at startup as a fallback for standalone dev mode. +const getKubeconfigToken = () => { + try { + const token = execSync( + "kubectl config view --raw --minify --flatten -o jsonpath='{.users[].user.token}'", + ) + .toString() + .trim(); + const username = execSync("kubectl auth whoami -o jsonpath='{.status.userInfo.username}'") + .toString() + .trim(); + console.info('Logged in as user:', username); + return token; + } catch (error) { + console.error('Failed to get Kubernetes token:', error.message); + return ''; + } +}; + +const fallbackToken = AUTH_METHOD === 'user_token' ? getKubeconfigToken() : ''; + +// Build static proxy headers for auth methods that don't need dynamic forwarding. const getProxyHeaders = () => { if (AUTH_METHOD === 'internal') { return { 'kubeflow-userid': 'user@example.com', }; } - if (AUTH_METHOD === 'user_token') { - try { - const token = execSync( - "kubectl config view --raw --minify --flatten -o jsonpath='{.users[].user.token}'", - ) - .toString() - .trim(); - const username = execSync("kubectl auth whoami -o jsonpath='{.status.userInfo.username}'") - .toString() - .trim(); - console.info('Logged in as user:', username); - return { - Authorization: `Bearer ${token}`, - 'x-forwarded-access-token': token, - }; - } catch (error) { - console.error('Failed to get Kubernetes token:', error.message); - return {}; - } - } + // For user_token, auth headers are set dynamically in onProxyReq below. return {}; }; +// When using user_token auth, dynamically forward the authorization header from the +// incoming request if present (e.g. from a host backend proxy with dev impersonation). +// Fall back to the kubeconfig token captured at startup for standalone dev mode. +const onProxyReq = (proxyReq, req) => { + if (AUTH_METHOD !== 'user_token') { + return; + } + const incomingAuth = req.headers.authorization; + if (incomingAuth) { + proxyReq.setHeader('Authorization', incomingAuth); + const token = incomingAuth.replace(/^Bearer\s+/i, ''); + proxyReq.setHeader('x-forwarded-access-token', token); + } else if (fallbackToken) { + proxyReq.setHeader('Authorization', `Bearer ${fallbackToken}`); + proxyReq.setHeader('x-forwarded-access-token', fallbackToken); + } +}; + module.exports = smp.wrap( merge( { @@ -89,6 +110,7 @@ module.exports = smp.wrap( target: `${PROXY_PROTOCOL}://${PROXY_HOST}:${PROXY_PORT}`, changeOrigin: true, headers: getProxyHeaders(), + onProxyReq, }, ], devMiddleware: { diff --git a/packages/autorag/frontend/config/webpack.dev.js b/packages/autorag/frontend/config/webpack.dev.js index aefedb79c9..515ef8d1bf 100644 --- a/packages/autorag/frontend/config/webpack.dev.js +++ b/packages/autorag/frontend/config/webpack.dev.js @@ -28,35 +28,56 @@ const DEPLOYMENT_MODE = process.env._DEPLOYMENT_MODE; const AUTH_METHOD = process.env._AUTH_METHOD; const BASE_PATH = DEPLOYMENT_MODE === 'kubeflow' ? '/autorag/' : PUBLIC_PATH; +// Get the kubeconfig token at startup as a fallback for standalone dev mode. +const getKubeconfigToken = () => { + try { + const token = execSync( + "kubectl config view --raw --minify --flatten -o jsonpath='{.users[].user.token}'", + ) + .toString() + .trim(); + const username = execSync("kubectl auth whoami -o jsonpath='{.status.userInfo.username}'") + .toString() + .trim(); + console.info('Logged in as user:', username); + return token; + } catch (error) { + console.error('Failed to get Kubernetes token:', error.message); + return ''; + } +}; + +const fallbackToken = AUTH_METHOD === 'user_token' ? getKubeconfigToken() : ''; + +// Build static proxy headers for auth methods that don't need dynamic forwarding. const getProxyHeaders = () => { if (AUTH_METHOD === 'internal') { return { 'kubeflow-userid': 'user@example.com', }; } - if (AUTH_METHOD === 'user_token') { - try { - const token = execSync( - "kubectl config view --raw --minify --flatten -o jsonpath='{.users[].user.token}'", - ) - .toString() - .trim(); - const username = execSync("kubectl auth whoami -o jsonpath='{.status.userInfo.username}'") - .toString() - .trim(); - console.info('Logged in as user:', username); - return { - Authorization: `Bearer ${token}`, - 'x-forwarded-access-token': token, - }; - } catch (error) { - console.error('Failed to get Kubernetes token:', error.message); - return {}; - } - } + // For user_token, auth headers are set dynamically in onProxyReq below. return {}; }; +// When using user_token auth, dynamically forward the authorization header from the +// incoming request if present (e.g. from a host backend proxy with dev impersonation). +// Fall back to the kubeconfig token captured at startup for standalone dev mode. +const onProxyReq = (proxyReq, req) => { + if (AUTH_METHOD !== 'user_token') { + return; + } + const incomingAuth = req.headers.authorization; + if (incomingAuth) { + proxyReq.setHeader('Authorization', incomingAuth); + const token = incomingAuth.replace(/^Bearer\s+/i, ''); + proxyReq.setHeader('x-forwarded-access-token', token); + } else if (fallbackToken) { + proxyReq.setHeader('Authorization', `Bearer ${fallbackToken}`); + proxyReq.setHeader('x-forwarded-access-token', fallbackToken); + } +}; + module.exports = smp.wrap( merge( { @@ -93,6 +114,7 @@ module.exports = smp.wrap( }, changeOrigin: true, headers: getProxyHeaders(), + onProxyReq, }, ], devMiddleware: { diff --git a/packages/eval-hub/frontend/config/webpack.dev.js b/packages/eval-hub/frontend/config/webpack.dev.js index f97ae27fdf..8fb9214721 100644 --- a/packages/eval-hub/frontend/config/webpack.dev.js +++ b/packages/eval-hub/frontend/config/webpack.dev.js @@ -29,35 +29,56 @@ const DEPLOYMENT_MODE = process.env._DEPLOYMENT_MODE; const AUTH_METHOD = process.env._AUTH_METHOD; const BASE_PATH = DEPLOYMENT_MODE === 'kubeflow' ? '/eval-hub/' : PUBLIC_PATH; +// Get the kubeconfig token at startup as a fallback for standalone dev mode. +const getKubeconfigToken = () => { + try { + const token = execSync( + "kubectl config view --raw --minify --flatten -o jsonpath='{.users[].user.token}'", + ) + .toString() + .trim(); + const username = execSync("kubectl auth whoami -o jsonpath='{.status.userInfo.username}'") + .toString() + .trim(); + console.info('Logged in as user:', username); + return token; + } catch (error) { + console.error('Failed to get Kubernetes token:', error.message); + return ''; + } +}; + +const fallbackToken = AUTH_METHOD === 'user_token' ? getKubeconfigToken() : ''; + +// Build static proxy headers for auth methods that don't need dynamic forwarding. const getProxyHeaders = () => { if (AUTH_METHOD === 'internal') { return { 'kubeflow-userid': 'user@example.com', }; } - if (AUTH_METHOD === 'user_token') { - try { - const token = execSync( - "kubectl config view --raw --minify --flatten -o jsonpath='{.users[].user.token}'", - ) - .toString() - .trim(); - const username = execSync("kubectl auth whoami -o jsonpath='{.status.userInfo.username}'") - .toString() - .trim(); - console.info('Logged in as user:', username); - return { - Authorization: `Bearer ${token}`, - 'x-forwarded-access-token': token, - }; - } catch (error) { - console.error('Failed to get Kubernetes token:', error.message); - return {}; - } - } + // For user_token, auth headers are set dynamically in onProxyReq below. return {}; }; +// When using user_token auth, dynamically forward the authorization header from the +// incoming request if present (e.g. from a host backend proxy with dev impersonation). +// Fall back to the kubeconfig token captured at startup for standalone dev mode. +const onProxyReq = (proxyReq, req) => { + if (AUTH_METHOD !== 'user_token') { + return; + } + const incomingAuth = req.headers.authorization; + if (incomingAuth) { + proxyReq.setHeader('Authorization', incomingAuth); + const token = incomingAuth.replace(/^Bearer\s+/i, ''); + proxyReq.setHeader('x-forwarded-access-token', token); + } else if (fallbackToken) { + proxyReq.setHeader('Authorization', `Bearer ${fallbackToken}`); + proxyReq.setHeader('x-forwarded-access-token', fallbackToken); + } +}; + module.exports = smp.wrap( merge( { @@ -94,6 +115,7 @@ module.exports = smp.wrap( }, changeOrigin: true, headers: getProxyHeaders(), + onProxyReq, }, { context: ['/mlflow'], @@ -104,6 +126,7 @@ module.exports = smp.wrap( }, changeOrigin: true, headers: getProxyHeaders(), + onProxyReq, }, ], devMiddleware: { diff --git a/packages/gen-ai/frontend/config/webpack.dev.js b/packages/gen-ai/frontend/config/webpack.dev.js index fc2604fd33..02a8f98314 100644 --- a/packages/gen-ai/frontend/config/webpack.dev.js +++ b/packages/gen-ai/frontend/config/webpack.dev.js @@ -18,24 +18,39 @@ const DIST_DIR = process.env._DIST_DIR; const PUBLIC_PATH = process.env._PUBLIC_PATH; const AUTH_METHOD = process.env._AUTH_METHOD; -const getProxyHeaders = () => { - if (AUTH_METHOD === 'user_token') { - try { - const token = execSync('oc whoami --show-token').toString().trim(); - const username = execSync('oc whoami').toString().trim(); - // eslint-disable-next-line no-console - console.info('Logged in as user:', username); - return { - Authorization: `Bearer ${token}`, - 'x-forwarded-access-token': token, - }; - } catch (error) { - // eslint-disable-next-line no-console - console.error('Failed to get Kubernetes token:', error.message); - return {}; - } +// Get the oc token at startup as a fallback for standalone dev mode. +const getOcToken = () => { + try { + const token = execSync('oc whoami --show-token').toString().trim(); + const username = execSync('oc whoami').toString().trim(); + // eslint-disable-next-line no-console + console.info('Logged in as user:', username); + return token; + } catch (error) { + // eslint-disable-next-line no-console + console.error('Failed to get Kubernetes token:', error.message); + return ''; + } +}; + +const fallbackToken = AUTH_METHOD === 'user_token' ? getOcToken() : ''; + +// When using user_token auth, dynamically forward the authorization header from the +// incoming request if present (e.g. from a host backend proxy with dev impersonation). +// Fall back to the oc token captured at startup for standalone dev mode. +const onProxyReq = (proxyReq, req) => { + if (AUTH_METHOD !== 'user_token') { + return; + } + const incomingAuth = req.headers.authorization; + if (incomingAuth) { + proxyReq.setHeader('Authorization', incomingAuth); + const token = incomingAuth.replace(/^Bearer\s+/i, ''); + proxyReq.setHeader('x-forwarded-access-token', token); + } else if (fallbackToken) { + proxyReq.setHeader('Authorization', `Bearer ${fallbackToken}`); + proxyReq.setHeader('x-forwarded-access-token', fallbackToken); } - return {}; }; module.exports = merge( @@ -82,7 +97,7 @@ module.exports = merge( protocol: PROXY_PROTOCOL, }, changeOrigin: true, - headers: getProxyHeaders(), + onProxyReq, }, ], }, diff --git a/packages/maas/frontend/config/webpack.dev.js b/packages/maas/frontend/config/webpack.dev.js index c0ddcf4b2e..905a71ce5f 100644 --- a/packages/maas/frontend/config/webpack.dev.js +++ b/packages/maas/frontend/config/webpack.dev.js @@ -28,34 +28,56 @@ const DEPLOYMENT_MODE = process.env._DEPLOYMENT_MODE; const AUTH_METHOD = process.env._AUTH_METHOD; const BASE_PATH = DEPLOYMENT_MODE === 'kubeflow' ? '/mod-arch/' : PUBLIC_PATH; +// Get the kubeconfig token at startup as a fallback for standalone dev mode. +const getKubeconfigToken = () => { + try { + const token = execSync( + "kubectl config view --raw --minify --flatten -o jsonpath='{.users[].user.token}'", + ) + .toString() + .trim(); + const username = execSync("kubectl auth whoami -o jsonpath='{.status.userInfo.username}'") + .toString() + .trim(); + console.info('Logged in as user:', username); + return token; + } catch (error) { + console.error('Failed to get Kubernetes token:', error.message); + return ''; + } +}; + +const fallbackToken = AUTH_METHOD === 'user_token' ? getKubeconfigToken() : ''; + +// Build static proxy headers for auth methods that don't need dynamic forwarding. const getProxyHeaders = () => { if (AUTH_METHOD === 'internal') { return { 'kubeflow-userid': 'user@example.com', }; } - if (AUTH_METHOD === 'user_token') { - try { - const token = execSync( - "kubectl config view --raw --minify --flatten -o jsonpath='{.users[].user.token}'", - ) - .toString() - .trim(); - const username = execSync("kubectl auth whoami -o jsonpath='{.status.userInfo.username}'") - .toString() - .trim(); - console.info('Logged in as user:', username); - return { - 'x-forwarded-access-token': token, - }; - } catch (error) { - console.error('Failed to get Kubernetes token:', error.message); - return {}; - } - } + // For user_token, auth headers are set dynamically in onProxyReq below. return {}; }; +// When using user_token auth, dynamically forward the authorization header from the +// incoming request if present (e.g. from a host backend proxy with dev impersonation). +// Fall back to the kubeconfig token captured at startup for standalone dev mode. +const onProxyReq = (proxyReq, req) => { + if (AUTH_METHOD !== 'user_token') { + return; + } + const incomingAuth = req.headers.authorization; + if (incomingAuth) { + proxyReq.setHeader('Authorization', incomingAuth); + const token = incomingAuth.replace(/^Bearer\s+/i, ''); + proxyReq.setHeader('x-forwarded-access-token', token); + } else if (fallbackToken) { + proxyReq.setHeader('Authorization', `Bearer ${fallbackToken}`); + proxyReq.setHeader('x-forwarded-access-token', fallbackToken); + } +}; + module.exports = smp.wrap( merge( { @@ -92,6 +114,7 @@ module.exports = smp.wrap( }, changeOrigin: true, headers: getProxyHeaders(), + onProxyReq, }, ], devMiddleware: { diff --git a/packages/mlflow/frontend/config/webpack.dev.js b/packages/mlflow/frontend/config/webpack.dev.js index e2f84fb938..e3714c794c 100644 --- a/packages/mlflow/frontend/config/webpack.dev.js +++ b/packages/mlflow/frontend/config/webpack.dev.js @@ -27,28 +27,43 @@ const ROOT_NODE_MODULES = path.resolve(RELATIVE_DIRNAME, '../../../node_modules' const AUTH_METHOD = process.env._AUTH_METHOD; const BASE_PATH = PUBLIC_PATH; -const getProxyHeaders = () => { - if (AUTH_METHOD === 'user_token') { - try { - const token = execSync( - "kubectl config view --raw --minify --flatten -o jsonpath='{.users[].user.token}'", - ) - .toString() - .trim(); - const username = execSync("kubectl auth whoami -o jsonpath='{.status.userInfo.username}'") - .toString() - .trim(); - console.info('Logged in as user:', username); - return { - Authorization: `Bearer ${token}`, - 'x-forwarded-access-token': token, - }; - } catch (error) { - console.error('Failed to get Kubernetes token:', error.message); - return {}; - } +// Get the kubeconfig token at startup as a fallback for standalone dev mode. +const getKubeconfigToken = () => { + try { + const token = execSync( + "kubectl config view --raw --minify --flatten -o jsonpath='{.users[].user.token}'", + ) + .toString() + .trim(); + const username = execSync("kubectl auth whoami -o jsonpath='{.status.userInfo.username}'") + .toString() + .trim(); + console.info('Logged in as user:', username); + return token; + } catch (error) { + console.error('Failed to get Kubernetes token:', error.message); + return ''; + } +}; + +const fallbackToken = AUTH_METHOD === 'user_token' ? getKubeconfigToken() : ''; + +// When using user_token auth, dynamically forward the authorization header from the +// incoming request if present (e.g. from a host backend proxy with dev impersonation). +// Fall back to the kubeconfig token captured at startup for standalone dev mode. +const onProxyReq = (proxyReq, req) => { + if (AUTH_METHOD !== 'user_token') { + return; + } + const incomingAuth = req.headers.authorization; + if (incomingAuth) { + proxyReq.setHeader('Authorization', incomingAuth); + const token = incomingAuth.replace(/^Bearer\s+/i, ''); + proxyReq.setHeader('x-forwarded-access-token', token); + } else if (fallbackToken) { + proxyReq.setHeader('Authorization', `Bearer ${fallbackToken}`); + proxyReq.setHeader('x-forwarded-access-token', fallbackToken); } - return {}; }; module.exports = smp.wrap( @@ -87,7 +102,7 @@ module.exports = smp.wrap( }, pathRewrite: { '^/_bff/mlflow/api': '/api' }, changeOrigin: true, - headers: getProxyHeaders(), + onProxyReq, }, ], devMiddleware: {