diff --git a/amtmanager.js b/amtmanager.js index e081ce3c..b7d5004a 100644 --- a/amtmanager.js +++ b/amtmanager.js @@ -862,8 +862,14 @@ module.exports.CreateAmtManager = function (parent) { var serverName = 'MeshCentral'; if ((domain != null) && (domain.title != null)) { serverName = domain.title; } const certattributes = { 'CN': commonName, 'O': serverName, 'ST': 'MC', 'C': 'MC' }; - const issuerattributes = { 'CN': obj.rootCertCN }; - const xxCaPrivateKey = obj.parent.certificates.root.key; + + // See what root certificate to use to sign the TLS cert + var xxCaPrivateKey = obj.parent.certificates.root.key; // Use our own root by default + var issuerattributes = { 'CN': obj.rootCertCN }; + if (domain.amtmanager.tlsrootcert2 != null) { + xxCaPrivateKey = domain.amtmanager.tlsrootcert2.key; + issuerattributes = domain.amtmanager.tlsrootcert2.attributes; + } // Set the extended key usages var extKeyUsage = { name: 'extKeyUsage', serverAuth: true, clientAuth: true } diff --git a/certoperations.js b/certoperations.js index 4bf66402..8dce9719 100644 --- a/certoperations.js +++ b/certoperations.js @@ -212,6 +212,30 @@ module.exports.CertificateOperations = function (parent) { } } + // Load a generic certificate and key from PFX/P12 or PEM format. Load both keys and attributes. + obj.loadGenericCertAndKey = function (config) { + if ((typeof config.certpfx == 'string') || (typeof config.certpfxpass == 'string')) { + // Load a PFX certificate + var r = null; + try { r = obj.loadPfxCertificate(parent.getConfigFilePath(config.certpfx), config.certpfxpass); } catch (ex) { console.log(ex); } + if ((r != null) && (r.keys.length > 0) && (r.certs.length > 0)) { + var attributes = {}; + for (var j in r.certs[0].subject.attributes) { attributes[r.certs[0].subject.attributes[j].shortName] = r.certs[0].subject.attributes[j].value; } + return { cert: obj.pki.certificateToPem(r.certs[0]), key: obj.pki.privateKeyToPem(r.keys[0]), attributes: attributes }; + } + } + if ((typeof config.certfile == 'string') || (typeof config.keyfile == 'string')) { + // Load a PEM certificate + var r = {} + r.cert = obj.fs.readFileSync(parent.getConfigFilePath(config.certfile), 'utf8'); + r.key = obj.fs.readFileSync(parent.getConfigFilePath(config.keyfile), 'utf8'); + var cert = obj.pki.certificateFromPem(r.cert); + r.attributes = {}; + for (var j in cert.subject.attributes) { r.attributes[cert.subject.attributes[j].shortName] = cert.subject.attributes[j].value; } + return r; + } + return null; + } // Get the setup.bin file obj.GetSetupBinFile = function (amtacmactivation, oldmebxpass, newmebxpass, domain, user) { diff --git a/meshcentral-config-schema.json b/meshcentral-config-schema.json index 2f82ea0c..14d983f9 100644 --- a/meshcentral-config-schema.json +++ b/meshcentral-config-schema.json @@ -337,6 +337,28 @@ "uniqueItems": true } }, + "TlsRootCert": { + "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.", + "type": "object", + "properties": { + "certpfx": { + "description": "Name of the certificate file that is in .p12 or .pfx format in meshcentral-data, use this with certpfxpass.", + "type": "string" + }, + "certpfxpass": { + "description": "Password for the file specified in certpfx.", + "type": "string" + }, + "certfile": { + "description": "Name of the certificate file in PEM format located in meshcentral-data. Using this with keyfile.", + "type": "string" + }, + "keyfile": { + "description": "Name of the private key file in PEM format located in meshcentral-data. Using this with certfile.", + "type": "string" + } + } + }, "WifiProfiles": { "description": "List of WIFI profiles to setup in any managed Intel AMT device with a WIFI network interface.", "type": "array", diff --git a/meshcentral.js b/meshcentral.js index 48e0e886..acedc0ca 100644 --- a/meshcentral.js +++ b/meshcentral.js @@ -1119,6 +1119,9 @@ function CreateMeshCentralServer(config, args) { obj.StartEx1b = function () { var i; + // Setup certificate operations + obj.certificateOperations = require('./certoperations.js').CertificateOperations(obj); + // Linux format /var/log/auth.log if (obj.config.settings.authlog != null) { obj.fs.open(obj.config.settings.authlog, 'a', function (err, fd) { @@ -1224,6 +1227,20 @@ function CreateMeshCentralServer(config, args) { if (obj.config.domains[i].userconsentflags.desktopprivacybar == true) { flags |= 64; } obj.config.domains[i].userconsentflags = flags; } + + // If we have Intel AMT manager settings, take a look at them here. + if (typeof obj.config.domains[i].amtmanager == 'object') { + if (typeof obj.config.domains[i].amtmanager.tlsrootcert == 'object') { + obj.config.domains[i].amtmanager.tlsrootcert2 = obj.certificateOperations.loadGenericCertAndKey(obj.config.domains[i].amtmanager.tlsrootcert); + if (obj.config.domains[i].amtmanager.tlsrootcert2 == null) { // Show an error message if needed + if (i == '') { + addServerWarning("Unable to load Intel AMT TLS root certificate for default domain."); + } else { + addServerWarning("Unable to load Intel AMT TLS root certificate for domain " + i + "."); + } + } + } + } } // Log passed arguments into Windows Service Log @@ -1340,7 +1357,6 @@ function CreateMeshCentralServer(config, args) { // Done starting the redirection server, go on to load the server certificates obj.StartEx2 = function () { // Load server certificates - obj.certificateOperations = require('./certoperations.js').CertificateOperations(obj); obj.certificateOperations.GetMeshServerCertificate(obj.args, obj.config, function (certs) { // Get the current node version const nodeVersion = Number(process.version.match(/^v(\d+\.\d+)/)[1]);