node-sap-secure-store
Advanced tools
+12
| language: node_js | ||
| install: | ||
| - npm install | ||
| node_js: | ||
| - 0.10 | ||
| script: | ||
| - gulp build | ||
| after_script: "cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js" |
| 'use strict'; | ||
| var fs = require('fs'); | ||
| require('node-sap-promise'); | ||
| /** | ||
| * Simple file system based store | ||
| * @param {string} filename | ||
| * @param {string} [encoding] | ||
| * @param {number} [fileMode] | ||
| * @constructor | ||
| */ | ||
| function FileStore(filename, encoding, fileMode) { | ||
| if (typeof filename !== 'string') { | ||
| throw new TypeError('Missing mandatory filename parameter'); | ||
| } | ||
| this.filename = filename; | ||
| if (typeof encoding === 'number') { | ||
| fileMode = encoding; | ||
| encoding = undefined; | ||
| } | ||
| this.encoding = encoding || 'utf-8'; | ||
| this.fileMode = fileMode || 420; // default file mode 644 | ||
| } | ||
| module.exports = FileStore; | ||
| FileStore.prototype.read = function () { | ||
| return Promise.invoke(fs.readFile, this.filename, { encoding: this.encoding }) | ||
| .then(function (content) { | ||
| return JSON.parse(content); | ||
| }); | ||
| }; | ||
| FileStore.prototype.write = function (store) { | ||
| var content; | ||
| try { | ||
| content = JSON.stringify(store, null, ' '); | ||
| return Promise.invoke(fs.writeFile, this.filename, content, { mode: this.fileMode }); | ||
| } | ||
| catch (err) { | ||
| return Promise.reject(err); | ||
| } | ||
| }; |
@@ -0,0 +0,0 @@ |
+7
-7
@@ -8,6 +8,6 @@ ## Modules | ||
| <dl> | ||
| <dt><a href="#readSecureData">readSecureData(filename, [password])</a> ⇒ <code>Promise</code></dt> | ||
| <dt><a href="#readSecureData">readSecureData(store, [password])</a> ⇒ <code>Promise</code></dt> | ||
| <dd><p>Read encrypted, password protected configuration data</p> | ||
| </dd> | ||
| <dt><a href="#writeSecureData">writeSecureData(filename, data, [password], [customOptions])</a> ⇒ <code>Promise</code></dt> | ||
| <dt><a href="#writeSecureData">writeSecureData(store, data, [password], [customOptions])</a> ⇒ <code>Promise</code></dt> | ||
| <dd><p>Write encrypted, password protected configuration data</p> | ||
@@ -29,3 +29,3 @@ </dd> | ||
| | options | <code>object</code> | Default encryption options | | ||
| | options.algorithm | <code>string</code> | Encryption algorithm (default "aes-256-cbc") | | ||
| | options.algorithm | <code>string</code> | Encryption algorithm (default 'aes-256-cbc') | | ||
| | options.keyLength | <code>number</code> | Key length in bytes (default 32) | | ||
@@ -38,3 +38,3 @@ | options.ivLength | <code>number</code> | Initialization Vector length in bytes (default 16) | | ||
| <a name="readSecureData"></a> | ||
| ## readSecureData(filename, [password]) ⇒ <code>Promise</code> | ||
| ## readSecureData(store, [password]) ⇒ <code>Promise</code> | ||
| Read encrypted, password protected configuration data | ||
@@ -48,7 +48,7 @@ | ||
| | --- | --- | --- | | ||
| | filename | <code>string</code> | Encrypted configuration file | | ||
| | store | <code>string</code> | <code>object</code> | Encrypted store or filename of the encrypted FileStore | | ||
| | [password] | <code>string</code> | Password | | ||
| <a name="writeSecureData"></a> | ||
| ## writeSecureData(filename, data, [password], [customOptions]) ⇒ <code>Promise</code> | ||
| ## writeSecureData(store, data, [password], [customOptions]) ⇒ <code>Promise</code> | ||
| Write encrypted, password protected configuration data | ||
@@ -61,3 +61,3 @@ | ||
| | --- | --- | --- | | ||
| | filename | <code>string</code> | Encrypted configuration file | | ||
| | store | <code>string</code> | <code>Store</code> | Encrypted store or filename of the encrypted FileStore | | ||
| | data | <code>object</code> | <code>string</code> | <code>buffer</code> | Configuration data | | ||
@@ -64,0 +64,0 @@ | [password] | <code>string</code> | Password | |
+11
-10
| #!/usr/bin/env node | ||
| var helper = require("./helper.js"); | ||
| var secureStore = require("../index.js"); | ||
| 'use strict'; | ||
| var helper = require('./helper.js'); | ||
| var secureStore = require('../index.js'); | ||
| var usage = "\nUsage: cryptjson [-p <password>] [-e <environment-variable>] filename | -h\n\nEncrypts a JSON configuration file ('cryptjson -h' displays this help).\n\n"; | ||
| usage += " -p <password> specifies that file will be encrypted using password '<password>'\n"; | ||
| usage += " -e <environment-variable> specifies that file will be encrypted using the password stored in the environment variable <environment-variable>\n"; | ||
| usage += " filename path of the JSON file to encrypt\n\n"; | ||
| usage += "If neither -p nor -e options are used, password is read from CRYPT_JSON_PWD environment variable."; | ||
| var usage = '\nUsage: cryptjson [-p <password>] [-e <environment-variable>] filename | -h\n\nEncrypts a JSON configuration file ("cryptjson -h" displays this help).\n\n'; | ||
| usage += ' -p <password> specifies that file will be encrypted using password "<password>"\n'; | ||
| usage += ' -e <environment-variable> specifies that file will be encrypted using the password stored in the environment variable "<environment-variable>"\n'; | ||
| usage += ' filename path of the JSON file to encrypt\n\n'; | ||
| usage += 'If neither -p nor -e options are used, password is read from CRYPT_JSON_PWD environment variable.'; | ||
@@ -19,9 +20,9 @@ function run() { | ||
| else { | ||
| console.log("Encrypting JSON file " + args.filename); | ||
| console.log('Encrypting JSON file ' + args.filename); | ||
| secureStore.cryptJSON(args.filename, args.password) | ||
| .then(function () { | ||
| console.log("File encrypted"); | ||
| console.log('File encrypted'); | ||
| }) | ||
| .catch(function (err) { | ||
| console.error("Failed to encrypt file: " + err.message); | ||
| console.error('Failed to encrypt file: ' + err.message); | ||
| }); | ||
@@ -28,0 +29,0 @@ } |
+11
-10
| #!/usr/bin/env node | ||
| var helper = require("./helper.js"); | ||
| var secureStore = require("../index.js"); | ||
| 'use strict'; | ||
| var helper = require('./helper.js'); | ||
| var secureStore = require('../index.js'); | ||
| var usage = "\nUsage: decryptjson [-p <password>] [-e <environment-variable>] filename | -h\n\nDecrypts a JSON configuration file ('cryptjson -h' displays this help).\n\n"; | ||
| usage += " -p <password> specifies that file will be decrypted using password '<password>'\n"; | ||
| usage += " -e <environment-variable> specifies that file will be decrypted using the password stored in the environment variable <environment-variable>\n"; | ||
| usage += " filename path of the JSON file to decrypt\n\n"; | ||
| usage += "If neither -p nor -e options are used, password is read from CRYPT_JSON_PWD environment variable."; | ||
| var usage = '\nUsage: decryptjson [-p <password>] [-e <environment-variable>] filename | -h\n\nDecrypts a JSON configuration file ("decryptjson -h" displays this help).\n\n'; | ||
| usage += ' -p <password> specifies that file will be decrypted using password "<password>"\n'; | ||
| usage += ' -e <environment-variable> specifies that file will be decrypted using the password stored in the environment variable "<environment-variable>"\n'; | ||
| usage += ' filename path of the JSON file to decrypt\n\n'; | ||
| usage += 'If neither -p nor -e options are used, password is read from CRYPT_JSON_PWD environment variable.'; | ||
@@ -19,9 +20,9 @@ function run() { | ||
| else { | ||
| console.log("Decrypting JSON file " + args.filename); | ||
| console.log('Decrypting JSON file ' + args.filename); | ||
| secureStore.decryptJSON(args.filename, args.password, 2) | ||
| .then(function () { | ||
| console.log("File decrypted"); | ||
| console.log('File decrypted'); | ||
| }) | ||
| .catch(function (err) { | ||
| console.error("Failed to decrypt file: " + err.message); | ||
| console.error('Failed to decrypt file: ' + err.message); | ||
| }); | ||
@@ -28,0 +29,0 @@ } |
+12
-11
@@ -1,3 +0,4 @@ | ||
| var path = require("path"); | ||
| var util = require("util"); | ||
| 'use strict'; | ||
| var path = require('path'); | ||
| var util = require('util'); | ||
@@ -9,5 +10,5 @@ function CommandLineError(message) { | ||
| util.inherits(CommandLineError, Error); | ||
| CommandLineError.prototype.name = "CommandLineError"; | ||
| CommandLineError.prototype.name = 'CommandLineError'; | ||
| function parseCommandLine () { | ||
| function parseCommandLine() { | ||
| var k, n, args = {}, argv = process.argv; | ||
@@ -17,14 +18,14 @@ n = argv.length; | ||
| switch (argv[k]) { | ||
| case "-h": | ||
| case '-h': | ||
| args.help = true; | ||
| break; | ||
| case "-p": | ||
| case '-p': | ||
| if (k >= n - 2) { | ||
| throw new CommandLineError("-p option requires an additional password argument"); | ||
| throw new CommandLineError('-p option requires an additional password argument'); | ||
| } | ||
| args.password = argv[++k]; | ||
| break; | ||
| case "-e": | ||
| case '-e': | ||
| if (k >= n - 2) { | ||
| throw new CommandLineError("-e option requires an additional environment variable name argument"); | ||
| throw new CommandLineError('-e option requires an additional environment variable name argument'); | ||
| } | ||
@@ -39,3 +40,3 @@ args.password = process.env[argv[++k]]; | ||
| if (!args.filename && !args.help) { | ||
| throw new CommandLineError("Missing filename argument"); | ||
| throw new CommandLineError('Missing filename argument'); | ||
| } | ||
@@ -51,2 +52,2 @@ if (!args.password) { | ||
| parseCommandLine: parseCommandLine | ||
| }; | ||
| }; |
+53
-43
@@ -1,13 +0,14 @@ | ||
| "use strict"; | ||
| var fs = require("fs"); | ||
| var crypto = require("crypto"); | ||
| var util = require("util"); | ||
| require("node-sap-promise"); | ||
| 'use strict'; | ||
| var fs = require('fs'); | ||
| var crypto = require('crypto'); | ||
| var util = require('util'); | ||
| require('node-sap-promise'); | ||
| var FileStore = require('./lib/FileStore'); | ||
| var pbkdf2 = crypto.pbkdf2; | ||
| var defaultOptions = { | ||
| algorithm: "aes-256-cbc", | ||
| algorithm: 'aes-256-cbc', | ||
| keyLength: 32, | ||
| ivLength: 16, | ||
| digest: "sha256", | ||
| digest: 'sha256', | ||
| iterationCount: 10000, | ||
@@ -19,3 +20,3 @@ fileMode: 420 // default file mode 644 | ||
| // In 0.10.x, digest option not supported (hard-coded to SHA1) | ||
| defaultOptions.digest = "sha1"; | ||
| defaultOptions.digest = 'sha1'; | ||
| pbkdf2 = function (password, salt, iterations, keylen, digest, callback) { | ||
@@ -31,18 +32,18 @@ // digest no supported on 0.10.x | ||
| result.buffer = data; | ||
| result.type = "buffer"; | ||
| result.type = 'buffer'; | ||
| } | ||
| else { | ||
| switch (typeof data) { | ||
| case "object": | ||
| case 'object': | ||
| result.buffer = new Buffer(JSON.stringify(data)); | ||
| result.type = "object"; | ||
| result.type = 'object'; | ||
| break; | ||
| case "string": | ||
| encoding = encoding || "utf-8"; | ||
| case 'string': | ||
| encoding = encoding || 'utf-8'; | ||
| result.buffer = new Buffer(data, encoding); | ||
| result.type = "string"; | ||
| result.type = 'string'; | ||
| result.encoding = encoding; | ||
| break; | ||
| default: | ||
| throw new TypeError("Unsupported data type"); | ||
| throw new TypeError('Unsupported data type'); | ||
| } | ||
@@ -56,13 +57,13 @@ } | ||
| switch (type) { | ||
| case "buffer": | ||
| case 'buffer': | ||
| result = buffer; | ||
| break; | ||
| case "object": | ||
| case 'object': | ||
| result = JSON.parse(buffer.toString()); | ||
| break; | ||
| case "string": | ||
| case 'string': | ||
| result = buffer.toString(encoding); | ||
| break; | ||
| default: | ||
| throw new TypeError("Unsupported data type"); | ||
| throw new TypeError('Unsupported data type'); | ||
| } | ||
@@ -73,7 +74,7 @@ return result; | ||
| function checkStore(store) { | ||
| var props = [ "algorithm", "keyLength", "ivLength", "digest", "salt", "iterationCount", "type", "data" ]; | ||
| var props = [ 'algorithm', 'keyLength', 'ivLength', 'digest', 'salt', 'iterationCount', 'type', 'data' ]; | ||
| var k, n = props.length; | ||
| for (k = 0; k < n; ++k) { | ||
| if (!store[props[k]]) { | ||
| throw new TypeError("Invalid encrypted configuration, \"" + props[k] + "\" property is missing"); | ||
| throw new TypeError('Invalid encrypted configuration, \'' + props[k] + '\' property is missing'); | ||
| } | ||
@@ -85,3 +86,3 @@ } | ||
| * Read encrypted, password protected configuration data | ||
| * @param {string} filename Encrypted configuration file | ||
| * @param {string|object} store Encrypted store or filename of the encrypted FileStore | ||
| * @param {string} [password] Password | ||
@@ -91,11 +92,15 @@ * @returns {Promise} Promise eventually fulfilled with the configuration data | ||
| */ | ||
| function readSecureData(filename, password) { | ||
| var store = {}; | ||
| password = password || ""; | ||
| return Promise.invoke(fs.readFile, filename, { encoding: "utf-8" }) | ||
| .then(function (content) { | ||
| store = JSON.parse(content); | ||
| checkStore(store); | ||
| function readSecureData(storeReader, password) { | ||
| var store; | ||
| if (typeof storeReader === 'string') { | ||
| storeReader = new FileStore(storeReader); | ||
| } | ||
| password = password || ''; | ||
| return storeReader.read() | ||
| .then(function (storeObj) { | ||
| checkStore(storeObj); | ||
| store = storeObj; | ||
| var pwdBuffer = new Buffer(password); | ||
| var salt = new Buffer(store.salt, "base64"); | ||
| var salt = new Buffer(store.salt, 'base64'); | ||
| return Promise.invoke(pbkdf2, pwdBuffer, salt, store.iterationCount, store.keyLength + store.ivLength, store.digest); | ||
@@ -107,3 +112,3 @@ }) | ||
| var decipher = crypto.createDecipheriv(store.algorithm, key, iv); | ||
| var buffer = decipher.update(store.data, "base64"); | ||
| var buffer = decipher.update(store.data, 'base64'); | ||
| buffer = Buffer.concat([buffer, decipher.final() ]); | ||
@@ -116,3 +121,3 @@ return decodeData(buffer, store.type, store.encoding); | ||
| * Write encrypted, password protected configuration data | ||
| * @param {string} filename Encrypted configuration file | ||
| * @param {string|Store} store Encrypted store or filename of the encrypted FileStore | ||
| * @param {object|string|buffer} data Configuration data | ||
@@ -124,9 +129,12 @@ * @param {string} [password] Password | ||
| */ | ||
| function writeSecureData(filename, data, password, customOptions) { | ||
| function writeSecureData(storeWriter, data, password, customOptions) { | ||
| var options, pwdBuffer, salt; | ||
| if (typeof password === "object") { | ||
| if (typeof password === 'object') { | ||
| customOptions = password; | ||
| password = undefined; | ||
| } | ||
| password = password || ""; | ||
| if (typeof storeWriter === 'string') { | ||
| storeWriter = new FileStore(storeWriter); | ||
| } | ||
| password = password || ''; | ||
| try { | ||
@@ -136,3 +144,3 @@ options = util._extend({}, module.exports.options); | ||
| pwdBuffer = new Buffer(password); | ||
| salt = crypto.randomBytes(options.keyLength + options.ivLength); // Salt entropy should match key + IV | ||
| salt = crypto.randomBytes(options.keyLength); // Salt entropy should match key | ||
| return Promise.invoke(pbkdf2, pwdBuffer, salt, options.iterationCount, options.keyLength + options.ivLength, options.digest) | ||
@@ -144,4 +152,4 @@ .then(function (kiv) { | ||
| var encodedData = encodeData(data); | ||
| var cipherData = cipher.update(encodedData.buffer, "buffer", "base64"); | ||
| cipherData += cipher.final("base64"); | ||
| var cipherData = cipher.update(encodedData.buffer, 'buffer', 'base64'); | ||
| cipherData += cipher.final('base64'); | ||
| var store = { | ||
@@ -152,3 +160,3 @@ algorithm: options.algorithm, | ||
| digest: options.digest, | ||
| salt: salt.toString("base64"), | ||
| salt: salt.toString('base64'), | ||
| iterationCount: options.iterationCount, | ||
@@ -159,3 +167,3 @@ type: encodedData.type, | ||
| }; | ||
| return Promise.invoke(fs.writeFile, filename, JSON.stringify(store, null, " "), { mode: options.fileMode }); | ||
| return storeWriter.write(store); | ||
| }); | ||
@@ -176,3 +184,3 @@ } | ||
| function cryptJSON(filename, password, customOptions) { | ||
| return Promise.invoke(fs.readFile, filename, { encoding: "utf-8" }) | ||
| return Promise.invoke(fs.readFile, filename, { encoding: 'utf-8' }) | ||
| .then(function (content) { | ||
@@ -201,3 +209,3 @@ var data = JSON.parse(content); | ||
| * @property {object} options Default encryption options | ||
| * @property {string} options.algorithm Encryption algorithm (default "aes-256-cbc") | ||
| * @property {string} options.algorithm Encryption algorithm (default 'aes-256-cbc') | ||
| * @property {number} options.keyLength Key length in bytes (default 32) | ||
@@ -214,3 +222,5 @@ * @property {number} options.ivLength Initialization Vector length in bytes (default 16) | ||
| readSecureData: readSecureData, | ||
| writeSecureData: writeSecureData | ||
| writeSecureData: writeSecureData, | ||
| FileStore: FileStore | ||
| }; | ||
+0
-0
@@ -0,0 +0,0 @@ # License # |
+14
-19
| { | ||
| "name": "node-sap-secure-store", | ||
| "version": "0.1.0", | ||
| "version": "0.1.1", | ||
| "description": "Password protected encrypted configuration", | ||
| "repository": { | ||
| "type": "git", | ||
| "url": "https://github.com/SAP/BUILD.git" | ||
| "url": "https://github.com/sapbuild/node-sap-secure-store.git" | ||
| }, | ||
| "maintainers": [ | ||
| { | ||
| "name": "BUILD Team", | ||
| "email": "contact.build@sap.com" | ||
| } | ||
| ], | ||
| "licenses": [ | ||
| { | ||
| "type": "Apache License, Version 2.0", | ||
| "url": "https://github.com/SAP/BUILD/node-sap-secure-store/blob/master/LICENSE.md" | ||
| "url": "https://github.com/sapbuild/node-sap-secure-store/blob/master/LICENSE.md" | ||
| } | ||
@@ -32,12 +26,13 @@ ], | ||
| "devDependencies": { | ||
| "chai": "^2.2.0", | ||
| "del": "^1.1.1", | ||
| "gulp": "^3.8.11", | ||
| "gulp-concat": "^2.5.2", | ||
| "gulp-eslint": "^0.9.0", | ||
| "gulp-istanbul": "^0.8.1", | ||
| "gulp-jsdoc-to-markdown": "^1.0.2", | ||
| "gulp-mocha": "^2.0.1", | ||
| "gulp-util": "^3.0.4" | ||
| "chai": "~2.2.0", | ||
| "coveralls": "^2.11.3", | ||
| "del": "~1.2.0", | ||
| "gulp": "~3.9.0", | ||
| "gulp-concat": "~2.6.0", | ||
| "gulp-eslint": "~0.15.0", | ||
| "gulp-istanbul": "~0.10.0", | ||
| "gulp-jsdoc-to-markdown": "~1.1.1", | ||
| "gulp-mocha": "~2.1.2", | ||
| "gulp-util": "~3.0.5" | ||
| } | ||
| } | ||
| } |
+5
-5
@@ -0,1 +1,6 @@ | ||
| [](http://travis-ci.org/sapbuild/node-sap-secure-store) | ||
| [](https://npmjs.org/package/node-sap-secure-store) | ||
| [](https://david-dm.org/sapbuild/node-sap-secure-store) | ||
| [](https://david-dm.org/sapbuild/node-sap-secure-store#info=devDependencies) | ||
| [](https://coveralls.io/r/sapbuild/node-sap-secure-store?branch=master) | ||
| node-sap-secure-store | ||
@@ -6,7 +11,2 @@ ==================== | ||
| Further Information | ||
| ====================== | ||
| *node-sap-secure-store* is part of [BUILD](https://github.com/SAP/BUILD). | ||
| # Module use | ||
@@ -13,0 +13,0 @@ |
-151
| { | ||
| "env": { | ||
| "node": true | ||
| }, | ||
| "globals": { | ||
| "__Promise": true | ||
| }, | ||
| "rules": { | ||
| "no-alert": 1, | ||
| "no-array-constructor": 1, | ||
| "no-bitwise": 0, | ||
| "no-caller": 1, | ||
| "no-catch-shadow": 1, | ||
| "no-comma-dangle": 1, | ||
| "no-cond-assign": 1, | ||
| "no-console": 0, | ||
| "no-constant-condition": 1, | ||
| "no-control-regex": 1, | ||
| "no-debugger": 1, | ||
| "no-delete-var": 1, | ||
| "no-div-regex": 0, | ||
| "no-dupe-keys": 1, | ||
| "no-else-return": 0, | ||
| "no-empty": 1, | ||
| "no-empty-class": 1, | ||
| "no-empty-label": 1, | ||
| "no-eq-null": 0, | ||
| "no-eval": 1, | ||
| "no-ex-assign": 1, | ||
| "no-extend-native": 1, | ||
| "no-extra-bind": 1, | ||
| "no-extra-boolean-cast": 1, | ||
| "no-extra-parens": 0, | ||
| "no-extra-semi": 1, | ||
| "no-extra-strict": 1, | ||
| "no-fallthrough": 1, | ||
| "no-floating-decimal": 0, | ||
| "no-func-assign": 1, | ||
| "no-implied-eval": 1, | ||
| "no-inline-comments": 0, | ||
| "no-inner-declarations": [1, "functions"], | ||
| "no-invalid-regexp": 1, | ||
| "no-irregular-whitespace": 0, | ||
| "no-iterator": 1, | ||
| "no-label-var": 1, | ||
| "no-labels": 1, | ||
| "no-lone-blocks": 1, | ||
| "no-lonely-if": 0, | ||
| "no-loop-func": 1, | ||
| "no-mixed-requires": [0, false], | ||
| "no-mixed-spaces-and-tabs": [0, false], | ||
| "no-multi-spaces": 1, | ||
| "no-multi-str": 1, | ||
| "no-multiple-empty-lines": [0, {"max": 1}], | ||
| "no-native-reassign": 1, | ||
| "no-negated-in-lhs": 1, | ||
| "no-nested-ternary": 0, | ||
| "no-new": 1, | ||
| "no-new-func": 1, | ||
| "no-new-object": 1, | ||
| "no-new-require": 0, | ||
| "no-new-wrappers": 1, | ||
| "no-obj-calls": 1, | ||
| "no-octal": 1, | ||
| "no-octal-escape": 1, | ||
| "no-path-concat": 0, | ||
| "no-plusplus": 0, | ||
| "no-process-env": 0, | ||
| "no-process-exit": 1, | ||
| "no-proto": 1, | ||
| "no-redeclare": 1, | ||
| "no-regex-spaces": 1, | ||
| "no-reserved-keys": 0, | ||
| "no-restricted-modules": 0, | ||
| "no-return-assign": 1, | ||
| "no-script-url": 1, | ||
| "no-self-compare": 0, | ||
| "no-sequences": 1, | ||
| "no-shadow": 1, | ||
| "no-shadow-restricted-names": 1, | ||
| "no-space-before-semi": 1, | ||
| "no-spaced-func": 1, | ||
| "no-sparse-arrays": 1, | ||
| "no-sync": 0, | ||
| "no-ternary": 0, | ||
| "no-trailing-spaces": 1, | ||
| "no-undef": 1, | ||
| "no-undef-init": 1, | ||
| "no-undefined": 0, | ||
| "no-underscore-dangle": 0, | ||
| "no-unreachable": 1, | ||
| "no-unused-expressions": 1, | ||
| "no-unused-vars": [1, {"vars": "all", "args": "after-used"}], | ||
| "no-use-before-define": 1, | ||
| "no-void": 0, | ||
| "no-warning-comments": [0, { "terms": ["todo", "fixme", "xxx"], "location": "start" }], | ||
| "no-with": 1, | ||
| "no-wrap-func": 1, | ||
| "block-scoped-var": 0, | ||
| "brace-style": [0, "1tbs"], | ||
| "camelcase": 0, | ||
| "comma-spacing": 1, | ||
| "comma-style": 0, | ||
| "complexity": [0, 11], | ||
| "consistent-return": 1, | ||
| "consistent-this": [0, "that"], | ||
| "curly": 0, | ||
| "default-case": 0, | ||
| "dot-notation": 1, | ||
| "eol-last": 1, | ||
| "eqeqeq": 1, | ||
| "func-names": 0, | ||
| "func-style": [0, "declaration"], | ||
| "global-strict": 0, | ||
| "guard-for-in": 0, | ||
| "handle-callback-err": 0, | ||
| "key-spacing": [1, { "beforeColon": false, "afterColon": true }], | ||
| "max-depth": [0, 4], | ||
| "max-len": [0, 80, 4], | ||
| "max-nested-callbacks": [0, 1], | ||
| "max-params": [0, 3], | ||
| "max-statements": [0, 10], | ||
| "new-cap": 1, | ||
| "new-parens": 1, | ||
| "one-var": 0, | ||
| "operator-assignment": [0, "always"], | ||
| "padded-blocks": 0, | ||
| "quote-props": 0, | ||
| "quotes": [1, "double"], | ||
| "radix": 0, | ||
| "semi": 1, | ||
| "sort-vars": 0, | ||
| "space-after-function-name": [0, "never"], | ||
| "space-after-keywords": [0, "always"], | ||
| "space-before-blocks": [0, "always"], | ||
| "space-in-brackets": [0, "never"], | ||
| "space-in-parens": [0, "never"], | ||
| "space-infix-ops": 1, | ||
| "space-return-throw-case": 1, | ||
| "space-unary-ops": [1, { "words": true, "nonwords": false }], | ||
| "spaced-line-comment": [0, "always"], | ||
| "strict": 1, | ||
| "use-isnan": 1, | ||
| "valid-jsdoc": 0, | ||
| "valid-typeof": 1, | ||
| "vars-on-top": 0, | ||
| "wrap-iife": 0, | ||
| "wrap-regex": 0, | ||
| "yoda": [1, "never"] | ||
| } | ||
| } |
-75
| var exec = require("child_process").exec; | ||
| var gulp = require("gulp"); | ||
| var helper = { | ||
| plugins: {}, | ||
| getPlugin: function (name) { | ||
| var plugin = this.plugins[name]; | ||
| if (!plugin) { | ||
| plugin = require(name); | ||
| this.plugins[name] = plugin; | ||
| } | ||
| return plugin; | ||
| } | ||
| }; | ||
| var pkg = require("./package.json"); | ||
| gulp.task("default", [ "build" ], function () { | ||
| }); | ||
| gulp.task("clean", function (done) { | ||
| var del = helper.getPlugin("del"); | ||
| del([ "coverage", "tmp" ], function (err) { | ||
| done(err); | ||
| }); | ||
| }); | ||
| gulp.task("build", [ "clean", "eslint", "coverage" ], function () { | ||
| }); | ||
| gulp.task("dist", [ "build" ], function () { | ||
| }); | ||
| gulp.task("doc", [ "mddoc" ], function () { | ||
| }); | ||
| gulp.task("eslint", function () { | ||
| var eslint = helper.getPlugin("gulp-eslint"); | ||
| return gulp.src(["index.js", "lib/**/*.js"]) | ||
| .pipe(eslint()) | ||
| .pipe(eslint.format()) | ||
| .pipe(eslint.failOnError()); | ||
| }); | ||
| gulp.task("test", function () { | ||
| return gulp.src("test/**/*.spec.js", { read: false }) | ||
| .pipe(helper.getPlugin("gulp-mocha")({ slow: 200 })); | ||
| }); | ||
| gulp.task("coverage", [ "clean" ], function (done) { | ||
| var mocha = helper.getPlugin("gulp-mocha"); | ||
| var istanbul = helper.getPlugin("gulp-istanbul"); | ||
| gulp.src(["lib/**/*.js", "bin/**/*.js", "index.js"]) | ||
| .pipe(istanbul()) // Covering files | ||
| .pipe(istanbul.hookRequire()) // Force `require` to return covered files | ||
| .on('finish', function () { | ||
| gulp.src("test/**/*.spec.js", { read: false }) | ||
| .pipe(mocha({ slow: 200 })) | ||
| .pipe(istanbul.writeReports({})) // Creating the reports after tests ran | ||
| .on('end', done); | ||
| }); | ||
| }); | ||
| gulp.task("mddoc", [ "eslint" ], function () { | ||
| var gutil = helper.getPlugin("gulp-util"); | ||
| var gulpJsdoc2md = helper.getPlugin("gulp-jsdoc-to-markdown"); | ||
| var concat = helper.getPlugin("gulp-concat"); | ||
| return gulp.src([ "index.js" ]) | ||
| .pipe(concat("API.md")) | ||
| .pipe(gulpJsdoc2md()) | ||
| .on("error", function (err) { | ||
| gutil.log("jsdoc2md failed:", err.message); | ||
| }) | ||
| .pipe(gulp.dest("")); | ||
| }); |
Sorry, the diff of this file is not supported yet
| { | ||
| "algorithm": "aes-256-cbc", | ||
| "keyLength": 32, | ||
| "ivLength": 16, | ||
| "digest": "sha1", | ||
| "iterationCount": 10000, | ||
| "type": "object", | ||
| "data": "dsDuUA+sDoPtMbsx3tSR/rctzZEuBtzhABuLnq+bdmK0AaSJgwQFLQsZj/BEi//J" | ||
| } |
| { | ||
| "algorithm": "aes-256-cbc", | ||
| "keyLength": 32, | ||
| "ivLength": 16, | ||
| "digest": "sha1", | ||
| "salt": "4wh54a912AMBT4yKfWJQCDEYmmR8ahx+GNcEWWwIva9xCT1woQsJQAkvJF0lMwvC", | ||
| "iterationCount": 10000, | ||
| "type": "buffer", | ||
| "data": "wtCAP4qXj0Dy1ypwxVHwKg==" | ||
| } |
| { | ||
| "algorithm": "aes-256-cbc", | ||
| "keyLength": 32, | ||
| "ivLength": 16, | ||
| "digest": "sha1", | ||
| "salt": "4wh54a912AMBT4yKfWJQCDEYmmR8ahx+GNcEWWwIva9xCT1woQsJQAkvJF0lMwvC", | ||
| "iterationCount": 10000, | ||
| "type": "number", | ||
| "data": "wtCAP4qXj0Dy1ypwxVHwKg==" | ||
| } |
| { | ||
| "algorithm": "aes-256-cbc", | ||
| "keyLength": 32, | ||
| "ivLength": 16, | ||
| "digest": "sha1", | ||
| "salt": "Vy7frmWVyca4geuyin1ZfNu1iz7AP6NommBIw47431dmXwlLFpxhRydttOcosaUd", | ||
| "iterationCount": 10000, | ||
| "type": "object", | ||
| "data": "dsDuUA+sDoPtMbsx3tSR/rctzZEuBtzhABuLnq+bdmK0AaSJgwQFLQsZj/BEi//J" | ||
| } |
| { | ||
| "algorithm": "aes-256-cbc", | ||
| "keyLength": 32, | ||
| "ivLength": 16, | ||
| "digest": "sha1", | ||
| "salt": "Jxhc3mUEhjERYFolK1uXgU71bfZJjP/WFs5G0EeEWY4OHG467mjEQzW12xT3AMgg", | ||
| "iterationCount": 10000, | ||
| "type": "string", | ||
| "encoding": "utf-8", | ||
| "data": "KFecIZP49mq/c9uV+0C7ZSbvDmiY6Y91NFbWVBXdm90=" | ||
| } |
| var fs = require("fs"); | ||
| var path = require("path"); | ||
| var crypto = require("crypto"); | ||
| require("node-sap-promise"); | ||
| var expect = require("chai").expect; | ||
| var secureStore = require("../index.js"); | ||
| var password = "Oops, no magic today!"; | ||
| var objConfigFile = path.join(__dirname, "../tmp/object-config.json"); | ||
| var strConfigFile = path.join(__dirname, "../tmp/string-config.json"); | ||
| var bufferConfigFile = path.join(__dirname, "../tmp/buffer-config.json"); | ||
| var jsonConfigFile = path.join(__dirname, "../tmp/json-config.json"); | ||
| var jsonEncryptedConfigFile = path.join(__dirname, "../tmp/json-enc-config.json"); | ||
| var binConfigFile = path.join(__dirname, "../tmp/bin-config.json"); | ||
| var binEncryptedConfigFile = path.join(__dirname, "../tmp/bin-enc-config.json"); | ||
| var objConfig = { | ||
| foo: "bar", | ||
| toto: { | ||
| a: 1, | ||
| b: 2 | ||
| } | ||
| }; | ||
| var strConfig = "A simple string-based config"; | ||
| var bufferConfig = new Buffer([0, 1, 2, 3, 4, 5, 6, 7]); | ||
| var savedArgs = process.argv.slice(); | ||
| process.env.CRYPT_JSON_PWD = password; | ||
| function testPassed(done) { | ||
| return function () { | ||
| done(); | ||
| }; | ||
| } | ||
| function testFailed(done) { | ||
| return function (err) { | ||
| done(err); | ||
| }; | ||
| } | ||
| function preventOnFulfilled() { | ||
| throw new Error("Promise should not be fulfilled"); | ||
| } | ||
| function checkTempDir() { | ||
| var tempPath = path.join(__dirname, "../tmp"); | ||
| if (!fs.existsSync(tempPath)) { | ||
| fs.mkdirSync(tempPath); | ||
| } | ||
| } | ||
| function deleteConfigFiles() { | ||
| var files = [ objConfigFile, strConfigFile, bufferConfigFile, jsonConfigFile, jsonEncryptedConfigFile, binConfigFile, binEncryptedConfigFile ]; | ||
| files.forEach(function (file) { | ||
| try { | ||
| fs.unlinkSync(file); | ||
| } | ||
| catch (err) { | ||
| // ignore errors | ||
| } | ||
| }); | ||
| } | ||
| function mockRun(scriptFile, args, done) { | ||
| var error, binFile = require.resolve(scriptFile); | ||
| delete require.cache[binFile]; | ||
| process.argv = savedArgs.slice(0, 2).concat(args); | ||
| console.log("Running " + scriptFile + " with arguments: ", process.argv); | ||
| try { | ||
| require(scriptFile); | ||
| } | ||
| catch (err) { | ||
| error = err; | ||
| } | ||
| process.argv = savedArgs; | ||
| if (error) { | ||
| done(error); | ||
| } | ||
| else { | ||
| Promise.delay(200).callback(done); | ||
| } | ||
| } | ||
| describe("node-sap-secure-conf", function () { | ||
| before(checkTempDir); | ||
| before(deleteConfigFiles); | ||
| after(deleteConfigFiles); | ||
| describe("readSecureData", function () { | ||
| it("should decrypt an object configuration", function (done) { | ||
| secureStore.readSecureData(path.join(__dirname, "data/object-config.json"), password) | ||
| .then(function (config) { | ||
| expect(config).to.be.an("object"); | ||
| expect(config).to.deep.equal(objConfig); | ||
| }) | ||
| .then(testPassed(done), testFailed(done)); | ||
| }); | ||
| it("should decrypt a string configuration", function (done) { | ||
| secureStore.readSecureData(path.join(__dirname, "data/string-config.json"), password) | ||
| .then(function (config) { | ||
| expect(config).to.be.a("string"); | ||
| expect(config).to.equal(strConfig); | ||
| }) | ||
| .then(testPassed(done), testFailed(done)); | ||
| }); | ||
| it("should decrypt a buffer configuration", function (done) { | ||
| secureStore.readSecureData(path.join(__dirname, "data/buffer-config.json"), password) | ||
| .then(function (config) { | ||
| var k; | ||
| expect(Buffer.isBuffer(config)).to.be.true; | ||
| expect(config.length).to.equal(8); | ||
| for (k = 0; k < 8; ++k) { | ||
| expect(config[k]).to.equal(k); | ||
| } | ||
| }) | ||
| .then(testPassed(done), testFailed(done)); | ||
| }); | ||
| it("should fail on invalid data type", function (done) { | ||
| secureStore.readSecureData(path.join(__dirname, "data/invalid-config.json"), password) | ||
| .then(preventOnFulfilled, function (err) { | ||
| expect(err).to.be.an.instanceof(TypeError); | ||
| }) | ||
| .then(testPassed(done), testFailed(done)); | ||
| }); | ||
| it("should fail for an invalid password", function (done) { | ||
| secureStore.readSecureData(path.join(__dirname, "data/object-config.json"), "bad password") | ||
| .then(preventOnFulfilled, function (err) { | ||
| expect(err).to.be.an.instanceof(Error); | ||
| }) | ||
| .then(testPassed(done), testFailed(done)); | ||
| }); | ||
| it("should fail for an invalid input file", function (done) { | ||
| secureStore.readSecureData(path.join(__dirname, "data/bad-config.json"), password) | ||
| .then(preventOnFulfilled, function (err) { | ||
| expect(err).to.be.an.instanceof(TypeError); | ||
| }) | ||
| .then(testPassed(done), testFailed(done)); | ||
| }); | ||
| }); | ||
| describe("writeSecureData", function () { | ||
| it("should encrypt an object configuration", function (done) { | ||
| secureStore.writeSecureData(objConfigFile, objConfig, password) | ||
| .then(function () { | ||
| return secureStore.readSecureData(objConfigFile, password); | ||
| }) | ||
| .then(function (config) { | ||
| expect(config).to.be.an("object"); | ||
| expect(config).to.deep.equal(objConfig); | ||
| }) | ||
| .then(testPassed(done), testFailed(done)); | ||
| }); | ||
| it("should encrypt a string configuration", function (done) { | ||
| secureStore.writeSecureData(strConfigFile, strConfig, password) | ||
| .then(function () { | ||
| return secureStore.readSecureData(strConfigFile, password); | ||
| }) | ||
| .then(function (config) { | ||
| expect(config).to.be.a("string"); | ||
| expect(config).to.equal(strConfig); | ||
| }) | ||
| .then(testPassed(done), testFailed(done)); | ||
| }); | ||
| it("should encrypt a buffer configuration", function (done) { | ||
| secureStore.writeSecureData(bufferConfigFile, bufferConfig, password) | ||
| .then(function () { | ||
| return secureStore.readSecureData(bufferConfigFile, password); | ||
| }) | ||
| .then(function (config) { | ||
| var k; | ||
| expect(Buffer.isBuffer(config)).to.be.true; | ||
| expect(config.length).to.equal(8); | ||
| for (k = 0; k < 8; ++k) { | ||
| expect(config[k]).to.equal(k); | ||
| } | ||
| }) | ||
| .then(testPassed(done), testFailed(done)); | ||
| }); | ||
| it("should fail on other type of data", function (done) { | ||
| secureStore.writeSecureData(bufferConfigFile, 42, password) | ||
| .then(preventOnFulfilled, function (err) { | ||
| expect(err).to.be.an.instanceof(TypeError); | ||
| }) | ||
| .then(testPassed(done), testFailed(done)); | ||
| }); | ||
| it("should fail if crypto.randomBytes fails", function (done) { | ||
| var randomBytes = crypto.randomBytes; | ||
| crypto.randomBytes = function () { | ||
| throw new Error("Entropy sources drained"); | ||
| }; | ||
| secureStore.writeSecureData(bufferConfigFile, objConfig, password) | ||
| .then(preventOnFulfilled, function (err) { | ||
| expect(err).to.be.an.instanceof(Error); | ||
| }) | ||
| .then(testPassed(done), testFailed(done)); | ||
| crypto.randomBytes = randomBytes; | ||
| }); | ||
| it("should support a missing or empty password", function (done) { | ||
| secureStore.writeSecureData(objConfigFile, objConfig) | ||
| .then(function () { | ||
| return secureStore.readSecureData(objConfigFile) | ||
| }) | ||
| .then(function (config) { | ||
| expect(config).to.be.an("object"); | ||
| expect(config).to.deep.equal(objConfig); | ||
| }) | ||
| .then(testPassed(done), testFailed(done)); | ||
| }); | ||
| it("should support custom options", function (done) { | ||
| secureStore.writeSecureData(objConfigFile, objConfig, password, { iterationCount: 1000 }) | ||
| .then(function () { | ||
| return secureStore.readSecureData(objConfigFile, password) | ||
| }) | ||
| .then(function (config) { | ||
| expect(config).to.be.an("object"); | ||
| expect(config).to.deep.equal(objConfig); | ||
| }) | ||
| .then(testPassed(done), testFailed(done)); | ||
| }); | ||
| it("should support custom options with an empty password", function (done) { | ||
| secureStore.writeSecureData(objConfigFile, objConfig, { iterationCount: 1000 }) | ||
| .then(function () { | ||
| return secureStore.readSecureData(objConfigFile) | ||
| }) | ||
| .then(function (config) { | ||
| expect(config).to.be.an("object"); | ||
| expect(config).to.deep.equal(objConfig); | ||
| }) | ||
| .then(testPassed(done), testFailed(done)); | ||
| }); | ||
| }); | ||
| describe("cryptJSON", function () { | ||
| it("should encrypt a JSON configuration file", function (done) { | ||
| Promise.invoke(fs.writeFile, jsonConfigFile, JSON.stringify(objConfig)) | ||
| .then(function () { | ||
| return secureStore.cryptJSON(jsonConfigFile, password); | ||
| }) | ||
| .then(function () { | ||
| return secureStore.readSecureData(jsonConfigFile, password); | ||
| }) | ||
| .then(function (config) { | ||
| expect(config).to.be.an("object"); | ||
| expect(config).to.deep.equal(objConfig); | ||
| }) | ||
| .then(testPassed(done), testFailed(done)); | ||
| }); | ||
| }); | ||
| describe("decryptJSON", function () { | ||
| it("should decrypt a JSON configuration file", function (done) { | ||
| Promise.invoke(fs.writeFile, jsonEncryptedConfigFile, JSON.stringify(objConfig)) | ||
| .then(function () { | ||
| return secureStore.cryptJSON(jsonEncryptedConfigFile, password); | ||
| }) | ||
| .then(function () { | ||
| return secureStore.decryptJSON(jsonEncryptedConfigFile, password); | ||
| }) | ||
| .then(function () { | ||
| return Promise.invoke(fs.readFile, jsonEncryptedConfigFile, { encoding: "utf-8" }); | ||
| }) | ||
| .then(function (content) { | ||
| var config = JSON.parse(content); | ||
| expect(config).to.be.an("object"); | ||
| expect(config).to.deep.equal(objConfig); | ||
| }) | ||
| .then(function () { | ||
| return secureStore.cryptJSON(jsonEncryptedConfigFile, password); | ||
| }) | ||
| .then(function () { | ||
| return secureStore.decryptJSON(jsonEncryptedConfigFile, password, 2); | ||
| }) | ||
| .then(function () { | ||
| return Promise.invoke(fs.readFile, jsonEncryptedConfigFile, { encoding: "utf-8" }); | ||
| }) | ||
| .then(function (content) { | ||
| var config = JSON.parse(content); | ||
| expect(config).to.be.an("object"); | ||
| expect(config).to.deep.equal(objConfig); | ||
| expect(content.search(/\n|\r/)).to.not.equal(-1); // Check that optional indentLevel parameter yields a multi-line JSON output | ||
| }) | ||
| .then(testPassed(done), testFailed(done)); | ||
| }); | ||
| }); | ||
| describe("bin/cryptJSON", function () { | ||
| this.slow(600); | ||
| it("should require a filename argument", function (done) { | ||
| mockRun("../bin/cryptjson.js", [], done); | ||
| }); | ||
| it("should require a password argument after -p option", function (done) { | ||
| mockRun("../bin/cryptjson.js", [ "-p", binConfigFile ], done); | ||
| }); | ||
| it("should require an environment variable name argument after -e option", function (done) { | ||
| mockRun("../bin/cryptjson.js", [ "-e", binConfigFile ], done); | ||
| }); | ||
| it("should fail on a missing file", function (done) { | ||
| mockRun("../bin/cryptjson.js", [ "NonExistingFile.json" ], done); | ||
| }); | ||
| it("should display help", function (done) { | ||
| mockRun("../bin/cryptjson.js", [ "-h" ], done); | ||
| }); | ||
| it("should encrypt a JSON configuration file with CRYPT_JSON_PWD environment variable as default password", function (done) { | ||
| Promise.invoke(fs.writeFile, binConfigFile, JSON.stringify(objConfig)) | ||
| .then(function () { | ||
| var args = [ binConfigFile ]; | ||
| return Promise.invoke(mockRun, "../bin/cryptjson.js", args); | ||
| }) | ||
| .then(function () { | ||
| return secureStore.readSecureData(binConfigFile, password); | ||
| }) | ||
| .then(function (config) { | ||
| expect(config).to.be.an("object"); | ||
| expect(config).to.deep.equal(objConfig); | ||
| }) | ||
| .then(testPassed(done), testFailed(done)); | ||
| }); | ||
| it("should encrypt a JSON configuration file with explicit password argument", function (done) { | ||
| Promise.invoke(fs.writeFile, binConfigFile, JSON.stringify(objConfig)) | ||
| .then(function () { | ||
| var args = [ "-p", password, binConfigFile ]; | ||
| return Promise.invoke(mockRun, "../bin/cryptjson.js", args); | ||
| }) | ||
| .then(function () { | ||
| return secureStore.readSecureData(binConfigFile, password); | ||
| }) | ||
| .then(function (config) { | ||
| expect(config).to.be.an("object"); | ||
| expect(config).to.deep.equal(objConfig); | ||
| }) | ||
| .then(testPassed(done), testFailed(done)); | ||
| }); | ||
| it("should encrypt a JSON configuration file reading password from a given environment variable", function (done) { | ||
| Promise.invoke(fs.writeFile, binConfigFile, JSON.stringify(objConfig)) | ||
| .then(function () { | ||
| var args = [ "-e", "CRYPT_JSON_PWD", binConfigFile ]; | ||
| return Promise.invoke(mockRun, "../bin/cryptjson.js", args); | ||
| }) | ||
| .then(function () { | ||
| return secureStore.readSecureData(binConfigFile, password); | ||
| }) | ||
| .then(function (config) { | ||
| expect(config).to.be.an("object"); | ||
| expect(config).to.deep.equal(objConfig); | ||
| }) | ||
| .then(testPassed(done), testFailed(done)); | ||
| }); | ||
| }); | ||
| describe("bin/decryptJSON", function () { | ||
| this.slow(600); | ||
| it("should require a filename argument", function (done) { | ||
| mockRun("../bin/decryptjson.js", [], done); | ||
| }); | ||
| it("should require a password argument after -p option", function (done) { | ||
| mockRun("../bin/decryptjson.js", [ "-p", binEncryptedConfigFile ], done); | ||
| }); | ||
| it("should require an environment variable name argument after -e option", function (done) { | ||
| mockRun("../bin/decryptjson.js", [ "-e", binEncryptedConfigFile ], done); | ||
| }); | ||
| it("should fail on a missing file", function (done) { | ||
| mockRun("../bin/decryptjson.js", [ "NonExistingFile.json" ], done); | ||
| }); | ||
| it("should display help", function (done) { | ||
| mockRun("../bin/decryptjson.js", [ "-h" ], done); | ||
| }); | ||
| it("should decrypt a JSON configuration file with CRYPT_JSON_PWD environment variable as default password", function (done) { | ||
| Promise.invoke(fs.writeFile, binEncryptedConfigFile, JSON.stringify(objConfig)) | ||
| .then(function () { | ||
| return secureStore.cryptJSON(binEncryptedConfigFile, password); | ||
| }) | ||
| .then(function () { | ||
| var args = [ binEncryptedConfigFile ]; | ||
| return Promise.invoke(mockRun, "../bin/decryptjson.js", args); | ||
| }) | ||
| .then(function () { | ||
| return Promise.invoke(fs.readFile, binEncryptedConfigFile, { encoding: "utf-8" }); | ||
| }) | ||
| .then(function (content) { | ||
| var config = JSON.parse(content); | ||
| expect(config).to.be.an("object"); | ||
| expect(config).to.deep.equal(objConfig); | ||
| }) | ||
| .then(testPassed(done), testFailed(done)); | ||
| }); | ||
| it("should decrypt a JSON configuration file with explicit password argument", function (done) { | ||
| Promise.invoke(fs.writeFile, binEncryptedConfigFile, JSON.stringify(objConfig)) | ||
| .then(function () { | ||
| return secureStore.cryptJSON(binEncryptedConfigFile, password); | ||
| }) | ||
| .then(function () { | ||
| var args = [ "-p", password, binEncryptedConfigFile ]; | ||
| return Promise.invoke(mockRun, "../bin/decryptjson.js", args); | ||
| }) | ||
| .then(function () { | ||
| return Promise.invoke(fs.readFile, binEncryptedConfigFile, { encoding: "utf-8" }); | ||
| }) | ||
| .then(function (content) { | ||
| var config = JSON.parse(content); | ||
| expect(config).to.be.an("object"); | ||
| expect(config).to.deep.equal(objConfig); | ||
| }) | ||
| .then(testPassed(done), testFailed(done)); | ||
| }); | ||
| it("should decrypt a JSON configuration file reading password from a given environment variable", function (done) { | ||
| Promise.invoke(fs.writeFile, binEncryptedConfigFile, JSON.stringify(objConfig)) | ||
| .then(function () { | ||
| return secureStore.cryptJSON(binEncryptedConfigFile, password); | ||
| }) | ||
| .then(function () { | ||
| var args = [ "-p", password, "-e", "CRYPT_JSON_PWD", binEncryptedConfigFile ]; | ||
| return Promise.invoke(mockRun, "../bin/decryptjson.js", args); | ||
| }) | ||
| .then(function () { | ||
| return Promise.invoke(fs.readFile, binEncryptedConfigFile, { encoding: "utf-8" }); | ||
| }) | ||
| .then(function (content) { | ||
| var config = JSON.parse(content); | ||
| expect(config).to.be.an("object"); | ||
| expect(config).to.deep.equal(objConfig); | ||
| }) | ||
| .then(testPassed(done), testFailed(done)); | ||
| }); | ||
| }); | ||
| }); | ||
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 2 instances in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 2 instances in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
4
-50%32276
-42.36%10
11.11%11
-38.89%349
-57.28%2
100%