mirror of
https://github.com/Ylianst/MeshCentral.git
synced 2025-02-12 11:01:52 +00:00
More work on Intel AMT One Click Recovery.
This commit is contained in:
parent
d750077f45
commit
a3f9ffc68b
4 changed files with 55 additions and 24 deletions
|
@ -295,9 +295,9 @@ module.exports.CreateAmtManager = function (parent) {
|
||||||
if (Array.isArray(event.nodeids)) { for (var i in event.nodeids) { performPowerAction(event.nodeids[i], 2); } }
|
if (Array.isArray(event.nodeids)) { for (var i in event.nodeids) { performPowerAction(event.nodeids[i], 2); } }
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'clickoncerecovery': { // React to Intel AMT Click Once Recovery command
|
case 'oneclickrecovery': { // React to Intel AMT One Click Recovery command
|
||||||
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.
|
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.
|
||||||
if (Array.isArray(event.nodeids)) { for (var i in event.nodeids) { performClickOnceRecoveryAction(event.nodeids[i], event.file); } }
|
if (Array.isArray(event.nodeids)) { for (var i in event.nodeids) { performOneClickRecoveryAction(event.nodeids[i], event.file); } }
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'changenode': { // React to changes in a device
|
case 'changenode': { // React to changes in a device
|
||||||
|
@ -810,23 +810,53 @@ module.exports.CreateAmtManager = function (parent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Perform Intel AMT Click Once Recovery on a device
|
//
|
||||||
function performClickOnceRecoveryAction(nodeid, file) {
|
// Intel AMT One Click Recovery
|
||||||
|
//
|
||||||
|
|
||||||
|
// Perform Intel AMT One Click Recovery on a device
|
||||||
|
function performOneClickRecoveryAction(nodeid, file) {
|
||||||
var devices = obj.amtDevices[nodeid];
|
var devices = obj.amtDevices[nodeid];
|
||||||
if (devices == null) return;
|
if (devices == null) return;
|
||||||
for (var i in devices) {
|
for (var i in devices) {
|
||||||
var dev = devices[i];
|
var dev = devices[i];
|
||||||
// If not LMS, has a AMT stack present and is in connected state, perform operation.
|
// If not LMS, has a AMT stack present and is in connected state, perform operation.
|
||||||
if ((dev.connType != 2) && (dev.state == 1) && (dev.amtstack != null)) {
|
if ((dev.connType != 2) && (dev.state == 1) && (dev.amtstack != null)) {
|
||||||
console.log('Perform Click Once Recovery', nodeid, file);
|
// Make sure the MPS server root certificate is present.
|
||||||
|
// Start by looking at existing certificates.
|
||||||
// TODO: Make sure the MPS server root certificate is present.
|
dev.ocrfile = file;
|
||||||
// TODO: Generate the one-time URL.
|
dev.amtstack.BatchEnum(null, ['AMT_PublicKeyCertificate'], performOneClickRecoveryActionEx);
|
||||||
// TODO: Issue the WSMAN command.
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Response with list of certificates in Intel AMT
|
||||||
|
function performOneClickRecoveryActionEx(stack, name, responses, status) {
|
||||||
|
const dev = stack.dev;
|
||||||
|
if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request.
|
||||||
|
if (status != 200) { dev.consoleMsg("Failed to get security information (" + status + ")."); removeAmtDevice(dev, 19); return; }
|
||||||
|
|
||||||
|
// Organize the certificates
|
||||||
|
var xxCertificates = responses['AMT_PublicKeyCertificate'].responses;
|
||||||
|
for (var i in xxCertificates) {
|
||||||
|
xxCertificates[i].TrustedRootCertficate = (xxCertificates[i]['TrustedRootCertficate'] == true);
|
||||||
|
xxCertificates[i].X509CertificateBin = Buffer.from(xxCertificates[i]['X509Certificate'], 'base64').toString('binary');
|
||||||
|
xxCertificates[i].XIssuer = parseCertName(xxCertificates[i]['Issuer']);
|
||||||
|
xxCertificates[i].XSubject = parseCertName(xxCertificates[i]['Subject']);
|
||||||
|
}
|
||||||
|
dev.policy.certificates = xxCertificates;
|
||||||
|
attemptRootCertSync(dev, performOneClickRecoveryActionEx2, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function performOneClickRecoveryActionEx2(dev) {
|
||||||
|
// Generate the one-time URL.
|
||||||
|
var cookie = obj.parent.encodeCookie({ a: 'ocr', f: dev.ocrfile }, obj.parent.loginCookieEncryptionKey)
|
||||||
|
var url = 'https://' + parent.webserver.certificates.AmtMpsName + ':' + ((parent.args.mpsaliasport != null) ? parent.args.mpsaliasport : parent.args.mpsport) + '/ocr/' + cookie + '.iso';
|
||||||
|
|
||||||
|
// TODO: Issue the WSMAN command.
|
||||||
|
console.log('Perform One Click Recovery', url);
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Intel AMT Clock Syncronization
|
// Intel AMT Clock Syncronization
|
||||||
//
|
//
|
||||||
|
@ -1188,10 +1218,11 @@ module.exports.CreateAmtManager = function (parent) {
|
||||||
//
|
//
|
||||||
|
|
||||||
// Check if Intel AMT has the server root certificate
|
// Check if Intel AMT has the server root certificate
|
||||||
function attemptRootCertSync(dev, func) {
|
function attemptRootCertSync(dev, func, forced) {
|
||||||
if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request.
|
if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request.
|
||||||
if (dev.policy.amtPolicy == 0) { func(dev); return; } // If there is no Intel AMT policy, skip this operation.
|
if (dev.policy.amtPolicy == 0) { func(dev); return; } // If there is no Intel AMT policy, skip this operation.
|
||||||
if ((dev.connType != 2) || (dev.policy.ciraPolicy != 2) || (parent.mpsserver.server == null)) { func(dev); return; } // Server root certificate does not need to be present is CIRA is not needed
|
if (forced !== true) { if ((dev.connType != 2) || (dev.policy.ciraPolicy != 2)) { func(dev); return; } } // Server root certificate does not need to be present if CIRA is not needed and "forced" is false
|
||||||
|
if (parent.mpsserver.server == null) { func(dev); return; } // Root cert not needed if MPS is not active.
|
||||||
|
|
||||||
// Find the current TLS certificate & MeshCentral root certificate
|
// Find the current TLS certificate & MeshCentral root certificate
|
||||||
var xxMeshCentralRoot = null;
|
var xxMeshCentralRoot = null;
|
||||||
|
|
|
@ -5492,7 +5492,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'clickoncerecovery': { // Intel(R) AMT Click once recovery
|
case 'oneclickrecovery': { // Intel(R) AMT One Click Recovery (OCR)
|
||||||
if (common.validateStrArray(command.nodeids, 1) == false) break; // Check nodeids
|
if (common.validateStrArray(command.nodeids, 1) == false) break; // Check nodeids
|
||||||
if (common.validateString(command.path, 1, 2048) == false) break; // Check file path
|
if (common.validateString(command.path, 1, 2048) == false) break; // Check file path
|
||||||
if (command.type != 'diskimage') break; // Make sure type is correct
|
if (command.type != 'diskimage') break; // Make sure type is correct
|
||||||
|
@ -5510,8 +5510,8 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||||
// Check if we found this device and if we have full rights
|
// Check if we found this device and if we have full rights
|
||||||
if ((node == null) || (rights != 0xFFFFFFFF)) return;
|
if ((node == null) || (rights != 0xFFFFFFFF)) return;
|
||||||
|
|
||||||
// Event Intel AMT Click Once Recovery, this will cause Intel AMT wake operations on this and other servers.
|
// Event Intel AMT One Click Recovery, this will cause Intel AMT wake operations on this and other servers.
|
||||||
parent.parent.DispatchEvent('*', obj, { action: 'clickoncerecovery', userid: user._id, username: user.name, nodeids: [node._id], domain: domain.id, nolog: 1, file: file.fullpath });
|
parent.parent.DispatchEvent('*', obj, { action: 'oneclickrecovery', userid: user._id, username: user.name, nodeids: [node._id], domain: domain.id, nolog: 1, file: file.fullpath });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6613,7 +6613,7 @@
|
||||||
if (((currentNode.conn & 1) != 0) && ((rights & 131072) != 0)) { count++; y += '<option value=106>' + "Run Commands" + '</option>'; } // Remote command permission
|
if (((currentNode.conn & 1) != 0) && ((rights & 131072) != 0)) { count++; y += '<option value=106>' + "Run Commands" + '</option>'; } // Remote command permission
|
||||||
if ((currentNode.conn != 0) && ((rights & 262144) != 0)) { count++; y += '<option value=4>' + "Sleep" + '</option><option value=3>' + "Reset" + '</option><option value=2>' + "Power off" + '</option>'; }
|
if ((currentNode.conn != 0) && ((rights & 262144) != 0)) { count++; y += '<option value=4>' + "Sleep" + '</option><option value=3>' + "Reset" + '</option><option value=2>' + "Power off" + '</option>'; }
|
||||||
if ((currentNode.conn & 16) != 0) { count++; y += '<option value=103>' + "Send MQTT Message" + '</option>'; }
|
if ((currentNode.conn & 16) != 0) { count++; y += '<option value=103>' + "Send MQTT Message" + '</option>'; }
|
||||||
if ((getNodeAmtVersion(currentNode) >= 15) && (currentNode.intelamt.state == 2) && ((currentNode.conn & 6) != 0) && (rights == 0xFFFFFFFF) && ((features & 0x00000400) == 0)) { count++; y += '<option value=107>' + "Intel® AMT Click Once Recovery" + '</option>'; } // CIRA (2) or AMT (4) connected
|
if ((getNodeAmtVersion(currentNode) >= 15) && (currentNode.intelamt.state == 2) && ((currentNode.conn & 6) != 0) && (rights == 0xFFFFFFFF) && ((features & 0x00000400) == 0)) { count++; y += '<option value=107>' + "Intel® AMT One Click Recovery" + '</option>'; } // CIRA (2) or AMT (4) connected
|
||||||
if (((currentNode.conn & 1) != 0) && ((rights & 32768) != 0)) { count++; y += '<option value=104>' + "Uninstall Agent" + '</option>'; }
|
if (((currentNode.conn & 1) != 0) && ((rights & 32768) != 0)) { count++; y += '<option value=104>' + "Uninstall Agent" + '</option>'; }
|
||||||
y += '</select>';
|
y += '</select>';
|
||||||
x += addHtmlValue("Operation", y);
|
x += addHtmlValue("Operation", y);
|
||||||
|
@ -6651,12 +6651,12 @@
|
||||||
//QE('idx_dlgOkButton', true);
|
//QE('idx_dlgOkButton', true);
|
||||||
}
|
}
|
||||||
} else if (op == 107) {
|
} else if (op == 107) {
|
||||||
// Intel AMT Click Once Recovery (OCR)
|
// Intel AMT One Click Recovery (OCR)
|
||||||
Q('d3localmodeform').action = 'clickoncerecovery.ashx';
|
Q('d3localmodeform').action = 'oneclickrecovery.ashx';
|
||||||
Q('d3auth').value = authCookie;
|
Q('d3auth').value = authCookie;
|
||||||
Q('d3filter').value = '.iso';
|
Q('d3filter').value = '.iso';
|
||||||
Q('d3attrib').value = currentNode._id;
|
Q('d3attrib').value = currentNode._id;
|
||||||
setDialogMode(3, "Intel® AMT Click Once Recovery", 3, deviceActionClickOnceRecovery);
|
setDialogMode(3, "Intel® AMT One Click Recovery", 3, deviceActionOneClickRecovery);
|
||||||
d3init();
|
d3init();
|
||||||
} else {
|
} else {
|
||||||
// Power operation
|
// Power operation
|
||||||
|
@ -6664,7 +6664,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function deviceActionClickOnceRecovery() {
|
function deviceActionOneClickRecovery() {
|
||||||
var mode = Q('d3uploadMode').value;
|
var mode = Q('d3uploadMode').value;
|
||||||
if (mode == 1) {
|
if (mode == 1) {
|
||||||
// Boot using local disk image file
|
// Boot using local disk image file
|
||||||
|
@ -6672,7 +6672,7 @@
|
||||||
} else {
|
} else {
|
||||||
// Boot using server image file
|
// Boot using server image file
|
||||||
var files = d3getFileSel();
|
var files = d3getFileSel();
|
||||||
if (files.length == 1) { meshserver.send({ action: 'clickoncerecovery', nodeids: [ Q('d3attrib').value ], type: 'diskimage', path: d3filetreelocation.join('/') + '/' + files[0] }); }
|
if (files.length == 1) { meshserver.send({ action: 'oneclickrecovery', nodeids: [ Q('d3attrib').value ], type: 'diskimage', path: d3filetreelocation.join('/') + '/' + files[0] }); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3408,7 +3408,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Upload a MeshCore.js file to the server
|
// Upload a MeshCore.js file to the server
|
||||||
function handleClickOnceRecoveryFile(req, res) {
|
function handleOneClickRecoveryFile(req, res) {
|
||||||
const domain = checkUserIpAddress(req, res);
|
const domain = checkUserIpAddress(req, res);
|
||||||
if (domain == null) { return; }
|
if (domain == null) { return; }
|
||||||
if (domain.id !== '') { res.sendStatus(401); return; }
|
if (domain.id !== '') { res.sendStatus(401); return; }
|
||||||
|
@ -3439,8 +3439,8 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
for (var i in files.files) {
|
for (var i in files.files) {
|
||||||
var file = files.files[i];
|
var file = files.files[i];
|
||||||
|
|
||||||
// Event Intel AMT Click Once Recovery, this will cause Intel AMT wake operations on this and other servers.
|
// Event Intel AMT One Click Recovery, this will cause Intel AMT wake operations on this and other servers.
|
||||||
parent.DispatchEvent('*', obj, { action: 'clickoncerecovery', userid: user._id, username: user.name, nodeids: [node._id], domain: domain.id, nolog: 1, file: file.path });
|
parent.DispatchEvent('*', obj, { action: 'oneclickrecovery', userid: user._id, username: user.name, nodeids: [node._id], domain: domain.id, nolog: 1, file: file.path });
|
||||||
|
|
||||||
try { obj.fs.unlinkSync(file.path); } catch (e) { } // TODO: Remove this file after 30 minutes.
|
try { obj.fs.unlinkSync(file.path); } catch (e) { } // TODO: Remove this file after 30 minutes.
|
||||||
}
|
}
|
||||||
|
@ -5250,7 +5250,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
obj.app.post(url + 'uploadfile.ashx', handleUploadFile);
|
obj.app.post(url + 'uploadfile.ashx', handleUploadFile);
|
||||||
obj.app.post(url + 'uploadfilebatch.ashx', handleUploadFileBatch);
|
obj.app.post(url + 'uploadfilebatch.ashx', handleUploadFileBatch);
|
||||||
obj.app.post(url + 'uploadmeshcorefile.ashx', handleUploadMeshCoreFile);
|
obj.app.post(url + 'uploadmeshcorefile.ashx', handleUploadMeshCoreFile);
|
||||||
obj.app.post(url + 'clickoncerecovery.ashx', handleClickOnceRecoveryFile);
|
obj.app.post(url + 'oneclickrecovery.ashx', handleOneClickRecoveryFile);
|
||||||
obj.app.get(url + 'userfiles/*', handleDownloadUserFiles);
|
obj.app.get(url + 'userfiles/*', handleDownloadUserFiles);
|
||||||
obj.app.ws(url + 'echo.ashx', handleEchoWebSocket);
|
obj.app.ws(url + 'echo.ashx', handleEchoWebSocket);
|
||||||
obj.app.ws(url + 'apf.ashx', function (ws, req) { obj.parent.mpsserver.onWebSocketConnection(ws, req); })
|
obj.app.ws(url + 'apf.ashx', function (ws, req) { obj.parent.mpsserver.onWebSocketConnection(ws, req); })
|
||||||
|
|
Loading…
Reference in a new issue