/** * [ref]([ref];clay 裁定 **[ref]** 形:「响亮警告继续连」)—— SSH lane 的**主机密钥校验**两旋钮。 * * ## 病灶(修前逐字形) * `connectOnce` 的 `ConnectConfig` 从来不设 `hostVerifier`,而 ssh2 在缺席时**不做任何主机密钥校验** —— * 这条 lane 于是恒等于 `ssh -o StrictHostKeyChecking=no`:握手对面是谁都照连、照把 agent 的命令与 * sftp 写入交出去。适配器持有的是控制面注入的私钥([ref] §5 #2),中间人拿不到私钥,但**拿得到 * 这次会话的全部命令、全部产物、以及 agent 在那台机器上的全部动作**。 * * ## 为什么不是「一律拒连」(裁定形) * 本 lane 的既有部署形是「AI 编排批量部署到一批 SSH 可达的机器」,那些机器的密钥指纹通常不在任何 * known_hosts 里。默认拒连 = 一次静默的**可用性**断裂,而 [ref] 裁的是:**在场即严格,缺席即响亮**。 * 缺席那一格是登记在案的 fail-open(`server.exec-lane.ssh-host-key-unverified`,census §1),不是遗漏。 * * ## 两旋钮(config 面 `SSH_HOST_FINGERPRINT` / `SSH_KNOWN_HOSTS`,坏值拒启 —— [ref] 律) * · `fingerprintSha256` —— 主机公钥的 **SHA256 base64** 指纹(`ssh-keyscan` + `ssh-keygen -lf` 打印的 * 那一串)。归一后存**裸 base64**(无 `SHA256:` 前缀、无 `=` 填充); * · `knownHostsPath` —— known_hosts 文件路径,按 `host` / `[host]:port` **逐字**匹配行。 * * **两只同时在场 = 合取**(都必须过)。任一在场 ⇒ 严格校验,不符**拒连**;两只都缺席 ⇒ 每连接一条 * 响亮 warn + 计数,照常连。 * * ## 明确**不支持**的 known_hosts 语法(成文,不是遗漏 —— 遇到即拒连并在拒因里说清) * · **hashed 行**(`|1||`,`ssh-keyscan -H` / `HashKnownHosts yes` 的产物):要按 HMAC-SHA1 * 反查主机名,而本适配器刻意不实现那一步(它把「读一个文件、比一串字节」变成一个需要自己实现 * OpenSSH 私有派生的解析器)。⇒ hashed 行一律**跳过**;若某台机器只有 hashed 行,结果是**拒连** * (fail-closed,不是悄悄放行),拒因里逐字点名这一条并给出 `ssh-keyscan` 指路; * · **通配符 pattern**(`*.example.com`、`!host` 取反):同上跳过 ⇒ 只有通配符行的主机会被拒连; * · **`@cert-authority` 行**:证书信任链本适配器不实现 ⇒ 跳过(同样是拒连方向)。 * · **`@revoked` 行**:不跳过 —— 匹配上就是**硬拒**(吊销是收紧方向,跳过它才是 fail-open)。 */ export interface SshHostKeyPolicy { /** 归一后的**裸 base64** SHA256 指纹(无 `SHA256:` 前缀、无 `=` 填充)。 */ fingerprintSha256?: string; /** known_hosts 文件路径。 */ knownHostsPath?: string; } /** {@link createSshHostKeyVerifier} 的判词。`verified:false` = 两旋钮都缺席那一格(照连,但响亮)。 */ export type SshHostKeyVerdict = { ok: true; verified: boolean; } | { ok: false; reason: string; }; /** SHA256 base64 指纹的**归一**:`SHA256:` 前缀可选、`=` 填充可选;形不合 ⇒ **抛**(调用方在 boot 期拒启)。 */ export declare function normalizeSshFingerprint(raw: string): string; /** ssh2 交来的**主机公钥 wire blob** → `SHA256:`(OpenSSH 打印的同一形,无 `=` 填充)。 */ export declare function sshHostKeyFingerprint(key: Buffer): string; /** * 主机密钥判官([ref] / [ref])。返回一个**收 ssh2 的公钥 blob、给判词**的闭包(有捕获行为 ⇒ `create*`)。 * * 缺席那一格调用 `onUnverified` —— **每连接一次**,不是每进程一次:一台长期未配旋钮的机器上, * 「这条 lane 一直在裸连」必须在每一条连接上都看得见,否则它会随第一条日志滚出视野。 */ export declare function createSshHostKeyVerifier(opts: { host: string; port: number; policy?: SshHostKeyPolicy; /** 测试缝:替掉 known_hosts 的读盘(缺省 `readFileSync`)。 */ readKnownHosts?: (p: string) => string; /** 两旋钮全缺席时的响亮口(缺省 = 本模块 logger 的一条 warn + fail-open 计数)。 */ onUnverified?: (message: string) => void; }): (key: Buffer) => SshHostKeyVerdict; //# sourceMappingURL=ssh-host-key.d.ts.map