feat(pi-ssh): support SSH agent authentication

This commit is contained in:
云服务部-叶林立
2026-08-26 20:01:45 +08:00
parent b7758b239e
commit 874d4da096
10 changed files with 98 additions and 22 deletions
+13 -2
View File
@@ -13,7 +13,12 @@ export interface PrivateKeyAuthConfig {
passphrase?: string;
}
export type SshAuthConfig = PasswordAuthConfig | PrivateKeyAuthConfig;
export interface AgentAuthConfig {
type: "agent";
socketPath: string;
}
export type SshAuthConfig = PasswordAuthConfig | PrivateKeyAuthConfig | AgentAuthConfig;
export interface SshHostConfig {
label?: string;
@@ -108,7 +113,13 @@ function validateAuth(value: unknown, name: string): SshAuthConfig {
...(auth.passphrase === undefined ? {} : { passphrase: nonEmptyString(auth.passphrase, `${name}.passphrase`) }),
};
}
throw new Error(`${name}.type must be password or private-key`);
if (auth.type === "agent") {
return {
type: "agent",
socketPath: nonEmptyString(auth.socketPath, `${name}.socketPath`),
};
}
throw new Error(`${name}.type must be password, private-key, or agent`);
}
function validateHost(value: unknown, name: string): SshHostConfig {
+12
View File
@@ -37,6 +37,18 @@ export function effectiveValues(config: EffectiveSshConfig, key: string): string
return config.get(key.toLowerCase()) ?? [];
}
export function effectiveIdentityAgent(
config: EffectiveSshConfig,
env: NodeJS.ProcessEnv = process.env,
): string | undefined {
const configured = effectiveValue(config, "identityagent")?.replace(/^"|"$/g, "");
if (!configured || configured.toLowerCase() === "none") return undefined;
if (configured === "SSH_AUTH_SOCK" || configured === "$SSH_AUTH_SOCK" || configured === "${SSH_AUTH_SOCK}") {
return env.SSH_AUTH_SOCK;
}
return configured;
}
export function listDirectSshAliases(configPath = join(homedir(), ".ssh", "config")): string[] {
if (!existsSync(configPath)) return [];
const aliases: string[] = [];
+1
View File
@@ -8,6 +8,7 @@ declare module "ssh2" {
username: string;
password?: string;
privateKey?: Buffer | string;
agent?: string;
passphrase?: string;
tryKeyboard?: boolean;
readyTimeout?: number;
+3 -1
View File
@@ -128,9 +128,11 @@ function buildConnectConfig(host: SshHostConfig): ConnectConfig {
if (host.auth.type === "password") {
config.password = host.auth.password;
config.tryKeyboard = host.auth.method !== "password";
} else {
} else if (host.auth.type === "private-key") {
config.privateKey = readFileSync(expandUserPath(host.auth.identityFile));
if (host.auth.passphrase) config.passphrase = host.auth.passphrase;
} else {
config.agent = host.auth.socketPath === "pageant" ? "pageant" : expandUserPath(host.auth.socketPath);
}
return config;
}