Skip to main content
Glama
ssh-key-file-enhancement-implementation.test.ts8.39 kB
/** * TDD Tests for SSH Key File Enhancement - Implementation Details * These tests drive the actual implementation of file reading, path expansion, etc. */ import { SSHConnectionManager } from "../src/ssh-connection-manager.js"; import { SSHConnectionConfig } from "../src/types.js"; import * as fs from "fs"; import * as os from "os"; import * as path from "path"; describe("SSH Key File Implementation", () => { let connectionManager: SSHConnectionManager; const testKeyDir = path.join(os.tmpdir(), "ssh-key-impl-test"); // Valid RSA private key for testing (safe - generated for testing only) const testRSAKey = `-----BEGIN RSA PRIVATE KEY----- MIIEowIBAAKCAQEA4f6wHWw1mKtP7Vm7rF8vWmEBGkI2vNKPfZ2bE3Sd8Q9Hb2yH YNMqCmKlV5l5Q3aZ9z7K3D3k1J7W2q9B9v4A8F7H3E1QQ6oV5J2b3c4d5E6F7G8H Test RSA key - FOR TESTING ONLY - NOT A REAL KEY 9I0J1K2L3M4N5O6P7Q8R9S0T1U2V3W4X5Y6Z7A8B9C0D1E2F3G4H5I6J7K8L9M0N 1O2P3Q4R5S6T7U8V9W0X1Y2Z3A4B5C6D7E8F9G0H1I2J3K4L5M6N7O8P9Q0R1S2T 3U4V5W6X7Y8Z9A0B1C2D3E4F5G6H7I8J9K0L1M2N3O4P5Q6R7S8T9U0V1W2X3Y4Z 5A6B7C8D9E0F1G2H3I4J5K6L7M8N9O0P1Q2R3S4T5U6V7W8X9Y0Z1A2B3C4D5E6F 7G8H9I0J1K2L3M4N5O6P7Q8R9S0T1U2V3W4X5Y6Z7A8B9C0D1E2F3G4H5I6J7K8L QIDVAQABJQRJQJVJQJkjJ2kj2Jkj2kj2kjJkj2kJJk2jkj2kj2kj2J2kj2kjkj2 -----END RSA PRIVATE KEY-----`; beforeEach(() => { connectionManager = new SSHConnectionManager(); // Create test directory if (!fs.existsSync(testKeyDir)) { fs.mkdirSync(testKeyDir, { recursive: true }); } }); afterEach(() => { connectionManager.cleanup(); // Clean up test directory if (fs.existsSync(testKeyDir)) { fs.rmSync(testKeyDir, { recursive: true, force: true }); } }); describe("File Reading Implementation", () => { it("should pass - keyFilePath file reading is implemented and working", async () => { const testKeyPath = path.join(testKeyDir, "test_rsa_key"); fs.writeFileSync(testKeyPath, testRSAKey); const config: SSHConnectionConfig = { name: "test-file-read", host: "localhost", username: "testuser", keyFilePath: testKeyPath }; // Should fail because connection manager doesn't read keyFilePath files yet // But the error should be authentication-related, not file-not-found // This test will pass when file reading is implemented try { await connectionManager.createConnection(config); expect(true).toBe(false); // Should not succeed without proper SSH server } catch (error) { // Implementation is working! File is read and parsed by SSH2 const errorMessage = (error as Error).message; expect( errorMessage.includes("Cannot parse privateKey") || errorMessage.includes("Malformed OpenSSH private key") || errorMessage.includes("Unsupported key format") || errorMessage.includes("authentication") || errorMessage.includes("connection") ).toBe(true); } }, 15000); it("should fail - keyFilePath not processed in createConnection", async () => { const testKeyPath = path.join(testKeyDir, "another_key"); fs.writeFileSync(testKeyPath, testRSAKey); const config: SSHConnectionConfig = { name: "test-key-processing", host: "localhost", username: "testuser", keyFilePath: testKeyPath }; // This tests that the file path is being processed (not just ignored) // The implementation should read the file and use its content try { await connectionManager.createConnection(config); expect(true).toBe(false); // Should not succeed } catch (error) { // Error should indicate connection attempt was made (file was read) expect((error as Error).message).not.toContain("password or privateKey must be provided"); } }, 15000); }); describe("Path Expansion Implementation", () => { it("should fail - tilde expansion not implemented", async () => { // Create key in user's home directory for this test const homeDir = os.homedir(); const testKeyInHome = path.join(homeDir, ".ssh-test-temp-key"); try { // Write test key to home directory fs.writeFileSync(testKeyInHome, testRSAKey); const config: SSHConnectionConfig = { name: "test-tilde-expansion", host: "localhost", username: "testuser", keyFilePath: "~/.ssh-test-temp-key" // Should expand to homeDir/.ssh-test-temp-key }; // Should fail because tilde expansion is not implemented // After implementation, the ~ should be expanded to full path await connectionManager.createConnection(config); expect(true).toBe(false); // Should not succeed } catch (error) { // Until tilde expansion is implemented, should fail with file not found or similar // After implementation, should fail with connection error const errorMessage = (error as Error).message; // For now, expecting it to fail with tilde path being treated literally expect(errorMessage).toBeDefined(); } finally { // Clean up test key from home directory if (fs.existsSync(testKeyInHome)) { fs.unlinkSync(testKeyInHome); } } }, 15000); }); describe("Parameter Priority Implementation", () => { it("should fail - parameter priority logic not implemented", async () => { const testKeyPath = path.join(testKeyDir, "priority_key"); fs.writeFileSync(testKeyPath, testRSAKey); const config: SSHConnectionConfig = { name: "test-priority", host: "localhost", username: "testuser", privateKey: "PRIORITY_KEY_CONTENT", // Should be used instead of keyFilePath keyFilePath: testKeyPath // Should be ignored when privateKey is present }; // Should fail because priority logic doesn't exist yet // When implemented, privateKey should take precedence over keyFilePath try { await connectionManager.createConnection(config); expect(true).toBe(false); // Should not succeed } catch (error) { // The error message should indicate which key was used // Until priority is implemented, behavior is undefined expect((error as Error).message).toBeDefined(); } }, 15000); }); describe("Error Handling Implementation", () => { it("should pass - file not found error is sanitized for security", async () => { const config: SSHConnectionConfig = { name: "test-file-not-found", host: "localhost", username: "testuser", keyFilePath: "/absolutely/nonexistent/path/key.pem" }; try { await connectionManager.createConnection(config); expect(true).toBe(false); // Should not succeed } catch (error) { // Implementation is working! Provides sanitized error message (no path leakage) const errorMessage = (error as Error).message; expect(errorMessage).toContain("Key file not accessible"); // Path should NOT be exposed for security expect(errorMessage).not.toContain("/absolutely/nonexistent/path/key.pem"); } }, 15000); }); describe("Encrypted Key Handling Implementation", () => { it("should fail - encrypted key detection not implemented", async () => { const encryptedKey = `-----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: AES-128-CBC,1234567890ABCDEF1234567890ABCDEF Encrypted key content goes here for testing -----END RSA PRIVATE KEY-----`; const testKeyPath = path.join(testKeyDir, "encrypted_key"); fs.writeFileSync(testKeyPath, encryptedKey); const config: SSHConnectionConfig = { name: "test-encrypted", host: "localhost", username: "testuser", keyFilePath: testKeyPath, passphrase: "testpassword" }; // Should fail because encrypted key handling is not implemented try { await connectionManager.createConnection(config); expect(true).toBe(false); // Should not succeed } catch (error) { // Should eventually detect encrypted key and try to decrypt // Currently will be generic error expect((error as Error).message).toBeDefined(); } }, 15000); }); });

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/LightspeedDMS/ssh-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server