mirror of
https://github.com/stablyai/orca.git
synced 2026-10-28 08:02:54 +00:00
Improve SSH config target handling (#3899)
This commit is contained in:
@@ -343,6 +343,33 @@ describe('buildConnectConfig', () => {
|
||||
expect(config.username).toBe('admin')
|
||||
})
|
||||
|
||||
it('uses ssh -G HostName when a config-host target still points at its alias', () => {
|
||||
const config = buildConnectConfig(
|
||||
makeTarget({ label: 'workbox', configHost: 'workbox', host: 'workbox' }),
|
||||
makeResolved({ hostname: 'workbox.internal' })
|
||||
)
|
||||
|
||||
expect(config.host).toBe('workbox.internal')
|
||||
})
|
||||
|
||||
it('uses ssh -G Port when a config-host target still has the default port', () => {
|
||||
const config = buildConnectConfig(
|
||||
makeTarget({ configHost: 'workbox', host: 'workbox', port: 22 }),
|
||||
makeResolved({ port: 2202 })
|
||||
)
|
||||
|
||||
expect(config.port).toBe(2202)
|
||||
})
|
||||
|
||||
it('keeps explicit non-default target ports ahead of ssh -G Port', () => {
|
||||
const config = buildConnectConfig(
|
||||
makeTarget({ configHost: 'workbox', host: 'workbox', port: 2022 }),
|
||||
makeResolved({ port: 2202 })
|
||||
)
|
||||
|
||||
expect(config.port).toBe(2022)
|
||||
})
|
||||
|
||||
it('sets readyTimeout to CONNECT_TIMEOUT_MS', () => {
|
||||
const config = buildConnectConfig(makeTarget(), null)
|
||||
expect(config.readyTimeout).toBe(30_000)
|
||||
@@ -358,6 +385,26 @@ describe('buildConnectConfig', () => {
|
||||
expect(config.agent).toBe('/tmp/agent.sock')
|
||||
})
|
||||
|
||||
it('enables agent forwarding when OpenSSH config requests it and an agent is available', () => {
|
||||
const config = buildConnectConfig(makeTarget(), makeResolved({ forwardAgent: true }))
|
||||
|
||||
expect(config.agent).toBe('/tmp/agent.sock')
|
||||
expect(config.agentForward).toBe(true)
|
||||
})
|
||||
|
||||
it('does not enable agent forwarding without a usable agent', () => {
|
||||
const platformSpy = vi.spyOn(process, 'platform', 'get').mockReturnValue('linux')
|
||||
delete process.env.SSH_AUTH_SOCK
|
||||
|
||||
try {
|
||||
const config = buildConnectConfig(makeTarget(), makeResolved({ forwardAgent: true }))
|
||||
expect(config.agent).toBeUndefined()
|
||||
expect(config.agentForward).toBeUndefined()
|
||||
} finally {
|
||||
platformSpy.mockRestore()
|
||||
}
|
||||
})
|
||||
|
||||
it('uses configured IdentityAgent before SSH_AUTH_SOCK', () => {
|
||||
const config = buildConnectConfig(
|
||||
makeTarget(),
|
||||
|
||||
@@ -105,8 +105,8 @@ export function buildConnectConfig(
|
||||
resolved: SshResolvedConfig | null,
|
||||
options: BuildConnectConfigOptions = {}
|
||||
): ConnectConfig {
|
||||
const effectiveHost = target.host || resolved?.hostname || target.label
|
||||
const effectivePort = target.port || resolved?.port || 22
|
||||
const effectiveHost = resolveEffectiveHost(target, resolved)
|
||||
const effectivePort = resolveEffectivePort(target, resolved)
|
||||
const effectiveUser = target.username || resolved?.user || ''
|
||||
|
||||
const config: Record<string, unknown> = {
|
||||
@@ -125,6 +125,10 @@ export function buildConnectConfig(
|
||||
config.agent = agent
|
||||
}
|
||||
|
||||
if (agent && resolved?.forwardAgent) {
|
||||
config.agentForward = true
|
||||
}
|
||||
|
||||
const key =
|
||||
(options.includePrivateKey ?? !agent)
|
||||
? resolvePrivateKey(target, resolved)
|
||||
@@ -136,6 +140,30 @@ export function buildConnectConfig(
|
||||
return config as ConnectConfig
|
||||
}
|
||||
|
||||
function resolveEffectiveHost(target: SshTarget, resolved: SshResolvedConfig | null): string {
|
||||
if (shouldUseResolvedEndpoint(target, resolved)) {
|
||||
return resolved!.hostname
|
||||
}
|
||||
return target.host || resolved?.hostname || target.label
|
||||
}
|
||||
|
||||
function resolveEffectivePort(target: SshTarget, resolved: SshResolvedConfig | null): number {
|
||||
// Why: imported config aliases store 22 as the schema default even when an
|
||||
// included/wildcard OpenSSH rule later resolves a different effective Port.
|
||||
if (target.configHost && target.port === 22 && resolved?.port) {
|
||||
return resolved.port
|
||||
}
|
||||
return target.port || resolved?.port || 22
|
||||
}
|
||||
|
||||
function shouldUseResolvedEndpoint(target: SshTarget, resolved: SshResolvedConfig | null): boolean {
|
||||
if (!target.configHost || !resolved?.hostname) {
|
||||
return false
|
||||
}
|
||||
const host = target.host.trim()
|
||||
return host === '' || host === target.configHost || host === target.label
|
||||
}
|
||||
|
||||
// Why: ProxyJump and jumpHost are syntactic sugar for ProxyCommand.
|
||||
// OpenSSH internally converts `ProxyJump bastion` to
|
||||
// `ProxyCommand ssh -W %h:%p bastion`. We do the same so that ssh2
|
||||
|
||||
Reference in New Issue
Block a user