diff --git a/packages/cli/src/commands/env/metadata.ts b/packages/cli/src/commands/env/metadata.ts index c6d455d9..f706831e 100644 --- a/packages/cli/src/commands/env/metadata.ts +++ b/packages/cli/src/commands/env/metadata.ts @@ -92,6 +92,7 @@ export default class EnvMetadataCommand extends DriverCommand { onFailedAttempt: e => { this.logger.debug(`Failed to query tunnels: ${inspect(e)}`) }, }, fetchTimeout: flags['fetch-urls-timeout'], + log: this.logger, }), { text: 'Getting tunnel URLs...' }) const urls = await filterUrls({ diff --git a/packages/cli/src/commands/up.ts b/packages/cli/src/commands/up.ts index 108b91ec..fbe94ed4 100644 --- a/packages/cli/src/commands/up.ts +++ b/packages/cli/src/commands/up.ts @@ -210,6 +210,7 @@ export default class Up extends MachineCreationDriverCommand { retryOpts: urlsRetryOpts(this.logger), fetchTimeout: flags['fetch-urls-timeout'], waitForAllTunnels: flags.wait, + log: this.logger, }), { text: 'Getting tunnel URLs...' }) const urls = await filterUrls({ diff --git a/packages/cli/src/commands/urls.ts b/packages/cli/src/commands/urls.ts index dc965a06..02d71ce2 100644 --- a/packages/cli/src/commands/urls.ts +++ b/packages/cli/src/commands/urls.ts @@ -141,6 +141,7 @@ export default class Urls extends ProfileCommand { retryOpts: flags.wait ? urlsRetryOpts(this.logger) : noWaitUrlsRetryOpts, fetchTimeout: flags['fetch-urls-timeout'], waitForAllTunnels: flags.wait, + log: this.logger, }) const urls = await filterUrls({ diff --git a/packages/core/src/commands/urls.ts b/packages/core/src/commands/urls.ts index 3b6060d1..a3205be4 100644 --- a/packages/core/src/commands/urls.ts +++ b/packages/core/src/commands/urls.ts @@ -1,5 +1,5 @@ import retry from 'p-retry' -import { COMPOSE_TUNNEL_AGENT_SERVICE_NAME } from '@preevy/common' +import { COMPOSE_TUNNEL_AGENT_SERVICE_NAME, Logger } from '@preevy/common' import { generateBasicAuthCredentials, jwtGenerator } from '../credentials/index.js' import { queryTunnels } from '../compose-tunnel-agent-client.js' import { FlatTunnel, flattenTunnels } from '../tunneling/index.js' @@ -27,6 +27,7 @@ export const urls = async ({ composeTunnelServiceUrl, fetchTimeout, waitForAllTunnels, + log, }: { serviceAndPort?: { service: string; port?: number } tunnelingKey: string | Buffer @@ -36,6 +37,7 @@ export const urls = async ({ composeTunnelServiceUrl: string fetchTimeout: number waitForAllTunnels?: boolean + log: Logger }) => { const credentials = await generateBasicAuthCredentials(jwtGenerator(tunnelingKey)) @@ -46,6 +48,7 @@ export const urls = async ({ includeAccessCredentials, fetchTimeout, waitForAllTunnels, + log, }) return flattenTunnels(tunnels).filter(tunnelFilter({ serviceAndPort, showPreevyService })) diff --git a/packages/core/src/compose-tunnel-agent-client.ts b/packages/core/src/compose-tunnel-agent-client.ts index 3a8a0168..7457ddb0 100644 --- a/packages/core/src/compose-tunnel-agent-client.ts +++ b/packages/core/src/compose-tunnel-agent-client.ts @@ -3,7 +3,7 @@ import retry from 'p-retry' import { inspect } from 'util' import { createRequire } from 'module' import { mapValues, merge } from 'lodash-es' -import { COMPOSE_TUNNEL_AGENT_PORT, COMPOSE_TUNNEL_AGENT_SERVICE_LABELS, COMPOSE_TUNNEL_AGENT_SERVICE_NAME, ComposeTunnelAgentState, MachineStatusCommand, ScriptInjection, dateReplacer } from '@preevy/common' +import { COMPOSE_TUNNEL_AGENT_PORT, COMPOSE_TUNNEL_AGENT_SERVICE_LABELS, COMPOSE_TUNNEL_AGENT_SERVICE_NAME, ComposeTunnelAgentState, Logger, MachineStatusCommand, ScriptInjection, dateReplacer } from '@preevy/common' import { ComposeModel, ComposeService, composeModelFilename } from './compose/model.js' import { TunnelOpts } from './ssh/url.js' import { Tunnel } from './tunneling/index.js' @@ -161,6 +161,7 @@ export type ComposeTunnelAgentFetchOpts = { credentials: { user: string; password: string } retryOpts?: retry.Options fetchTimeout: number + log: Logger } export class AgentFetchError extends Error {} @@ -171,10 +172,15 @@ const fetchFromComposeTunnelAgent = async ({ credentials, fetchTimeout, pathAndQuery, + log, }: ComposeTunnelAgentFetchOpts & { pathAndQuery: string }) => await retry(async () => { + const headers = { Authorization: `Bearer ${credentials.password}` } + // TODO: sensitive data in logs for debugging, remove in release + log.debug(`Fetching from compose tunnel agent at ${composeTunnelServiceUrl}/${pathAndQuery}, headers: ${inspect(headers)}`) + const normalizedComposeTunnelServiceUrl = composeTunnelServiceUrl.replace(/\/$/, '') const r = await fetch( - `${composeTunnelServiceUrl}/${pathAndQuery}`, - { signal: AbortSignal.timeout(fetchTimeout), headers: { Authorization: `Bearer ${credentials.password}` } } + `${normalizedComposeTunnelServiceUrl}/${pathAndQuery}`, + { signal: AbortSignal.timeout(fetchTimeout), headers } ).catch(e => { throw new AgentFetchError(`Failed to connect to preevy agent at ${composeTunnelServiceUrl}: ${e}`, { cause: e }) }) if (!r.ok) { throw new AgentFetchError(`Failed to connect to preevy agent at ${composeTunnelServiceUrl}: ${r.status}: ${r.statusText}`)