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]);