mirror of https://github.com/grpc/grpc-node.git
Refactor checkServerIdentity callback to pass in cert as an object with raw DER buffer.
This commit is contained in:
parent
ac0718883a
commit
34930310d2
|
|
@ -44,6 +44,7 @@
|
||||||
"istanbul": "^0.4.4",
|
"istanbul": "^0.4.4",
|
||||||
"lodash": "^4.17.4",
|
"lodash": "^4.17.4",
|
||||||
"minimist": "^1.1.0",
|
"minimist": "^1.1.0",
|
||||||
|
"node-forge": "^0.7.5",
|
||||||
"poisson-process": "^0.2.1"
|
"poisson-process": "^0.2.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
|
|
||||||
|
|
@ -76,6 +76,31 @@ var _ = require('lodash');
|
||||||
* @see https://github.com/google/google-auth-library-nodejs
|
* @see https://github.com/google/google-auth-library-nodejs
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
const PEM_CERT_HEADER = "-----BEGIN CERTIFICATE-----";
|
||||||
|
const PEM_CERT_FOOTER = "-----END CERTIFICATE-----";
|
||||||
|
|
||||||
|
function wrapCheckServerIdentityCallback(callback) {
|
||||||
|
return function(hostname, cert) {
|
||||||
|
// Parse cert from pem to a version that matches the tls.checkServerIdentity
|
||||||
|
// format.
|
||||||
|
// https://nodejs.org/api/tls.html#tls_tls_checkserveridentity_hostname_cert
|
||||||
|
|
||||||
|
var pemHeaderIndex = cert.indexOf(PEM_CERT_HEADER);
|
||||||
|
if (pemHeaderIndex === -1) {
|
||||||
|
return new Error("Unable to parse certificate PEM.");
|
||||||
|
}
|
||||||
|
cert = cert.substring(pemHeaderIndex);
|
||||||
|
var pemFooterIndex = cert.indexOf(PEM_CERT_FOOTER);
|
||||||
|
if (pemFooterIndex === -1) {
|
||||||
|
return new Error("Unable to parse certificate PEM.");
|
||||||
|
}
|
||||||
|
cert = cert.substring(PEM_CERT_HEADER.length, pemFooterIndex);
|
||||||
|
var rawBuffer = new Buffer(cert.replace("\n", "").replace(" ", ""), "base64");
|
||||||
|
|
||||||
|
return callback(hostname, { raw: rawBuffer });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an SSL Credentials object. If using a client-side certificate, both
|
* Create an SSL Credentials object. If using a client-side certificate, both
|
||||||
* the second and third arguments must be passed. Additional peer verification
|
* the second and third arguments must be passed. Additional peer verification
|
||||||
|
|
@ -93,7 +118,24 @@ var _ = require('lodash');
|
||||||
* fails and otherwise return undefined.
|
* fails and otherwise return undefined.
|
||||||
* @return {grpc.credentials~ChannelCredentials} The SSL Credentials object
|
* @return {grpc.credentials~ChannelCredentials} The SSL Credentials object
|
||||||
*/
|
*/
|
||||||
exports.createSsl = ChannelCredentials.createSsl;
|
exports.createSsl = function(root_certs, private_key, cert_chain, verify_options) {
|
||||||
|
// The checkServerIdentity callback from gRPC core will receive the cert as a PEM.
|
||||||
|
// To better match the checkServerIdentity callback of Node, we wrap the callback
|
||||||
|
// to decode the PEM and populate a cert object.
|
||||||
|
if (verify_options && verify_options.checkServerIdentity) {
|
||||||
|
if (typeof verify_options.checkServerIdentity !== 'function') {
|
||||||
|
throw new TypeError("Value of checkServerIdentity must be a function.");
|
||||||
|
}
|
||||||
|
// Make a shallow clone of verify_options so our modification of the callback
|
||||||
|
// isn't reflected to the caller
|
||||||
|
var updated_verify_options = Object.assign({}, verify_options);
|
||||||
|
updated_verify_options.checkServerIdentity = wrapCheckServerIdentityCallback(
|
||||||
|
verify_options.checkServerIdentity);
|
||||||
|
arguments[3] = updated_verify_options;
|
||||||
|
}
|
||||||
|
return ChannelCredentials.createSsl.apply(this, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @callback grpc.credentials~metadataCallback
|
* @callback grpc.credentials~metadataCallback
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
var fs = require('fs');
|
var fs = require('fs');
|
||||||
var path = require('path');
|
var path = require('path');
|
||||||
|
var forge = require('node-forge');
|
||||||
|
|
||||||
var grpc = require('..');
|
var grpc = require('..');
|
||||||
|
|
||||||
|
|
@ -292,7 +293,16 @@ describe('client credentials', function() {
|
||||||
client.unary({}, function(err, data) {
|
client.unary({}, function(err, data) {
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
assert.equal(callback_host, 'foo.test.google.fr');
|
assert.equal(callback_host, 'foo.test.google.fr');
|
||||||
assert.equal(callback_cert, pem_data);
|
|
||||||
|
// The roundabout forge APIs for converting PEM to a node DER Buffer
|
||||||
|
var expected_der = new Buffer(forge.asn1.toDer(
|
||||||
|
forge.pki.certificateToAsn1(forge.pki.certificateFromPem(pem_data)))
|
||||||
|
.getBytes(), 'binary');
|
||||||
|
|
||||||
|
// Assert the buffers are equal by converting them to hex strings
|
||||||
|
assert.equal(callback_cert.raw.toString('hex'), expected_der.toString('hex'));
|
||||||
|
// Documented behavior of callback cert is that raw should be its only property
|
||||||
|
assert.equal(Object.keys(callback_cert).length, 1);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue