module.exports = function * handleRequest (options) { this.log.info('[cert] Handling certificate signing request...'); var options = _.defaults(options, { caKeyPath: this.config.get('ca.keyPath'), certsDir: this.config.get('ca.certsDir'), csrsDir: this.config.get('ca.csrsDir'), force: false }); // Extract the hostname from the CSR var certInfo = yield pem.readCertificateInfo(options.csr); var hostname = certInfo.commonName; var csrPath = path.resolve(options.csrsDir, hostname +'.csr.pem'); var certPath = path.resolve(options.certsDir, hostname +'.cert.pem'); // If the `force` option is false then check if there is an existing // signed certiticate if (!options.force) { let exists = _.sum(yield [ fs.exists(csrPath), fs.exists(certPath) ]); // Check if a cert already exists if (exists) { let certData = yield fs.readFile(path.resolve(certPath)); return certData.toString(); } } // Save the CSR let fd = yield fs.open(csrPath, 'w', '0600'); yield fs.write(fd, options.csr); yield fs.close(fd); var shouldSign = this.config.get('ca.autoSign'); // Check if we should auto-sign the certificate if (shouldSign) { // Set the `hostname` option options.hostname = hostname; // Sign and return the certificate return yield this.modules.cert.commands.sign(options); } }
module.exports = function * sign (options) { this.log.info('[cert] Signing certificate...'); var app = this; assert(options instanceof Object, 'Invalid options.'); assert(options.hostname, 'Missing `hostname`.'); options = _.defaults(options, { caKeyPath: app.config.get('ca.keyPath'), caCertPath: app.config.get('ca.certPath'), certsDir: app.config.get('ca.certsDir'), csrsDir: app.config.get('ca.csrsDir'), daysValid: app.config.get('ca.certDaysValid') }); var caKeyPath = path.resolve(options.caKeyPath); var caCertPath = path.resolve(options.caCertPath); var csrPath = path.resolve(options.csrsDir, options.hostname +'.csr.pem'); var certPath = path.resolve(options.certsDir, options.hostname +'.cert.pem'); var serial = (yield rand.randomInts({ num: 20, max: 9 })).join(''); var certOptions = { serviceKey: yield fs.readFile(caKeyPath), serviceCertificate: yield fs.readFile(caCertPath), csr: yield fs.readFile(csrPath), serial: serial, days: options.daysValid }; // Sign the certificate var keys = yield pem.createCertificate(certOptions); var certData = keys.certificate.toString(); // Save the cert var fd = yield fs.open(certPath, 'w', '0644'); yield fs.write(fd, certData); yield fs.close(fd); return certData; }
module.exports = function * sendRequest (options) { this.log.info('[cert] Sending certificate signing request...'); var app = this; options = _.defaults(options, { hostname: os.hostname(), caHost: app.config.get('ca.host'), caPort: app.config.get('ca.port'), caCertPath: app.config.get('ca.certPath'), orgUnit: 'ClusterFCUK Node', keyPath: app.config.get('server.keyPath'), certPath: app.config.get('server.certPath'), csrPath: app.config.get('server.csrPath'), force: false }); var csrPath = path.resolve(options.csrPath); var keyPath = path.resolve(options.keyPath); var certPath = path.resolve(options.certPath); var caCertPath = path.resolve(options.caCertPath); var exists = _.sum(yield [ fs.exists(csrPath), fs.exists(keyPath), fs.exists(certPath) ]); var certOptions = { commonName: options.hostname, organizationUnit: options.orgUnit }; var csrData; if (!exists || options.force) { // Generate the certificate or CSR var keys = yield pem.createCSR(certOptions); var keyData = keys.clientKey.toString(); csrData = keys.csr.toString(); // Save the private key { let fd = yield fs.open(keyPath, 'w', '0600'); yield fs.write(fd, keyData); yield fs.close(fd); } // Save the CSR { let fd = yield fs.open(csrPath, 'w', '0644'); yield fs.write(fd, csrData); yield fs.close(fd); } } else { // Read the existing CSR data csrData = (yield fs.readFile(csrPath)).toString(); } var requestUri = 'https://'+ options.caHost +':'+ options.caPort +'/cert/request'; var requestBody = { csr: csrData, force: options.force }; try { var caCert; // Send the certificate signing request var response = yield new Promise(function (fulfill, reject) { var req = request({ method: 'POST', uri: requestUri, body: requestBody, json: true, gzip: true, strictSSL: false }, function (err, res, body) { if (err) { reject(err); } else { fulfill(res); } }); // Listen for the `response` event so we can get the server cert req.once('response', function () { caCert = this.req.connection.getPeerCertificate(); }); }); } catch (err) { throw new Error('Could not send certificate signing request: '+ err.message); } switch (response.statusCode) { case 200: var certData = response.body.data; // Make sure we got a certificate back if (certData) { // Save the certificate { let fd = yield fs.open(certPath, 'w', '0644'); yield fs.write(fd, certData); yield fs.close(fd); } if (!caCert) { throw new Error('Cannot get the server certificate.'); } var caCertData = '-----BEGIN CERTIFICATE-----\n'; caCertData += caCert.raw.toString('base64').match(/.{1,64}/g).join('\n'); caCertData += '\n-----END CERTIFICATE-----'; // Save the CA certificate { let fd = yield fs.open(caCertPath, 'w', '0644'); yield fs.write(fd, caCertData); yield fs.close(fd); } return certData; } else { throw new Error('A certificate was not returned by the server.'); } break; case 202: return null; default: throw new Error(response.statusCode +' '+ response.statusMessage +': '+ response.body); } }