UNPKG

@robotti.io/escrypt

Version:

Enterprise Secret Encryptor

98 lines (87 loc) 3.1 kB
const fs = require('fs'); const { Validator } = require('jsonschema'); const path = require('path'); const configSchema = { id: '/configSchema', type: 'object', additionalProperties: false, properties: { directory: { type: 'string' }, filename: { type: 'string' }, type: { type: 'string', enum: ['json'] } }, required: ['directory', 'filename', 'type'] }; module.exports = class ConfigurationInteractor { // Private Declarations #encryptedFilePath; #secrets; #type; /** * Configuration Interactor Constructor * @param {Object} config - Configuration Object * @param {string} config.directory - Directory for secrets file * @param {string} config.filename - Filename for secrets file * @param {string} config.type - Storage type for secrets file */ constructor(config) { try { const validator = new Validator(); const validationResults = validator.validate(config, configSchema); if (!validationResults.valid) throw new Error(validationResults); const directory = path.resolve(config.directory); if (!fs.existsSync(directory) || !fs.lstatSync(directory).isDirectory()) throw new Error('Invalid directory provided'); this.#encryptedFilePath = path.join(directory, config.filename); if (!fs.existsSync(this.#encryptedFilePath)) throw new Error('Configuration files does not exists'); this.#type = config.type; this.#readSecretsFile(); } catch (err) { throw new Error(err); } } /** * Read the secrets file * @returns {string} */ #readSecretsFile() { const secrets = fs.readFileSync(this.#encryptedFilePath, 'utf8'); if (this.#type === 'json') return this.#readJSON(secrets); throw new Error('Invalid configuration type'); } /** * JSON Parser * @param {string} secrets - The content of the secrets file */ #readJSON(secrets) { if (typeof secrets !== 'string') throw new Error('Invalid configuration file'); if (secrets === '') this.#secrets = {}; else this.#secrets = JSON.parse(secrets); } /** * Write the secrets file JSON */ #writeJSON() { fs.writeFileSync(this.#encryptedFilePath, JSON.stringify(this.#secrets)); } /** * Store encrypted secret into secrets file * @param {string} key - Secret key name * @param {string} encryptedSecret - Encrypted secret value */ storeEncryptedSecret(key, encryptedSecret) { if (typeof key !== 'string' || key === '') throw new Error('Invalid key provided'); if (typeof encryptedSecret !== 'string') throw new Error('Expected encrypted secret to be a string'); this.#secrets[key] = encryptedSecret; if (this.#type === 'json') this.#writeJSON(); } /** * Retrieve encrypted secret from secrets file * @param {string} key - Secret key name * @returns {string} */ retrieveEncryptedSecret(key) { if (typeof key !== 'string' || key === '') throw new Error('Invalid key provided'); if (Object.keys(this.#secrets).indexOf(key) < 0) throw new Error('Secret does not exist'); return this.#secrets[key]; } };