Skip to content

Commit d29bf44

Browse files
committed
feat(cli): update SSH key deletion to use fingerprint
1 parent 7901e3a commit d29bf44

File tree

1 file changed

+40
-8
lines changed

1 file changed

+40
-8
lines changed

src/cli/ssh-key.ts

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import * as fs from 'fs';
44
import * as path from 'path';
55
import axios from 'axios';
6+
import { utils } from 'ssh2';
7+
import * as crypto from 'crypto';
68

79
const API_BASE_URL = process.env.GIT_PROXY_API_URL || 'http://localhost:3000';
810
const GIT_PROXY_COOKIE_FILE = path.join(
@@ -23,6 +25,23 @@ interface ErrorWithResponse {
2325
message: string;
2426
}
2527

28+
// Calculate SHA-256 fingerprint from SSH public key
29+
// Note: This function is duplicated in src/service/routes/users.js to keep CLI and server independent
30+
function calculateFingerprint(publicKeyStr: string): string | null {
31+
try {
32+
const parsed = utils.parseKey(publicKeyStr);
33+
if (!parsed || parsed instanceof Error) {
34+
return null;
35+
}
36+
const pubKey = parsed.getPublicSSH();
37+
const hash = crypto.createHash('sha256').update(pubKey).digest('base64');
38+
return `SHA256:${hash}`;
39+
} catch (err) {
40+
console.error('Error calculating fingerprint:', err);
41+
return null;
42+
}
43+
}
44+
2645
async function addSSHKey(username: string, keyPath: string): Promise<void> {
2746
try {
2847
// Check for authentication
@@ -90,15 +109,28 @@ async function removeSSHKey(username: string, keyPath: string): Promise<void> {
90109
// Read the public key file
91110
const publicKey = fs.readFileSync(keyPath, 'utf8').trim();
92111

93-
// Make the API request
94-
await axios.delete(`${API_BASE_URL}/api/v1/user/${username}/ssh-keys`, {
95-
data: { publicKey },
96-
withCredentials: true,
97-
headers: {
98-
'Content-Type': 'application/json',
99-
Cookie: cookies,
112+
// Strip the comment from the key (everything after the last space)
113+
const keyWithoutComment = publicKey.split(' ').slice(0, 2).join(' ');
114+
115+
// Calculate fingerprint
116+
const fingerprint = calculateFingerprint(keyWithoutComment);
117+
if (!fingerprint) {
118+
console.error('Invalid SSH key format. Unable to calculate fingerprint.');
119+
process.exit(1);
120+
}
121+
122+
console.log(`Removing SSH key with fingerprint: ${fingerprint}`);
123+
124+
// Make the API request using fingerprint in path
125+
await axios.delete(
126+
`${API_BASE_URL}/api/v1/user/${username}/ssh-keys/${encodeURIComponent(fingerprint)}`,
127+
{
128+
withCredentials: true,
129+
headers: {
130+
Cookie: cookies,
131+
},
100132
},
101-
});
133+
);
102134

103135
console.log('SSH key removed successfully!');
104136
} catch (error) {

0 commit comments

Comments
 (0)