Skip to content

Commit

Permalink
FABN-1403 NodeSDK check multiple certs
Browse files Browse the repository at this point in the history
Certificate settings may be mutiple certs. Check that
there is newline on the  end statement of the cert
to provide the parser with 'end of' this cert.

Signed-off-by: Bret Harrison <[email protected]>
Change-Id: I8a5d8e2569a0358515e6361a821dc55da127a200
  • Loading branch information
harrisob committed Oct 21, 2019
1 parent d1be543 commit bb5cad2
Show file tree
Hide file tree
Showing 6 changed files with 127 additions and 30 deletions.
10 changes: 5 additions & 5 deletions fabric-client/lib/Channel.js
Original file line number Diff line number Diff line change
Expand Up @@ -1337,11 +1337,11 @@ const Channel = class {
const msp_config = {
id: id,
orgs: q_msp.organizational_unit_identifiers,
rootCerts: sdk_utils.convertBytetoString(q_msp.root_certs),
intermediateCerts: sdk_utils.convertBytetoString(q_msp.intermediate_certs),
admins: sdk_utils.convertBytetoString(q_msp.admins),
tls_root_certs: sdk_utils.convertBytetoString(q_msp.tls_root_certs),
tls_intermediate_certs: sdk_utils.convertBytetoString(q_msp.tls_intermediate_certs)
rootCerts: sdk_utils.byteToNormalizedPEM(q_msp.root_certs),
intermediateCerts: sdk_utils.byteToNormalizedPEM(q_msp.intermediate_certs),
admins: sdk_utils.byteToNormalizedPEM(q_msp.admins),
tls_root_certs: sdk_utils.byteToNormalizedPEM(q_msp.tls_root_certs),
tls_intermediate_certs: sdk_utils.byteToNormalizedPEM(q_msp.tls_intermediate_certs)
};
config.msps[id] = msp_config;
}
Expand Down
45 changes: 31 additions & 14 deletions fabric-client/test/Channel.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,23 @@ describe('Channel', () => {

mspId = 'mspId';

const pem_cert =
'-----BEGIN CERTIFICATE-----\n' +
'MIICSTCCAe+gAwIBAgIQPHXmPqjzn2bon7JrBRPS2DAKBggqhkjOPQQDAjB2MQsw\n' +
'CQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZy\n' +
'YW5jaXNjbzEZMBcGA1UEChMQb3JnMS5leGFtcGxlLmNvbTEfMB0GA1UEAxMWdGxz\n' +
'Y2Eub3JnMS5leGFtcGxlLmNvbTAeFw0xOTAyMjExNDI4MDBaFw0yOTAyMTgxNDI4\n' +
'MDBaMHYxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQH\n' +
'Ew1TYW4gRnJhbmNpc2NvMRkwFwYDVQQKExBvcmcxLmV4YW1wbGUuY29tMR8wHQYD\n' +
'VQQDExZ0bHNjYS5vcmcxLmV4YW1wbGUuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0D\n' +
'AQcDQgAELAsSPvzK3EdhGPZAMKYh67s02WqfYUe09xMzy7BzNODUKcbyIW5i7GVQ\n' +
'3YurSkR/auRsk6FG45Q1zTZaEvwVH6NfMF0wDgYDVR0PAQH/BAQDAgGmMA8GA1Ud\n' +
'JQQIMAYGBFUdJQAwDwYDVR0TAQH/BAUwAwEB/zApBgNVHQ4EIgQg8HHn3ScArMdH\n' +
'lkp+jpcDXtIAzWnVf4F9rBHvUNjcC1owCgYIKoZIzj0EAwIDSAAwRQIhAMi+R+ZI\n' +
'XgZV40IztD8aQDr/sntDTu/8Nw7Y0DGEhwaQAiBEnBCdRXaBcENWnAnastAg+RA5\n' +
'XALSidlQqZKrK4L3Yg==\n' +
'-----END CERTIFICATE-----\n';

beforeEach(() => {
const FakeLogger = {
debug: () => {
Expand Down Expand Up @@ -91,11 +108,11 @@ describe('Channel', () => {

stubMsp = sinon.createStubInstance(MSP);
stubMsp.organizational_unit_identifiers = mspId;
stubMsp.root_certs = Buffer.from('root-certs');
stubMsp.intermediate_certs = Buffer.from('intermediate-certs');
stubMsp.admins = Buffer.from('admin');
stubMsp.tls_root_certs = Buffer.from('tls_root_certs');
stubMsp.tls_intermediate_certs = Buffer.from('tls_intermediate_certs');
stubMsp.root_certs = Buffer.from(pem_cert);
stubMsp.intermediate_certs = Buffer.from(pem_cert);
stubMsp.admins = Buffer.from(pem_cert);
stubMsp.tls_root_certs = Buffer.from(pem_cert);
stubMsp.tls_intermediate_certs = Buffer.from(pem_cert);
stubMsp.deserializeIdentity.returns(stubMspIdentity);

sinon.stub(channel.getMSPManager(), 'getMSP').withArgs(mspId).returns(stubMsp);
Expand Down Expand Up @@ -1030,7 +1047,7 @@ describe('Channel', () => {
return expect(channel.initialize({discover: true, target: peer1})).to.be.rejectedWith('No MSP information found');
});

it('should set the clientTlsCertHash if the cert has is available', async () => {
it('should set the clientTlsCertHash if the cert is available', async () => {
const setClientTlsCertHashStub = sinon.stub();
ChannelRewire.__set__('fabprotos.discovery.AuthInfo.prototype.setClientTlsCertHash', setClientTlsCertHashStub);
peer2.identity = new identityProto.SerializedIdentity({mspid: mspId}).toBuffer();
Expand All @@ -1052,7 +1069,7 @@ describe('Channel', () => {
{
config_result: {
msps: {[mspId]: stubMsp},
orderers: {[mspId]: {endpoint: [{host: orderer1._endpoint.addr, port: orderer1._endpoint.port}]}}
orderers: {[mspId]: {endpoint: [{host: orderer1._endpoint.addr, port: 7050}]}}
}
}
]
Expand All @@ -1066,9 +1083,9 @@ describe('Channel', () => {
expect(init.orderers).to.deep.equal({
[mspId]: {
endpoints: [{
name: `${orderer1._endpoint.addr}:${orderer1._endpoint.port}`,
name: `${orderer1._endpoint.addr}:7050`,
host: orderer1._endpoint.addr,
port: orderer1._endpoint.port
port: 7050
}]
}
});
Expand Down Expand Up @@ -1340,13 +1357,13 @@ describe('Channel', () => {
const discoveryResults = await channel.getDiscoveryResults({});
expect(discoveryResults.msps).to.deep.equal({
[mspId]: {
admins: 'admin',
admins: pem_cert,
id: 'org1',
intermediateCerts: 'intermediate-certs',
intermediateCerts: pem_cert,
orgs: mspId,
rootCerts: 'root-certs',
tls_intermediate_certs: 'tls_intermediate_certs',
tls_root_certs: 'tls_root_certs'
rootCerts: pem_cert,
tls_intermediate_certs: pem_cert,
tls_root_certs: pem_cert
}
});
expect(discoveryResults.orders).to.be.undefined;
Expand Down
12 changes: 6 additions & 6 deletions fabric-common/lib/Discovery.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
const TYPE = 'Discovery';
const Long = require('long');

const {convertBytetoString, checkParameter, getLogger} = require('./Utils.js');
const {byteToNormalizedPEM, checkParameter, getLogger} = require('./Utils.js');
const ServiceAction = require('./ServiceAction.js');
const DiscoveryHandler = require('./DiscoveryHandler.js');

Expand Down Expand Up @@ -412,11 +412,11 @@ class Discovery extends ServiceAction {
id: id,
name: id,
organizational_unit_identifiers: q_msp.organizational_unit_identifiers,
root_certs: convertBytetoString(q_msp.root_certs),
intermediate_certs: convertBytetoString(q_msp.intermediate_certs),
admins: convertBytetoString(q_msp.admins),
tls_root_certs: convertBytetoString(q_msp.tls_root_certs),
tls_intermediate_certs: convertBytetoString(q_msp.tls_intermediate_certs)
root_certs: byteToNormalizedPEM(q_msp.root_certs),
intermediate_certs: byteToNormalizedPEM(q_msp.intermediate_certs),
admins: byteToNormalizedPEM(q_msp.admins),
tls_root_certs: byteToNormalizedPEM(q_msp.tls_root_certs),
tls_intermediate_certs: byteToNormalizedPEM(q_msp.tls_intermediate_certs)
};
config.msps[id] = msp_config;
this.channel.addMSP(msp_config, true);
Expand Down
17 changes: 16 additions & 1 deletion fabric-common/lib/Utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -466,7 +466,13 @@ module.exports.normalizeX509 = (raw) => {

// make sure '-----BEGIN CERTIFICATE-----' and '-----END CERTIFICATE-----' are in their own lines
// and that it ends in a new line
return matches.join('\n') + '\n';
let result = matches.join('\n') + '\n';

// could be this has multiple certs within
const regex2 = /----------/;
result = result.replace(new RegExp(regex2, 'g'), '-----\n-----');

return result;
};

/*
Expand Down Expand Up @@ -526,6 +532,15 @@ module.exports.convertBytetoString = (buffer_array, encoding) => {
return result;
};

module.exports.byteToNormalizedPEM = (buffer_array, encoding) => {
let result = module.exports.convertBytetoString(buffer_array, encoding);
if (result) {
result = module.exports.normalizeX509(result);
}

return result;
};

/*
* Converts to a Long number
* Returns a null if the incoming value is not a string that represents a
Expand Down
65 changes: 65 additions & 0 deletions fabric-common/test/Utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,71 @@ chai.use(chaiAsPromised);
chai.use(sinonChai);

describe('Utils', () => {
describe('#byteToNormalizedPEM', () => {
let pem, pem_no_new_line;
beforeEach(() => {
pem =
'-----BEGIN CERTIFICATE-----\n' +
'MIICSTCCAe+gAwIBAgIQPHXmPqjzn2bon7JrBRPS2DAKBggqhkjOPQQDAjB2MQsw\n' +
'CQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZy\n' +
'YW5jaXNjbzEZMBcGA1UEChMQb3JnMS5leGFtcGxlLmNvbTEfMB0GA1UEAxMWdGxz\n' +
'Y2Eub3JnMS5leGFtcGxlLmNvbTAeFw0xOTAyMjExNDI4MDBaFw0yOTAyMTgxNDI4\n' +
'MDBaMHYxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQH\n' +
'Ew1TYW4gRnJhbmNpc2NvMRkwFwYDVQQKExBvcmcxLmV4YW1wbGUuY29tMR8wHQYD\n' +
'VQQDExZ0bHNjYS5vcmcxLmV4YW1wbGUuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0D\n' +
'AQcDQgAELAsSPvzK3EdhGPZAMKYh67s02WqfYUe09xMzy7BzNODUKcbyIW5i7GVQ\n' +
'3YurSkR/auRsk6FG45Q1zTZaEvwVH6NfMF0wDgYDVR0PAQH/BAQDAgGmMA8GA1Ud\n' +
'JQQIMAYGBFUdJQAwDwYDVR0TAQH/BAUwAwEB/zApBgNVHQ4EIgQg8HHn3ScArMdH\n' +
'lkp+jpcDXtIAzWnVf4F9rBHvUNjcC1owCgYIKoZIzj0EAwIDSAAwRQIhAMi+R+ZI\n' +
'XgZV40IztD8aQDr/sntDTu/8Nw7Y0DGEhwaQAiBEnBCdRXaBcENWnAnastAg+RA5\n' +
'XALSidlQqZKrK4L3Yg==\n' +
'-----END CERTIFICATE-----\n';
pem_no_new_line =
'-----BEGIN CERTIFICATE-----\n' +
'MIICSTCCAe+gAwIBAgIQPHXmPqjzn2bon7JrBRPS2DAKBggqhkjOPQQDAjB2MQsw\n' +
'CQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZy\n' +
'YW5jaXNjbzEZMBcGA1UEChMQb3JnMS5leGFtcGxlLmNvbTEfMB0GA1UEAxMWdGxz\n' +
'Y2Eub3JnMS5leGFtcGxlLmNvbTAeFw0xOTAyMjExNDI4MDBaFw0yOTAyMTgxNDI4\n' +
'MDBaMHYxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQH\n' +
'Ew1TYW4gRnJhbmNpc2NvMRkwFwYDVQQKExBvcmcxLmV4YW1wbGUuY29tMR8wHQYD\n' +
'VQQDExZ0bHNjYS5vcmcxLmV4YW1wbGUuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0D\n' +
'AQcDQgAELAsSPvzK3EdhGPZAMKYh67s02WqfYUe09xMzy7BzNODUKcbyIW5i7GVQ\n' +
'3YurSkR/auRsk6FG45Q1zTZaEvwVH6NfMF0wDgYDVR0PAQH/BAQDAgGmMA8GA1Ud\n' +
'JQQIMAYGBFUdJQAwDwYDVR0TAQH/BAUwAwEB/zApBgNVHQ4EIgQg8HHn3ScArMdH\n' +
'lkp+jpcDXtIAzWnVf4F9rBHvUNjcC1owCgYIKoZIzj0EAwIDSAAwRQIhAMi+R+ZI\n' +
'XgZV40IztD8aQDr/sntDTu/8Nw7Y0DGEhwaQAiBEnBCdRXaBcENWnAnastAg+RA5\n' +
'XALSidlQqZKrK4L3Yg==\n' +
'-----END CERTIFICATE-----';
});

it('should convert one byte to a good PEM', () => {
const normalized = Utils.byteToNormalizedPEM(Buffer.from(pem));
normalized.should.be.equal(pem);
});

it('should convert two certs in byte to a good PEM', () => {
const twoCerts = Buffer.concat([Buffer.from(pem), Buffer.from(pem)]);
const normalized = Utils.byteToNormalizedPEM(twoCerts);
normalized.should.be.equal(pem + pem);
});

it('should convert one byte to a good PEM with no ending new line', () => {
const normalized = Utils.byteToNormalizedPEM(Buffer.from(pem_no_new_line));
normalized.should.be.equal(pem);
});

it('should convert two certs in byte to a good PEM', () => {
const twoCerts = Buffer.concat([Buffer.from(pem_no_new_line), Buffer.from(pem_no_new_line)]);
const normalized = Utils.byteToNormalizedPEM(twoCerts);
normalized.should.be.equal(pem + pem);
});

it('should convert three certs in byte to a good PEM', () => {
const twoCerts = Buffer.concat([Buffer.from(pem_no_new_line), Buffer.from(pem_no_new_line), Buffer.from(pem_no_new_line)]);
const normalized = Utils.byteToNormalizedPEM(twoCerts);
normalized.should.be.equal(pem + pem + pem);
});
});

describe('#newCryptoSuite', () => {

Expand Down
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@
"test:ca-client": "npm run coverage -- 'fabric-ca-client/test/**/*.{js,ts}'",
"test:client": "npm run coverage -- 'fabric-client/test/**/*.{js,ts}'",
"test:network": "npm run compile-src && npm run coverage -- 'fabric-network/test/**/*.{js,ts}'",
"test:protos": "npm run coverage -- 'fabric-protos/test/**/*.{js,ts}",
"test:protos": "npm run coverage -- 'fabric-protos/test/**/*.{js,ts}",
"test:cucumber": "cucumber-js ./test/scenario/features/*.feature",
"test:ts-cucumber": "cucumber-js ./test/ts-scenario/features/*.feature --require './test/ts-scenario/steps/**/*.ts' --require './test/ts-scenario/support/**/*.ts' --require-module ts-node/register --format progress-bar",
"test:ts-cucumber-tagged": "cucumber-js ./test/ts-scenario/features/*.feature --require './test/ts-scenario/steps/**/*.ts' --require './test/ts-scenario/support/**/*.ts' --require-module ts-node/register --format progress-bar --tags @deprecated",
"test:all": "nyc npm run unit-test:all",
"test:ts-cucumber": "cucumber-js ./test/ts-scenario/features/*.feature --require './test/ts-scenario/steps/**/*.ts' --require './test/ts-scenario/support/**/*.ts' --require-module ts-node/register --format progress-bar",
"test:ts-cucumber-tagged": "cucumber-js ./test/ts-scenario/features/*.feature --require './test/ts-scenario/steps/**/*.ts' --require './test/ts-scenario/support/**/*.ts' --require-module ts-node/register --format progress-bar --tags @deprecated",
"test:all": "nyc npm run unit-test:all",
"unit-test:all": "npm run unit-test -- 'fabric-common/test/**/*.{js,ts}' && npm run unit-test -- 'fabric-ca-client/test/**/*.{js,ts}' && npm run unit-test -- 'fabric-client/test/**/*.{js,ts}' && npm run unit-test -- 'fabric-network/test/**/*.{js,ts}'",
"unit-test": "mocha --require ts-node/register --exclude 'fabric-client/test/data/**'",
"compile": "npm run compile-src && npm run compile-test",
Expand Down

0 comments on commit bb5cad2

Please sign in to comment.