Skip to content

Commit

Permalink
feat(credstash): Add credstash support (#14)
Browse files Browse the repository at this point in the history
* feat(credstash): Add credstash support

* feat(credstash): Add credstash support

* feat(credstash): Fix error validation formatting

* feat(credstash): Add credstash support

* feat(credstash): Fix .vscode
  • Loading branch information
Ben Ross authored Apr 20, 2018
1 parent fc9f369 commit d62bd69
Show file tree
Hide file tree
Showing 9 changed files with 147 additions and 18 deletions.
42 changes: 42 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Jest",
"type": "node",
"request": "launch",
"program": "${workspaceRoot}/node_modules/jest-cli/bin/jest.js",
"stopOnEntry": false,
"args": [
"--runInBand",
"${file}"
],
"cwd": "${workspaceRoot}",
"protocol": "legacy",
"runtimeArgs": [
"--nolazy"
],
"sourceMaps": true,
"outFiles": [
"${workspaceRoot}/dist/**/*.js"
]
},
{
"name": "TS-Node",
"type": "node",
"request": "launch",
"args": [
"${relativeFile}"
],
"runtimeArgs": [
"--nolazy",
"-r",
"ts-node/register"
],
"sourceMaps": true,
"cwd": "${workspaceRoot}",
"protocol": "inspector",
"runtimeVersion": "8.10.0"
}
]
}
18 changes: 18 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"prettier.printWidth": 100,
"prettier.singleQuote": true,
"typescript.tsdk": "./node_modules/typescript/lib",
"search.exclude": {
"dist/": true
},
"[javascript]": {
"editor.formatOnSave": true
},
"[json]": {
"editor.formatOnSave": true
},
"[typescript]": {
"editor.formatOnSave": true
}
}

8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ Define your configuration in a yaml file at the root of your application:
default_env: &default_env
SERVICE_URL: ${cft:my-stack.ServiceURL} ## Reference to an AWS CFT stack output
SOME_ENV_VARIABLE: ${env:SOME_ENV_VARIABLE} ## Reference to an external environment variable
SOME_CREDSTASH_VARIABLE: ${cred:SOME_CREDSTASH_VARIABLE} ## Reference to a credstash key
SOME_CONSTANT: SOME_CONSTANT

development:
Expand All @@ -36,15 +37,20 @@ staging:
<<: *default_env

production:
SOME_CONSTANT: OVERRIDE_FOR_PRODUCTION
<<: *default_env
SOME_CONSTANT: OVERRIDE_FOR_PRODUCTION
```
Then, run `yarn dotenvi -s <stage>` to generate a `.env` file for the stage desired (e.g., development, staging, production, etc...). Use the generated `.env` file in your normal processes using [dotenv](https://github.com/motdotla/dotenv).

Note that stages are not required in your yaml file - you can also define it without stages, in which case you should not specify a stage with the `-s` option when you run `dotenvi`.


## Configuration

Note that any AWS references (cred, cft, etc...) are currently hard-coded to us-east-1.


## Discussion

The main design goals of dotenvi are as follows:
Expand Down
1 change: 1 addition & 0 deletions env.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ default_env: &default_env
IA_FARMAPI_ENV: ${env:IA_FARMAPI_ENV}
FOO: ${cft:forms-api-fargate-stack.ServiceURL}
BAZ: BAR
CRED: ${cred:IA_VPC_PRIVATE_SUBNET1_ID}

sandbox:
<<: *default_env
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"aws-sdk": "^2.224.1",
"jest": "^22.4.3",
"js-yaml": "^3.11.0",
"nodecredstash": "^2.0.2",
"ts-jest": "^22.4.4",
"typescript": "^2.8.1"
},
Expand Down
36 changes: 19 additions & 17 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { ArgumentParser } from 'argparse';
import { Rewriter } from './rewriter';
import { ResolverMap, Document } from './types';
import { resolvers } from './resolvers';
import { validateDocument, writeFile } from './utils';

const parser = new ArgumentParser();
parser.addArgument(['-s', '--stage'], {
Expand All @@ -15,30 +16,31 @@ parser.addArgument(['-s', '--stage'], {
});
const args = parser.parseArgs();

function writeFile(document: { [name: string]: string }) {
let output = '';
const variables = Object.keys(document);
for (const variable of variables) {
output += `${variable}=${document[variable]}\n`;
}
fs.writeFileSync('.env', output);
}

let document;
try {
// TODO Load external resolvers

let document = yaml.safeLoad(fs.readFileSync('./env.yml', 'utf8')) as Document;
document = yaml.safeLoad(fs.readFileSync('./env.yml', 'utf8')) as Document;
if (args.stage) {
document = (document as any)[args.stage];
if (!document) {
throw new Error(`Could not locate stage ${args.stage} in file ${args.file}`);
}
}
const rewriter = new Rewriter(resolvers);
rewriter.rewrite(document).then(result => {
console.info(`Writing .env file to ${process.cwd()}/.env`);
writeFile(result);
});
} catch (e) {
console.error(`Could not load yaml ${e}`);

const errors = validateDocument(document);
if (errors.length) {
throw new Error(`Validation errors found while loading document. Did you forget to specify -s?: \n${errors.join("\n")}`);
}
} catch (error) {
console.error(`Could not load yaml ${error.stack}`);
process.exit(1);
}
const rewriter = new Rewriter(resolvers);
rewriter.rewrite(document).then(result => {
console.info(`Writing .env file to ${process.cwd()}/.env`);
writeFile(result);
}).catch((error: Error) => {
console.error(`Could not write .env file: ${error.stack}`);
process.exit(1);
});
11 changes: 11 additions & 0 deletions src/resolvers.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import * as AWS from 'aws-sdk';
import { CloudFormation, Config } from 'aws-sdk';
import { DescribeStacksOutput } from 'aws-sdk/clients/cloudformation';
import { promisify } from 'util';

import { ResolverMap } from './types';

const Credstash = require('nodecredstash');

export const resolvers: ResolverMap = {
cft: async (argument: string) => {

if (!AWS.config.region) {
AWS.config.update({ region: 'us-east-1' });
}
Expand Down Expand Up @@ -37,5 +40,13 @@ export const resolvers: ResolverMap = {
},
constant: async (argument: string) => {
return argument;
},
cred: async (argument: string) => {
const credstash = new Credstash({ awsOpts: { region: 'us-east-1' } });
const promisified = promisify(credstash.getSecret);
return promisified({ name: argument })
.catch((error: Error) => {
throw new Error(`Could not load value ${argument} from credstash: ${error.stack}`);
});
}
};
21 changes: 21 additions & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import * as fs from 'fs';

export function writeFile(document: { [name: string]: string }) {
let output = '';
const keys = Object.keys(document);
for (const key of keys) {
output += `${key}=${document[key]}\n`;
}
fs.writeFileSync('.env', output);
}

export function validateDocument(document: any): string[] {
const errors = [];
const keys = Object.keys(document);
for (const key of keys) {
if (typeof document[key] !== 'string') {
errors.push(`${key} has an invalid value ${JSON.stringify(document[key])}`);
}
}
return errors;
}
27 changes: 27 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,10 @@ acorn@^5.0.0, acorn@^5.3.0:
version "5.5.3"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.5.3.tgz#f473dd47e0277a08e28e9bec5aeeb04751f0b8c9"

aes-js@^3.1.0:
version "3.1.1"
resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.1.1.tgz#89fd1f94ae51b4c72d62466adc1a7323ff52f072"

agent-base@4, agent-base@^4.1.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.2.0.tgz#9838b5c3392b962bad031e6a4c5e1024abec45ce"
Expand Down Expand Up @@ -417,6 +421,21 @@ aws-sdk@*, aws-sdk@^2.224.1:
xml2js "0.4.17"
xmlbuilder "4.2.1"

aws-sdk@^2.171.0:
version "2.225.1"
resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.225.1.tgz#6ec6994a6337f2b553b16f6576df34ea1ac314d8"
dependencies:
buffer "4.9.1"
events "1.1.1"
ieee754 "1.1.8"
jmespath "0.15.0"
querystring "0.2.0"
sax "1.2.1"
url "0.10.3"
uuid "3.1.0"
xml2js "0.4.17"
xmlbuilder "4.2.1"

aws-sign2@~0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f"
Expand Down Expand Up @@ -4300,6 +4319,14 @@ node-uuid@~1.4.7:
version "1.4.8"
resolved "https://registry.yarnpkg.com/node-uuid/-/node-uuid-1.4.8.tgz#b040eb0923968afabf8d32fb1f17f1167fdab907"

nodecredstash@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/nodecredstash/-/nodecredstash-2.0.2.tgz#2a36ae12534c4e975aafde1deafdd85773eb5dcb"
dependencies:
aes-js "^3.1.0"
aws-sdk "^2.171.0"
debug "^3.1.0"

noop-logger@^0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/noop-logger/-/noop-logger-0.1.1.tgz#94a2b1633c4f1317553007d8966fd0e841b6a4c2"
Expand Down

0 comments on commit d62bd69

Please sign in to comment.