const _ = require('lodash');
const { inspectCertificate, validateCertificate } = require('./certificates');
const { addCachedCertificate, removeCachedCertificate } = require('./cachedCertificates');
const { extractPath } = require('./utils');
const { CA_KEY } = require('./constants');
/**
* Adds a trusted CA for the current user.
* @param {object} context The session context.
* @param {string} filepath The CA certificate.
* @param {boolean} isOverwrite Whether or not to overwrite an existing CA with the same name.
* @returns {Promise<boolean>} Whether or not the CA was written successfully.
*/
async function addCertificateAuthority(context, filepath, isOverwrite = true) {
// validate the CA certificate before adding it.
const ca = await inspectCertificate(filepath);
const { platformName } = extractPath(ca.certificate.subject.name);
const address = ca.certificate.signatureAddress;
const { status, error } = await validateCertificate(ca, address);
if (error) {
throw new Error(error);
}
// check overwrite settings and whether or not there is an existing CA.
const { forAddress } = ca.certificate;
const caName = `${ca.certificate.subject.organization} (${platformName})`;
if (!isOverwrite && await context.storage.getKeyItem(CA_KEY, caName)) {
return null;
}
// add the CA and also cache the certificate.
const key = await addCachedCertificate(context, ca, isOverwrite);
await context.storage.addKeyItem(CA_KEY, caName, {
platform: platformName, address, forAddress, status, key,
});
return caName;
}
/**
* Removes a trusted CA by name.
* @param {object} context The session context.
* @param {string} name The name of the CA to remove.
* @returns {Promise<boolean>} Whether or not the CA was removed successfully.
*/
async function removeCertificateAuthority(context, name) {
const item = await context.storage.getKeyItem(CA_KEY, name);
if (!item) { return false; }
await context.storage.removeKeyItem(CA_KEY, name);
await removeCachedCertificate(item.key);
return true;
}
/**
* Retrieves a list of all trusted CAs.
* @param {object} context The session context.
* @returns {Promise<Array>}
*/
async function getCertificateAuthorities(context) {
const items = await context.storage.getItems(CA_KEY);
return _.keys(items).map((i) => ({ name: i, ...items[i] }));
}
module.exports = {
addCertificateAuthority,
removeCertificateAuthority,
getCertificateAuthorities,
};