@cto.af/ca
Version:
Testing-only Certificate Authority (CA) for your local development environment ONLY. This is in no way suitable for production of any kind.
92 lines (91 loc) • 2.64 kB
JavaScript
import { AsyncEntry, findCredentialsAsync } from '@napi-rs/keyring';
import { errCode } from '@cto.af/utils';
import fs from 'node:fs/promises';
/**
* Retrieve secret information from the keychain.
*
* @param log Logging service.
* @param service Keychain service name.
* @param account Full path to a filename that *could* store the secret.
* @returns Secret.
*/
export async function getSecret(log, service, account) {
const e = new AsyncEntry(service, account);
let secret = await e.getPassword();
if (secret) {
return secret;
}
try {
log.warn('Reading key from untrusted store: "%s"', account);
secret = await fs.readFile(account, 'utf8');
log.info('Converting key to trusted store: "%s"', account);
await e.setPassword(secret);
log.info('Deleting old untrusted store: "%s"', account);
await fs.rm(account);
return secret;
}
catch (err) {
if (errCode(err, 'ENOENT')) {
return undefined;
}
throw err;
}
}
/**
* Store a secret in the keychain.
*
* @param log Logging service.
* @param service Keychain service name.
* @param account Full path to a filename that *could* store the secret.
* @param secret Secret to store.
*/
export async function setSecret(log, service, account, secret) {
const e = new AsyncEntry(service, account);
await e.setPassword(secret);
try {
await fs.stat(account);
log.warn('Removing old untrusted store: "%s"', account);
await fs.rm(account);
}
catch (err) {
if (!errCode(err, 'ENOENT')) {
throw err;
}
}
}
/**
* Delete a secret from the keychain.
*
* @param service Keychain service name.
* @param account Full path to a filename that *could* store the secret.
* @param log Logging service.
*/
export async function deleteSecret(service, account, log) {
const e = new AsyncEntry(service, account);
log?.debug?.('Deleting secret: "%s"', account);
await e.deletePassword();
try {
await fs.stat(account);
log?.warn('Removing old untrusted store: "%s"', account);
await fs.rm(account);
}
catch (err) {
if (!errCode(err, 'ENOENT')) {
throw err;
}
}
}
/**
* List all of the keys in this service.
*
* @param service Keychain service name.
* @yields An entry for each key found.
*/
export async function* listSecrets(service) {
for (const { account } of await findCredentialsAsync(service)) {
yield {
entry: new AsyncEntry(service, account),
account,
};
}
}