diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..a5b82de --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,3 @@ +module.exports = { + "extends": "standard" +}; \ No newline at end of file diff --git a/README.md b/README.md index 115bb63..e0f4193 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,10 @@ some build directly from sources like github - you may require things like * libnetfilter-queue-dev * libnfnetlink-dev +## Note: +Some child dependencies have not been updated in some time failing builds +with later versions of NodeJS. For best results; use LTS/Carbon (8) + # Getting Started Clone this repo within git, cd, and `npm install`. @@ -46,7 +50,17 @@ I personally use; ```sudo `which node` src/index.js``` # Usage -You can customize your rules within the *.json configuration files. +You can customize your rules within the *.json configuration files. To +ensure you take some responsibility, these are then loaded from a 'config' +folder in the root directory of the project. I symlink them; +``` +mkdir config +cd config +ln -s ../src/config/rules.json . +ln -s ../src/config/interfaces.json . +ln -s ../src/config/rules-base.nft . +ln -s ../src/config/rules-locked.nft . +``` Output, when running, shows some basic stats of what has been achieved; @@ -56,11 +70,17 @@ Where A: Accepted, R: Rejected (Determined; anything other than accepted) # Customisation 'Skeleton' Configuration files may be found in `src/config`, and should -then be placed in `config/`. +then be placed in `config/` - as mentioned above' * interfaces.json - specify your trusted, and untrusted, interfaces. * rules.json - Specify what ports, in which 'trust' zones you want to allow * Note: Changes to this file are 'hot loaded'. Care should be taken. -* rules-base.nft - Is the 'initial' template of rules deployed. (Creates the +* rules-base.nft - Is the 'initial' template of rules deployed. (Creates the appropriate table, chains) * rules-locked.nft - Is basically what the script 'should' fall back to if there are any failures on init (SHOULD..) + +# Further notes: +Interfaces are detected, with appropriate rules created, upon start. This +can be troublesome for non-persistent interfaces such as vpn (ppp/tun). I +restart the scrupt upon these interfaces becoming available. (And this will +be fixed in an upcoming release) diff --git a/config b/config new file mode 120000 index 0000000..374b6ec --- /dev/null +++ b/config @@ -0,0 +1 @@ +src/config \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 83a73ca..3cb548a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,39 +4,59 @@ "lockfileVersion": 1, "requires": true, "dependencies": { - "acorn": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.5.3.tgz", - "integrity": "sha512-jd5MkIUlbbmb07nXH0DT3y7rDVtkzDi4XZOUVWAer8ajmF/DTSSbl5oNFyDOl/OXA33Bl79+ypHhl2pN20VeOQ==", - "dev": true + "@babel/code-frame": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", + "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } }, - "acorn-jsx": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", - "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", + "@babel/highlight": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", + "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", "dev": true, "requires": { - "acorn": "^3.0.4" + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" }, "dependencies": { - "acorn": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", - "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "dev": true } } }, + "acorn": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", + "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", + "dev": true + }, + "acorn-jsx": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-4.1.1.tgz", + "integrity": "sha512-JY+iV6r+cO21KtntVvFkD+iqjtdpRUpGqKWgfkCdZq1R+kbreEl8EcdcJR4SmiIgsIQT33s6QzheQ9a275Q8xw==", + "dev": true, + "requires": { + "acorn": "^5.0.3" + } + }, "ajv": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", - "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.4.tgz", + "integrity": "sha512-4Wyjt8+t6YszqaXnLDfMmG/8AlO5Zbcsy3ATHncCzjW/NoPzAId8AK6749Ybjmdt+kUY1gP60fCu46oDxPv/mg==", "dev": true, "requires": { - "co": "^4.6.0", - "fast-deep-equal": "^1.0.0", + "fast-deep-equal": "^2.0.1", "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.3.0" + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" } }, "ajv-keywords": { @@ -52,16 +72,19 @@ "dev": true }, "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } }, "argparse": { "version": "1.0.10", @@ -120,9 +143,21 @@ "js-tokens": "^3.0.2" }, "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, "chalk": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { @@ -135,12 +170,18 @@ }, "strip-ansi": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "requires": { "ansi-regex": "^2.0.0" } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true } } }, @@ -161,9 +202,9 @@ } }, "buffer-from": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.0.0.tgz", - "integrity": "sha512-83apNb8KK0Se60UE1+4Ukbe3HbfELJ6UlI4ldtOGs7So4KD26orJM8hIY9lxdzP+UpItH1Yh/Y8GUvNFWFFRxA==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", "dev": true }, "builtin-modules": { @@ -196,32 +237,12 @@ "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } } }, "chardet": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", - "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", "dev": true }, "circular-json": { @@ -252,12 +273,12 @@ "dev": true }, "color-convert": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", - "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, "requires": { - "color-name": "^1.1.1" + "color-name": "1.1.3" } }, "color-name": { @@ -303,23 +324,25 @@ "dev": true }, "cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", "dev": true, "requires": { - "lru-cache": "^4.0.1", + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", "shebang-command": "^1.2.0", "which": "^1.2.9" } }, "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.0.tgz", + "integrity": "sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg==", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "^2.1.1" } }, "debug-log": { @@ -431,48 +454,57 @@ "dev": true }, "eslint": { - "version": "4.18.2", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.18.2.tgz", - "integrity": "sha512-qy4i3wODqKMYfz9LUI8N2qYDkHkoieTbiHpMrYUI/WbjhXJQr7lI4VngixTgaG+yHX+NBCv7nW4hA0ShbvaNKw==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.7.0.tgz", + "integrity": "sha512-zYCeFQahsxffGl87U2aJ7DPyH8CbWgxBC213Y8+TCanhUTf2gEvfq3EKpHmEcozTLyPmGe9LZdMAwC/CpJBM5A==", "dev": true, "requires": { - "ajv": "^5.3.0", - "babel-code-frame": "^6.22.0", + "@babel/code-frame": "^7.0.0", + "ajv": "^6.5.3", "chalk": "^2.1.0", - "concat-stream": "^1.6.0", - "cross-spawn": "^5.1.0", - "debug": "^3.1.0", + "cross-spawn": "^6.0.5", + "debug": "^4.0.1", "doctrine": "^2.1.0", - "eslint-scope": "^3.7.1", + "eslint-scope": "^4.0.0", + "eslint-utils": "^1.3.1", "eslint-visitor-keys": "^1.0.0", - "espree": "^3.5.2", - "esquery": "^1.0.0", + "espree": "^4.0.0", + "esquery": "^1.0.1", "esutils": "^2.0.2", "file-entry-cache": "^2.0.0", "functional-red-black-tree": "^1.0.1", "glob": "^7.1.2", - "globals": "^11.0.1", - "ignore": "^3.3.3", + "globals": "^11.7.0", + "ignore": "^4.0.6", "imurmurhash": "^0.1.4", - "inquirer": "^3.0.6", - "is-resolvable": "^1.0.0", - "js-yaml": "^3.9.1", + "inquirer": "^6.1.0", + "is-resolvable": "^1.1.0", + "js-yaml": "^3.12.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.3.0", - "lodash": "^4.17.4", - "minimatch": "^3.0.2", + "lodash": "^4.17.5", + "minimatch": "^3.0.4", "mkdirp": "^0.5.1", "natural-compare": "^1.4.0", "optionator": "^0.8.2", "path-is-inside": "^1.0.2", "pluralize": "^7.0.0", "progress": "^2.0.0", + "regexpp": "^2.0.1", "require-uncached": "^1.0.3", - "semver": "^5.3.0", + "semver": "^5.5.1", "strip-ansi": "^4.0.0", - "strip-json-comments": "~2.0.1", - "table": "4.0.2", - "text-table": "~0.2.0" + "strip-json-comments": "^2.0.1", + "table": "^5.0.2", + "text-table": "^0.2.0" + }, + "dependencies": { + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + } } }, "eslint-config-semistandard": { @@ -482,9 +514,9 @@ "dev": true }, "eslint-config-standard": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-11.0.0.tgz", - "integrity": "sha512-oDdENzpViEe5fwuRCWla7AXQd++/oyIp8zP+iP9jiUPG6NBj3SHgdgtl/kTn00AjeN+1HNvavTKmYbMo+xMOlw==", + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-12.0.0.tgz", + "integrity": "sha512-COUz8FnXhqFitYj4DTqHzidjIL/t4mumGZto5c7DrBpvWoie+Sn3P4sLEzUGeYhRElWuFEf8K1S1EfvD1vixCQ==", "dev": true }, "eslint-config-standard-jsx": { @@ -511,6 +543,12 @@ "requires": { "ms": "2.0.0" } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true } } }, @@ -532,25 +570,41 @@ "requires": { "ms": "2.0.0" } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true } } }, + "eslint-plugin-es": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-1.3.1.tgz", + "integrity": "sha512-9XcVyZiQRVeFjqHw8qHNDAZcQLqaHlOGGpeYqzYh8S4JYCWTCO3yzyen8yVmA5PratfzTRWDwCOFphtDEG+w/w==", + "dev": true, + "requires": { + "eslint-utils": "^1.3.0", + "regexpp": "^2.0.0" + } + }, "eslint-plugin-import": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.8.0.tgz", - "integrity": "sha512-Rf7dfKJxZ16QuTgVv1OYNxkZcsu/hULFnC+e+w0Gzi6jMC3guQoWQgxYxc54IDRinlb6/0v5z/PxxIKmVctN+g==", + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.14.0.tgz", + "integrity": "sha512-FpuRtniD/AY6sXByma2Wr0TXvXJ4nA/2/04VPlfpmUDPOpOY264x+ILiwnrk/k4RINgDAyFZByxqPUbSQ5YE7g==", "dev": true, "requires": { - "builtin-modules": "^1.1.1", "contains-path": "^0.1.0", "debug": "^2.6.8", "doctrine": "1.5.0", "eslint-import-resolver-node": "^0.3.1", - "eslint-module-utils": "^2.1.1", + "eslint-module-utils": "^2.2.0", "has": "^1.0.1", - "lodash.cond": "^4.3.0", + "lodash": "^4.17.4", "minimatch": "^3.0.3", - "read-pkg-up": "^2.0.0" + "read-pkg-up": "^2.0.0", + "resolve": "^1.6.0" }, "dependencies": { "debug": { @@ -571,25 +625,41 @@ "esutils": "^2.0.2", "isarray": "^1.0.0" } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true } } }, "eslint-plugin-node": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-6.0.1.tgz", - "integrity": "sha512-Q/Cc2sW1OAISDS+Ji6lZS2KV4b7ueA/WydVWd1BECTQwVvfQy5JAi3glhINoKzoMnfnuRgNP+ZWKrGAbp3QDxw==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-7.0.1.tgz", + "integrity": "sha512-lfVw3TEqThwq0j2Ba/Ckn2ABdwmL5dkOgAux1rvOk6CO7A6yGyPI2+zIxN6FyNkp1X1X/BSvKOceD6mBWSj4Yw==", "dev": true, "requires": { - "ignore": "^3.3.6", + "eslint-plugin-es": "^1.3.1", + "eslint-utils": "^1.3.1", + "ignore": "^4.0.2", "minimatch": "^3.0.4", - "resolve": "^1.3.3", - "semver": "^5.4.1" + "resolve": "^1.8.1", + "semver": "^5.5.0" + }, + "dependencies": { + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + } } }, "eslint-plugin-promise": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-3.6.0.tgz", - "integrity": "sha512-YQzM6TLTlApAr7Li8vWKR+K3WghjwKcYzY0d2roWap4SLK+kzuagJX/leTetIDWsFcTFnKNJXWupDCD6aZkP2Q==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-4.0.1.tgz", + "integrity": "sha512-Si16O0+Hqz1gDHsys6RtFRrW7cCTB6P7p3OJmKp3Y3dxpQE2qwOA7d3xnV+0mBmrPoi0RBnxlCKvqu70te6wjg==", "dev": true }, "eslint-plugin-react": { @@ -605,21 +675,27 @@ } }, "eslint-plugin-standard": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-3.0.1.tgz", - "integrity": "sha1-NNDJFbRe3G8BA5PH7vOCOwhWXPI=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-4.0.0.tgz", + "integrity": "sha512-OwxJkR6TQiYMmt1EsNRMe5qG3GsbjlcOhbGUBY4LtavF9DsLaTcoR+j2Tdjqi23oUwKNUqX7qcn5fPStafMdlA==", "dev": true }, "eslint-scope": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz", - "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.0.tgz", + "integrity": "sha512-1G6UTDi7Jc1ELFwnR58HV4fK9OQK4S6N985f166xqXxpjU6plxFISJa2Ba9KCQuFa8RCnj/lSFJbHo7UFDBnUA==", "dev": true, "requires": { "esrecurse": "^4.1.0", "estraverse": "^4.1.1" } }, + "eslint-utils": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.3.1.tgz", + "integrity": "sha512-Z7YjnIldX+2XMcjr7ZkgEsOj/bREONV60qYeB/bjMAqqqZ4zxKyWX+BOUkdmRmA9riiIPVvo5x86m5elviOk0Q==", + "dev": true + }, "eslint-visitor-keys": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", @@ -627,19 +703,19 @@ "dev": true }, "espree": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", - "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-4.0.0.tgz", + "integrity": "sha512-kapdTCt1bjmspxStVKX6huolXVV5ZfyZguY1lcfhVVZstce3bqxH9mcLzNn3/mlgW6wQ732+0fuG9v7h0ZQoKg==", "dev": true, "requires": { - "acorn": "^5.5.0", - "acorn-jsx": "^3.0.0" + "acorn": "^5.6.0", + "acorn-jsx": "^4.1.1" } }, "esprima": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", - "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true }, "esquery": { @@ -673,20 +749,31 @@ "dev": true }, "external-editor": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", - "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.0.3.tgz", + "integrity": "sha512-bn71H9+qWoOQKyZDo25mOMVpSmXROAsTJVVVYzrrtol3d4y+AsKjf4Iwl2Q+IuT0kFSQ1qo166UuIwqYq7mGnA==", "dev": true, "requires": { - "chardet": "^0.4.0", - "iconv-lite": "^0.4.17", + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", "tmp": "^0.0.33" + }, + "dependencies": { + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + } } }, "fast-deep-equal": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", - "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", "dev": true }, "fast-json-stable-stringify": { @@ -808,9 +895,9 @@ } }, "globals": { - "version": "11.5.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.5.0.tgz", - "integrity": "sha512-hYyf+kI8dm3nORsiiXUQigOU62hDLfJ9G01uyGMxhc6BKsircrUhC4uJPQPUSuq2GrTmiiEt7ewxlMdBewfmKQ==", + "version": "11.8.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.8.0.tgz", + "integrity": "sha512-io6LkyPVuzCHBSQV9fmOwxZkUk6nIaGmxheLDgmuFv89j0fm2aqDbIXKAGfzCMHqz3HLF2Zf8WSG6VqMh2qFmA==", "dev": true }, "globby": { @@ -849,6 +936,14 @@ "dev": true, "requires": { "ansi-regex": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + } } }, "has-flag": { @@ -858,9 +953,9 @@ "dev": true }, "hosted-git-info": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.6.0.tgz", - "integrity": "sha512-lIbgIIQA3lz5XaB6vxakj6sDHADJiZadYEJB+FgA+C4nubM1NwcuvUr9EJPmnH1skZqpqUzWborWo8EIUi0Sdw==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", + "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", "dev": true }, "iconv-lite": { @@ -901,22 +996,21 @@ "dev": true }, "inquirer": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", - "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.2.0.tgz", + "integrity": "sha512-QIEQG4YyQ2UYZGDC4srMZ7BjHOmNk1lR2JQj5UknBapklm6WHA+VVH7N+sUdX3A7NeCfGF8o4X1S3Ao7nAcIeg==", "dev": true, "requires": { "ansi-escapes": "^3.0.0", "chalk": "^2.0.0", "cli-cursor": "^2.1.0", "cli-width": "^2.0.0", - "external-editor": "^2.0.4", + "external-editor": "^3.0.0", "figures": "^2.0.0", - "lodash": "^4.3.0", + "lodash": "^4.17.10", "mute-stream": "0.0.7", "run-async": "^2.2.0", - "rx-lite": "^4.0.8", - "rx-lite-aggregates": "^4.0.8", + "rxjs": "^6.1.0", "string-width": "^2.1.0", "strip-ansi": "^4.0.0", "through": "^2.3.6" @@ -930,7 +1024,7 @@ }, "is-builtin-module": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "resolved": "http://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", "dev": true, "requires": { @@ -1041,9 +1135,9 @@ "dev": true }, "js-yaml": { - "version": "3.11.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.11.0.tgz", - "integrity": "sha512-saJstZWv7oNeOyBh3+Dx1qWzhW0+e6/8eDzo7p5rDFqxntSztloLtuKu+Ejhtq82jsilwOIZYsCz+lIjthg1Hw==", + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", + "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", "dev": true, "requires": { "argparse": "^1.0.7", @@ -1057,9 +1151,9 @@ "dev": true }, "json-schema-traverse": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true }, "json-stable-stringify-without-jsonify": { @@ -1089,7 +1183,7 @@ }, "load-json-file": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", "dev": true, "requires": { @@ -1118,9 +1212,9 @@ } }, "lodash": { - "version": "4.17.10", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", - "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", "dev": true }, "lodash.cond": { @@ -1165,13 +1259,13 @@ }, "minimist": { "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "dev": true }, "mkdirp": { "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "dev": true, "requires": { @@ -1179,9 +1273,9 @@ } }, "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", "dev": true }, "mute-stream": { @@ -1208,6 +1302,12 @@ "nan": "^2.10.0" } }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, "node-fetch": { "version": "1.7.3", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", @@ -1334,10 +1434,16 @@ "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", "dev": true }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, "path-parse": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", - "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", "dev": true }, "path-type": { @@ -1359,7 +1465,7 @@ }, "pify": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true }, @@ -1466,9 +1572,9 @@ "dev": true }, "progress": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz", - "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.1.tgz", + "integrity": "sha512-OE+a6vzqazc+K6LxJrX5UPyKFvGnL5CYmq2jFGNIBWHpc4QyE49/YOumcrpQFJpfejmvRtbJzgO1zPmMCqlbBg==", "dev": true }, "promise": { @@ -1497,6 +1603,12 @@ "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", "dev": true }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, "read-pkg": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", @@ -1531,7 +1643,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { @@ -1544,6 +1656,12 @@ "util-deprecate": "~1.0.1" } }, + "regexpp": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", + "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", + "dev": true + }, "require-uncached": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", @@ -1555,9 +1673,9 @@ } }, "resolve": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.7.1.tgz", - "integrity": "sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz", + "integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==", "dev": true, "requires": { "path-parse": "^1.0.5" @@ -1618,6 +1736,15 @@ "rx-lite": "*" } }, + "rxjs": { + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.3.3.tgz", + "integrity": "sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", @@ -1646,12 +1773,268 @@ "eslint-plugin-react": "~7.6.1", "eslint-plugin-standard": "~3.0.1", "standard-engine": "~8.0.0" + }, + "dependencies": { + "acorn-jsx": { + "version": "3.0.1", + "resolved": "http://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", + "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", + "dev": true, + "requires": { + "acorn": "^3.0.4" + }, + "dependencies": { + "acorn": { + "version": "3.3.0", + "resolved": "http://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", + "dev": true + } + } + }, + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "dev": true, + "requires": { + "co": "^4.6.0", + "fast-deep-equal": "^1.0.0", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.3.0" + } + }, + "chardet": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", + "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", + "dev": true + }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "eslint": { + "version": "4.18.2", + "resolved": "http://registry.npmjs.org/eslint/-/eslint-4.18.2.tgz", + "integrity": "sha512-qy4i3wODqKMYfz9LUI8N2qYDkHkoieTbiHpMrYUI/WbjhXJQr7lI4VngixTgaG+yHX+NBCv7nW4hA0ShbvaNKw==", + "dev": true, + "requires": { + "ajv": "^5.3.0", + "babel-code-frame": "^6.22.0", + "chalk": "^2.1.0", + "concat-stream": "^1.6.0", + "cross-spawn": "^5.1.0", + "debug": "^3.1.0", + "doctrine": "^2.1.0", + "eslint-scope": "^3.7.1", + "eslint-visitor-keys": "^1.0.0", + "espree": "^3.5.2", + "esquery": "^1.0.0", + "esutils": "^2.0.2", + "file-entry-cache": "^2.0.0", + "functional-red-black-tree": "^1.0.1", + "glob": "^7.1.2", + "globals": "^11.0.1", + "ignore": "^3.3.3", + "imurmurhash": "^0.1.4", + "inquirer": "^3.0.6", + "is-resolvable": "^1.0.0", + "js-yaml": "^3.9.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.4", + "minimatch": "^3.0.2", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.2", + "path-is-inside": "^1.0.2", + "pluralize": "^7.0.0", + "progress": "^2.0.0", + "require-uncached": "^1.0.3", + "semver": "^5.3.0", + "strip-ansi": "^4.0.0", + "strip-json-comments": "~2.0.1", + "table": "4.0.2", + "text-table": "~0.2.0" + } + }, + "eslint-config-standard": { + "version": "11.0.0", + "resolved": "http://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-11.0.0.tgz", + "integrity": "sha512-oDdENzpViEe5fwuRCWla7AXQd++/oyIp8zP+iP9jiUPG6NBj3SHgdgtl/kTn00AjeN+1HNvavTKmYbMo+xMOlw==", + "dev": true + }, + "eslint-plugin-import": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.8.0.tgz", + "integrity": "sha512-Rf7dfKJxZ16QuTgVv1OYNxkZcsu/hULFnC+e+w0Gzi6jMC3guQoWQgxYxc54IDRinlb6/0v5z/PxxIKmVctN+g==", + "dev": true, + "requires": { + "builtin-modules": "^1.1.1", + "contains-path": "^0.1.0", + "debug": "^2.6.8", + "doctrine": "1.5.0", + "eslint-import-resolver-node": "^0.3.1", + "eslint-module-utils": "^2.1.1", + "has": "^1.0.1", + "lodash.cond": "^4.3.0", + "minimatch": "^3.0.3", + "read-pkg-up": "^2.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "doctrine": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "isarray": "^1.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "eslint-plugin-node": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-6.0.1.tgz", + "integrity": "sha512-Q/Cc2sW1OAISDS+Ji6lZS2KV4b7ueA/WydVWd1BECTQwVvfQy5JAi3glhINoKzoMnfnuRgNP+ZWKrGAbp3QDxw==", + "dev": true, + "requires": { + "ignore": "^3.3.6", + "minimatch": "^3.0.4", + "resolve": "^1.3.3", + "semver": "^5.4.1" + } + }, + "eslint-plugin-promise": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-3.6.0.tgz", + "integrity": "sha512-YQzM6TLTlApAr7Li8vWKR+K3WghjwKcYzY0d2roWap4SLK+kzuagJX/leTetIDWsFcTFnKNJXWupDCD6aZkP2Q==", + "dev": true + }, + "eslint-plugin-standard": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-3.0.1.tgz", + "integrity": "sha1-NNDJFbRe3G8BA5PH7vOCOwhWXPI=", + "dev": true + }, + "eslint-scope": { + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.3.tgz", + "integrity": "sha512-W+B0SvF4gamyCTmUc+uITPY0989iXVfKvhwtmJocTaYoc/3khEHmEmvfY/Gn9HA9VV75jrQECsHizkNw1b68FA==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "espree": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", + "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", + "dev": true, + "requires": { + "acorn": "^5.5.0", + "acorn-jsx": "^3.0.0" + } + }, + "external-editor": { + "version": "2.2.0", + "resolved": "http://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", + "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", + "dev": true, + "requires": { + "chardet": "^0.4.0", + "iconv-lite": "^0.4.17", + "tmp": "^0.0.33" + } + }, + "fast-deep-equal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", + "dev": true + }, + "inquirer": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", + "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", + "dev": true, + "requires": { + "ansi-escapes": "^3.0.0", + "chalk": "^2.0.0", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^2.0.4", + "figures": "^2.0.0", + "lodash": "^4.3.0", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rx-lite": "^4.0.8", + "rx-lite-aggregates": "^4.0.8", + "string-width": "^2.1.0", + "strip-ansi": "^4.0.0", + "through": "^2.3.6" + } + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", + "dev": true + }, + "table": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz", + "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", + "dev": true, + "requires": { + "ajv": "^5.2.3", + "ajv-keywords": "^2.1.0", + "chalk": "^2.1.0", + "lodash": "^4.17.4", + "slice-ansi": "1.0.0", + "string-width": "^2.1.1" + } + } } }, "semver": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", - "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", + "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", "dev": true }, "setimmediate": { @@ -1699,9 +2082,9 @@ } }, "spdx-correct": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz", - "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.2.tgz", + "integrity": "sha512-q9hedtzyXHr5S0A1vEPoK/7l8NpfkFYTq6iCY+Pno2ZbdZR6WexZFtqeVGkGxW3TEJMN914Z55EnAGMmenlIQQ==", "dev": true, "requires": { "spdx-expression-parse": "^3.0.0", @@ -1709,9 +2092,9 @@ } }, "spdx-exceptions": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz", - "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", "dev": true }, "spdx-expression-parse": { @@ -1725,9 +2108,9 @@ } }, "spdx-license-ids": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz", - "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.1.tgz", + "integrity": "sha512-TfOfPcYGBB5sDuPn3deByxPhmfegAhpDYKSOXZQN81Oyrrif8ZCodOLzK3AesELnCx03kikhyDwh0pfvvQvF8w==", "dev": true }, "sprintf-js": { @@ -1782,14 +2165,6 @@ "dev": true, "requires": { "ansi-regex": "^3.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - } } }, "strip-bom": { @@ -1805,21 +2180,22 @@ "dev": true }, "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } }, "table": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz", - "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/table/-/table-5.1.0.tgz", + "integrity": "sha512-e542in22ZLhD/fOIuXs/8yDZ9W61ltF8daM88rkRNtgTIct+vI2fTnAyu/Db2TCfEcI8i7mjZz6meLq0nW7TYg==", "dev": true, "requires": { - "ajv": "^5.2.3", - "ajv-keywords": "^2.1.0", - "chalk": "^2.1.0", - "lodash": "^4.17.4", + "ajv": "^6.5.3", + "lodash": "^4.17.10", "slice-ansi": "1.0.0", "string-width": "^2.1.1" } @@ -1832,7 +2208,7 @@ }, "through": { "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz", "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", "dev": true }, @@ -1845,6 +2221,12 @@ "os-tmpdir": "~1.0.2" } }, + "tslib": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", + "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==", + "dev": true + }, "type-check": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", @@ -1872,6 +2254,15 @@ "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", "dev": true }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -1879,9 +2270,9 @@ "dev": true }, "validate-npm-package-license": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz", - "integrity": "sha512-63ZOUnL4SIXj4L0NixR3L1lcjO38crAbgrTpl28t8jjrfuiOBL5Iygm+60qPs/KsZGzPNg6Smnc/oY16QTjF0g==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", "dev": true, "requires": { "spdx-correct": "^3.0.0", @@ -1895,9 +2286,9 @@ "dev": true }, "which": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", - "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, "requires": { "isexe": "^2.0.0" diff --git a/package.json b/package.json index cf4d1ce..aabe0bd 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,12 @@ "pcap": "https://github.com/dmblack/node_pcap.git" }, "devDependencies": { + "eslint": "^5.7.0", + "eslint-config-standard": "^12.0.0", + "eslint-plugin-import": "^2.14.0", + "eslint-plugin-node": "^7.0.1", + "eslint-plugin-promise": "^4.0.1", + "eslint-plugin-standard": "^4.0.0", "semistandard": "^12.0.1" } } diff --git a/src/actions/filesystem.js b/src/actions/filesystem.js index b0c7ab2..08cde28 100644 --- a/src/actions/filesystem.js +++ b/src/actions/filesystem.js @@ -2,18 +2,18 @@ function write (fs, content) { return new Promise((resolve, reject) => { fs.appendFile('./logs/logger.log', content + '\n', (error) => { if (error) { - reject(error); + reject(error) } else { - resolve(); + resolve() } - }); - }); + }) + }) } const filesystem = (fs) => ({ log: (content) => { - return write(fs, content); + return write(fs, content) } -}); +}) -module.exports = filesystem; +module.exports = filesystem diff --git a/src/actions/index.js b/src/actions/index.js index 812cb0b..d5aabe2 100644 --- a/src/actions/index.js +++ b/src/actions/index.js @@ -1,4 +1,4 @@ -const filesystem = require('./filesystem'); +const filesystem = require('./filesystem') const actions = (dependencies) => { if (Object.keys(dependencies).includes('fs')) { @@ -6,10 +6,10 @@ const actions = (dependencies) => { {}, actions, filesystem(dependencies.fs) - ); + ) } - return false; -}; + return false +} -module.exports = actions; +module.exports = actions diff --git a/src/config/interfaces.json b/src/config/interfaces.json index e942e49..9ad9123 100644 --- a/src/config/interfaces.json +++ b/src/config/interfaces.json @@ -1,17 +1,21 @@ { "detail": "This file should be copied into './config/' and setup as necessary.", "interfaces": { - "lo": { - "zone": "trusted" - }, "enp0s25": { "zone": "untrusted" }, - "tun0": { + "lo": { "zone": "trusted" }, + "tun0": { + "zone": "trusted", + "required": "true", + "persistent": "true" + }, "wlo1": { - "zone": "untrusted" + "zone": "untrusted", + "required": "true", + "persistent": "true" } } } diff --git a/src/config/rules.json b/src/config/rules.json index 968503f..9c8ff57 100644 --- a/src/config/rules.json +++ b/src/config/rules.json @@ -5,31 +5,36 @@ "_1": "ICMP", "1": { "global": { - "policy": "reject" + "policy": "reject", + "action": "log" }, "trusted": { "policy": "accept" }, "untrusted": { - "policy": "reject" + "policy": "reject", + "action": "log" } }, "_2": "IGMP", "2": { "global": { - "policy": "reject" + "policy": "reject", + "action": "log" }, "trusted": { "policy": "accept" }, "untrusted": { - "policy": "reject" + "policy": "reject", + "action": "log" } }, "_6": "TCP", "6": { "global": { - "policy": "reject" + "policy": "reject", + "action": "log" }, "trusted": { "policy": "accept", @@ -43,13 +48,15 @@ } }, "untrusted": { - "policy": "reject" + "policy": "reject", + "action": "log" } }, "_17": "UDP", "17": { "global": { - "policy": "reject" + "policy": "reject", + "action": "log" }, "trusted": { "policy": "accept", @@ -63,7 +70,8 @@ } }, "untrusted": { - "policy": "reject" + "policy": "reject", + "action": "log" } } }, @@ -191,8 +199,7 @@ "policy": "accept" }, "9981": { - "policy": "accept", - "action": "log" + "policy": "accept" } } }, diff --git a/src/index.js b/src/index.js index cc8758b..0272059 100644 --- a/src/index.js +++ b/src/index.js @@ -1,88 +1,97 @@ // // Rewrite to enable nodewatch CD // -const sysClassNetInterfaces = '/sys/class/net/'; -const fs = require('fs'); -const nfq = require('nfqueue'); -const IPv4 = require('pcap/decode/ipv4'); -const { exec } = require('child_process'); -const nft = require('./nftables')({ exec: exec }); -const netFilterPacket = require('./nfpacket')({ nfq: nfq, pcapIPv4: IPv4 }); -const actions = require('./actions')({ fs: fs }); +console.log(process.env.debug) +const debug = process.env.debug === 1 +const sysClassNetInterfaces = '/sys/class/net/' +const fs = require('fs') +const nfq = require('nfqueue') +const IPv4 = require('pcap/decode/ipv4') +const { exec } = require('child_process') +const nft = require('./nftables')({ exec: exec }) +const netFilterPacket = require('./nfpacket')({ nfq: nfq, pcapIPv4: IPv4 }) +const actions = require('./actions')({ fs: fs }) // The buffer size we will use binding to nfqueues. -const buffer = 131070; +const buffer = 131070 -process.stdout.write('\x1Bc'); +process.stdout.write('\x1Bc') -let rules = require('./config/rules.json').rules; -let systemInterfaces = require('./config/interfaces.json').interfaces; +let rules = require('./config/rules.json').rules +let systemInterfaces = require('./config/interfaces.json').interfaces -fs.watch('./config', checkConfig); +fs.watch('./config', checkConfig) function checkConfig (eventType, filename) { setTimeout(() => { switch (filename) { case 'rules.json': - console.log('Rules Configuration Changed - Reloding..'); + console.log('Rules Configuration Changed - Reloding..') fs.readFile('./config/rules.json', 'utf8', (err, data) => { - if (err) throw err; - let newRules = JSON.parse(data); - rules = newRules.rules; - }); - break; + if (err) throw err + let newRules = JSON.parse(data) + rules = newRules.rules + }) + break case 'interfaces.json': - console.log('Interfaces Configuration Changed - Reloding..'); + console.log('Interfaces Configuration Changed - Reloding..') fs.readFile('./config/interfaces.json', 'utf8', (err, data) => { - if (err) throw err; - let newInterfaces = JSON.parse(data); + if (err) throw err + let newInterfaces = JSON.parse(data) Object.keys(newInterfaces.interfaces).forEach(newNetworkInterface => { interfaces.forEach(thisInterface => { if (thisInterface.name === newNetworkInterface && thisInterface.zone !== newInterfaces.interfaces[newNetworkInterface].zone) { - thisInterface.zone = newInterfaces.interfaces[newNetworkInterface].zone; + thisInterface.zone = newInterfaces.interfaces[newNetworkInterface].zone } - }); - }); + }) + }) - systemInterfaces = newInterfaces.interfaces; - }); - break; + systemInterfaces = newInterfaces.interfaces + }) + break } - }, 500); + }, 500) } // Some counters for connection analysis (Used for stdio) -let packetsIn = 0; -let packetsInAccept = 0; -let packetsOut = 0; -let packetsOutAccept = 0; +let packetsIn = 0 +let packetsInAccept = 0 +let packetsOut = 0 +let packetsOutAccept = 0 // An array to store our interfaces. -let interfaces = []; +let interfaces = [] // Sets base rules, with default to 'drop', but allows established and related connections. function insertFinalCounters () { return Promise.all([ nft.add('rule ip filter input counter'), nft.add('rule ip filter output counter') - ]); + ]) } function insertInterfaceRules (networkInterface) { + console.log('This network interface: %s', networkInterface); + const interfaceSelector = typeof(networkInterface.persistent) !== 'undefined' + ? networkInterface.persistent === true + ? 'if' + : 'ifname' + : 'ifname' + return Promise.all([ - nft.add('rule ip filter input iif ' + networkInterface.name + ' counter nftrace set 1 queue num ' + networkInterface.number), + nft.add('rule ip filter input i' + interfaceSelector + ' ' + networkInterface.name + ' counter nftrace set 1 queue num ' + networkInterface.number), // nft.add('rule ip filter input iif ' + networkInterface.name + ' meta mark 9999 counter nftrace set 1 queue num 200' + networkInterface.number), - nft.add('rule ip filter output oif ' + networkInterface.name + ' counter nftrace set 1 queue num 100' + networkInterface.number) + nft.add('rule ip filter output o' + interfaceSelector + ' ' + networkInterface.name + ' counter nftrace set 1 queue num 100' + networkInterface.number) // nft.add('rule ip filter output oif ' + networkInterface.name + ' meta mark 9999 counter nftrace set 1 queue num 210' + networkInterface.number) - ]); + ]) } function getInterfaces (path) { - const interfaces = fs.readdirSync(path); + const interfaces = fs.readdirSync(path) return interfaces instanceof (Array) ? interfaces - : []; + : [] } /** @@ -95,56 +104,41 @@ function runPromiseArrayInSequence (arr) { return arr.reduce((promiseChain, currentPromise) => { return promiseChain.then((chainedResult) => { return currentPromise(chainedResult) - .then((res) => res); - }); - }, Promise.resolve()); + .then((res) => res) + }) + }, Promise.resolve()) } function setupInterfaces () { - let interfacePromises = []; + let interfacePromises = [] getInterfaces(sysClassNetInterfaces).forEach(networkInterface => { - let zone = 'untrusted'; - if (systemInterfaces[networkInterface] && systemInterfaces[networkInterface].zone) { - zone = systemInterfaces[networkInterface].zone || 'untrusted'; + let zone = 'untrusted' + if (systemInterfaces[networkInterface]) { + zone = systemInterfaces[networkInterface].zone + ? systemInterfaces[networkInterface].zone + : 'untrusted' + persistent = systemInterfaces[networkInterface].persistent + ? systemInterfaces[networkInterface].persistent + : false + } - let newInterface = { name: networkInterface, number: interfaces.length + 1, zone }; - interfacePromises.push(() => insertInterfaceRules(newInterface)); - interfaces.push(newInterface); - }); + let newInterface = { name: networkInterface, number: interfaces.length + 1, zone, } + interfacePromises.push(() => insertInterfaceRules(newInterface)) + interfaces.push(newInterface) + }) - return runPromiseArrayInSequence(interfacePromises); + return runPromiseArrayInSequence(interfacePromises) } function handleActions (action, packet) { switch (action) { case 'log': - actions.log(JSON.stringify(packet)); - break; + actions.log(JSON.stringify(packet)) + break default: - break; - } -} - -function handlePacket1(packet) { - // Set our default action (Reject!)Reject - rule = getRule(packet); - packet.verdict = typeof(rule) === 'undefined' - ? packet.enums.netfilterVerdict.NF_REJECT - : packet.enums.netfilterVerdict[rule.policy]; - - console.log(rule); - packet.action = typeof (rule) === 'undefined' - ? undefined - : rule.action; - - packet.action = undefined; - - if (typeof(getRule(packet)) !== 'undefined') { - packet.verdict = getRule(packet) + break } - - return packet.verdicts.getVerdict(); } const findRule = (packet) => { @@ -152,108 +146,103 @@ const findRule = (packet) => { // protocol // zone // *port (not applicable for some protocols) - const direction = packet.direction; - const protocol = packet.nfpacketDecoded.protocol.toString(); - const zone = packet.networkInterface.zone || 'untrusted'; - const targetPort = packet.nfpacketDecoded.payload.dport || undefined; - const sourcePort = packet.nfpacketDecoded.payload.sport || undefined; - const flags = packet.nfpacketDecoded.payload.flags || undefined; - packet.verdict = undefined; + const direction = packet.direction + const protocol = packet.nfpacketDecoded.protocol.toString() + const zone = packet.networkInterface.zone || 'untrusted' + const targetPort = packet.nfpacketDecoded.payload.dport || undefined + const sourcePort = packet.nfpacketDecoded.payload.sport || undefined + const flags = packet.nfpacketDecoded.payload.flags || undefined + packet.verdict = undefined // Check if related connection if (targetPort && sourcePort) { - // catch explicit rule direction, protocol, zone, and port - if (rules[direction] && rules[direction][protocol] && rules[direction][protocol][zone] && rules[direction][protocol][zone].ports) { - packet.verdict = rules[direction][protocol][zone].ports[targetPort] - ? packet.enums.ruleVerdict[rules[direction][protocol][zone].ports[targetPort].policy] - : undefined; - packet.action = rules[direction][protocol][zone].ports[targetPort] - ? rules[direction][protocol][zone].ports[targetPort].action - : undefined; - } - - if (typeof(packet.verdict) !== 'undefined') { - console.log('We found an explicit rule for direction: %s, zone: %s, protocol: %s, target port: %s', direction, zone, protocol, targetPort); + // catch explicit rule direction, protocol, zone, and port + if (rules[direction] && rules[direction][protocol] && rules[direction][protocol][zone] && rules[direction][protocol][zone].ports) { + packet.verdict = rules[direction][protocol][zone].ports[targetPort] + ? packet.enums.ruleVerdict[rules[direction][protocol][zone].ports[targetPort].policy] + : undefined + packet.action = rules[direction][protocol][zone].ports[targetPort] + ? rules[direction][protocol][zone].ports[targetPort].action + : undefined } + if (typeof (packet.verdict) !== 'undefined' && debug) { + console.log('We found an explicit rule for direction: %s, zone: %s, protocol: %s, target port: %s', direction, zone, protocol, targetPort) + } - - // Catch 'global' zone policy - if (rules[direction] && rules[direction][protocol] && rules[direction][protocol].global && typeof(packet.verdict) === 'undefined') { - if (rules[direction][protocol].global.ports) { - packet.verdict = rules[direction][protocol].global.ports[targetPort] - ? packet.enums.ruleVerdict[rules[direction][protocol].global.ports[targetPort].policy] - : undefined; - packet.action = rules[direction][protocol].global.ports[targetPort] - ? rules[direction][protocol].global.ports[targetPort].action - : undefined; - } else { - packet.verdict = rules[direction][protocol].global - ? packet.enums.ruleVerdict[rules[direction][protocol].global.policy] - : undefined; - packet.action = rules[direction][protocol].global - ? rules[direction][protocol].global.action - : undefined; - } - if (typeof(packet.verdict) !== 'undefined') { - console.log('We found a global rule for direction: %s, zone: %s, protocol: %s, target port: %s', direction, zone, protocol, targetPort); - } - - } - - // Catch 'zone' default policy (Eg; trusted; accept) - if (rules[direction] && rules[direction][protocol] && rules[direction][protocol][zone] && typeof(packet.verdict) === 'undefined') { - packet.verdict = rules[direction][protocol][zone] - ? packet.enums.ruleVerdict[rules[direction][protocol][zone].policy] - : undefined; - packet.action = rules[direction][protocol][zone] - ? rules[direction][protocol][zone].action - : undefined; - if (typeof(packet.verdict) !== 'undefined') { - console.log('We found a default zone policy for direction: %s, zone: %s, protocol: %s, target port: %s', direction, zone, protocol, targetPort); - } - } - - } else { - if (rules[direction] && rules[direction][protocol] && rules[direction][protocol][zone] && typeof(packet.verdict) === 'undefined') { - packet.verdict = rules[direction][protocol][zone] - ? packet.enums.ruleVerdict[rules[direction][protocol][zone].policy] - : undefined; - packet.action = rules[direction][protocol][zone] - ? rules[direction][protocol][zone].action - : undefined; - } else if (rules[direction] && rules[direction][protocol] && rules[direction][protocol].global && typeof(packet.verdict) === 'undefined') { - packet.verdict= rules[direction][protocol].global + // Catch 'global' zone policy + if (rules[direction] && rules[direction][protocol] && rules[direction][protocol].global && typeof (packet.verdict) === 'undefined') { + if (rules[direction][protocol].global.ports) { + packet.verdict = rules[direction][protocol].global.ports[targetPort] + ? packet.enums.ruleVerdict[rules[direction][protocol].global.ports[targetPort].policy] + : undefined + packet.action = rules[direction][protocol].global.ports[targetPort] + ? rules[direction][protocol].global.ports[targetPort].action + : undefined + } else { + packet.verdict = rules[direction][protocol].global ? packet.enums.ruleVerdict[rules[direction][protocol].global.policy] - : undefined; + : undefined packet.action = rules[direction][protocol].global ? rules[direction][protocol].global.action - : undefined; + : undefined } - } - + if (typeof (packet.verdict) !== 'undefined' && debug) { + console.log('We found a global rule for direction: %s, zone: %s, protocol: %s, target port: %s', direction, zone, protocol, targetPort) + } + } - if (typeof(packet.verdict) === 'unefined') { - console.log('We did not find a rule for zone: %s, direction %s, protocol, %s, packet target port: %s', zone, direction, protocol, targetPort); + // Catch 'zone' default policy (Eg; trusted; accept) + if (rules[direction] && rules[direction][protocol] && rules[direction][protocol][zone] && typeof (packet.verdict) === 'undefined') { + packet.verdict = rules[direction][protocol][zone] + ? packet.enums.ruleVerdict[rules[direction][protocol][zone].policy] + : undefined + packet.action = rules[direction][protocol][zone] + ? rules[direction][protocol][zone].action + : undefined + if (typeof (packet.verdict) !== 'undefined' && debug) { + console.log('We found a default zone policy for direction: %s, zone: %s, protocol: %s, target port: %s', direction, zone, protocol, targetPort) + } + } } else { + if (rules[direction] && rules[direction][protocol] && rules[direction][protocol][zone] && typeof (packet.verdict) === 'undefined') { + packet.verdict = rules[direction][protocol][zone] + ? packet.enums.ruleVerdict[rules[direction][protocol][zone].policy] + : undefined + packet.action = rules[direction][protocol][zone] + ? rules[direction][protocol][zone].action + : undefined + } else if (rules[direction] && rules[direction][protocol] && rules[direction][protocol].global && typeof (packet.verdict) === 'undefined') { + packet.verdict = rules[direction][protocol].global + ? packet.enums.ruleVerdict[rules[direction][protocol].global.policy] + : undefined + packet.action = rules[direction][protocol].global + ? rules[direction][protocol].global.action + : undefined + } + } + + if (typeof (packet.verdict) === 'unefined' && debug) { + console.log('We did not find a rule for zone: %s, direction %s, protocol, %s, packet target port: %s', zone, direction, protocol, targetPort) + } else if (debug) { console.log('Verdict: %s', packet.verdict) } } -function handlePacket(packet) { - findRule(packet); +function handlePacket (packet) { + findRule(packet) if (packet.action) { handleActions(packet.action, packet) } - return packet.verdicts.getVerdict(); + return packet.verdicts.getVerdict() } -function noLongerUsed(packet) { +function noLongerUsed (packet) { // Check we even handle this protocol if (rules[packet.direction][packet.nfpacketDecoded.protocol.toString()]) { // Check if the global (blanket) rule applies if (rules[packet.direction][packet.nfpacketDecoded.protocol.toString()].global.policy && rules[packet.direction][packet.nfpacketDecoded.protocol.toString()].global.policy === 'allow') { // Trigger the callback, if it exists.. if (rules[packet.direction][packet.nfpacketDecoded.protocol.toString()].global.action) { - handleActions(rules[packet.direction][packet.nfpacketDecoded.protocol.toString()].global.action, packet); + handleActions(rules[packet.direction][packet.nfpacketDecoded.protocol.toString()].global.action, packet) } // Check if the global setting has any specific ports if (rules[packet.direction][packet.nfpacketDecoded.protocol.toString()].global.ports) { @@ -262,21 +251,21 @@ function noLongerUsed(packet) { // Check if the policy is allow if (rules[packet.direction][packet.nfpacketDecoded.protocol.toString()].global.ports[packet.nfpacketDecoded.payload.dport].policy && rules[packet.direction][packet.nfpacketDecoded.protocol.toString()].global.ports[packet.nfpacketDecoded.payload.dport].policy === 'allow') { // Set to accept packet. - packet.verdict = packet.enums.netfilterVerdict.NF_ACCEPT; + packet.verdict = packet.enums.netfilterVerdict.NF_ACCEPT } // Finally - if the port is allowed, check if there's a callback to trigger. if (rules[packet.direction][packet.nfpacketDecoded.protocol.toString()].global.ports[packet.nfpacketDecoded.payload.dport].action) { - handleActions(rules[packet.direction][packet.nfpacketDecoded.protocol.toString()].global.ports[packet.nfpacketDecoded.payload.dport].action, packet); + handleActions(rules[packet.direction][packet.nfpacketDecoded.protocol.toString()].global.ports[packet.nfpacketDecoded.payload.dport].action, packet) } // Do not further traverse ruleset, or this function ; wasted cycles. - return packet.verdicts.getVerdict(); + return packet.verdicts.getVerdict() } // The global default is enabled, yet there is no ports key.. // (Likely) means this is a port-less protocol, or a blanket 'allow' rule is in place. } else { - packet.verdict = packet.enums.netfilterVerdict.NF_ACCEPT; - return packet.verdicts.getVerdict(); + packet.verdict = packet.enums.netfilterVerdict.NF_ACCEPT + return packet.verdicts.getVerdict() // packet.nfpacket.setVerdict(packet.verdict, packet.mark); } // Else, as if globally accepted we don't need to traverse other zones. @@ -289,22 +278,22 @@ function noLongerUsed(packet) { if (rules[packet.direction][packet.nfpacketDecoded.protocol.toString()][packet.networkInterface.zone].policy && rules[packet.direction][packet.nfpacketDecoded.protocol.toString()][packet.networkInterface.zone].policy === 'allow') { // Trigger the protocol zone callback, if it exists. if (rules[packet.direction][packet.nfpacketDecoded.protocol.toString()][packet.networkInterface.zone].action) { - handleActions(rules[packet.direction][packet.nfpacketDecoded.protocol.toString()][packet.networkInterface.zone].action, packet); + handleActions(rules[packet.direction][packet.nfpacketDecoded.protocol.toString()][packet.networkInterface.zone].action, packet) } // Check if the protocol's zone setting has any specific ports if (rules[packet.direction][packet.nfpacketDecoded.protocol.toString()][packet.networkInterface.zone].ports) { // Check, if there are ports, if the port is allowed. if (rules[packet.direction][packet.nfpacketDecoded.protocol.toString()][packet.networkInterface.zone].ports[packet.nfpacketDecoded.payload.dport] && rules[packet.direction][packet.nfpacketDecoded.protocol.toString()][packet.networkInterface.zone].ports[packet.nfpacketDecoded.payload.dport].policy && rules[packet.direction][packet.nfpacketDecoded.protocol.toString()][packet.networkInterface.zone].ports[packet.nfpacketDecoded.payload.dport].policy === 'allow') { - packet.verdict = packet.enums.netfilterVerdict.NF_ACCEPT; + packet.verdict = packet.enums.netfilterVerdict.NF_ACCEPT // Finally - if the port is allowed, check if there's a callback to trigger. if (rules[packet.direction][packet.nfpacketDecoded.protocol.toString()][packet.networkInterface.zone].ports[packet.nfpacketDecoded.payload.dport].action) { - handleActions(rules[packet.direction][packet.nfpacketDecoded.protocol.toString()][packet.networkInterface.zone].ports[packet.nfpacketDecoded.payload.dport].action, packet); + handleActions(rules[packet.direction][packet.nfpacketDecoded.protocol.toString()][packet.networkInterface.zone].ports[packet.nfpacketDecoded.payload.dport].action, packet) } } // The global default is enabled, yet there are no ports.. which likely // Means this is a port-less protocol. } else { - packet.verdict = packet.enums.netfilterVerdict.NF_ACCEPT; + packet.verdict = packet.enums.netfilterVerdict.NF_ACCEPT } } } @@ -319,102 +308,102 @@ function noLongerUsed(packet) { // Check if the policy is allow if (rules['outgoing'][packet.nfpacketDecoded.protocol.toString()].global.ports[packet.nfpacketDecoded.payload.sport].policy && rules['outgoing'][packet.nfpacketDecoded.protocol.toString()].global.ports[packet.nfpacketDecoded.payload.sport].policy === 'allow') { // Set to accept packet. - packet.verdict = packet.enums.netfilterVerdict.NF_ACCEPT; + packet.verdict = packet.enums.netfilterVerdict.NF_ACCEPT } // Finally - if the port is allowed, check if there's a callback to trigger. if (rules['outgoing'][packet.nfpacketDecoded.protocol.toString()].global.ports[packet.nfpacketDecoded.payload.sport].action) { - handleActions(rules['outgoing'][packet.nfpacketDecoded.protocol.toString()].global.ports[packet.nfpacketDecoded.payload.sport].action, packet); + handleActions(rules['outgoing'][packet.nfpacketDecoded.protocol.toString()].global.ports[packet.nfpacketDecoded.payload.sport].action, packet) } // Do not further traverse ruleset, or this function ; wasted cycles. - return packet.verdicts.getVerdict(); + return packet.verdicts.getVerdict() // packet.nfpacket.setVerdict(packet.verdict, packet.mark); } } if (rules['outgoing'][packet.nfpacketDecoded.protocol.toString()][packet.networkInterface.zone] && rules['outgoing'][packet.nfpacketDecoded.protocol.toString()][packet.networkInterface.zone].ports && rules['outgoing'][packet.nfpacketDecoded.protocol.toString()][packet.networkInterface.zone].ports[packet.nfpacketDecoded.payload.sport] && rules['outgoing'][packet.nfpacketDecoded.protocol.toString()][packet.networkInterface.zone].ports[packet.nfpacketDecoded.payload.sport].policy && rules['outgoing'][packet.nfpacketDecoded.protocol.toString()][packet.networkInterface.zone].ports[packet.nfpacketDecoded.payload.sport].policy === 'allow') { - packet.verdict = packet.enums.netfilterVerdict.NF_ACCEPT; + packet.verdict = packet.enums.netfilterVerdict.NF_ACCEPT // Finally - if the port is allowed, check if there's a callback to trigger. if (rules['outgoing'][packet.nfpacketDecoded.protocol.toString()][packet.networkInterface.zone].ports[packet.nfpacketDecoded.payload.sport].action) { - handleActions(rules['outgoing'][packet.nfpacketDecoded.protocol.toString()][packet.networkInterface.zone].ports[packet.nfpacketDecoded.payload.sport].action, packet); + handleActions(rules['outgoing'][packet.nfpacketDecoded.protocol.toString()][packet.networkInterface.zone].ports[packet.nfpacketDecoded.payload.sport].action, packet) } } } - return packet.verdicts.getVerdict(); + return packet.verdicts.getVerdict() } function updateOutput () { - process.stdout.write('\x1Bc'); - let packetsInReject = packetsIn - packetsInAccept; - let packetsOutReject = packetsOut - packetsOutAccept; + process.stdout.write('\x1Bc') + let packetsInReject = packetsIn - packetsInAccept + let packetsOutReject = packetsOut - packetsOutAccept - process.stdout.write('Packets: ' + (packetsIn + packetsOut) + ' - IN: ' + packetsIn + ' (A: ' + packetsInAccept + ' - R: ' + packetsInReject + ') - OUT: ' + packetsOut + ' (A: ' + packetsOutAccept + ' - R: ' + packetsOutReject + ')\r');// - Accepted: ' + packetsAccepted + ' (I: ' + packetsAcceptedIn + ' O: ' + packetsAcceptedOut + ') - Rejected: ' + packetsRejected + ' (I: ' + packetsRejectedIn + ' O: ' + packetsRejectedOut + ')\r'); + process.stdout.write('Packets: ' + (packetsIn + packetsOut) + ' - IN: ' + packetsIn + ' (A: ' + packetsInAccept + ' - R: ' + packetsInReject + ') - OUT: ' + packetsOut + ' (A: ' + packetsOutAccept + ' - R: ' + packetsOutReject + ')\r')// - Accepted: ' + packetsAccepted + ' (I: ' + packetsAcceptedIn + ' O: ' + packetsAcceptedOut + ') - Rejected: ' + packetsRejected + ' (I: ' + packetsRejectedIn + ' O: ' + packetsRejectedOut + ')\r'); } function bindQueueHandlers () { interfaces.forEach(networkInterface => { networkInterface.queueIn = nfq.createQueueHandler(parseInt(networkInterface.number), buffer, (nfpacket) => { - packetsIn++; - let thisPacket = netFilterPacket(nfpacket); - thisPacket.direction = 'incoming'; - thisPacket.networkInterface = networkInterface; + packetsIn++ + let thisPacket = netFilterPacket(nfpacket) + thisPacket.direction = 'incoming' + thisPacket.networkInterface = networkInterface - thisPacket.encoding.decode(); + thisPacket.encoding.decode() - let verdict = handlePacket(thisPacket); + let verdict = handlePacket(thisPacket) if (verdict.name === 'accept') { - packetsInAccept++; + packetsInAccept++ } - verdict(); - }); + verdict() + }) networkInterface.queueOut = nfq.createQueueHandler(parseInt('100' + networkInterface.number), buffer, (nfpacket) => { - packetsOut++; - let thisPacket = netFilterPacket(nfpacket); - thisPacket.direction = 'outgoing'; - thisPacket.networkInterface = networkInterface; + packetsOut++ + let thisPacket = netFilterPacket(nfpacket) + thisPacket.direction = 'outgoing' + thisPacket.networkInterface = networkInterface - thisPacket.encoding.decode(); + thisPacket.encoding.decode() - let verdict = handlePacket(thisPacket); + let verdict = handlePacket(thisPacket) if (verdict.name === 'accept') { - packetsOutAccept++; + packetsOutAccept++ } - verdict(); - }); - }); + verdict() + }) + }) } -console.log('Flushing rules...'); +console.log('Flushing rules...') nft.flush().then( (resolved) => { - console.log('Injecting NFTables base ruleset...'); - nft.inject('./src/config/rules-base.nft'); + console.log('Injecting NFTables base ruleset...') + nft.inject('./src/config/rules-base.nft') }, (reject) => console.log('Failed to flush rules: ' + reject) ).then( (resolved) => { - console.log('Configuring interfaces...'); - setupInterfaces(); + console.log('Configuring interfaces...') + setupInterfaces() }, (reject) => console.log('Failed to inject base rules: ' + reject) ).then( (resolved) => { - console.log('Binding NFQueue handlers...'); - bindQueueHandlers(); + console.log('Binding NFQueue handlers...') + bindQueueHandlers() }, (reject) => console.log('Failed to setup interfaces: ' + reject) ).then( (resolved) => { - console.log('Inserting final (counter) rules...'); - setTimeout(insertFinalCounters, 2000); + console.log('Inserting final (counter) rules...') + setTimeout(insertFinalCounters, 2000) }, (reject) => console.log('Failed to bind queue handlers: ' + reject) ).catch( (err) => console.log('Failed to insert final counters: ' + err) -); +) -setInterval(updateOutput, 250000); +setInterval(updateOutput, 1000) diff --git a/src/nfpacket/index.js b/src/nfpacket/index.js index 3a13674..0ecf862 100644 --- a/src/nfpacket/index.js +++ b/src/nfpacket/index.js @@ -1,7 +1,7 @@ -const verdicts = require('./verdicts'); -const encoding = require('./encoding'); -const enums = require('./enums.js'); -const statable = require('./../state'); +const verdicts = require('./verdicts') +const encoding = require('./encoding') +const enums = require('./enums.js') +const statable = require('./../state') module.exports = (dependencies) => (nfpacket) => { let state = statable('mutable')({ @@ -11,7 +11,7 @@ module.exports = (dependencies) => (nfpacket) => { mark: undefined, nfpacket: nfpacket, verdict: enums.netfilterVerdict.NF_DROP - }); + }) if (Object.keys(dependencies).includes('nfq') && Object.keys(dependencies).includes('pcapIPv4')) { return Object.assign( @@ -20,8 +20,8 @@ module.exports = (dependencies) => (nfpacket) => { verdicts: verdicts(dependencies)(state), encoding: encoding(dependencies.pcapIPv4)(state) } - ); + ) } - return false; -}; + return false +} diff --git a/src/nfpacket/verdicts.js b/src/nfpacket/verdicts.js index 926d9ef..1834192 100644 --- a/src/nfpacket/verdicts.js +++ b/src/nfpacket/verdicts.js @@ -16,7 +16,7 @@ module.exports = (dependencies) => (state) => ({ return state.nfpacket.setVerdict(state.enums.netfilterVerdict.NF_REPEAT, 777); } else { return state.nfpacket - ? state.nfpacket.setVerdict(state.enums.netfilterVerdict.NF_DROP, state.mark) + ? state.nfpacket.setVerdict(state.enums.netfilterVerdict.NF_REPEAT, 666) : false; } }, diff --git a/src/nftables/index.js b/src/nftables/index.js index c5ae491..2888dad 100644 --- a/src/nftables/index.js +++ b/src/nftables/index.js @@ -1,4 +1,4 @@ -const rules = require('./rules'); +const rules = require('./rules') const nft = (dependencies) => { if (Object.keys(dependencies).includes('exec')) { @@ -6,10 +6,10 @@ const nft = (dependencies) => { {}, nft, rules(dependencies.exec) - ); + ) } - return false; -}; + return false +} -module.exports = nft; +module.exports = nft diff --git a/src/state/index.js b/src/state/index.js index f017d14..5a40e18 100644 --- a/src/state/index.js +++ b/src/state/index.js @@ -1,11 +1,11 @@ -const immutable = require('./immutable'); -const mutable = require('./mutable'); +const immutable = require('./immutable') +const mutable = require('./mutable') module.exports = (type) => (initialState) => { - let state = {}; + let state = {} if (typeof initialState !== 'undefined') { - state = initialState; + state = initialState } if (typeof type === 'string' && (type === 'mutable' || type === 'immutable')) { @@ -13,16 +13,16 @@ module.exports = (type) => (initialState) => { return Object.freeze(Object.assign( state, immutable(state) - )); + )) } if (type === 'mutable') { return Object.assign( state, mutable(state) - ); + ) } } - return state; -}; + return state +} diff --git a/src/state/mutable.js b/src/state/mutable.js index eed4865..ab06aca 100644 --- a/src/state/mutable.js +++ b/src/state/mutable.js @@ -1,22 +1,22 @@ const checkSetObject = (setObject) => { - return typeof Object.keys(setObject)[0] !== 'undefined'; -}; + return typeof Object.keys(setObject)[0] !== 'undefined' +} module.exports = (state) => ({ get: (property) => { - return state[property] || undefined; + return state[property] || undefined }, set: (setObject) => { if (checkSetObject(setObject)) { - let currentState = Object.assign({}, state); + let currentState = Object.assign({}, state) - let targetProperty = Object.keys(setObject)[0]; - let targetValue = setObject[targetProperty]; + let targetProperty = Object.keys(setObject)[0] + let targetValue = setObject[targetProperty] - console.log('Attempting to set %s, with %s.', targetProperty, targetValue); - let newState = Object.assign({ [targetProperty]: targetValue }, currentState); + console.log('Attempting to set %s, with %s.', targetProperty, targetValue) + let newState = Object.assign({ [targetProperty]: targetValue }, currentState) - state = newState; + state = newState } } -}); +})