101 lines
2.7 KiB
TypeScript
Executable File
101 lines
2.7 KiB
TypeScript
Executable File
#!/usr/bin/env -S deno run --allow-env --allow-import --allow-read --allow-net
|
|
|
|
import { parseArgs } from "jsr:@std/cli/parse-args";
|
|
import {
|
|
log,
|
|
} from "https://hatter.ink/script/fetch/library/deno-commons-mod.ts?202501191623";
|
|
import {
|
|
fetchKeys,
|
|
SshKey,
|
|
} from "https://hatter.ink/script/fetch/library/deno-github-mod.ts?202501191443";
|
|
import {
|
|
SshSignature,
|
|
} from "https://hatter.ink/script/fetch/library/deno-sshsig-mod.ts?202501191510";
|
|
|
|
const flags = parseArgs(Deno.args, {
|
|
boolean: ["help", "debug"],
|
|
string: ["username"],
|
|
});
|
|
|
|
if (Deno.args.length === 0) {
|
|
log.info("ssh-verify.ts --help for help");
|
|
Deno.exit(1);
|
|
}
|
|
|
|
if (flags.help) {
|
|
console.log(`ssh-verify.ts - SSH verify tool
|
|
|
|
ssh-verify.ts --help
|
|
ssh-verify.ts --username <github-username> <filename>
|
|
`);
|
|
Deno.exit(0);
|
|
}
|
|
|
|
if (flags._.length === 0) {
|
|
log.error("Requires filename.");
|
|
Deno.exit(1);
|
|
}
|
|
|
|
const filename = flags._[0] as string;
|
|
const sshSigFilename = `${filename}.sshsig`;
|
|
|
|
if (flags.debug) {
|
|
log.debug(`SSH signature file: ${sshSigFilename}`);
|
|
}
|
|
const sshSignature = await SshSignature.parseFile(sshSigFilename);
|
|
|
|
const verifyResult = await sshSignature.verifyFile(filename);
|
|
|
|
if (!verifyResult) {
|
|
log.error(
|
|
`Verify ${filename}, signature: ${sshSigFilename} failed.`,
|
|
);
|
|
Deno.exit(1);
|
|
}
|
|
|
|
const sshPublicKey = sshSignature.publicKey;
|
|
const sshPublicKeyRawBase64 = sshSignature.publicKey.asRawBase64();
|
|
const sshPublicKeySshFormat = sshPublicKey.toSshKeyFormat();
|
|
|
|
log.success(`File ${filename} verify success.`);
|
|
log.success(`Signing SSH key: ${sshPublicKeySshFormat}`);
|
|
|
|
if (flags.username) {
|
|
let matches = false;
|
|
try {
|
|
log.info(`Fetch SSH keys for user: ${flags.username}`);
|
|
const keys: Array<SshKey> = await fetchKeys(flags.username);
|
|
|
|
if (flags.debug) {
|
|
for (let i = 0; i < keys.length; i++) {
|
|
const key = keys[i];
|
|
log.debug(
|
|
`[DEBUG] Found SSH key: ${key.algorithm} ${key.material}`,
|
|
);
|
|
}
|
|
}
|
|
for (let i = 0; i < keys.length; i++) {
|
|
const key = keys[i];
|
|
if (key.material == sshPublicKeyRawBase64) {
|
|
matches = true;
|
|
break;
|
|
}
|
|
}
|
|
} catch (e) {
|
|
log.error(
|
|
`Fetch SSH keys for ${flags.username} failed: ${e}`,
|
|
);
|
|
}
|
|
if (matches) {
|
|
log.success(
|
|
`SSH key matches for GitHub user: ${flags.username} success.`,
|
|
);
|
|
} else {
|
|
log.error(
|
|
`SSH key NOT matched for GitHub user: ${flags.username}.`,
|
|
);
|
|
}
|
|
} else {
|
|
log.warn("GitHub user is not assigned.");
|
|
}
|