MeshCentral can now issue AMT TLS certificates using a specified custom root cert.

Ylian Saint-Hilaire committed Jan 20, 2021 at 09:54 UTC d3fd8e731156ec616c4a49ca68766caa1d71ee94
4 files changed +71 -3
amtmanager.js
+8 -2
@@ -862,8 +862,14 @@ module.exports.CreateAmtManager = function (parent) {
862 var serverName = 'MeshCentral';
863 if ((domain != null) && (domain.title != null)) { serverName = domain.title; }
864 const certattributes = { 'CN': commonName, 'O': serverName, 'ST': 'MC', 'C': 'MC' };
865 - const issuerattributes = { 'CN': obj.rootCertCN };
866 - const xxCaPrivateKey = obj.parent.certificates.root.key;
865 +
866 + // See what root certificate to use to sign the TLS cert
867 + var xxCaPrivateKey = obj.parent.certificates.root.key; // Use our own root by default
868 + var issuerattributes = { 'CN': obj.rootCertCN };
869 + if (domain.amtmanager.tlsrootcert2 != null) {
870 + xxCaPrivateKey = domain.amtmanager.tlsrootcert2.key;
871 + issuerattributes = domain.amtmanager.tlsrootcert2.attributes;
872 + }
873
874 // Set the extended key usages
875 var extKeyUsage = { name: 'extKeyUsage', serverAuth: true, clientAuth: true }
certoperations.js
+24
@@ -212,6 +212,30 @@ module.exports.CertificateOperations = function (parent) {
212 }
213 }
214
215 + // Load a generic certificate and key from PFX/P12 or PEM format. Load both keys and attributes.
216 + obj.loadGenericCertAndKey = function (config) {
217 + if ((typeof config.certpfx == 'string') || (typeof config.certpfxpass == 'string')) {
218 + // Load a PFX certificate
219 + var r = null;
220 + try { r = obj.loadPfxCertificate(parent.getConfigFilePath(config.certpfx), config.certpfxpass); } catch (ex) { console.log(ex); }
221 + if ((r != null) && (r.keys.length > 0) && (r.certs.length > 0)) {
222 + var attributes = {};
223 + for (var j in r.certs[0].subject.attributes) { attributes[r.certs[0].subject.attributes[j].shortName] = r.certs[0].subject.attributes[j].value; }
224 + return { cert: obj.pki.certificateToPem(r.certs[0]), key: obj.pki.privateKeyToPem(r.keys[0]), attributes: attributes };
225 + }
226 + }
227 + if ((typeof config.certfile == 'string') || (typeof config.keyfile == 'string')) {
228 + // Load a PEM certificate
229 + var r = {}
230 + r.cert = obj.fs.readFileSync(parent.getConfigFilePath(config.certfile), 'utf8');
231 + r.key = obj.fs.readFileSync(parent.getConfigFilePath(config.keyfile), 'utf8');
232 + var cert = obj.pki.certificateFromPem(r.cert);
233 + r.attributes = {};
234 + for (var j in cert.subject.attributes) { r.attributes[cert.subject.attributes[j].shortName] = cert.subject.attributes[j].value; }
235 + return r;
236 + }
237 + return null;
238 + }
239
240 // Get the setup.bin file
241 obj.GetSetupBinFile = function (amtacmactivation, oldmebxpass, newmebxpass, domain, user) {
meshcentral-config-schema.json
+22
@@ -337,6 +337,28 @@
337 "uniqueItems": true
338 }
339 },
340 + "TlsRootCert": {
341 + "description": "Specifies a certificate and private key to use to issue Intel AMT TLS certificates. By default the MeshCentral self-signed root certificate is used.",
342 + "type": "object",
343 + "properties": {
344 + "certpfx": {
345 + "description": "Name of the certificate file that is in .p12 or .pfx format in meshcentral-data, use this with certpfxpass.",
346 + "type": "string"
347 + },
348 + "certpfxpass": {
349 + "description": "Password for the file specified in certpfx.",
350 + "type": "string"
351 + },
352 + "certfile": {
353 + "description": "Name of the certificate file in PEM format located in meshcentral-data. Using this with keyfile.",
354 + "type": "string"
355 + },
356 + "keyfile": {
357 + "description": "Name of the private key file in PEM format located in meshcentral-data. Using this with certfile.",
358 + "type": "string"
359 + }
360 + }
361 + },
362 "WifiProfiles": {
363 "description": "List of WIFI profiles to setup in any managed Intel AMT device with a WIFI network interface.",
364 "type": "array",
meshcentral.js
+17 -1
@@ -1119,6 +1119,9 @@ function CreateMeshCentralServer(config, args) {
1119 obj.StartEx1b = function () {
1120 var i;
1121
1122 + // Setup certificate operations
1123 + obj.certificateOperations = require('./certoperations.js').CertificateOperations(obj);
1124 +
1125 // Linux format /var/log/auth.log
1126 if (obj.config.settings.authlog != null) {
1127 obj.fs.open(obj.config.settings.authlog, 'a', function (err, fd) {
@@ -1224,6 +1227,20 @@ function CreateMeshCentralServer(config, args) {
1227 if (obj.config.domains[i].userconsentflags.desktopprivacybar == true) { flags |= 64; }
1228 obj.config.domains[i].userconsentflags = flags;
1229 }
1230 +
1231 + // If we have Intel AMT manager settings, take a look at them here.
1232 + if (typeof obj.config.domains[i].amtmanager == 'object') {
1233 + if (typeof obj.config.domains[i].amtmanager.tlsrootcert == 'object') {
1234 + obj.config.domains[i].amtmanager.tlsrootcert2 = obj.certificateOperations.loadGenericCertAndKey(obj.config.domains[i].amtmanager.tlsrootcert);
1235 + if (obj.config.domains[i].amtmanager.tlsrootcert2 == null) { // Show an error message if needed
1236 + if (i == '') {
1237 + addServerWarning("Unable to load Intel AMT TLS root certificate for default domain.");
1238 + } else {
1239 + addServerWarning("Unable to load Intel AMT TLS root certificate for domain " + i + ".");
1240 + }
1241 + }
1242 + }
1243 + }
1244 }
1245
1246 // Log passed arguments into Windows Service Log
@@ -1340,7 +1357,6 @@ function CreateMeshCentralServer(config, args) {
1357 // Done starting the redirection server, go on to load the server certificates
1358 obj.StartEx2 = function () {
1359 // Load server certificates
1343 - obj.certificateOperations = require('./certoperations.js').CertificateOperations(obj);
1360 obj.certificateOperations.GetMeshServerCertificate(obj.args, obj.config, function (certs) {
1361 // Get the current node version
1362 const nodeVersion = Number(process.version.match(/^v(\d+\.\d+)/)[1]);