provisioning/tools/create_test_cert.js (113 lines of code) (raw):

// Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. 'use strict'; var fs = require('fs'); var pem = require('pem'); var chalk = require('chalk'); var camelcase = require('camelcase'); var argv = require('yargs') .command('root [commonName]', 'create a root certificate', (yargs) => { return yargs .positional('commonName', { describe: 'name to use for cert', default: 'Test Root Cert' }); }) .command('intermediate <commonName> <parentCommonName>', 'create an intermediate cert', (yargs) => { return yargs .positional('commonName', { describe: 'name to use for cert' }) .positional('parentCommonName', { describe: 'common name of parent cert' }); }) .command('device <commonName> [parentCommonName]', 'create a device cert', (yargs) => { return yargs .positional('commonName', { describe: 'name to use for cert' }) .positional('parentCommonName', { describe: 'common name of parent cert' }); }) .command('verification [--ca root cert pem file name] [--key root cert key pem file name] [--nonce nonce]', 'provide proof of possession for a cert using a verification code', (yargs) => { return yargs .option('ca', { describe: 'pem file name of the root' }) .option('key', { describe: 'pem file name of the key' }) .option('nonce', { describe: 'verification code from portal' }) .demandOption(['ca', 'key', 'nonce']); }) .demandCommand() .help(false) .version(false) .wrap(null) .argv; var command = argv._[0]; var commonName = null; var outputFilenameRoot = null; var parentCert = null; var parentKey = null; var parentChain = null; if (command === 'verification') { commonName = argv.nonce; outputFilenameRoot = 'verification'; parentCert = fs.readFileSync(argv.ca).toString('ascii'); parentKey = fs.readFileSync(argv.key).toString('ascii'); } else { commonName = argv.commonName; outputFilenameRoot = camelcase(commonName); if (argv.parentCommonName) { var parentFilenameRoot = camelcase(argv.parentCommonName); console.log(chalk.green('reading parent cert from ' + parentFilenameRoot + '_*.pem')); parentCert = fs.readFileSync(parentFilenameRoot + '_cert.pem').toString('ascii'); parentKey = fs.readFileSync(parentFilenameRoot + '_key.pem').toString('ascii'); parentChain = fs.readFileSync(parentFilenameRoot + '_fullchain.pem').toString('ascii'); } } var certOptions = { commonName: commonName, serial: Math.floor(Math.random() * 1000000000), days: 1, }; if (command === 'root' || command === 'intermediate') { certOptions.config = [ '[req]', 'req_extensions = v3_req', 'distinguished_name = req_distinguished_name', 'x509_extensions = v3_ca', '[req_distinguished_name]', 'commonName = ' + commonName, '[v3_req]', 'basicConstraints = critical, CA:true' ].join('\n'); } else { certOptions.config = [ '[req]', 'req_extensions = v3_req', 'distinguished_name = req_distinguished_name', '[req_distinguished_name]', 'commonName = ' + commonName, '[v3_req]', 'extendedKeyUsage = critical,clientAuth' ].join('\n'); } if (parentCert) { certOptions.serviceKey = parentKey; certOptions.serviceCertificate = parentCert; } else { certOptions.selfSigned = true; } console.log(chalk.green('creating certificate with common name=' + commonName)); pem.createCertificate(certOptions, function(err, cert) { if (err) { console.log(chalk.red('Could not create certificate: ' + err.message)); process.exit(1); } else { console.log(chalk.green('saving cert to ' + outputFilenameRoot + '_cert.pem.')); fs.writeFileSync(outputFilenameRoot + '_cert.pem', cert.certificate); console.log(chalk.green('saving key to ' + outputFilenameRoot + '_key.pem.')); fs.writeFileSync(outputFilenameRoot + '_key.pem', cert.clientKey); // Note: this saves the root cert as part of the chain. This isn't necessary, but it doesn't hurt either. console.log(chalk.green('saving cert with chain to ' + outputFilenameRoot + '_fullchain.pem.')); fs.writeFileSync(outputFilenameRoot + '_fullchain.pem', cert.certificate + '\n' + parentChain); pem.convert.PEM2PFX( { key: outputFilenameRoot + '_key.pem', cert: outputFilenameRoot + '_cert.pem' }, outputFilenameRoot + '.pfx', '1234', (e,r) => { if (e) throw e; if (r) console.log('PFX created with default password'); } ); } });