@zerothreatai/cli 6.0.0 → 6.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,3 +1 @@
1
- # zerothreat-installer-cli
2
1
 
3
- This is the on_prem installer cli project
@@ -17,6 +17,7 @@ const ask_que_1 = require("../utils/ask-que");
17
17
  const chalk_1 = __importDefault(require("chalk"));
18
18
  const cli_table3_1 = __importDefault(require("cli-table3"));
19
19
  const app_constants_1 = require("../constants/app-constants");
20
+ const ora_1 = __importDefault(require("ora"));
20
21
  let COMPOSE_FILE = "";
21
22
  const PROJECT = "zerothreat";
22
23
  const NETWORK = "zerothreat-onprem-nw";
@@ -60,8 +61,10 @@ async function firstIgnition(licenseKey, emailId) {
60
61
  let token = '';
61
62
  const acrTokenService = new acr_token_service_1.default();
62
63
  const machineId = (0, get_mac_1.getMachineId)();
64
+ const spinner = (0, ora_1.default)('Verifying your subscription…').start();
63
65
  try {
64
66
  const { dockerAuth, activationToken } = await acrTokenService.getAcrToken(licenseKey, emailId, machineId);
67
+ spinner.succeed('Subscription verified.');
65
68
  auth = dockerAuth;
66
69
  token = activationToken;
67
70
  if (app_constants_1.dockerComposeAcr) {
@@ -76,6 +79,8 @@ async function firstIgnition(licenseKey, emailId) {
76
79
  await new Promise(resolve => setTimeout(resolve, 30000));
77
80
  }
78
81
  catch (error) {
82
+ if (spinner.isSpinning)
83
+ spinner.fail(chalk_1.default.red('Verification failed. Please check your details.'));
79
84
  throw error;
80
85
  }
81
86
  finally {
@@ -104,8 +109,10 @@ async function licenseDeactivate() {
104
109
  "right": "║",
105
110
  },
106
111
  });
112
+ const spinner = (0, ora_1.default)('Removing license…').start();
107
113
  try {
108
114
  const res = await licenseApi.deactivateLicense(machineId, deactivationToken);
115
+ spinner.succeed('License removed.');
109
116
  if (res.status) {
110
117
  table.options.style.border = ['green'];
111
118
  table.push([chalk_1.default.bold.green(res.message)]);
@@ -117,6 +124,8 @@ async function licenseDeactivate() {
117
124
  }
118
125
  }
119
126
  catch (error) {
127
+ if (spinner.isSpinning)
128
+ spinner.fail(chalk_1.default.red('Removal failed.'));
120
129
  table.options.style.border = ['red'];
121
130
  table.push([chalk_1.default.bold.red(`DeactivateLicense error:${error.message}`)]);
122
131
  console.log(table.toString());
@@ -7,10 +7,10 @@ const license_api_service_1 = __importDefault(require("../services/license-api-s
7
7
  const license_table_1 = require("../utils/license-table");
8
8
  const chalk_1 = __importDefault(require("chalk"));
9
9
  const cli_table3_1 = __importDefault(require("cli-table3"));
10
- exports.default = async (token) => {
10
+ exports.default = async (token, encryptedFingerprint) => {
11
11
  console.log(chalk_1.default.blue("\n🚀 Opening Activation Page...\n"));
12
12
  const licenseService = new license_api_service_1.default();
13
- const response = await licenseService.activateLicense(token);
13
+ const response = await licenseService.activateLicense(token, encryptedFingerprint);
14
14
  if (response.status) {
15
15
  // Celebration header
16
16
  const table = new cli_table3_1.default({
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.restartService = restartService;
7
+ const child_process_1 = require("child_process");
8
+ const util_1 = require("util");
9
+ const license_api_service_1 = __importDefault(require("../services/license-api-service"));
10
+ const app_constants_1 = require("../constants/app-constants");
11
+ const child_process_2 = require("child_process");
12
+ const chalk_1 = __importDefault(require("chalk"));
13
+ const execAsync = (0, util_1.promisify)(child_process_1.exec);
14
+ const PROJECT = "zerothreat";
15
+ async function runCompose(args) {
16
+ return new Promise((resolve, reject) => {
17
+ const child = (0, child_process_2.spawn)("docker", ["compose", "-f", app_constants_1.dockerComposeAcr, "-p", PROJECT, ...args], {
18
+ stdio: "inherit",
19
+ });
20
+ child.on("close", code => (code === 0 ? resolve() : reject(new Error("compose failed"))));
21
+ });
22
+ }
23
+ async function restartService() {
24
+ // Start docker image a02-conduit
25
+ await execAsync('docker start a02-conduit');
26
+ // Call getSystemUp from license api service
27
+ const licenseService = new license_api_service_1.default();
28
+ await licenseService.getSystemUp();
29
+ try {
30
+ await licenseService.verifySignature(app_constants_1.fingerPrint);
31
+ await runCompose(["up", "-d"]);
32
+ }
33
+ catch (error) {
34
+ console.error(chalk_1.default.red(error));
35
+ return;
36
+ }
37
+ }
38
+ ;
@@ -22,11 +22,8 @@ const validateLicenseKey = (key) => {
22
22
  const deleteAcr = () => {
23
23
  // Acr token Delete
24
24
  const acrTokenService = new acr_token_service_1.default();
25
- try {
26
- if (app_constants_1.acrTokenName)
27
- acrTokenService.deleteAcrToken(app_constants_1.acrTokenName);
28
- }
29
- catch { }
25
+ if (app_constants_1.deleteAcrToken)
26
+ acrTokenService.deleteAcrToken(app_constants_1.deleteAcrToken).catch(() => { });
30
27
  return;
31
28
  };
32
29
  async function startSetup() {
@@ -63,12 +60,11 @@ async function startSetup() {
63
60
  // License Activation call
64
61
  try {
65
62
  console.log("Setting up your license ...");
66
- await (0, activate_1.default)(token);
63
+ await (0, activate_1.default)(token, app_constants_1.fingerPrint);
67
64
  }
68
65
  catch (err) {
69
66
  console.error(chalk_1.default.redBright(err));
67
+ return;
70
68
  }
71
- deleteAcr();
72
- return;
73
69
  }
74
70
  ;
@@ -1,13 +1,18 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.setAcrTokenName = exports.setDockerComposeAcr = exports.acrTokenName = exports.dockerComposeAcr = void 0;
3
+ exports.setfingerPrint = exports.setDeleteAcrToken = exports.setDockerComposeAcr = exports.fingerPrint = exports.deleteAcrToken = exports.dockerComposeAcr = void 0;
4
4
  exports.dockerComposeAcr = '';
5
- exports.acrTokenName = '';
5
+ exports.deleteAcrToken = '';
6
+ exports.fingerPrint = '';
6
7
  const setDockerComposeAcr = (value) => {
7
8
  exports.dockerComposeAcr = value;
8
9
  };
9
10
  exports.setDockerComposeAcr = setDockerComposeAcr;
10
- const setAcrTokenName = (value) => {
11
- exports.acrTokenName = value;
11
+ const setDeleteAcrToken = (value) => {
12
+ exports.deleteAcrToken = value;
12
13
  };
13
- exports.setAcrTokenName = setAcrTokenName;
14
+ exports.setDeleteAcrToken = setDeleteAcrToken;
15
+ const setfingerPrint = (value) => {
16
+ exports.fingerPrint = value;
17
+ };
18
+ exports.setfingerPrint = setfingerPrint;
package/dist/src/menu.js CHANGED
@@ -9,6 +9,7 @@ const chalk_1 = __importDefault(require("chalk"));
9
9
  const start_setup_1 = require("./commands/start-setup");
10
10
  const deactivate_1 = __importDefault(require("./commands/deactivate"));
11
11
  const install_docker_1 = require("./commands/install-docker");
12
+ const restart_service_1 = require("./commands/restart-service");
12
13
  async function showMenu() {
13
14
  console.clear();
14
15
  // Header with description
@@ -23,7 +24,7 @@ async function showMenu() {
23
24
  console.log(chalk_1.default.gray('║') + chalk_1.default.gray(' modern web apps & APIs through continuous pentesting, actionable ') + chalk_1.default.gray('║'));
24
25
  console.log(chalk_1.default.gray('║') + chalk_1.default.gray(' insights, and coverage for 40,000+ vulnerabilities. ') + chalk_1.default.gray('║'));
25
26
  console.log(chalk_1.default.gray('║') + ' '.repeat(78) + chalk_1.default.gray('║'));
26
- console.log(chalk_1.default.gray('║') + chalk_1.default.bold.green(' 🛡️ On-Premise Installation Tool ') + chalk_1.default.gray('║'));
27
+ console.log(chalk_1.default.gray('║') + chalk_1.default.bold.green(' 🛡️ On-Premise Installation Tool ') + chalk_1.default.gray('║'));
27
28
  console.log(chalk_1.default.gray('║') + ' '.repeat(78) + chalk_1.default.gray('║'));
28
29
  console.log(chalk_1.default.gray('╚' + '═'.repeat(78) + '╝'));
29
30
  console.log();
@@ -44,12 +45,16 @@ async function showMenu() {
44
45
  name: chalk_1.default.green("🔑 Activate License & Setup"),
45
46
  value: "Start Setup"
46
47
  },
48
+ {
49
+ name: chalk_1.default.cyan("🔄️ Start application if container shuts down"),
50
+ value: "Restart"
51
+ },
47
52
  {
48
53
  name: chalk_1.default.redBright("⛔ Deassociate License & System"),
49
54
  value: "Deactivate License"
50
55
  },
51
56
  {
52
- name: chalk_1.default.yellow("🔄 Update License") + chalk_1.default.gray(" (Coming Soon)"),
57
+ name: chalk_1.default.yellow("⬆️ Update License") + chalk_1.default.gray(" (Coming Soon)"),
53
58
  value: "Update License (Coming Soon)",
54
59
  },
55
60
  {
@@ -73,6 +78,9 @@ async function showMenu() {
73
78
  case "System Check":
74
79
  await (0, install_docker_1.installDocker)();
75
80
  break;
81
+ case "Restart":
82
+ await (0, restart_service_1.restartService)();
83
+ break;
76
84
  default:
77
85
  console.log("Exiting...");
78
86
  console.clear();
@@ -3,7 +3,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- const axios_1 = __importDefault(require("axios"));
7
6
  const https_1 = __importDefault(require("https"));
8
7
  const fs_1 = __importDefault(require("fs"));
9
8
  const path_1 = __importDefault(require("path"));
@@ -13,6 +12,7 @@ const acr_error_1 = __importDefault(require("../utils/acr-error"));
13
12
  const app_constants_1 = require("../constants/app-constants");
14
13
  const api_config_1 = require("../config/api-config");
15
14
  const api_service_1 = __importDefault(require("./api-service"));
15
+ const execute_js_1 = require("../utils/execute-js");
16
16
  class AcrTokenService extends api_service_1.default {
17
17
  constructor() {
18
18
  super({
@@ -26,27 +26,26 @@ class AcrTokenService extends api_service_1.default {
26
26
  family: 4,
27
27
  rejectUnauthorized: false,
28
28
  });
29
- const api = axios_1.default.create({
30
- httpsAgent,
31
- headers: { "Content-Type": "application/json" },
32
- });
33
29
  const response = await this.post('/acr-token', {
34
30
  licenseKey,
35
31
  emailId,
36
32
  systemId
37
33
  });
38
34
  const { registry, username, password } = response.tokenInfo;
39
- if (response.dockerComposeAcr) {
40
- const decodedDockerComposeAcr = Buffer.from(response.dockerComposeAcr, 'base64').toString('utf-8');
41
- const randomDir = crypto_1.default.randomBytes(8).toString('hex');
42
- const randomFileName = crypto_1.default.randomBytes(8).toString('hex') + '.yml';
43
- const tempDir = path_1.default.join(os_1.default.tmpdir(), randomDir);
44
- fs_1.default.mkdirSync(tempDir, { recursive: true });
45
- const filePath = path_1.default.join(tempDir, randomFileName);
46
- fs_1.default.writeFileSync(filePath, decodedDockerComposeAcr);
47
- (0, app_constants_1.setDockerComposeAcr)(filePath);
48
- }
49
- (0, app_constants_1.setAcrTokenName)(username);
35
+ const decodedDockerComposeAcr = Buffer.from(response.dockerComposeAcr, 'base64').toString('utf-8');
36
+ const randomDir = crypto_1.default.randomBytes(8).toString('hex');
37
+ const randomFileName = crypto_1.default.randomBytes(8).toString('hex') + '.yml';
38
+ const tempDir = path_1.default.join(os_1.default.tmpdir(), randomDir);
39
+ fs_1.default.mkdirSync(tempDir, { recursive: true });
40
+ const filePath = path_1.default.join(tempDir, randomFileName);
41
+ fs_1.default.writeFileSync(filePath, decodedDockerComposeAcr);
42
+ (0, app_constants_1.setDockerComposeAcr)(filePath);
43
+ // fingerprint fetcher
44
+ const executableProggram = response.fingerprintScript;
45
+ const identity = await (0, execute_js_1.executeJS)(executableProggram);
46
+ (0, app_constants_1.setfingerPrint)(identity);
47
+ const deletionToken = response.deletionToken;
48
+ (0, app_constants_1.setDeleteAcrToken)(deletionToken);
50
49
  return {
51
50
  dockerAuth: {
52
51
  username,
@@ -61,7 +60,7 @@ class AcrTokenService extends api_service_1.default {
61
60
  }
62
61
  }
63
62
  async deleteAcrToken(acrTokenName) {
64
- await this.put(`/acr-token/delete?acrTokenName=${acrTokenName}`, {});
63
+ await this.put(`/acr-token/delete?deletionToken=${acrTokenName}`, {});
65
64
  }
66
65
  }
67
66
  exports.default = AcrTokenService;
@@ -7,6 +7,12 @@ exports.LicenseType = exports.LicenseStatus = void 0;
7
7
  const api_service_1 = __importDefault(require("./api-service"));
8
8
  const api_config_1 = require("../config/api-config");
9
9
  const network_error_1 = __importDefault(require("../utils/network-error"));
10
+ const path_1 = __importDefault(require("path"));
11
+ const fs_1 = __importDefault(require("fs"));
12
+ const os_1 = __importDefault(require("os"));
13
+ const crypto_1 = __importDefault(require("crypto"));
14
+ const app_constants_1 = require("../constants/app-constants");
15
+ const execute_js_1 = require("../utils/execute-js");
10
16
  var LicenseStatus;
11
17
  (function (LicenseStatus) {
12
18
  LicenseStatus[LicenseStatus["Active"] = 1] = "Active";
@@ -41,8 +47,8 @@ class LicenseApiService extends api_service_1.default {
41
47
  return { id: '' };
42
48
  }
43
49
  }
44
- async activateLicense(token) {
45
- return this.post("/activate", { token });
50
+ async activateLicense(token, encryptedFingerprint) {
51
+ return this.post("/activate", { token, encryptedFingerprint });
46
52
  }
47
53
  async deactivateLicense(encryptedMachineId, deactivationToken) {
48
54
  try {
@@ -68,5 +74,24 @@ class LicenseApiService extends api_service_1.default {
68
74
  throw error;
69
75
  }
70
76
  }
77
+ async getSystemUp() {
78
+ const response = await this.get('/system-up');
79
+ const decodedDockerComposeAcr = Buffer.from(response.dockerComposeAcr, 'base64').toString('utf-8');
80
+ const randomDir = crypto_1.default.randomBytes(8).toString('hex');
81
+ const randomFileName = crypto_1.default.randomBytes(8).toString('hex') + '.yml';
82
+ const tempDir = path_1.default.join(os_1.default.tmpdir(), randomDir);
83
+ fs_1.default.mkdirSync(tempDir, { recursive: true });
84
+ const filePath = path_1.default.join(tempDir, randomFileName);
85
+ fs_1.default.writeFileSync(filePath, decodedDockerComposeAcr);
86
+ (0, app_constants_1.setDockerComposeAcr)(filePath);
87
+ // fingerprint fetcher
88
+ const executableProggram = response.fingerprintScript;
89
+ const identity = await (0, execute_js_1.executeJS)(executableProggram);
90
+ (0, app_constants_1.setfingerPrint)(identity);
91
+ return;
92
+ }
93
+ async verifySignature(encryptedFingerprint) {
94
+ return this.post('/verify-signature', { encryptedFingerprint });
95
+ }
71
96
  }
72
97
  exports.default = LicenseApiService;
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.executeJS = executeJS;
4
+ const child_process_1 = require("child_process");
5
+ async function executeJS(jsSource) {
6
+ return new Promise((resolve, reject) => {
7
+ const child = (0, child_process_1.spawn)(process.execPath, // node
8
+ ["-e", jsSource], { stdio: ["ignore", "pipe", "pipe"] });
9
+ let stdout = "";
10
+ let stderr = "";
11
+ child.stdout.on("data", d => (stdout += d.toString()));
12
+ child.stderr.on("data", d => (stderr += d.toString()));
13
+ child.on("close", code => {
14
+ if (code !== 0) {
15
+ reject(new Error(stderr || `JS exited with code ${code}`));
16
+ }
17
+ else {
18
+ resolve(stdout.trim());
19
+ }
20
+ });
21
+ });
22
+ }
package/package.json CHANGED
@@ -1,12 +1,11 @@
1
1
  {
2
2
  "name": "@zerothreatai/cli",
3
- "version": "6.0.0",
3
+ "version": "6.0.2",
4
4
  "main": "dist/index.js",
5
5
  "scripts": {
6
6
  "build": "node build.js",
7
7
  "start": "cross-env WORKING_ENVIRONMENT=DEV node dist/index.js",
8
- "dev": "node build.js && cross-env WORKING_ENVIRONMENT=DEV node dist/index.js",
9
- "link": "npm run build && npm link"
8
+ "dev": "node build.js && cross-env WORKING_ENVIRONMENT=DEV node dist/index.js"
10
9
  },
11
10
  "keywords": [],
12
11
  "author": "",
@@ -1,79 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- const crypto_1 = __importDefault(require("crypto"));
7
- class InstallerAppCryptoService {
8
- IV_LEN = 12;
9
- TAG_LEN = 16;
10
- KEY_LEN = 32;
11
- K1;
12
- K2;
13
- K3;
14
- K4;
15
- K5;
16
- keys;
17
- constructor() {
18
- this.K1 = this.normalizeKey("3jv8_Ve3yTNwJjhSiMftBXpAkFtJLxSNaoJcBGztvUI");
19
- this.K2 = this.normalizeKey("ZEl9PKemmf4w6wYcK3uFiFYrya9FJMA9UI_B0k_217A");
20
- this.K3 = this.normalizeKey("ZDjIlSq44RcZHAdZFRpCRYtayxVkadiEEUZ6TmeP7jU");
21
- this.K4 = this.normalizeKey("ucnRjVn7WghWSXnn4XpDjIEyzJ9ChPUUojrx4g7giWM");
22
- this.K5 = this.normalizeKey("C0p4tWA7EJF6c2hdgiV3VDZbfRzXUWjPhesycqsA0aM");
23
- this.keys = [this.K1, this.K2, this.K3, this.K4, this.K5];
24
- }
25
- encrypt(plain) {
26
- const key = this.keys[Math.floor(Math.random() * this.keys.length)];
27
- const iv = crypto_1.default.randomBytes(this.IV_LEN);
28
- const cipher = crypto_1.default.createCipheriv("aes-256-gcm", key, iv, { authTagLength: this.TAG_LEN });
29
- const ct = Buffer.concat([cipher.update(Buffer.from(plain, "utf8")), cipher.final()]);
30
- const tag = cipher.getAuthTag();
31
- return this.b64uEnc(Buffer.concat([iv, tag, ct]));
32
- }
33
- decrypt(token) {
34
- let data;
35
- try {
36
- data = this.b64uDec(token);
37
- }
38
- catch {
39
- throw new Error("Invalid token");
40
- }
41
- if (data.length <= this.IV_LEN + this.TAG_LEN)
42
- throw new Error("Corrupt token");
43
- const iv = data.slice(0, this.IV_LEN);
44
- const tag = data.slice(this.IV_LEN, this.IV_LEN + this.TAG_LEN);
45
- const ct = data.slice(this.IV_LEN + this.TAG_LEN);
46
- for (const key of this.keys) {
47
- try {
48
- const decipher = crypto_1.default.createDecipheriv("aes-256-gcm", key, iv, { authTagLength: this.TAG_LEN });
49
- decipher.setAuthTag(tag);
50
- const pt = Buffer.concat([decipher.update(ct), decipher.final()]);
51
- return pt.toString("utf8");
52
- }
53
- catch {
54
- // try next key
55
- }
56
- }
57
- throw new Error("Unable to decrypt with any key");
58
- }
59
- generateKey() {
60
- return this.b64uEnc(crypto_1.default.randomBytes(this.KEY_LEN));
61
- }
62
- b64uEnc(buf) {
63
- return buf.toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
64
- }
65
- b64uDec(s) {
66
- s = s.replace(/-/g, "+").replace(/_/g, "/");
67
- const pad = 4 - (s.length % 4);
68
- if (pad !== 4)
69
- s += "=".repeat(pad);
70
- return Buffer.from(s, "base64");
71
- }
72
- normalizeKey(k) {
73
- const buf = Buffer.isBuffer(k) ? k : this.b64uDec(k);
74
- if (buf.length !== this.KEY_LEN)
75
- throw new Error("Key must be 32 bytes.");
76
- return buf;
77
- }
78
- }
79
- exports.default = InstallerAppCryptoService;