AMT Manager improvements.
Ylian Saint-Hilaire committed
Feb 22, 2021 at 14:41 UTC
5298d1c5c96c101adb9300169eca07eb03299641
6 files changed
+48
-26
amtmanager.js
+27
-20
@@ -183,7 +183,7 @@ module.exports.CreateAmtManager = function (parent) {
183
parent.debug('amt', "Start Management", nodeid, connType);
184
addAmtDevice(dev);
185
186
- // Start the device manager the task limiter so not to flood the server. Low priority task
186
+ // Start the device manager in the task limiter so not to flood the server. Low priority task
187
obj.parent.taskLimiter.launch(function (dev, taskid, taskLimiterQueue) {
188
if (isAmtDeviceValid(dev)) {
189
// Start managing this device
@@ -255,34 +255,41 @@ module.exports.CreateAmtManager = function (parent) {
255
// Handle server events
256
// Make sure to only manage devices with connections to this server. In a multi-server setup, we don't want multiple managers talking to the same device.
257
obj.HandleEvent = function (source, event, ids, id) {
258
- if (event.noact == 1) return; // Take no action on these events. We are likely in peering mode and need to only act when the database signals the change in state.
258
switch (event.action) {
259
case 'removenode': { // React to node being removed
260
+ if (event.noact == 1) return; // Take no action on these events. We are likely in peering mode and need to only act when the database signals the change in state.
261
removeDevice(event.nodeid);
262
break;
263
}
264
case 'wakedevices': { // React to node wakeup command, perform Intel AMT wake if possible
265
+ if (event.noact == 1) return; // Take no action on these events. We are likely in peering mode and need to only act when the database signals the change in state.
266
if (Array.isArray(event.nodeids)) { for (var i in event.nodeids) { performPowerAction(event.nodeids[i], 2); } }
267
break;
268
}
269
case 'changenode': { // React to changes in a device
269
- var devices = obj.amtDevices[event.nodeid];
270
- if (devices == null) break; // We are not managing this device
271
- for (var i in devices) {
272
- var dev = devices[i];
273
- if (dev.name != event.node.name) {
274
- //console.log('device name change');
270
+ var devices = obj.amtDevices[event.nodeid], rescan = false;
271
+ if (devices != null) {
272
+ for (var i in devices) {
273
+ var dev = devices[i];
274
dev.name = event.node.name;
275
+ if (event.node.intelamt != null) { dev.intelamt = event.node.intelamt; }
276
+ if ((dev.connType == 3) && (dev.host != event.node.host)) {
277
+ dev.host = event.node.host; // The host has changed, if we are connected to this device locally, we need to reset.
278
+ removeAmtDevice(dev); // We are going to wait for the AMT scanned to find this device again.
279
+ rescan = true;
280
+ }
281
}
277
- if (event.node.intelamt != null) {
278
- dev.intelamt = event.node.intelamt;
279
- }
280
- if ((dev.connType == 3) && (dev.host != event.node.host)) {
281
- //console.log('device host change', dev.host, event.node.host);
282
- dev.host = event.node.host; // The host has changed, if we are connected to this device locally, we need to reset.
283
- removeAmtDevice(dev); // We are going to wait for the AMT scanned to find this device again.
284
- }
282
+ } else {
283
+ // If this event provides a hint that something changed with AMT and we are not managing this device, let's rescan the local network now.
284
+ if (event.amtchange == 1) { rescan = true; }
285
}
286
+
287
+ // If there is a significant change to the device AMT settings and this server manages local devices, perform a re-scan of the device now.
288
+ if (rescan && (parent.amtScanner != null)) { parent.amtScanner.performSpecificScan(event.node); }
289
+ break;
290
+ }
291
+ case 'meshchange': {
292
+ // TODO
293
break;
294
}
295
}
@@ -581,7 +588,7 @@ module.exports.CreateAmtManager = function (parent) {
588
589
// Set an error that we can't login to this device
590
if (dev.aquired == null) { dev.aquired = {}; }
584
- dev.aquired.warn = 1; // Intel AMT Warning Flags: 1 = Unknown credentials, 2 = Realm Mismatch, 4 = TLS Cert Mismatch
591
+ dev.aquired.warn = 1; // Intel AMT Warning Flags: 1 = Unknown credentials, 2 = Realm Mismatch, 4 = TLS Cert Mismatch, 8 = Trying credentials
592
UpdateDevice(dev);
593
}
594
//console.log(dev.nodeid, dev.name, dev.host, status, 'Bad response');
@@ -620,7 +627,7 @@ module.exports.CreateAmtManager = function (parent) {
627
if ((typeof dev.aquired.tls == 'number') && (dev.aquired.tls != device.intelamt.tls)) { change = 1; log = 1; device.intelamt.tls = dev.aquired.tls; changes.push('AMT TLS'); }
628
if ((typeof dev.aquired.state == 'number') && (dev.aquired.state != device.intelamt.state)) { change = 1; log = 1; device.intelamt.state = dev.aquired.state; changes.push('AMT state'); }
629
623
- // Intel AMT Warning Flags: 1 = Unknown credentials, 2 = Realm Mismatch, 4 = TLS Cert Mismatch
630
+ // Intel AMT Warning Flags: 1 = Unknown credentials, 2 = Realm Mismatch, 4 = TLS Cert Mismatch, 8 = Trying credentials
631
if ((typeof dev.aquired.warn == 'number')) { if ((dev.aquired.warn == 0) && (device.intelamt.warn != null)) { delete device.intelamt.warn; change = 1; } else if (dev.aquired.warn != device.intelamt.warn) { device.intelamt.warn = dev.aquired.warn; change = 1; } }
632
633
// Update Intel AMT flags if needed
@@ -737,8 +744,8 @@ module.exports.CreateAmtManager = function (parent) {
744
if (devices == null) return;
745
for (var i in devices) {
746
var dev = devices[i];
740
- if (dev.amtstack != null) {
741
- // TODO: Check if the device passed initial connection
747
+ // If not LMS, has a AMT stack present and is in connected state, perform power operation.
748
+ if ((dev.connType != 2) && (dev.state == 1) && (dev.amtstack != null)) {
749
try { dev.amtstack.RequestPowerStateChange(action, performPowerActionResponse); } catch (ex) { }
750
}
751
}
amtscanner.js
+12
-1
@@ -167,7 +167,7 @@ module.exports.CreateAmtScanner = function (parent) {
167
const ciraConnections = obj.parent.mpsserver ? obj.parent.mpsserver.GetConnectionToNode(doc._id, null, true) : null; // See if any OOB connections are present
168
if ((host != '127.0.0.1') && (host != '::1') && (host.toLowerCase() != 'localhost') && (ciraConnections == null)) {
169
var scaninfo = obj.scanTable[doc._id];
170
- if (scaninfo == undefined) {
170
+ if (scaninfo == null) {
171
var tag = obj.nextTag++;
172
obj.scanTableTags[tag] = obj.scanTable[doc._id] = scaninfo = { nodeinfo: doc, present: true, tag: tag, state: 0 };
173
//console.log('Scan ' + host + ', state=' + scaninfo.state + ', delta=' + delta);
@@ -212,6 +212,17 @@ module.exports.CreateAmtScanner = function (parent) {
212
return true;
213
};
214
215
+ // Look for all Intel AMT computers that may be locally reachable and poll their presence
216
+ obj.performSpecificScan = function (node) {
217
+ var host = node.host.toLowerCase();
218
+ const ciraConnections = obj.parent.mpsserver ? obj.parent.mpsserver.GetConnectionToNode(node._id, null, true) : null; // See if any OOB connections are present
219
+ if ((host != '127.0.0.1') && (host != '::1') && (host.toLowerCase() != 'localhost') && (ciraConnections == null)) {
220
+ obj.checkTcpPresence(host, (node.intelamt.tls == 1) ? 16993 : 16992, { nodeinfo: node }, function (tag, result, version) {
221
+ if ((result == true) && (obj.parent.amtManager != null)) { obj.parent.amtManager.startAmtManagement(tag.nodeinfo._id, 3, tag.nodeinfo.host); }
222
+ });
223
+ }
224
+ };
225
+
226
// Check the presense of a specific Intel AMT computer using RMCP
227
obj.checkAmtPresence = function (host, tag) { obj.ResolveName(host, function (hostname, ip) { obj.checkAmtPresenceEx(ip, tag); }); };
228
meshagent.js
+4
@@ -439,6 +439,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
439
parent.parent.debug('agent', 'Agent reported web cert hash:' + (Buffer.from(msg.substring(2, 50), 'binary').toString('hex')) + '.');
440
console.log('Agent bad web cert hash (Agent:' + (Buffer.from(msg.substring(2, 50), 'binary').toString('hex').substring(0, 10)) + ' != Server:' + (Buffer.from(getWebCertHash(domain), 'binary').toString('hex').substring(0, 10)) + ' or ' + (Buffer.from(getWebCertFullHash(domain), 'binary').toString('hex').substring(0, 10)) + '), holding connection (' + obj.remoteaddrport + ').');
441
console.log('Agent reported web cert hash:' + (Buffer.from(msg.substring(2, 50), 'binary').toString('hex')) + '.');
442
+ delete obj.agentSeenCerthash;
443
return;
444
} else {
445
// The hash matched one of the acceptable values, send the agent web hash back to the agent
@@ -1078,6 +1079,9 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
1079
if (isIgnoreHashCheck() == false) {
1080
var verified = false;
1081
1082
+ // This agent did not report a valid TLS certificate hash, fail now.
1083
+ if (obj.agentSeenCerthash == null) return false;
1084
+
1085
// Raw RSA signatures have an exact length of 256 or 384. PKCS7 is larger.
1086
if ((msg.length != 384) && (msg.length != 256)) {
1087
// Verify a PKCS7 signature.
meshuser.js
+2
-2
@@ -4047,12 +4047,12 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
4047
}
4048
if (command.desc != null && (command.desc != node.desc)) { change = 1; node.desc = command.desc; changes.push('description'); }
4049
if (command.intelamt != null) {
4050
- if ((parent.parent.amtManager == null) || (node.intelamt.user == null) || (node.intelamt.user == '') || ((node.intelamt.warn != null) && ((node.intelamt.warn) & 3 != 0))) { // Only allow changes to Intel AMT credentials if AMT manager is not running, or manager warned of unknown/trying credentials.
4050
+ if ((parent.parent.amtManager == null) || (node.intelamt.user == null) || (node.intelamt.user == '') || ((node.intelamt.warn != null) && (((node.intelamt.warn) & 9) != 0))) { // Only allow changes to Intel AMT credentials if AMT manager is not running, or manager warned of unknown/trying credentials.
4051
if ((command.intelamt.user != null) && (command.intelamt.pass != null) && ((command.intelamt.user != node.intelamt.user) || (command.intelamt.pass != node.intelamt.pass))) {
4052
change = 1;
4053
node.intelamt.user = command.intelamt.user;
4054
node.intelamt.pass = command.intelamt.pass;
4055
- node.intelamt.warn = 2; // Change warning to "Trying". Bit flags: 0 = Valid credentials, 1 = Invalid credentials, 2 = Trying new credentials.
4055
+ node.intelamt.warn |= 8; // Change warning to "Trying". Bit flags: 1 = Unknown credentials, 2 = Realm Mismatch, 4 = TLS Cert Mismatch, 8 = Trying credentials
4056
changes.push('Intel AMT credentials');
4057
amtchange = 1;
4058
}
views/default-mobile.handlebars
+1
-1
@@ -3128,7 +3128,7 @@
3128
} else if (((features2 & 1) != 0) && (node.intelamt.warn != null)) { // If AMT manager is running and warned of invalid credentials, allow setting them.
3129
var warn = null;
3130
if ((node.intelamt.warn & 1) != 0) { warn = "Invalid Credentials"; }
3131
- if ((node.intelamt.warn & 2) != 0) { warn = "Trying Credentials"; }
3131
+ if ((node.intelamt.warn & 8) != 0) { warn = "Trying Credentials"; }
3132
if (warn != null) {
3133
if ((meshrights & 4) != 0) {
3134
str += ', <i style=color:#FF0000;cursor:pointer title="' + "Edit Intel® AMT credentials" + '" onclick=editDeviceAmtSettings("' + node._id + '")>' + warn + '</i>';
views/default.handlebars
+2
-2
@@ -2772,7 +2772,7 @@
2772
meshserver.send({ action: 'nodes' }); // Request a refresh of all nodes (TODO: We could optimize this to only request nodes for the new mesh).
2773
}
2774
} else {
2775
- // This is an existing mesh
2775
+ // This is an existing device group
2776
if (message.event.name != null) {
2777
meshes[message.event.meshid].name = message.event.name;
2778
for (var i in nodes) { if (nodes[i].meshid == message.event.meshid) { nodes[i].meshnamel = message.event.name.toLowerCase(); } }
@@ -5927,7 +5927,7 @@
5927
} else if (((features2 & 1) != 0) && (node.intelamt.warn != null)) { // If AMT manager is running and warned of invalid credentials, allow setting them.
5928
var warn = null;
5929
if ((node.intelamt.warn & 1) != 0) { warn = "Invalid Credentials"; }
5930
- if ((node.intelamt.warn & 2) != 0) { warn = "Trying Credentials"; }
5930
+ if ((node.intelamt.warn & 8) != 0) { warn = "Trying Credentials"; }
5931
if (warn != null) {
5932
if ((meshrights & 4) != 0) {
5933
str += ', <i style=color:#FF0000;cursor:pointer title="' + "Edit Intel® AMT credentials" + '" onclick=editDeviceAmtSettings("' + node._id + '")>' + warn + '</i>';