128 lines
3.6 KiB
TypeScript
Executable File
128 lines
3.6 KiB
TypeScript
Executable File
#!/usr/bin/env -S deno run --allow-env --allow-run --allow-import
|
|
|
|
// Reference:
|
|
// - https://github.com/nwwdles/kpxcpc
|
|
// - https://stackoverflow.com/questions/62142699/how-do-i-run-an-arbitrary-shell-command-from-deno
|
|
// - https://docs.deno.com/api/deno/~/Deno.CommandOptions
|
|
// - https://github.com/aliyun/aliyun-cli
|
|
|
|
import {
|
|
compareVersion,
|
|
isEnvOn,
|
|
log,
|
|
} from "https://hatter.ink/script/get/@1/deno-commons-mod.ts";
|
|
|
|
const args = Deno.args;
|
|
if (args.length == 0) {
|
|
console.log(
|
|
`kpxcenv.js - KeepassXC environment tool (currently only support Alibaba Cloud)
|
|
|
|
kpxcenv.js aliyunak://ak-name
|
|
|
|
Environments:
|
|
KPXC_SHELL - Shell, default bash
|
|
KPXC_REGION - Region, default cn-hangzhou, effects env: ALIBABA_CLOUD_REGION_ID
|
|
KPXC_DEBUG - Debug, default false
|
|
`,
|
|
);
|
|
Deno.exit(0);
|
|
}
|
|
|
|
const KEEPASSXC_PROXY_COMMAND = "kpxcpc";
|
|
|
|
const isDebug = isEnvOn("KPXC_DEBUG");
|
|
|
|
const xdrRuntimeDir = Deno.env.get("XDG_RUNTIME_DIR");
|
|
if (xdrRuntimeDir == null) {
|
|
const tmpdir = Deno.env.get("TMPDIR");
|
|
if (tmpdir == null) {
|
|
log.error("Environment XDG_RUNTIME_DIR is not set.");
|
|
Deno.exit(1);
|
|
}
|
|
if (isDebug) {
|
|
log.debug("Set env XDG_RUNTIME_DIR=" + tmpdir);
|
|
}
|
|
Deno.env.set("XDG_RUNTIME_DIR", tmpdir);
|
|
}
|
|
const shellCommand = Deno.env.get("KPXC_SHELL") || "bash";
|
|
const region = Deno.env.get("KPXC_REGION") || "cn-hangzhou";
|
|
|
|
if (compareVersion(Deno.version.deno, "1.18.0") < 0) {
|
|
log.error("Require deno version >= 1.18.0 .");
|
|
Deno.exit(1);
|
|
}
|
|
|
|
async function commandExists(cmd: string): Promise<boolean> {
|
|
const whichCmd = new Deno.Command("which", {
|
|
args: [cmd],
|
|
});
|
|
const {
|
|
code: whichCmdCode,
|
|
stdout: _whichCmdStdout,
|
|
stderr: _whichCmdStderr,
|
|
} = await whichCmd.output();
|
|
return whichCmdCode === 0;
|
|
}
|
|
|
|
if (!await commandExists(KEEPASSXC_PROXY_COMMAND)) {
|
|
log.error(
|
|
"Command kpxcpc is not installed, please install from: https://github.com/nwwdles/kpxcpc",
|
|
);
|
|
Deno.exit(1);
|
|
}
|
|
|
|
const akName = args[0];
|
|
const kpxcpcCmd = new Deno.Command(KEEPASSXC_PROXY_COMMAND, {
|
|
args: ["--json", akName],
|
|
});
|
|
const {
|
|
code: kpxcpcCmdCode,
|
|
stdout: kpxcpcCmdStdout,
|
|
stderr: kpxcpcCmdStderr,
|
|
} = await kpxcpcCmd.output();
|
|
if (kpxcpcCmdCode != 0) {
|
|
console.error(new TextDecoder().decode(kpxcpcCmdStderr));
|
|
console.log(new TextDecoder().decode(kpxcpcCmdStdout));
|
|
Deno.exit(kpxcpcCmdCode);
|
|
}
|
|
|
|
const kpxcpcCmdStdoutString = new TextDecoder().decode(kpxcpcCmdStdout);
|
|
const kpxcpcCmdJsonObjects = JSON.parse(kpxcpcCmdStdoutString);
|
|
|
|
if (kpxcpcCmdJsonObjects.length == 0) {
|
|
log.error(
|
|
"Should not happen, since KeepassXC return JSON array is empty.",
|
|
);
|
|
Deno.exit(1);
|
|
}
|
|
if (kpxcpcCmdJsonObjects.length > 1) {
|
|
log.warn(
|
|
"Get more than one vaule from KeepassXC, default use the first.",
|
|
);
|
|
}
|
|
const kpxcpcCmdJsonObject = kpxcpcCmdJsonObjects[0];
|
|
|
|
const accessKeyName = kpxcpcCmdJsonObject.name;
|
|
const accessKeyId = kpxcpcCmdJsonObject.login;
|
|
const accessKeySecret = kpxcpcCmdJsonObject.password;
|
|
|
|
if (isDebug) {
|
|
log.debug("Found object: ", kpxcpcCmdJsonObject);
|
|
}
|
|
|
|
const command = new Deno.Command(shellCommand, {
|
|
args: [],
|
|
env: {
|
|
"PS1": accessKeyName + " (" + akName + ")" + "> ", // FIXME support fish
|
|
"ALIBABA_CLOUD_REGION_ID": region,
|
|
"ALIBABA_CLOUD_ACCESS_KEY_ID": accessKeyId,
|
|
"ALIBABA_CLOUD_ACCESS_KEY_SECRET": accessKeySecret,
|
|
},
|
|
stdin: "inherit",
|
|
stdout: "inherit",
|
|
});
|
|
const _child = command.spawn();
|
|
|
|
// @SCRIPT-SIGNATURE-V1: yk-r1.ES256.20250123T002653+08:00.MEUCIQC3RT5y3G8E891QVcnO
|
|
// Ooarh+NtpuAjHHWskZ0Pu48FegIgB/ybIyjpyW5VjpHKY3arLcw4rOOf1KGFIpkWJP6kF1U=
|