Added support fo domain MaxDevices limit
Ylian Saint-Hilaire committed
Jun 5, 2019 at 15:24 UTC
0a62aa8ae395b37ace74f12d1dbedd4fbe64281c
8 files changed
+219
-124
db.js
+2
-2
@@ -549,7 +549,7 @@ module.exports.CreateDB = function (parent, func) {
549
// TODO: Starting in MongoDB 4.0.3, you should use countDocuments() instead of count() that is deprecated. We should detect MongoDB version and switch.
550
// https://docs.mongodb.com/manual/reference/method/db.collection.countDocuments/
551
//obj.isMaxType = function (max, type, domainid, func) { if (max == null) { func(false); } else { obj.file.countDocuments({ type: type, domain: domainid }, function (err, count) { func((err != null) || (count > max)); }); } }
552
- obj.isMaxType = function (max, type, domainid, func) { if (max == null) { func(false); } else { obj.file.count({ type: type, domain: domainid }, function (err, count) { func((err != null) || (count > max)); }); } }
552
+ obj.isMaxType = function (max, type, domainid, func) { if (max == null) { func(false); } else { obj.file.count({ type: type, domain: domainid }, function (err, count) { func((err != null) || (count > max), count); }); } }
553
554
// Database actions on the events collection
555
obj.GetAllEvents = function (func) { obj.eventsfile.find({}).toArray(func); };
@@ -638,7 +638,7 @@ module.exports.CreateDB = function (parent, func) {
638
obj.dispose = function () { for (var x in obj) { if (obj[x].close) { obj[x].close(); } delete obj[x]; } };
639
obj.getLocalAmtNodes = function (func) { obj.file.find({ type: 'node', host: { $exists: true, $ne: null }, intelamt: { $exists: true } }, func); };
640
obj.getAmtUuidNode = function (meshid, uuid, func) { obj.file.find({ type: 'node', meshid: meshid, 'intelamt.uuid': uuid }, func); };
641
- obj.isMaxType = function (max, type, domainid, func) { if (max == null) { func(false); } else { obj.file.count({ type: type, domain: domainid }, function (err, count) { func((err != null) || (count > max)); }); } }
641
+ obj.isMaxType = function (max, type, domainid, func) { if (max == null) { func(false); } else { obj.file.count({ type: type, domain: domainid }, function (err, count) { func((err != null) || (count > max), count); }); } }
642
643
// Database actions on the events collection
644
obj.GetAllEvents = function (func) { obj.eventsfile.find({}, func); };
meshagent.js
+113
-89
@@ -616,40 +616,21 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
616
if ((nodes == null) || (nodes.length == 0)) {
617
// This device does not exist, use the meshid given by the device
618
619
- // See if this mesh exists, if it does not we may want to create it.
620
- mesh = getMeshAutoCreate();
621
-
622
- // Check if the mesh exists
623
- if (mesh == null) {
624
- // If we disconnect, the agent will just reconnect. We need to log this or tell agent to connect in a few hours.
625
- parent.agentStats.invalidDomainMeshCount++;
626
- console.log('Agent connected with invalid domain/mesh, holding connection (' + obj.remoteaddrport + ', ' + obj.dbMeshKey + ').');
627
- return;
628
- }
629
-
630
- // Check if the mesh is the right type
631
- if (mesh.mtype != 2) {
632
- // If we disconnect, the agent will just reconnect. We need to log this or tell agent to connect in a few hours.
633
- parent.agentStats.invalidMeshTypeCount++;
634
- console.log('Agent connected with invalid mesh type, holding connection (' + obj.remoteaddrport + ').');
635
- return;
636
- }
637
-
638
- // Mark when this device connected
639
- obj.connectTime = Date.now();
640
- db.Set({ _id: 'lc' + obj.dbNodeKey, type: 'lastconnect', domain: domain.id, time: obj.connectTime, addr: obj.remoteaddrport });
641
-
642
- // This node does not exist, create it.
643
- device = { type: 'node', mtype: mesh.mtype, _id: obj.dbNodeKey, icon: obj.agentInfo.platformType, meshid: obj.dbMeshKey, name: obj.agentInfo.computerName, rname: obj.agentInfo.computerName, domain: domain.id, agent: { ver: obj.agentInfo.agentVersion, id: obj.agentInfo.agentId, caps: obj.agentInfo.capabilities }, host: null };
644
- db.Set(device);
645
-
646
- // Event the new node
647
- if (obj.agentInfo.capabilities & 0x20) {
648
- // This is a temporary agent, don't log.
649
- parent.parent.DispatchEvent(['*', obj.dbMeshKey], obj, { etype: 'node', action: 'addnode', node: device, domain: domain.id, nolog: 1 });
619
+ // Check if we already have too many devices for this domain
620
+ if (domain.limits && (typeof domain.limits.maxdevices == 'number')) {
621
+ db.isMaxType(domain.limits.maxdevices, 'node', domain.id, function (ismax, count) {
622
+ if (ismax == true) {
623
+ // Too many devices in this domain.
624
+ parent.agentStats.maxDomainDevicesReached++;
625
+ } else {
626
+ // We are under the limit, create the new device.
627
+ completeAgentConnection2();
628
+ }
629
+ });
630
} else {
651
- parent.parent.DispatchEvent(['*', obj.dbMeshKey], obj, { etype: 'node', action: 'addnode', node: device, msg: ('Added device ' + obj.agentInfo.computerName + ' to mesh ' + mesh.name), domain: domain.id });
631
+ completeAgentConnection2();
632
}
633
+ return;
634
} else {
635
device = nodes[0];
636
@@ -715,76 +696,119 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
696
}
697
}
698
718
- // Check if this agent is already connected
719
- const dupAgent = parent.wsagents[obj.dbNodeKey];
720
- parent.wsagents[obj.dbNodeKey] = obj;
721
- if (dupAgent) {
722
- // Record duplicate agents
723
- if (parent.duplicateAgentsLog[obj.dbNodeKey] == null) {
724
- if (dupAgent.remoteaddr == obj.remoteaddr) {
725
- parent.duplicateAgentsLog[obj.dbNodeKey] = { name: device.name, group: mesh.name, ip: [obj.remoteaddr], count: 1 };
726
- } else {
727
- parent.duplicateAgentsLog[obj.dbNodeKey] = { name: device.name, group: mesh.name, ip: [obj.remoteaddr, dupAgent.remoteaddr], count: 1 };
728
- }
699
+ completeAgentConnection3();
700
+ });
701
+ }
702
+
703
+ function completeAgentConnection2(device) {
704
+ // See if this mesh exists, if it does not we may want to create it.
705
+ var mesh = getMeshAutoCreate();
706
+
707
+ // Check if the mesh exists
708
+ if (mesh == null) {
709
+ // If we disconnect, the agent will just reconnect. We need to log this or tell agent to connect in a few hours.
710
+ parent.agentStats.invalidDomainMeshCount++;
711
+ console.log('Agent connected with invalid domain/mesh, holding connection (' + obj.remoteaddrport + ', ' + obj.dbMeshKey + ').');
712
+ return;
713
+ }
714
+
715
+ // Check if the mesh is the right type
716
+ if (mesh.mtype != 2) {
717
+ // If we disconnect, the agent will just reconnect. We need to log this or tell agent to connect in a few hours.
718
+ parent.agentStats.invalidMeshTypeCount++;
719
+ console.log('Agent connected with invalid mesh type, holding connection (' + obj.remoteaddrport + ').');
720
+ return;
721
+ }
722
+
723
+ // Mark when this device connected
724
+ obj.connectTime = Date.now();
725
+ db.Set({ _id: 'lc' + obj.dbNodeKey, type: 'lastconnect', domain: domain.id, time: obj.connectTime, addr: obj.remoteaddrport });
726
+
727
+ // This node does not exist, create it.
728
+ var device = { type: 'node', mtype: mesh.mtype, _id: obj.dbNodeKey, icon: obj.agentInfo.platformType, meshid: obj.dbMeshKey, name: obj.agentInfo.computerName, rname: obj.agentInfo.computerName, domain: domain.id, agent: { ver: obj.agentInfo.agentVersion, id: obj.agentInfo.agentId, caps: obj.agentInfo.capabilities }, host: null };
729
+ db.Set(device);
730
+
731
+ // Event the new node
732
+ if (obj.agentInfo.capabilities & 0x20) {
733
+ // This is a temporary agent, don't log.
734
+ parent.parent.DispatchEvent(['*', obj.dbMeshKey], obj, { etype: 'node', action: 'addnode', node: device, domain: domain.id, nolog: 1 });
735
+ } else {
736
+ parent.parent.DispatchEvent(['*', obj.dbMeshKey], obj, { etype: 'node', action: 'addnode', node: device, msg: ('Added device ' + obj.agentInfo.computerName + ' to mesh ' + mesh.name), domain: domain.id });
737
+ }
738
+
739
+ completeAgentConnection3();
740
+ }
741
+
742
+ function completeAgentConnection3() {
743
+ // Check if this agent is already connected
744
+ const dupAgent = parent.wsagents[obj.dbNodeKey];
745
+ parent.wsagents[obj.dbNodeKey] = obj;
746
+ if (dupAgent) {
747
+ // Record duplicate agents
748
+ if (parent.duplicateAgentsLog[obj.dbNodeKey] == null) {
749
+ if (dupAgent.remoteaddr == obj.remoteaddr) {
750
+ parent.duplicateAgentsLog[obj.dbNodeKey] = { name: device.name, group: mesh.name, ip: [obj.remoteaddr], count: 1 };
751
} else {
730
- parent.duplicateAgentsLog[obj.dbNodeKey].name = device.name;
731
- parent.duplicateAgentsLog[obj.dbNodeKey].group = mesh.name;
732
- parent.duplicateAgentsLog[obj.dbNodeKey].count++;
733
- if (parent.duplicateAgentsLog[obj.dbNodeKey].ip.indexOf(obj.remoteaddr) == -1) { parent.duplicateAgentsLog[obj.dbNodeKey].ip.push(obj.remoteaddr); }
752
+ parent.duplicateAgentsLog[obj.dbNodeKey] = { name: device.name, group: mesh.name, ip: [obj.remoteaddr, dupAgent.remoteaddr], count: 1 };
753
}
735
-
736
- // Close the duplicate agent
737
- parent.agentStats.duplicateAgentCount++;
738
- if (obj.nodeid != null) { parent.parent.debug(1, 'Duplicate agent ' + obj.nodeid + ' (' + obj.remoteaddrport + ')'); }
739
- dupAgent.close(3);
754
} else {
741
- // Indicate the agent is connected
742
- parent.parent.SetConnectivityState(obj.dbMeshKey, obj.dbNodeKey, obj.connectTime, 1, 1);
755
+ parent.duplicateAgentsLog[obj.dbNodeKey].name = device.name;
756
+ parent.duplicateAgentsLog[obj.dbNodeKey].group = mesh.name;
757
+ parent.duplicateAgentsLog[obj.dbNodeKey].count++;
758
+ if (parent.duplicateAgentsLog[obj.dbNodeKey].ip.indexOf(obj.remoteaddr) == -1) { parent.duplicateAgentsLog[obj.dbNodeKey].ip.push(obj.remoteaddr); }
759
}
760
745
- // We are done, ready to communicate with this agent
746
- delete obj.pendingCompleteAgentConnection;
747
- obj.authenticated = 2;
761
+ // Close the duplicate agent
762
+ parent.agentStats.duplicateAgentCount++;
763
+ if (obj.nodeid != null) { parent.parent.debug(1, 'Duplicate agent ' + obj.nodeid + ' (' + obj.remoteaddrport + ')'); }
764
+ dupAgent.close(3);
765
+ } else {
766
+ // Indicate the agent is connected
767
+ parent.parent.SetConnectivityState(obj.dbMeshKey, obj.dbNodeKey, obj.connectTime, 1, 1);
768
+ }
769
749
- // Check how many times this agent disconnected in the last few minutes.
750
- const disconnectCount = parent.wsagentsDisconnections[obj.nodeid];
751
- if (disconnectCount > 6) {
752
- console.log('Agent in big trouble: NodeId=' + obj.nodeid + ', IP=' + obj.remoteaddrport + ', Agent=' + obj.agentInfo.agentId + '.');
753
- // TODO: Log or do something to recover?
754
- return;
755
- }
770
+ // We are done, ready to communicate with this agent
771
+ delete obj.pendingCompleteAgentConnection;
772
+ obj.authenticated = 2;
773
757
- // Command 4, inform mesh agent that it's authenticated.
758
- obj.send(common.ShortToStr(4));
774
+ // Check how many times this agent disconnected in the last few minutes.
775
+ const disconnectCount = parent.wsagentsDisconnections[obj.nodeid];
776
+ if (disconnectCount > 6) {
777
+ console.log('Agent in big trouble: NodeId=' + obj.nodeid + ', IP=' + obj.remoteaddrport + ', Agent=' + obj.agentInfo.agentId + '.');
778
+ // TODO: Log or do something to recover?
779
+ return;
780
+ }
781
760
- if (disconnectCount > 4) {
761
- // Too many disconnections, this agent has issues. Just clear the core.
762
- obj.send(common.ShortToStr(10) + common.ShortToStr(0));
763
- //console.log('Agent in trouble: NodeId=' + obj.nodeid + ', IP=' + obj.remoteaddrport + ', Agent=' + obj.agentInfo.agentId + '.');
764
- // TODO: Log or do something to recover?
765
- return;
766
- }
782
+ // Command 4, inform mesh agent that it's authenticated.
783
+ obj.send(common.ShortToStr(4));
784
768
- // Not sure why, but in rare cases, obj.agentInfo is undefined here.
769
- if ((obj.agentInfo == null) || (typeof obj.agentInfo.capabilities != 'number')) { return; } // This is an odd case.
785
+ if (disconnectCount > 4) {
786
+ // Too many disconnections, this agent has issues. Just clear the core.
787
+ obj.send(common.ShortToStr(10) + common.ShortToStr(0));
788
+ //console.log('Agent in trouble: NodeId=' + obj.nodeid + ', IP=' + obj.remoteaddrport + ', Agent=' + obj.agentInfo.agentId + '.');
789
+ // TODO: Log or do something to recover?
790
+ return;
791
+ }
792
771
- // Check if we need to make an native update check
772
- obj.agentExeInfo = parent.parent.meshAgentBinaries[obj.agentInfo.agentId];
773
- const corename = parent.parent.meshAgentsArchitectureNumbers[obj.agentInfo.agentId].core;
774
- if (corename == null) { obj.send(common.ShortToStr(10) + common.ShortToStr(0)); } // MeshCommand_CoreModule, ask mesh agent to clear the core
793
+ // Not sure why, but in rare cases, obj.agentInfo is undefined here.
794
+ if ((obj.agentInfo == null) || (typeof obj.agentInfo.capabilities != 'number')) { return; } // This is an odd case.
795
776
- if ((obj.agentExeInfo != null) && (obj.agentExeInfo.update == true)) {
777
- // Ask the agent for it's executable binary hash
778
- obj.send(common.ShortToStr(12) + common.ShortToStr(0));
796
+ // Check if we need to make an native update check
797
+ obj.agentExeInfo = parent.parent.meshAgentBinaries[obj.agentInfo.agentId];
798
+ const corename = parent.parent.meshAgentsArchitectureNumbers[obj.agentInfo.agentId].core;
799
+ if (corename == null) { obj.send(common.ShortToStr(10) + common.ShortToStr(0)); } // MeshCommand_CoreModule, ask mesh agent to clear the core
800
+
801
+ if ((obj.agentExeInfo != null) && (obj.agentExeInfo.update == true)) {
802
+ // Ask the agent for it's executable binary hash
803
+ obj.send(common.ShortToStr(12) + common.ShortToStr(0));
804
+ } else {
805
+ // Check the mesh core, if the agent is capable of running one
806
+ if (((obj.agentInfo.capabilities & 16) != 0) && (corename != null)) {
807
+ obj.send(common.ShortToStr(11) + common.ShortToStr(0)); // Command 11, ask for mesh core hash.
808
} else {
780
- // Check the mesh core, if the agent is capable of running one
781
- if (((obj.agentInfo.capabilities & 16) != 0) && (corename != null)) {
782
- obj.send(common.ShortToStr(11) + common.ShortToStr(0)); // Command 11, ask for mesh core hash.
783
- } else {
784
- agentCoreIsStable(); // No updates needed, agent is ready to go.
785
- }
809
+ agentCoreIsStable(); // No updates needed, agent is ready to go.
810
}
787
- });
811
+ }
812
}
813
814
// Take a basic Intel AMT policy and add all server information to it, making it ready to send to this agent.
mpsserver.js
+90
-21
@@ -128,6 +128,7 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
128
var disconnectCommandCount = 0;
129
var socketClosedCount = 0;
130
var socketErrorCount = 0;
131
+ var maxDomainDevicesReached = 0;
132
133
// Return statistics about this MPS server
134
obj.getStats = function () {
@@ -153,7 +154,8 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
154
channelCloseCount: channelCloseCount,
155
disconnectCommandCount: disconnectCommandCount,
156
socketClosedCount: socketClosedCount,
156
- socketErrorCount: socketErrorCount
157
+ socketErrorCount: socketErrorCount,
158
+ maxDomainDevicesReached : maxDomainDevicesReached
159
};
160
}
161
@@ -189,6 +191,11 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
191
var xx = socket.tag.clientCert.subject.O.split('/');
192
if (xx.length == 1) { meshid = xx[0]; } else { domainid = xx[0].toLowerCase(); meshid = xx[1]; }
193
194
+ // Check the incoming domain
195
+ var domain = obj.parent.config.domains[domainid];
196
+ if (domain == null) { console.log('CIRA connection for invalid domain. meshid: ' + meshid); socket.end(); return; }
197
+
198
+ socket.tag.domain = domain;
199
socket.tag.domainid = domainid;
200
socket.tag.meshid = 'mesh/' + domainid + '/' + meshid;
201
socket.tag.nodeid = 'node/' + domainid + '/' + require('crypto').createHash('sha384').update(common.hex2rstr(socket.tag.clientCert.modulus, 'binary')).digest('base64').replace(/\+/g, '@').replace(/\//g, '$');
@@ -203,16 +210,45 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
210
obj.db.Get(socket.tag.nodeid, function (err, nodes) {
211
if ((nodes == null) || (nodes.length !== 1)) {
212
if (mesh.mtype == 1) {
206
- // Node is not in the database, add it. Credentials will be empty until added by the user.
207
- var device = { type: 'node', mtype: 1, _id: socket.tag.nodeid, meshid: socket.tag.meshid, name: socket.tag.name, host: null, domain: domainid, intelamt: { user: '', pass: '', tls: 0, state: 2 } };
208
- obj.db.Set(device);
209
-
210
- // Event the new node
211
- addedTlsDeviceCount++;
212
- var device2 = common.Clone(device);
213
- if (device2.intelamt.pass != null) delete device2.intelamt.pass; // Remove the Intel AMT password before eventing this.
214
- var change = 'CIRA added device ' + socket.tag.name + ' to mesh ' + mesh.name;
215
- obj.parent.DispatchEvent(['*', socket.tag.meshid], obj, { etype: 'node', action: 'addnode', node: device2, msg: change, domain: domainid });
213
+ // Check if we already have too many devices for this domain
214
+ if (domain.limits && (typeof domain.limits.maxdevices == 'number')) {
215
+ db.isMaxType(domain.limits.maxdevices, 'node', domain.id, function (ismax, count) {
216
+ if (ismax == true) {
217
+ // Too many devices in this domain.
218
+ maxDomainDevicesReached++;
219
+ console.log('Too many devices on this domain to accept the CIRA connection. meshid: ' + socket.tag.meshid);
220
+ socket.end();
221
+ } else {
222
+ // We are under the limit, create the new device.
223
+ // Node is not in the database, add it. Credentials will be empty until added by the user.
224
+ var device = { type: 'node', mtype: 1, _id: socket.tag.nodeid, meshid: socket.tag.meshid, name: socket.tag.name, host: null, domain: domainid, intelamt: { user: '', pass: '', tls: 0, state: 2 } };
225
+ obj.db.Set(device);
226
+
227
+ // Event the new node
228
+ addedTlsDeviceCount++;
229
+ var device2 = common.Clone(device);
230
+ if (device2.intelamt.pass != null) delete device2.intelamt.pass; // Remove the Intel AMT password before eventing this.
231
+ var change = 'CIRA added device ' + socket.tag.name + ' to mesh ' + mesh.name;
232
+ obj.parent.DispatchEvent(['*', socket.tag.meshid], obj, { etype: 'node', action: 'addnode', node: device2, msg: change, domain: domainid });
233
+
234
+ // Add the connection to the MPS connection list
235
+ obj.ciraConnections[socket.tag.nodeid] = socket;
236
+ obj.parent.SetConnectivityState(socket.tag.meshid, socket.tag.nodeid, socket.tag.connectTime, 2, 7); // TODO: Right now report power state as "present" (7) until we can poll.
237
+ }
238
+ });
239
+ return;
240
+ } else {
241
+ // Node is not in the database, add it. Credentials will be empty until added by the user.
242
+ var device = { type: 'node', mtype: 1, _id: socket.tag.nodeid, meshid: socket.tag.meshid, name: socket.tag.name, host: null, domain: domainid, intelamt: { user: '', pass: '', tls: 0, state: 2 } };
243
+ obj.db.Set(device);
244
+
245
+ // Event the new node
246
+ addedTlsDeviceCount++;
247
+ var device2 = common.Clone(device);
248
+ if (device2.intelamt.pass != null) delete device2.intelamt.pass; // Remove the Intel AMT password before eventing this.
249
+ var change = 'CIRA added device ' + socket.tag.name + ' to mesh ' + mesh.name;
250
+ obj.parent.DispatchEvent(['*', socket.tag.meshid], obj, { etype: 'node', action: 'addnode', node: device2, msg: change, domain: domainid });
251
+ }
252
} else {
253
// New CIRA connection for unknown node, disconnect.
254
unknownTlsNodeCount++;
@@ -312,6 +348,9 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
348
// Intel AMT GUID (socket.tag.SystemId) will be used as NodeID
349
var systemid = socket.tag.SystemId.split('-').join('');
350
var nodeid = Buffer.from(systemid + systemid + systemid, 'hex').toString('base64').replace(/\+/g, '@').replace(/\//g, '$');
351
+ var domain = obj.parent.config.domains[mesh.domain];
352
+ socket.tag.domain = domain;
353
+ socket.tag.domainid = mesh.domain;
354
socket.tag.name = '';
355
socket.tag.nodeid = 'node/' + mesh.domain + '/' + nodeid; // Turn 16bit systemid guid into 48bit nodeid that is base64 encoded
356
socket.tag.meshid = mesh._id;
@@ -319,16 +358,46 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
358
359
obj.db.Get(socket.tag.nodeid, function (err, nodes) {
360
if ((nodes == null) || (nodes.length !== 1)) {
322
- // Node is not in the database, add it. Credentials will be empty until added by the user.
323
- var device = { type: 'node', mtype: 1, _id: socket.tag.nodeid, meshid: socket.tag.meshid, name: socket.tag.name, host: null, domain: mesh.domain, intelamt: { user: '', pass: '', tls: 0, state: 2 } };
324
- obj.db.Set(device);
325
-
326
- // Event the new node
327
- addedDeviceCount++;
328
- var device2 = common.Clone(device);
329
- if (device2.intelamt.pass != null) delete device2.intelamt.pass; // Remove the Intel AMT password before eventing this.
330
- var change = 'CIRA added device ' + socket.tag.name + ' to group ' + mesh.name;
331
- obj.parent.DispatchEvent(['*', socket.tag.meshid], obj, { etype: 'node', action: 'addnode', node: device2, msg: change, domain: mesh.domain });
361
+ // Check if we already have too many devices for this domain
362
+ if (domain.limits && (typeof domain.limits.maxdevices == 'number')) {
363
+ db.isMaxType(domain.limits.maxdevices, 'node', mesh.domain, function (ismax, count) {
364
+ if (ismax == true) {
365
+ // Too many devices in this domain.
366
+ maxDomainDevicesReached++;
367
+ console.log('Too many devices on this domain to accept the CIRA connection. meshid: ' + socket.tag.meshid);
368
+ socket.end();
369
+ } else {
370
+ // We are under the limit, create the new device.
371
+ // Node is not in the database, add it. Credentials will be empty until added by the user.
372
+ var device = { type: 'node', mtype: 1, _id: socket.tag.nodeid, meshid: socket.tag.meshid, name: socket.tag.name, host: null, domain: mesh.domain, intelamt: { user: '', pass: '', tls: 0, state: 2 } };
373
+ obj.db.Set(device);
374
+
375
+ // Event the new node
376
+ addedDeviceCount++;
377
+ var device2 = common.Clone(device);
378
+ if (device2.intelamt.pass != null) delete device2.intelamt.pass; // Remove the Intel AMT password before eventing this.
379
+ var change = 'CIRA added device ' + socket.tag.name + ' to group ' + mesh.name;
380
+ obj.parent.DispatchEvent(['*', socket.tag.meshid], obj, { etype: 'node', action: 'addnode', node: device2, msg: change, domain: mesh.domain });
381
+
382
+ // Add the connection to the MPS connection list
383
+ obj.ciraConnections[socket.tag.nodeid] = socket;
384
+ obj.parent.SetConnectivityState(socket.tag.meshid, socket.tag.nodeid, socket.tag.connectTime, 2, 7); // TODO: Right now report power state as "present" (7) until we can poll.
385
+ SendUserAuthSuccess(socket); // Notify the auth success on the CIRA connection
386
+ }
387
+ });
388
+ return;
389
+ } else {
390
+ // Node is not in the database, add it. Credentials will be empty until added by the user.
391
+ var device = { type: 'node', mtype: 1, _id: socket.tag.nodeid, meshid: socket.tag.meshid, name: socket.tag.name, host: null, domain: mesh.domain, intelamt: { user: '', pass: '', tls: 0, state: 2 } };
392
+ obj.db.Set(device);
393
+
394
+ // Event the new node
395
+ addedDeviceCount++;
396
+ var device2 = common.Clone(device);
397
+ if (device2.intelamt.pass != null) delete device2.intelamt.pass; // Remove the Intel AMT password before eventing this.
398
+ var change = 'CIRA added device ' + socket.tag.name + ' to group ' + mesh.name;
399
+ obj.parent.DispatchEvent(['*', socket.tag.meshid], obj, { etype: 'node', action: 'addnode', node: device2, msg: change, domain: mesh.domain });
400
+ }
401
} else {
402
// Node is already present
403
var node = nodes[0];
package.json
+1
-1
@@ -1,6 +1,6 @@
1
{
2
"name": "meshcentral",
3
- "version": "0.3.5-z",
3
+ "version": "0.3.6-a",
4
"keywords": [
5
"Remote Management",
6
"Intel AMT",
sample-config.json
+1
@@ -72,6 +72,7 @@
72
"__UserConsentFlags__" : "Set to: 1 for desktop, 2 for terminal, 3 for files, 7 for all",
73
"_UserConsentFlags" : 7,
74
"_Limits": {
75
+ "_MaxDevices": 100,
76
"_MaxUserAccounts": 100,
77
"_MaxUserSessions": 100,
78
"_MaxAgentSessions": 100,
views/default-min.handlebars
+5
-5
@@ -10189,7 +10189,7 @@ var QRCode;!function(){function a(a){this.mode=c.MODE_8BIT_BYTE,this.data=a,this
10189
10190
function addDeviceAttribute(name, value) { return '<tr><td class=style7>' + name + '</td><td class=style9>' + value + '</td></tr>'; }
10191
10192
- function editDeviceAmtSettings(nodeid, func) {
10192
+ function editDeviceAmtSettings(nodeid, func, arg) {
10193
if (xxdialogMode) return;
10194
var x = '', node = getNodeFromId(nodeid), buttons = 3, meshrights = getNodeRights(nodeid);
10195
if ((meshrights & 4) == 0) return;
@@ -10197,7 +10197,7 @@ var QRCode;!function(){function a(a){this.mode=c.MODE_8BIT_BYTE,this.data=a,this
10197
x += addHtmlValue('Password', '<input id=dp10password type=password style=width:230px autocomplete=nope maxlength=32 onchange=validateDeviceAmtSettings() onkeyup=validateDeviceAmtSettings() />');
10198
x += addHtmlValue('Security', '<select id=dp10tls style=width:236px><option value=0>No TLS security</option><option value=1>TLS security required</option></select>');
10199
if ((node.intelamt.user != null) && (node.intelamt.user != '')) { buttons = 7; }
10200
- setDialogMode(2, "Edit Intel® AMT credentials", buttons, editDeviceAmtSettingsEx, x, { node: node, func: func });
10200
+ setDialogMode(2, "Edit Intel® AMT credentials", buttons, editDeviceAmtSettingsEx, x, { node: node, func: func, arg: arg });
10201
if ((node.intelamt.user != null) && (node.intelamt.user != '')) { Q('dp10username').value = node.intelamt.user; } else { Q('dp10username').value = 'admin'; }
10202
Q('dp10tls').value = node.intelamt.tls;
10203
validateDeviceAmtSettings();
@@ -10220,7 +10220,7 @@ var QRCode;!function(){function a(a){this.mode=c.MODE_8BIT_BYTE,this.data=a,this
10220
meshserver.send({ action: 'changedevice', nodeid: tag.node._id, intelamt: { user: amtuser, pass: amtpass, tls: Q('dp10tls').value } });
10221
tag.node.intelamt.user = amtuser;
10222
tag.node.intelamt.tls = Q('dp10tls').value;
10223
- if (tag.func) { setTimeout(tag.func, 300); }
10223
+ if (tag.func) { setTimeout(function () { tag.func(null, tag.arg); }, 300); }
10224
}
10225
}
10226
@@ -10519,7 +10519,7 @@ var QRCode;!function(){function a(a){this.mode=c.MODE_8BIT_BYTE,this.data=a,this
10519
desktopNode = currentNode;
10520
if (contype == 2) {
10521
// Setup the Intel AMT remote desktop
10522
- if ((desktopNode.intelamt.user == null) || (desktopNode.intelamt.user == '')) { editDeviceAmtSettings(desktopNode._id, connectDesktop); return; }
10522
+ if ((desktopNode.intelamt.user == null) || (desktopNode.intelamt.user == '')) { editDeviceAmtSettings(desktopNode._id, connectDesktop, 2); return; }
10523
desktop = CreateAmtRedirect(CreateAmtRemoteDesktop('Desk'), authCookie);
10524
desktop.debugmode = debugmode;
10525
desktop.onStateChanged = onDesktopStateChange;
@@ -11111,7 +11111,7 @@ var QRCode;!function(){function a(a){this.mode=c.MODE_8BIT_BYTE,this.data=a,this
11111
if (!terminal) {
11112
if (contype == 2) {
11113
// Setup the Intel AMT terminal
11114
- if ((terminalNode.intelamt.user == null) || (terminalNode.intelamt.user == '')) { editDeviceAmtSettings(terminalNode._id, connectTerminal); return; }
11114
+ if ((terminalNode.intelamt.user == null) || (terminalNode.intelamt.user == '')) { editDeviceAmtSettings(terminalNode._id, connectTerminal, 2); return; }
11115
var termoptions = {};
11116
if (Q('termSizeList').value == 2) { termoptions.width = 100; termoptions.height = 30; }
11117
terminal = CreateAmtRedirect(CreateAmtRemoteTerminal('Term', termoptions), authCookie);
views/default.handlebars
+5
-5
@@ -4141,7 +4141,7 @@
4141
4142
function addDeviceAttribute(name, value) { return '<tr><td class=style7>' + name + '</td><td class=style9>' + value + '</td></tr>'; }
4143
4144
- function editDeviceAmtSettings(nodeid, func) {
4144
+ function editDeviceAmtSettings(nodeid, func, arg) {
4145
if (xxdialogMode) return;
4146
var x = '', node = getNodeFromId(nodeid), buttons = 3, meshrights = getNodeRights(nodeid);
4147
if ((meshrights & 4) == 0) return;
@@ -4149,7 +4149,7 @@
4149
x += addHtmlValue('Password', '<input id=dp10password type=password style=width:230px autocomplete=nope maxlength=32 onchange=validateDeviceAmtSettings() onkeyup=validateDeviceAmtSettings() />');
4150
x += addHtmlValue('Security', '<select id=dp10tls style=width:236px><option value=0>No TLS security</option><option value=1>TLS security required</option></select>');
4151
if ((node.intelamt.user != null) && (node.intelamt.user != '')) { buttons = 7; }
4152
- setDialogMode(2, "Edit Intel® AMT credentials", buttons, editDeviceAmtSettingsEx, x, { node: node, func: func });
4152
+ setDialogMode(2, "Edit Intel® AMT credentials", buttons, editDeviceAmtSettingsEx, x, { node: node, func: func, arg: arg });
4153
if ((node.intelamt.user != null) && (node.intelamt.user != '')) { Q('dp10username').value = node.intelamt.user; } else { Q('dp10username').value = 'admin'; }
4154
Q('dp10tls').value = node.intelamt.tls;
4155
validateDeviceAmtSettings();
@@ -4172,7 +4172,7 @@
4172
meshserver.send({ action: 'changedevice', nodeid: tag.node._id, intelamt: { user: amtuser, pass: amtpass, tls: Q('dp10tls').value } });
4173
tag.node.intelamt.user = amtuser;
4174
tag.node.intelamt.tls = Q('dp10tls').value;
4175
- if (tag.func) { setTimeout(tag.func, 300); }
4175
+ if (tag.func) { setTimeout(function () { tag.func(null, tag.arg); }, 300); }
4176
}
4177
}
4178
@@ -4471,7 +4471,7 @@
4471
desktopNode = currentNode;
4472
if (contype == 2) {
4473
// Setup the Intel AMT remote desktop
4474
- if ((desktopNode.intelamt.user == null) || (desktopNode.intelamt.user == '')) { editDeviceAmtSettings(desktopNode._id, connectDesktop); return; }
4474
+ if ((desktopNode.intelamt.user == null) || (desktopNode.intelamt.user == '')) { editDeviceAmtSettings(desktopNode._id, connectDesktop, 2); return; }
4475
desktop = CreateAmtRedirect(CreateAmtRemoteDesktop('Desk'), authCookie);
4476
desktop.debugmode = debugmode;
4477
desktop.onStateChanged = onDesktopStateChange;
@@ -5063,7 +5063,7 @@
5063
if (!terminal) {
5064
if (contype == 2) {
5065
// Setup the Intel AMT terminal
5066
- if ((terminalNode.intelamt.user == null) || (terminalNode.intelamt.user == '')) { editDeviceAmtSettings(terminalNode._id, connectTerminal); return; }
5066
+ if ((terminalNode.intelamt.user == null) || (terminalNode.intelamt.user == '')) { editDeviceAmtSettings(terminalNode._id, connectTerminal, 2); return; }
5067
var termoptions = {};
5068
if (Q('termSizeList').value == 2) { termoptions.width = 100; termoptions.height = 30; }
5069
terminal = CreateAmtRedirect(CreateAmtRemoteTerminal('Term', termoptions), authCookie);
webserver.js
+2
-1
@@ -261,7 +261,8 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
261
invalidMeshTypeCount: 0,
262
invalidDomainMesh2Count: 0,
263
invalidMeshType2Count: 0,
264
- duplicateAgentCount: 0
264
+ duplicateAgentCount: 0,
265
+ maxDomainDevicesReached: 0
266
}
267
obj.getAgentStats = function () { return obj.agentStats; }
268