Many improvements for Intel AMT agentless management.

This commit is contained in:
Ylian Saint-Hilaire 2020-12-10 00:03:00 -08:00
parent ffa861c0b4
commit ba9b72c11e
10 changed files with 34 additions and 220 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -157,6 +157,7 @@ function run(argv) {
if ((typeof args.token) == 'string') { settings.token = args.token; }
if ((typeof args.timeout) == 'string') { settings.timeout = parseInt(args.timeout); }
if ((typeof args.uuidoutput) == 'string' || args.uuidoutput) { settings.uuidoutput = args.uuidoutput; }
if ((typeof args.desc) == 'string') { settings.desc = args.desc; }
if (args.emailtoken) { settings.emailtoken = true; }
if (args.debug === true) { settings.debuglevel = 1; }
if (args.debug) { try { waitForDebugger(); } catch (e) { } }
@ -245,6 +246,9 @@ function run(argv) {
console.log(' --url [wss://server] The address of the MeshCentral server.');
console.log(' --id [groupid] The device group identifier.');
console.log(' --serverhttpshash [hash] Optional TLS server certificate hash.');
console.log(' --user [username] The Intel AMT admin username, admin is default.');
console.log(' --pass [password] The Intel AMT admin password.');
console.log(' --desc [description] Description of the device, used when first added to server.');
} else if (action == 'amtdeactivate') {
console.log('AmtDeactivate will attempt to deactivate Intel AMT on this computer when in client control mode (CCM). The command must be run on a computer with Intel AMT, must run as administrator and the Intel management driver must be installed. Intel AMT must be activated in client control mode for this command to work. Example usage:\r\n\r\n meshcmd amtdeactivate');
} else if (action == 'amtacmdeactivate') {
@ -1113,6 +1117,19 @@ function configureAmt2() {
if (state.ProvisioningState == null) { console.log('Intel AMT not ready for configuration.'); exit(1); return; }
console.log('Starting Intel AMT configuration...');
// Add indication if the device is battery powered, this is used to show a mobile icon when adding the device
state.isBatteryPowered = (require('identifiers').isBatteryPowered && require('identifiers').isBatteryPowered());
// Add Intel AMT credentials if provided
if ((typeof settings.password == 'string') && (settings.password != '')) {
state.amtpass = settings.password;
state.amtuser = 'admin';
if ((typeof settings.username == 'string') && (settings.username != '')) { state.amtuser = settings.username; }
}
// If a description is provided, send it to the server
if ((typeof settings.desc == 'string') && (settings.desc != '')) { state.desc = settings.desc; }
// Connect to MPS and start APF relay
var apfarg = {
mpsurl: settings.url,

View File

@ -1,208 +0,0 @@
/*
Copyright 2019-2020 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
function trimIdentifiers(val)
{
for(var v in val)
{
if (!val[v] || val[v] == 'None' || val[v] == '') { delete val[v]; }
}
}
function linux_identifiers()
{
var identifiers = {};
var ret = {};
var values = {};
if (!require('fs').existsSync('/sys/class/dmi/id')) { throw ('this platform does not have DMI statistics'); }
var entries = require('fs').readdirSync('/sys/class/dmi/id');
for(var i in entries)
{
if (require('fs').statSync('/sys/class/dmi/id/' + entries[i]).isFile())
{
ret[entries[i]] = require('fs').readFileSync('/sys/class/dmi/id/' + entries[i]).toString().trim();
if (ret[entries[i]] == 'None') { delete ret[entries[i]];}
}
}
identifiers['bios_date'] = ret['bios_date'];
identifiers['bios_vendor'] = ret['bios_vendor'];
identifiers['bios_version'] = ret['bios_version'];
identifiers['board_name'] = ret['board_name'];
identifiers['board_serial'] = ret['board_serial'];
identifiers['board_vendor'] = ret['board_vendor'];
identifiers['board_version'] = ret['board_version'];
identifiers['product_uuid'] = ret['product_uuid'];
values.identifiers = identifiers;
values.linux = ret;
trimIdentifiers(values.identifiers);
return (values);
}
function windows_wmic_results(str)
{
var lines = str.trim().split('\r\n');
var keys = lines[0].split(',');
var i, key, keyval;
var tokens;
var result = [];
for (i = 1; i < lines.length; ++i)
{
var obj = {};
tokens = lines[i].split(',');
for (key = 0; key < keys.length; ++key)
{
if (tokens[key].trim())
{
obj[keys[key].trim()] = tokens[key].trim();
}
}
result.push(obj);
}
return (result);
}
function windows_identifiers()
{
var ret = { windows: {}}; values = {}; var items; var i; var item;
var child = require('child_process').execFile(process.env['windir'] + '\\System32\\wbem\\wmic.exe', ['wmic', 'bios', 'get', '/VALUE']);
child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
child.waitExit();
var items = child.stdout.str.split('\r\r\n');
for(i in items)
{
item = items[i].split('=');
values[item[0]] = item[1];
}
ret['identifiers'] = {};
ret['identifiers']['bios_date'] = values['ReleaseDate'];
ret['identifiers']['bios_vendor'] = values['Manufacturer'];
ret['identifiers']['bios_version'] = values['SMBIOSBIOSVersion'];
child = require('child_process').execFile(process.env['windir'] + '\\System32\\wbem\\wmic.exe', ['wmic', 'BASEBOARD', 'get', '/VALUE']);
child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
child.waitExit();
var items = child.stdout.str.split('\r\r\n');
for (i in items)
{
item = items[i].split('=');
values[item[0]] = item[1];
}
ret['identifiers']['board_name'] = values['Product'];
ret['identifiers']['board_serial'] = values['SerialNumber'];
ret['identifiers']['board_vendor'] = values['Manufacturer'];
ret['identifiers']['board_version'] = values['Version'];
child = require('child_process').execFile(process.env['windir'] + '\\System32\\wbem\\wmic.exe', ['wmic', 'CSProduct', 'get', '/VALUE']);
child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
child.waitExit();
var items = child.stdout.str.split('\r\r\n');
for (i in items)
{
item = items[i].split('=');
values[item[0]] = item[1];
}
ret['identifiers']['product_uuid'] = values['UUID'];
trimIdentifiers(ret.identifiers);
child = require('child_process').execFile(process.env['windir'] + '\\System32\\wbem\\wmic.exe', ['wmic', 'MEMORYCHIP', 'LIST', '/FORMAT:CSV']);
child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
child.waitExit();
ret.windows.memory = windows_wmic_results(child.stdout.str);
child = require('child_process').execFile(process.env['windir'] + '\\System32\\wbem\\wmic.exe', ['wmic', 'OS', 'GET', '/FORMAT:CSV']);
child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
child.waitExit();
ret.windows.osinfo = windows_wmic_results(child.stdout.str)[0];
child = require('child_process').execFile(process.env['windir'] + '\\System32\\wbem\\wmic.exe', ['wmic', 'PARTITION', 'LIST', '/FORMAT:CSV']);
child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
child.waitExit();
ret.windows.partitions = windows_wmic_results(child.stdout.str);
return (ret);
}
function macos_identifiers()
{
var ret = { identifiers: {} };
var child;
child = require('child_process').execFile('/bin/sh', ['sh']);
child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
child.stdin.write('ioreg -d2 -c IOPlatformExpertDevice | grep board-id | awk -F= \'{ split($2, res, "\\""); print res[2]; }\'\nexit\n');
child.waitExit();
ret.identifiers.board_name = child.stdout.str.trim();
child = require('child_process').execFile('/bin/sh', ['sh']);
child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
child.stdin.write('ioreg -d2 -c IOPlatformExpertDevice | grep IOPlatformSerialNumber | awk -F= \'{ split($2, res, "\\""); print res[2]; }\'\nexit\n');
child.waitExit();
ret.identifiers.board_serial = child.stdout.str.trim();
child = require('child_process').execFile('/bin/sh', ['sh']);
child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
child.stdin.write('ioreg -d2 -c IOPlatformExpertDevice | grep manufacturer | awk -F= \'{ split($2, res, "\\""); print res[2]; }\'\nexit\n');
child.waitExit();
ret.identifiers.board_vendor = child.stdout.str.trim();
child = require('child_process').execFile('/bin/sh', ['sh']);
child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
child.stdin.write('ioreg -d2 -c IOPlatformExpertDevice | grep version | awk -F= \'{ split($2, res, "\\""); print res[2]; }\'\nexit\n');
child.waitExit();
ret.identifiers.board_version = child.stdout.str.trim();
child = require('child_process').execFile('/bin/sh', ['sh']);
child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
child.stdin.write('ioreg -d2 -c IOPlatformExpertDevice | grep IOPlatformUUID | awk -F= \'{ split($2, res, "\\""); print res[2]; }\'\nexit\n');
child.waitExit();
ret.identifiers.product_uuid = child.stdout.str.trim();
trimIdentifiers(ret.identifiers);
return (ret);
}
switch(process.platform)
{
case 'linux':
module.exports = { _ObjectID: 'identifiers', get: linux_identifiers };
break;
case 'win32':
module.exports = { _ObjectID: 'identifiers', get: windows_identifiers };
break;
case 'darwin':
module.exports = { _ObjectID: 'identifiers', get: macos_identifiers };
break;
default:
module.exports = { get: function () { throw ('Unsupported Platform'); } };
break;
}
// bios_date = BIOS->ReleaseDate
// bios_vendor = BIOS->Manufacturer
// bios_version = BIOS->SMBIOSBIOSVersion
// board_name = BASEBOARD->Product = ioreg/board-id
// board_serial = BASEBOARD->SerialNumber = ioreg/serial-number | ioreg/IOPlatformSerialNumber
// board_vendor = BASEBOARD->Manufacturer = ioreg/manufacturer
// board_version = BASEBOARD->Version

View File

@ -442,7 +442,8 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
} else {
// We are under the limit, create the new device.
// Node is not in the database, add it. Credentials will be empty until added by the user.
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 } };
var device = { type: 'node', mtype: 1, _id: socket.tag.nodeid, meshid: socket.tag.meshid, name: socket.tag.name, icon: (socket.tag.meiState.isBatteryPowered) ? 2 : 1, host: socket.remoteAddr, domain: domainid, intelamt: { user: (typeof socket.tag.meiState.amtuser == 'string') ? socket.tag.meiState.amtuser : '', pass: (typeof socket.tag.meiState.amtpass == 'string') ? socket.tag.meiState.amtpass : '', tls: 0, state: 2 } };
if ((typeof socket.tag.meiState.desc == 'string') && (socket.tag.meiState.desc.length > 0) && (socket.tag.meiState.desc.length < 1024)) { device.desc = socket.tag.meiState.desc; }
obj.db.Set(device);
// Event the new node
@ -457,7 +458,8 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
return;
} else {
// Node is not in the database, add it. Credentials will be empty until added by the user.
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 } };
var device = { type: 'node', mtype: 1, _id: socket.tag.nodeid, meshid: socket.tag.meshid, name: socket.tag.name, icon: (socket.tag.meiState.isBatteryPowered) ? 2 : 1, host: socket.remoteAddr, domain: domainid, intelamt: { user: (typeof socket.tag.meiState.amtuser == 'string') ? socket.tag.meiState.amtuser : '', pass: (typeof socket.tag.meiState.amtpass == 'string') ? socket.tag.meiState.amtpass : '', tls: 0, state: 2 } };
if ((typeof socket.tag.meiState.desc == 'string') && (socket.tag.meiState.desc.length > 0) && (socket.tag.meiState.desc.length < 1024)) { device.desc = socket.tag.meiState.desc; }
obj.db.Set(device);
// Event the new node
@ -578,7 +580,7 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
var domain = obj.parent.config.domains[mesh.domain];
socket.tag.domain = domain;
socket.tag.domainid = mesh.domain;
socket.tag.name = '';
if (socket.tag.name == null) { socket.tag.name = ''; }
socket.tag.nodeid = 'node/' + mesh.domain + '/' + nodeid; // Turn 16bit systemid guid into 48bit nodeid that is base64 encoded
socket.tag.meshid = mesh._id;
socket.tag.connectTime = Date.now();
@ -596,7 +598,8 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
} else {
// We are under the limit, create the new device.
// Node is not in the database, add it. Credentials will be empty until added by the user.
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 } };
var device = { type: 'node', mtype: 1, _id: socket.tag.nodeid, meshid: socket.tag.meshid, name: socket.tag.name, icon: (socket.tag.meiState.isBatteryPowered) ? 2 : 1, host: socket.remoteAddr, domain: mesh.domain, intelamt: { user: (typeof socket.tag.meiState.amtuser == 'string') ? socket.tag.meiState.amtuser : '', pass: (typeof socket.tag.meiState.amtpass == 'string') ? socket.tag.meiState.amtpass : '', tls: 0, state: 2 } };
if ((typeof socket.tag.meiState.desc == 'string') && (socket.tag.meiState.desc.length > 0) && (socket.tag.meiState.desc.length < 1024)) { device.desc = socket.tag.meiState.desc; }
obj.db.Set(device);
// Event the new node
@ -612,7 +615,8 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
return;
} else {
// Node is not in the database, add it. Credentials will be empty until added by the user.
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 } };
var device = { type: 'node', mtype: 1, _id: socket.tag.nodeid, meshid: socket.tag.meshid, name: socket.tag.name, icon: (socket.tag.meiState.isBatteryPowered) ? 2 : 1, host: socket.remoteAddr, domain: mesh.domain, intelamt: { user: (typeof socket.tag.meiState.amtuser == 'string') ? socket.tag.meiState.amtuser : '', pass: (typeof socket.tag.meiState.amtpass == 'string') ? socket.tag.meiState.amtpass : '', tls: 0, state: 2 } };
if ((typeof socket.tag.meiState.desc == 'string') && (socket.tag.meiState.desc.length > 0) && (socket.tag.meiState.desc.length < 1024)) { device.desc = socket.tag.meiState.desc; }
obj.db.Set(device);
// Event the new node
@ -919,6 +923,7 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
case 'meiState':
if (socket.tag.connType != 2) break; // Only accept MEI state on CIRA-LMS connection
socket.tag.meiState = jsondata.value;
if (((socket.tag.name == '') || (socket.tag.name == null)) && (typeof jsondata.value.OsHostname == 'string')) { socket.tag.name = jsondata.value.OsHostname; }
if (obj.parent.amtManager != null) { obj.parent.amtManager.mpsControlMessage(socket.tag.nodeid, socket, socket.tag.connType, jsondata); }
break;
case 'deactivate':

File diff suppressed because one or more lines are too long

View File

@ -21224,7 +21224,7 @@
"zh-chs": "Linux x8632位",
"zh-cht": "Linux x8632位",
"xloc": [
"default.handlebars->29->812"
"default.handlebars->29->813"
]
},
{
@ -21244,7 +21244,7 @@
"zh-chs": "Linux x8664位",
"zh-cht": "Linux x8664位",
"xloc": [
"default.handlebars->29->813"
"default.handlebars->29->812"
]
},
{
@ -40268,7 +40268,7 @@
"zh-chs": "Windows32位",
"zh-cht": "Windows32位",
"xloc": [
"default.handlebars->29->810"
"default.handlebars->29->811"
]
},
{
@ -40288,7 +40288,7 @@
"zh-chs": "Windows64位",
"zh-cht": "Windows64位",
"xloc": [
"default.handlebars->29->811"
"default.handlebars->29->810"
]
},
{

View File

@ -6725,10 +6725,10 @@
function p10showMeshCmdDialog(mode, nodeid) {
if (xxdialogMode) return;
var y = '<select id=aginsSelect onclick=meshCmdOsClick() style=width:236px>';
y += '<option value=3>' + "Windows (32bit)" + '</option>';
y += '<option value=4>' + "Windows (64bit)" + '</option>';
y += '<option value=5>' + "Linux x86 (32bit)" + '</option>';
y += '<option value=3>' + "Windows (32bit)" + '</option>';
y += '<option value=6>' + "Linux x86 (64bit)" + '</option>';
y += '<option value=5>' + "Linux x86 (32bit)" + '</option>';
y += '<option value=16>' + "macOS x86 (64bit)" + '</option>';
y += '<option value=29>' + "macOS ARM (64bit)" + '</option>';
y += '<option value=25>' + "Linux ARM, Raspberry Pi (32bit)" + '</option>';