feat: rebuild xiteng.site homelab platform
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
import {existsSync} from "node:fs";
|
||||
import {loadBuiltinProviders} from "./providers.mjs";
|
||||
import {breakGlassActor, loadKeyFile, Vault} from "./vault.mjs";
|
||||
|
||||
const databasePath = process.env.DATABASE_PATH || "/data/vault.db";
|
||||
const masterKeyFile = process.env.MASTER_KEY_FILE || "/run/secrets/vault_master_key";
|
||||
const [command, ...args] = process.argv.slice(2);
|
||||
|
||||
function usage() {
|
||||
console.log(`Usage:
|
||||
node cli.mjs list [owner-sub]
|
||||
node cli.mjs audit [limit]
|
||||
node cli.mjs verify <credential-id>
|
||||
node cli.mjs delete <credential-id>
|
||||
node cli.mjs reassign <credential-id> <issuer> <sub> <username>
|
||||
node cli.mjs rotate-master <new-key-file>
|
||||
node cli.mjs backup <destination.db>`);
|
||||
}
|
||||
|
||||
if (!command) {
|
||||
usage();
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const vault = new Vault({
|
||||
databasePath,
|
||||
masterKey: loadKeyFile(masterKeyFile),
|
||||
builtinProviders: loadBuiltinProviders(process.env.PROVIDER_CATALOG_FILE || "/app/providers.json")
|
||||
});
|
||||
const actor = breakGlassActor();
|
||||
|
||||
try {
|
||||
if (command === "list") {
|
||||
const credentials = vault.listCredentials(actor, {all: true});
|
||||
const filtered = args[0]
|
||||
? credentials.filter((credential) => credential.owner.sub === args[0])
|
||||
: credentials;
|
||||
console.table(filtered.map((credential) => ({
|
||||
id: credential.id,
|
||||
owner: credential.owner.username,
|
||||
sub: credential.owner.sub,
|
||||
provider: credential.provider,
|
||||
name: credential.name,
|
||||
fingerprint: credential.fingerprint,
|
||||
status: credential.status
|
||||
})));
|
||||
} else if (command === "audit") {
|
||||
console.table(vault.listAudit(actor, {all: true, limit: args[0] || 100}));
|
||||
} else if (command === "verify" && args[0]) {
|
||||
console.log(vault.verifyCredential(actor, args[0]));
|
||||
} else if (command === "delete" && args[0]) {
|
||||
console.log(vault.deleteCredential(actor, args[0]));
|
||||
} else if (command === "reassign" && args.length >= 4) {
|
||||
console.log(vault.reassignCredential(actor, args[0], {
|
||||
issuer: args[1],
|
||||
sub: args[2],
|
||||
username: args[3],
|
||||
type: "user"
|
||||
}));
|
||||
} else if (command === "rotate-master" && args[0]) {
|
||||
if (!existsSync(args[0])) {
|
||||
throw new Error(`New key file not found: ${args[0]}`);
|
||||
}
|
||||
console.log(vault.rotateMasterKey(actor, loadKeyFile(args[0])));
|
||||
console.error("Rotation succeeded. Replace the mounted vault_master_key before restarting the service.");
|
||||
} else if (command === "backup" && args[0]) {
|
||||
if (existsSync(args[0])) {
|
||||
throw new Error(`Refusing to overwrite existing backup: ${args[0]}`);
|
||||
}
|
||||
console.log(vault.backup(args[0]));
|
||||
} else {
|
||||
usage();
|
||||
process.exitCode = 1;
|
||||
}
|
||||
} finally {
|
||||
vault.close();
|
||||
}
|
||||
Reference in New Issue
Block a user