Skip to content

Commit

Permalink
cstore.download - download configs to random .env file on disk
Browse files Browse the repository at this point in the history
  • Loading branch information
shivpatel committed Oct 12, 2019
1 parent f1d9135 commit f673050
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 8 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

This module is only intended for use alongside an existing [cStore](https://github.com/turnerlabs/cstore) setup.

Tested against cStore `2.6.2`.
Tested against cStore `3.3.1`.

## Installation

Expand Down
45 changes: 39 additions & 6 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const parser = require('./lib/parser');
const s3 = require('./lib/stores/s3');
const ssm = require('./lib/stores/ssm');
const secretsmanager = require('./lib/stores/secretsmanager');
const fileSystem = require('./lib/file-system');

const provide = {};

Expand All @@ -11,23 +12,21 @@ const stores = {
}

/**
* Pull configs via cStore (S3) given the provided cstore.yml path and env tag.
* Get configs via cStore given the provided yml path and env tag. Returns as key/value object.
* @param {String} tag Name of the desired env tag
* @param {String} ymlPath Absolute path to cstore.yml file. Defaults to process.cwd()/cstore.yml
* @param {Boolean} injectIntoProcess If `true`, env vars will be automatically
* injected into process.env
* @param {String} ymlPath Absolute path to cstore.yml file
* @param {Boolean} injectSecrets If `true`, env vars referencing secrets manager
* will be fetched and returned in decrypted form.
*/
provide.pull = async (tag, ymlPath = `${process.cwd()}/cstore.yml`, injectIntoProcess = true, injectSecrets = true) => {
const getConfigs = async (tag, ymlPath, injectSecrets) => {
console.info(`Loading configuration for ${tag}`);
const doc = parser.parseYaml(ymlPath);
const context = doc.context;
const fileinfos = parser.locateTag(doc, tag);
let envVarsMerged = {};
for (let fileinfo of fileinfos) {
if (!stores[fileinfo.store]) {
throw new Error(`cstore-pull - unsupported store type ${fileinfo.store}`);
throw new Error(`cstore-js - unsupported store type ${fileinfo.store}`);
}
const envVars = await stores[fileinfo.store](context, fileinfo);
envVarsMerged = Object.assign(envVarsMerged, envVars);
Expand All @@ -36,6 +35,21 @@ provide.pull = async (tag, ymlPath = `${process.cwd()}/cstore.yml`, injectIntoPr
await secretsmanager.findAllAndInject(context, envVarsMerged);
}
console.info(`Loaded configuration for ${tag}`);
return envVarsMerged;
}

/**
* Pull configs via cStore given the provided cstore.yml path and env tag. Returns as object.
* Will also inject straight into `process.env`.
* @param {String} tag Name of the desired env tag
* @param {String} ymlPath Absolute path to cstore.yml file. Defaults to process.cwd()/cstore.yml
* @param {Boolean} injectIntoProcess If `true`, env vars will be automatically
* injected into process.env
* @param {Boolean} injectSecrets If `true`, env vars referencing secrets manager
* will be fetched and returned in decrypted form.
*/
provide.pull = async (tag, ymlPath = `${process.cwd()}/cstore.yml`, injectIntoProcess = true, injectSecrets = true) => {
const envVarsMerged = await getConfigs(tag, ymlPath, injectSecrets);
if (injectIntoProcess) {
for (let envKey in envVarsMerged) {
process.env[envKey] = envVarsMerged[envKey];
Expand All @@ -45,4 +59,23 @@ provide.pull = async (tag, ymlPath = `${process.cwd()}/cstore.yml`, injectIntoPr
return envVarsMerged;
}

/**
* Pull configs via cStore given the provided cstore.yml path and env tag. Stores the results
* in a random.env file located at `process.cwd()`. Returns the absolute filepath for the random
* env file.
* @param {String} tag Name of the desired env tag
* @param {String} ymlPath Absolute path to cstore.yml file. Defaults to process.cwd()/cstore.yml
* @param {Boolean} injectSecrets If `true`, env vars referencing secrets manager
* will be fetched and returned in decrypted form.
*/
provide.download = async (tag, ymlPath = `${process.cwd()}/cstore.yml`, injectSecrets = true) => {
const envVarsMerged = await getConfigs(tag, ymlPath, injectSecrets);
let dataToWrite = '';
for (let envKey in envVarsMerged) {
dataToWrite += `${envKey}=${envVarsMerged[envKey]}\n`;
}
const filepath = await fileSystem.saveToRandomLocation(dataToWrite);
return filepath;
}

module.exports = provide;
45 changes: 45 additions & 0 deletions lib/file-system.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
const crypto = require('crypto');
const fs = require('fs');

/**
* Generate and return a random string with `len` characters.
* @param {Number} len number of desired characters
*/
function randomValueHex(len) {
return crypto
.randomBytes(Math.ceil(len / 2))
.toString('hex')
.slice(0, len)
}

/**
* Returns a promise that will write `data` to `path` using `fs.writeFile`
* @param {String} path absolute filepath
* @param {String} data data to be stored in file
*/
function writeFile(path, data) {
return new Promise((resolve, reject) => {
fs.writeFile(path, data, err => {
if (err) reject(err);
else resolve(path);
});
});
}

const provide = {};

/**
* Saves `data` to random file location relative to `process.cwd()`.
* Returns the absolute path to the randomly saved file.
* @param {String} data data to be stored in file
* @param {Stirng} extension file extension including the dot. If not provided
* uses `.env`
*/
provide.saveToRandomLocation = async (data, extension = `.env`) => {
const randomFilename = randomValueHex(12);
const filepath = `${process.cwd()}/${randomFilename}${extension}`;
await writeFile(filepath, data);
return filepath;
}

module.exports = provide;
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cstore-js",
"version": "1.0.0",
"version": "1.1.0",
"author": "Shiv Patel",
"license": "Apache-2.0",
"description": "A lightweight package for using cStore configs in JavaScript",
Expand Down

0 comments on commit f673050

Please sign in to comment.