Skip to content

Instantly share code, notes, and snippets.

@ScreamZ
Last active May 4, 2020 16:35
Show Gist options
  • Save ScreamZ/6d9ed1c3661554ca0ae6b020ef1b3894 to your computer and use it in GitHub Desktop.
Save ScreamZ/6d9ed1c3661554ca0ae6b020ef1b3894 to your computer and use it in GitHub Desktop.
import crypto from "crypto";
import merge from "lodash/merge";
import { AppConfig, PrivateConfig, PublicConfig } from "./types";
/**
* Factory function that takes a public config and a HEX encrypted configuration.
* On call, this function will decipher, both configuration will be merged together to provide a single JSON object representating the configuration.
*
* @param {PublicConfig} publicConfig
* @param {string} hexEncodedPrivateConfig
* @returns {() => AppConfig}
*/
function buildConfig(publicConfig: PublicConfig, hexEncodedPrivateConfig: string): () => AppConfig {
return () => {
try {
// Isolate the IV from the encrypted string.
const [ivHex, encoded] = hexEncodedPrivateConfig.split(":");
// Initiate a deciper instance using the encryption key and the IV.
const decipher = crypto.createDecipheriv(
"aes-256-cbc",
Buffer.from(process.env.ENCRYPTION_KEY),
Buffer.from(ivHex, "hex"),
);
// Decrypt private configuration.
let decryptedString = decipher.update(Buffer.from(encoded, "hex"));
decryptedString = Buffer.concat([decryptedString, decipher.final()]);
// Parse decrypted configuration string into JSON object for usage.
const decryptedPrivateConfig: PrivateConfig = JSON.parse(decryptedString.toString("utf8"));
// Merge private with public config and freeze it to prevent alteration within program executation.
return Object.freeze(merge(publicConfig, decryptedPrivateConfig));
} catch (e) {
throw new Error("Error while decrypting server configuration. Probably bad decryption key…");
}
};
}
// Initiate factory for staging config
const getStagingConfig = buildConfig(
{
authentication: {
session_duration_seconds: 604800
},
database: {
db_name: "some_name",
},
mailing: {
templates_id: {
password_reset: 41,
},
},
},
"1e53e959b66e8e5e778cda7aedf5f400:7ertt…ytfh99", // HERE paste encrypted config string
);
// Initiate factory for production config
const getProdConfig = buildConfig(
{
authentication: {
session_duration_seconds: 604800
},
database: {
db_name: "some_prod_name",
},
mailing: {
templates_id: {
password_reset: 25,
},
},
},
"1e53e959b66e8e5e778cda7aedf5f400:7ertt…ytfh99", // HERE paste encrypted config string
);
export const APP_CONFIG = process.env.NODE_ENV === "production" ? getProdConfig() : getStagingConfig();
/**
* This script is made for encrypting a JSON file named config.json that lives in the same directory of that script.
* This config.json should never be committed in a version control system like Git.
*
* Usage:
* - node encrypt.js <encryption_key>
*/
const crypto = require("crypto");
// Config
let contentToEncrypt;
const IV_LENGTH = 16;
const KEY = process.argv.slice(2)[0];
// First, try to get the configuration file.
try {
contentToEncrypt = require("./config.json");
} catch (e) {}
// Ensure that an encryption key has been provided as first arg and that there is a JSON configuration to encrypt.
if (!KEY || !contentToEncrypt) {
console.error(
"Please ensure that an encryption key is provided as argument and that there is config file to encrypt.",
);
process.exit(1);
}
// Generate Random IV
const iv = crypto.randomBytes(IV_LENGTH);
const cipher = crypto.createCipheriv("aes-256-cbc", KEY, iv);
// Encrypt a stringified version of our JSON configuration.
let encrypted = cipher.update(JSON.stringify(contentToEncrypt));
encrypted = Buffer.concat([encrypted, cipher.final()]);
// Display the encrypted version that should be versionned.
console.log("Please store the following content in your configuration.");
console.log("---------------------------------------------------------");
console.log(iv.toString("hex") + ":" + encrypted.toString("hex"));
@ThisIsMissEm
Copy link

True, you can indeed roll your own crypto like this, but may I suggest using SOPS from Mozilla instead? https://github.com/mozilla/sops/blob/master/README.rst

@ScreamZ
Copy link
Author

ScreamZ commented May 4, 2020

Thanks for sharing,

also https://github.com/kuzzleio/kuzzle-vault available. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment