UNPKG

@robotti.io/escrypt

Version:

Enterprise Secret Encryptor

101 lines (90 loc) 3.43 kB
const { Validator } = require('jsonschema'); const path = require('path'); const fs = require('fs'); const Cryptor = require('./lib/cryptor'); const ConfigurationInteractor = require('./lib/configurationInteractor'); const { fstat } = require('fs'); const configSchema = { id: '/configSchema', type: 'object', additionalProperties: false, properties: { environment: { type: 'string' }, keyDirectory: { type: 'string' }, configurationDirectory: { type: 'string' }, configurationType: { type: 'string', enum: ['json'] } }, required: [ 'environment', 'keyDirectory', 'configurationDirectory', 'configurationType' ] }; module.exports = class ESCrypt { // Private Declarations #cryptor; #configurationInteractor; #instance; #configurationFile; constructor(config) { this.#instance = { encrypt: false, decrypt: false }; // Schema Validation const validator = new Validator(); const validationResults = validator.validate(config, configSchema); if (!validationResults.valid) throw new Error(validationResults); // Key Validation const keyDirectory = path.resolve(config.keyDirectory); if (!fs.existsSync(keyDirectory) || !fs.lstatSync(keyDirectory).isDirectory()) throw new Error('Invalid key directory provided'); const privateKey = `${config.environment}-private.pem`; const publicKey = `${config.environment}-public.pem`; const privateKeyFile = path.join(keyDirectory, privateKey); const publicKeyFile = path.join(keyDirectory, publicKey); this.#cryptor = new Cryptor({ publicKey: publicKeyFile, privateKey: privateKeyFile }); if (fs.existsSync(privateKeyFile)) this.#instance.decrypt = true; if (fs.existsSync(publicKeyFile)) this.#instance.encrypt = true; // Config Validation const configDirectory = path.resolve(config.configurationDirectory); if (!fs.existsSync(configDirectory) || !fs.lstatSync(configDirectory).isDirectory()) throw new Error('Invalid configuration directory provided'); const configFilename = `${config.environment}.config`; const configurationFile = path.join(configDirectory, configFilename); if (!fs.existsSync(configurationFile)) { fs.writeFileSync(configurationFile, JSON.stringify({})); } this.#configurationInteractor = new ConfigurationInteractor({ directory: configDirectory, filename: configFilename, type: config.configurationType }); this.#initializeInstance(); } #initializeInstance() { const { encrypt, decrypt } = this.#instance; if (!encrypt && !decrypt) { const keyGen = this.#cryptor.generateKeys(); if (keyGen.privateKeyFile && keyGen.publicKeyFile) { // This would only happen if the key generation failed due to permission issues this.#instance.encrypt = true; this.#instance.decrypt = true; } } if (this.#instance.encrypt) { this.encrypt = this.#encrypt; } if (this.#instance.decrypt) { this.decrypt = this.#decrypt; } } #encrypt(key, secret) { const encryptedSecret = this.#cryptor.encrypt(secret); this.#configurationInteractor.storeEncryptedSecret(key, encryptedSecret); } #decrypt(key) { const encryptedSecret = this.#configurationInteractor.retrieveEncryptedSecret(key); const decryptedSecret = this.#cryptor.decrypt(encryptedSecret); return decryptedSecret; } }