Added command line options to pull/push/read/delete config files in the db.

Ylian Saint-Hilaire committed Feb 1, 2019 at 15:16 UTC e8b08130b4cfb17e77634cc29cead7e18bc6918b
4 files changed +70 -5
db.js
+9
@@ -176,6 +176,15 @@ module.exports.CreateDB = function (parent) {
176 obj.getLocalAmtNodes = function (func) { obj.file.find({ type: 'node', host: { $exists: true, $ne: null }, intelamt: { $exists: true } }, func); };
177 obj.getAmtUuidNode = function (meshid, uuid, func) { obj.file.find({ type: 'node', meshid: meshid, 'intelamt.uuid': uuid }, func); };
178
179 + // Read a file from the database
180 + obj.getFile = function (path, func) { obj.Get('cfile/' + path, func); }
181 +
182 + // Write a file to the database
183 + obj.setFile = function (path, data, func) { obj.Set({ _id: 'cfile/' + path, type: 'cfile', data: data.toString('base64') }, func); }
184 +
185 + // List all files
186 + obj.listFiles = function (func) { obj.file.find({ type: 'cfile' }).sort({ _id: 1 }).exec(func); }
187 +
188 // Get the number of records in the database for various types, this is the slow NeDB way. TODO: MongoDB can use group() to do this faster.
189 obj.getStats = function (func) {
190 obj.file.count({ type: 'node' }, function (err, nodeCount) {
meshcentral.js
+56 -1
@@ -95,7 +95,7 @@ function CreateMeshCentralServer(config, args) {
95 try { require('./pass').hash('test', function () { }); } catch (e) { console.log('Old version of node, must upgrade.'); return; } // TODO: Not sure if this test works or not.
96
97 // Check for invalid arguments
98 - var validArguments = ['_', 'notls', 'user', 'port', 'aliasport', 'mpsport', 'mpsaliasport', 'redirport', 'cert', 'mpscert', 'deletedomain', 'deletedefaultdomain', 'showall', 'showusers', 'shownodes', 'showmeshes', 'showevents', 'showpower', 'clearpower', 'showiplocations', 'help', 'exactports', 'install', 'uninstall', 'start', 'stop', 'restart', 'debug', 'filespath', 'datapath', 'noagentupdate', 'launch', 'noserverbackup', 'mongodb', 'mongodbcol', 'wanonly', 'lanonly', 'nousers', 'mpsdebug', 'mpspass', 'ciralocalfqdn', 'dbexport', 'dbexportmin', 'dbimport', 'dbencryptkey', 'selfupdate', 'tlsoffload', 'userallowedip', 'userblockedip', 'swarmallowedip', 'agentallowedip', 'agentblockedip', 'fastcert', 'swarmport', 'swarmdebug', 'logintoken', 'logintokenkey', 'logintokengen', 'logintokengen', 'mailtokengen', 'admin', 'unadmin', 'sessionkey', 'sessiontime', 'minify', 'minifycore'];
98 + var validArguments = ['_', 'notls', 'user', 'port', 'aliasport', 'mpsport', 'mpsaliasport', 'redirport', 'cert', 'mpscert', 'deletedomain', 'deletedefaultdomain', 'showall', 'showusers', 'shownodes', 'showmeshes', 'showevents', 'showpower', 'clearpower', 'showiplocations', 'help', 'exactports', 'install', 'uninstall', 'start', 'stop', 'restart', 'debug', 'filespath', 'datapath', 'noagentupdate', 'launch', 'noserverbackup', 'mongodb', 'mongodbcol', 'wanonly', 'lanonly', 'nousers', 'mpsdebug', 'mpspass', 'ciralocalfqdn', 'dbexport', 'dbexportmin', 'dbimport', 'dbencryptkey', 'selfupdate', 'tlsoffload', 'userallowedip', 'userblockedip', 'swarmallowedip', 'agentallowedip', 'agentblockedip', 'fastcert', 'swarmport', 'swarmdebug', 'logintoken', 'logintokenkey', 'logintokengen', 'logintokengen', 'mailtokengen', 'admin', 'unadmin', 'sessionkey', 'sessiontime', 'minify', 'minifycore', 'dblistconfigfiles', 'dbshowconfigfile', 'dbpushconfigfiles', 'dbpullconfigfiles', 'dbdeleteconfigfiles'];
99 for (var arg in obj.args) { obj.args[arg.toLocaleLowerCase()] = obj.args[arg]; if (validArguments.indexOf(arg.toLocaleLowerCase()) == -1) { console.log('Invalid argument "' + arg + '", use --help.'); return; } }
100 if (obj.args.mongodb == true) { console.log('Must specify: --mongodb [connectionstring] \r\nSee https://docs.mongodb.com/manual/reference/connection-string/ for MongoDB connection string.'); return; }
101 for (i in obj.config.settings) { obj.args[i] = obj.config.settings[i]; } // Place all settings into arguments, arguments have already been placed into settings so arguments take precedence.
@@ -291,6 +291,61 @@ function CreateMeshCentralServer(config, args) {
291 if (obj.args.showiplocations) { obj.db.GetAllType('iploc', function (err, docs) { console.log(docs); process.exit(); }); return; }
292 if (obj.args.logintoken) { obj.getLoginToken(obj.args.logintoken, function (r) { console.log(r); process.exit(); }); return; }
293 if (obj.args.logintokenkey) { obj.showLoginTokenKey(function (r) { console.log(r); process.exit(); }); return; }
294 + if (obj.args.dblistconfigfiles) { obj.db.GetAllType('cfile', function (err, docs) { if (err == null) { if (docs.length == 0) { console.log('No files found.'); } else { for (var i in docs) { console.log(docs[i]._id.split('/')[1] + ', ' + Buffer.from(docs[i].data, 'base64').length + ' bytes.'); } } } else { console.log('Unable to read from database.'); } process.exit(); }); return; }
295 + if (obj.args.dbshowconfigfile) { obj.db.getFile(obj.args.dbshowconfigfile, function (err, docs) { if (err == null) { if (docs.length == 0) { console.log('File not found.'); } else { console.log(Buffer.from(docs[0].data, 'base64').toString()); } } else { console.log('Unable to read from database.'); } process.exit(); }); return; }
296 + if (obj.args.dbdeleteconfigfiles) { console.log('Delating all configuration files from the database...'); obj.db.RemoveAllOfType('cfile', function () { console.log('Done.'); process.exit(); }); } // Delete all configuration files from database
297 +
298 + // Push all relevent files from meshcentral-data into the database
299 + if (obj.args.dbpushconfigfiles) {
300 + if (typeof obj.args.dbpushconfigfiles != 'string') {
301 + console.log('Usage: --dbpulldatafiles (path) This will import files from folder into the database');
302 + console.log(' --dbpulldatafiles * This will import files from meshcentral-data into the db.');
303 + process.exit();
304 + } else {
305 + if (obj.args.dbpushconfigfiles == '*') { obj.args.dbpushconfigfiles = obj.datapath; }
306 + obj.fs.readdir(obj.datapath, (err, files) => {
307 + var lockCount = 1
308 + for (var i in files) {
309 + const file = files[i];
310 + if (file.endsWith('.json') || file.endsWith('.key') || file.endsWith('.crt')) {
311 + const path = obj.path.join(obj.args.dbpushconfigfiles, files[i]), binary = Buffer.from(obj.fs.readFileSync(path, { encoding: 'binary' }), 'binary');
312 + console.log('Pushing ' + file + ', ' + binary.length + ' bytes.');
313 + lockCount++;
314 + obj.db.setFile(file, binary, function () { if ((--lockCount) == 0) { console.log('Done.'); process.exit(); } });
315 + }
316 + }
317 + if (--lockCount == 0) { process.exit(); }
318 + })
319 + }
320 + return;
321 + }
322 +
323 + // Pull all database files into meshcentral-data
324 + if (obj.args.dbpullconfigfiles) {
325 + if (typeof obj.args.dbpullconfigfiles != 'string') {
326 + console.log('Usage: --dbpulldatafiles (path)');
327 + process.exit();
328 + } else {
329 + obj.db.GetAllType('cfile', function (err, docs) {
330 + if (err == null) {
331 + if (docs.length == 0) {
332 + console.log('File not found.');
333 + } else {
334 + for (var i in docs) {
335 + const file = docs[i]._id.split('/')[1], binary = Buffer.from(docs[i].data, 'base64');
336 + obj.fs.writeFileSync(obj.path.join(obj.args.dbpullconfigfiles, file), binary);
337 + console.log('Pulling ' + file + ', ' + binary.length + ' bytes.');
338 + }
339 + }
340 + } else {
341 + console.log('Unable to read from database.');
342 + }
343 + process.exit();
344 + });
345 + }
346 + return;
347 + }
348 +
349 if (obj.args.dbexport) {
350 // Export the entire database to a JSON file
351 if (obj.args.dbexport == true) { obj.args.dbexport = obj.getConfigFilePath('meshcentral.db.json'); }
sample-config.json
+2 -1
@@ -7,7 +7,8 @@
7 "_LANonly": true,
8 "_Minify": 1,
9 "_SessionTime": 30,
10 - "_SessionKey": "MyReallySecretPassword",
10 + "_SessionKey": "MyReallySecretPassword1",
11 + "_DbEncryptKey": "MyReallySecretPassword2",
12 "_Port": 443,
13 "_RedirPort": 80,
14 "_AllowLoginToken": true,
views/default.handlebars
+3 -3
@@ -1282,7 +1282,7 @@
1282 if (isPrivateIP(currentNode.lastaddr)) {
1283 x += addHtmlValue2('Last agent address', currentNode.lastaddr.split(':')[0]);
1284 } else {
1285 - x += addHtmlValue2('Last agent address', '<a href="https://iplocation.com/?ip=' + currentNode.lastaddr.split(':')[0] + '" rel="noreferrer noopener" target=_blank>' + currentNode.lastaddr.split(':')[0] + '</a>');
1285 + x += addHtmlValue2('Last agent address', '<a href="https://iplocation.com/?ip=' + currentNode.lastaddr.split(':')[0] + '" rel="noreferrer noopener" target="MeshIPLoopup">' + currentNode.lastaddr.split(':')[0] + '</a>');
1286 }
1287 }
1288
@@ -1293,11 +1293,11 @@
1293 if (net.name) { x += addHtmlValue2('Name', '<b>' + EscapeHtml(net.name) + '</b>'); }
1294 if (net.desc) { x += addHtmlValue2('Description', EscapeHtml(net.desc).replace('(R)', '&reg;').replace('(r)', '&reg;')); }
1295 if (net.dnssuffix) { x += addHtmlValue2('DNS suffix', EscapeHtml(net.dnssuffix)); }
1296 - if (net.mac) { x += addHtmlValue2('MAC address', EscapeHtml(net.mac.toUpperCase())); }
1296 + if (net.mac) { x += addHtmlValue2('MAC address', '<a href="https://dnslytics.com/mac-address-lookup/' + net.mac.substring(0,6) + '" rel="noreferrer noopener" target="MeshMACLoopup">' + EscapeHtml(net.mac.toLowerCase()) + '</a>'); }
1297 if (net.v4addr) { x += addHtmlValue2('IPv4 address', EscapeHtml(net.v4addr)); }
1298 if (net.v4mask) { x += addHtmlValue2('IPv4 mask', EscapeHtml(net.v4mask)); }
1299 if (net.v4gateway) { x += addHtmlValue2('IPv4 gateway', EscapeHtml(net.v4gateway)); }
1300 - if (net.gatewaymac) { x += addHtmlValue2('Gateway MAC', EscapeHtml(net.gatewaymac)); }
1300 + if (net.gatewaymac) { x += addHtmlValue2('Gateway MAC', '<a href="https://dnslytics.com/mac-address-lookup/' + net.gatewaymac.substring(0, 6) + '" rel="noreferrer noopener" target="MeshMACLoopup">' + EscapeHtml(net.gatewaymac.toLowerCase()) + '</a>'); }
1301 }
1302 x += '</div>';
1303 QH('d2netinfo', x);