From 6cc21f5709b953de4a74e6376833c660f79e4226 Mon Sep 17 00:00:00 2001 From: Ylian Saint-Hilaire Date: Fri, 1 Feb 2019 15:16:46 -0800 Subject: [PATCH] Added command line options to pull/push/read/delete config files in the db. --- db.js | 9 +++++++ meshcentral.js | 57 +++++++++++++++++++++++++++++++++++++++- sample-config.json | 3 ++- views/default.handlebars | 6 ++--- 4 files changed, 70 insertions(+), 5 deletions(-) diff --git a/db.js b/db.js index 2ba15fcf..998a78d1 100644 --- a/db.js +++ b/db.js @@ -176,6 +176,15 @@ module.exports.CreateDB = function (parent) { obj.getLocalAmtNodes = function (func) { obj.file.find({ type: 'node', host: { $exists: true, $ne: null }, intelamt: { $exists: true } }, func); }; obj.getAmtUuidNode = function (meshid, uuid, func) { obj.file.find({ type: 'node', meshid: meshid, 'intelamt.uuid': uuid }, func); }; + // Read a file from the database + obj.getFile = function (path, func) { obj.Get('cfile/' + path, func); } + + // Write a file to the database + obj.setFile = function (path, data, func) { obj.Set({ _id: 'cfile/' + path, type: 'cfile', data: data.toString('base64') }, func); } + + // List all files + obj.listFiles = function (func) { obj.file.find({ type: 'cfile' }).sort({ _id: 1 }).exec(func); } + // 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. obj.getStats = function (func) { obj.file.count({ type: 'node' }, function (err, nodeCount) { diff --git a/meshcentral.js b/meshcentral.js index 348ed2b6..98158e8e 100644 --- a/meshcentral.js +++ b/meshcentral.js @@ -95,7 +95,7 @@ function CreateMeshCentralServer(config, args) { 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. // Check for invalid arguments - 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']; + 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']; 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; } } 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; } 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) { if (obj.args.showiplocations) { obj.db.GetAllType('iploc', function (err, docs) { console.log(docs); process.exit(); }); return; } if (obj.args.logintoken) { obj.getLoginToken(obj.args.logintoken, function (r) { console.log(r); process.exit(); }); return; } if (obj.args.logintokenkey) { obj.showLoginTokenKey(function (r) { console.log(r); process.exit(); }); return; } + 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; } + 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; } + 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 + + // Push all relevent files from meshcentral-data into the database + if (obj.args.dbpushconfigfiles) { + if (typeof obj.args.dbpushconfigfiles != 'string') { + console.log('Usage: --dbpulldatafiles (path) This will import files from folder into the database'); + console.log(' --dbpulldatafiles * This will import files from meshcentral-data into the db.'); + process.exit(); + } else { + if (obj.args.dbpushconfigfiles == '*') { obj.args.dbpushconfigfiles = obj.datapath; } + obj.fs.readdir(obj.datapath, (err, files) => { + var lockCount = 1 + for (var i in files) { + const file = files[i]; + if (file.endsWith('.json') || file.endsWith('.key') || file.endsWith('.crt')) { + const path = obj.path.join(obj.args.dbpushconfigfiles, files[i]), binary = Buffer.from(obj.fs.readFileSync(path, { encoding: 'binary' }), 'binary'); + console.log('Pushing ' + file + ', ' + binary.length + ' bytes.'); + lockCount++; + obj.db.setFile(file, binary, function () { if ((--lockCount) == 0) { console.log('Done.'); process.exit(); } }); + } + } + if (--lockCount == 0) { process.exit(); } + }) + } + return; + } + + // Pull all database files into meshcentral-data + if (obj.args.dbpullconfigfiles) { + if (typeof obj.args.dbpullconfigfiles != 'string') { + console.log('Usage: --dbpulldatafiles (path)'); + process.exit(); + } else { + obj.db.GetAllType('cfile', function (err, docs) { + if (err == null) { + if (docs.length == 0) { + console.log('File not found.'); + } else { + for (var i in docs) { + const file = docs[i]._id.split('/')[1], binary = Buffer.from(docs[i].data, 'base64'); + obj.fs.writeFileSync(obj.path.join(obj.args.dbpullconfigfiles, file), binary); + console.log('Pulling ' + file + ', ' + binary.length + ' bytes.'); + } + } + } else { + console.log('Unable to read from database.'); + } + process.exit(); + }); + } + return; + } + if (obj.args.dbexport) { // Export the entire database to a JSON file if (obj.args.dbexport == true) { obj.args.dbexport = obj.getConfigFilePath('meshcentral.db.json'); } diff --git a/sample-config.json b/sample-config.json index 3e30ef31..3111728f 100644 --- a/sample-config.json +++ b/sample-config.json @@ -7,7 +7,8 @@ "_LANonly": true, "_Minify": 1, "_SessionTime": 30, - "_SessionKey": "MyReallySecretPassword", + "_SessionKey": "MyReallySecretPassword1", + "_DbEncryptKey": "MyReallySecretPassword2", "_Port": 443, "_RedirPort": 80, "_AllowLoginToken": true, diff --git a/views/default.handlebars b/views/default.handlebars index 05f842b3..b5294b5d 100644 --- a/views/default.handlebars +++ b/views/default.handlebars @@ -1282,7 +1282,7 @@ if (isPrivateIP(currentNode.lastaddr)) { x += addHtmlValue2('Last agent address', currentNode.lastaddr.split(':')[0]); } else { - x += addHtmlValue2('Last agent address', '' + currentNode.lastaddr.split(':')[0] + ''); + x += addHtmlValue2('Last agent address', '' + currentNode.lastaddr.split(':')[0] + ''); } } @@ -1293,11 +1293,11 @@ if (net.name) { x += addHtmlValue2('Name', '' + EscapeHtml(net.name) + ''); } if (net.desc) { x += addHtmlValue2('Description', EscapeHtml(net.desc).replace('(R)', '®').replace('(r)', '®')); } if (net.dnssuffix) { x += addHtmlValue2('DNS suffix', EscapeHtml(net.dnssuffix)); } - if (net.mac) { x += addHtmlValue2('MAC address', EscapeHtml(net.mac.toUpperCase())); } + if (net.mac) { x += addHtmlValue2('MAC address', '' + EscapeHtml(net.mac.toLowerCase()) + ''); } if (net.v4addr) { x += addHtmlValue2('IPv4 address', EscapeHtml(net.v4addr)); } if (net.v4mask) { x += addHtmlValue2('IPv4 mask', EscapeHtml(net.v4mask)); } if (net.v4gateway) { x += addHtmlValue2('IPv4 gateway', EscapeHtml(net.v4gateway)); } - if (net.gatewaymac) { x += addHtmlValue2('Gateway MAC', EscapeHtml(net.gatewaymac)); } + if (net.gatewaymac) { x += addHtmlValue2('Gateway MAC', '' + EscapeHtml(net.gatewaymac.toLowerCase()) + ''); } } x += ''; QH('d2netinfo', x);