mirror of
https://github.com/binaricat/Netcatty.git
synced 2026-10-09 15:58:34 +00:00
5a78ebcf7c
The dedupe in startSession.cjs runs under `with(ctx)`, where ctx is wired with sshBridge.cjs's own local findDefaultPrivateKey / findAllDefaultPrivateKeys — not the sshAuthHelper.cjs copies. The characterization test targeted the helper's exports, which the connect path never calls (sshAuthHelper.findDefaultPrivateKey has no production consumers at all), so it gave false confidence and the in-code comment pointed at the wrong test. Expose the local pair as _findDefaultPrivateKey / _findAllDefaultPrivateKeys (matching the existing _-prefixed test-export convention) and retarget the test at them, so it actually guards the path the optimization depends on. Behavior is unchanged; the two local functions are verified equivalent. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
102 lines
3.7 KiB
JavaScript
102 lines
3.7 KiB
JavaScript
"use strict";
|
|
|
|
// Characterization test pinning the property that `startSession.cjs` relies on
|
|
// after the connection-startup optimization: the single preferred default key
|
|
// equals `findAllDefaultPrivateKeys()[0]`, so the connect path can derive it
|
|
// from the (already-needed) full list instead of scanning ~/.ssh a second time.
|
|
//
|
|
// These are the *local* sshBridge functions actually wired into startSession via
|
|
// `with(ctx)` (sshBridge.cjs passes its own findDefaultPrivateKey /
|
|
// findAllDefaultPrivateKeys into createStartSessionApi), exposed here as
|
|
// `_findDefaultPrivateKey` / `_findAllDefaultPrivateKeys`. Testing the helper's
|
|
// copy would prove nothing about the path the change runs on.
|
|
|
|
const test = require("node:test");
|
|
const assert = require("node:assert");
|
|
const fs = require("node:fs");
|
|
const os = require("node:os");
|
|
const path = require("node:path");
|
|
|
|
const {
|
|
_findDefaultPrivateKey: findDefaultPrivateKey,
|
|
_findAllDefaultPrivateKeys: findAllDefaultPrivateKeys,
|
|
} = require("./sshBridge.cjs");
|
|
|
|
const UNENCRYPTED = (tag) =>
|
|
`-----BEGIN RSA PRIVATE KEY-----\nMIIBOgIBAAJBAK${tag}fakebody\n-----END RSA PRIVATE KEY-----\n`;
|
|
const ENCRYPTED =
|
|
"-----BEGIN ENCRYPTED PRIVATE KEY-----\nMIIBfake\n-----END ENCRYPTED PRIVATE KEY-----\n";
|
|
|
|
async function withFakeSshDir(files, run) {
|
|
const home = fs.mkdtempSync(path.join(os.tmpdir(), "netcatty-default-key-"));
|
|
const sshDir = path.join(home, ".ssh");
|
|
fs.mkdirSync(sshDir);
|
|
for (const [name, content] of Object.entries(files)) {
|
|
fs.writeFileSync(path.join(sshDir, name), content);
|
|
}
|
|
const originalHomedir = os.homedir;
|
|
os.homedir = () => home;
|
|
try {
|
|
return await run();
|
|
} finally {
|
|
os.homedir = originalHomedir;
|
|
fs.rmSync(home, { recursive: true, force: true });
|
|
}
|
|
}
|
|
|
|
// The refactor replaces `await findDefaultPrivateKey()` with `allDefaultKeys[0] ?? null`.
|
|
async function assertEquivalent() {
|
|
const single = await findDefaultPrivateKey();
|
|
const all = await findAllDefaultPrivateKeys();
|
|
assert.deepStrictEqual(single, all[0] ?? null);
|
|
return { single, all };
|
|
}
|
|
|
|
test("default key equals first of all default keys with mixed key files", async () => {
|
|
await withFakeSshDir(
|
|
{
|
|
id_ed25519: UNENCRYPTED("ed"),
|
|
id_ecdsa: ENCRYPTED, // preferred but encrypted -> skipped by both
|
|
id_rsa: UNENCRYPTED("rsa"),
|
|
id_custom: UNENCRYPTED("custom"),
|
|
id_notakey: "this is not a private key",
|
|
config: "Host *\n", // does not match id_* pattern -> ignored
|
|
},
|
|
async () => {
|
|
const { single, all } = await assertEquivalent();
|
|
// Preferred unencrypted key wins.
|
|
assert.strictEqual(single.keyName, "id_ed25519");
|
|
// Encrypted + non-key files are excluded from the full list.
|
|
assert.deepStrictEqual(
|
|
all.map((k) => k.keyName),
|
|
["id_ed25519", "id_rsa", "id_custom"],
|
|
);
|
|
// Returned shape is what the auth fallback consumes.
|
|
assert.deepStrictEqual(Object.keys(single).sort(), [
|
|
"keyName",
|
|
"keyPath",
|
|
"privateKey",
|
|
]);
|
|
},
|
|
);
|
|
});
|
|
|
|
test("both resolve to null/empty when only encrypted keys are present", async () => {
|
|
await withFakeSshDir({ id_ed25519: ENCRYPTED, id_rsa: ENCRYPTED }, async () => {
|
|
const { single, all } = await assertEquivalent();
|
|
assert.strictEqual(single, null);
|
|
assert.strictEqual(all.length, 0);
|
|
});
|
|
});
|
|
|
|
test("preferred ordering: a non-preferred key never wins over a preferred one", async () => {
|
|
await withFakeSshDir(
|
|
{ id_aaa_custom: UNENCRYPTED("aaa"), id_rsa: UNENCRYPTED("rsa") },
|
|
async () => {
|
|
const { single } = await assertEquivalent();
|
|
// id_rsa is in PREFERRED_KEY_NAMES; id_aaa_custom is not, despite sorting first.
|
|
assert.strictEqual(single.keyName, "id_rsa");
|
|
},
|
|
);
|
|
});
|