Skip to content

Commit

Permalink
[FAB-6507] NodeSDK - add caname
Browse files Browse the repository at this point in the history
NodeSDK use of the common network config was
missing the caname. Also added a method to the
Client to be able to get a CA based on the
common config.

Change-Id: Ib507c37dfd35686437d7239e2b1052add882969f
Signed-off-by: Bret Harrison <beharrison@nc.rr.com>
  • Loading branch information
harrisob committed Oct 9, 2017
1 parent 4800f64 commit 229c0fa
Show file tree
Hide file tree
Showing 10 changed files with 204 additions and 33 deletions.
17 changes: 15 additions & 2 deletions fabric-ca-client/lib/FabricCAClientImpl.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ var FabricCAServices = class extends BaseClient {
/**
* constructor
*
* @param {string} url The endpoint URL for Fabric CA services of the form: "http://host:port" or "https://host:port"
* @param {string | object} url The endpoint URL for Fabric CA services of the form: "http://host:port" or "https://host:port"
When this parameter is an object then it must include the parameters listed as key value pairs.
* @param {TLSOptions} tlsOptions The TLS settings to use when the Fabric CA services endpoint uses "https"
* @param {string} caName The optional name of the CA. Fabric-ca servers support multiple Certificate Authorities from
* a single server. If omitted or null or an empty string, then the default CA is the target of requests
Expand All @@ -60,8 +61,20 @@ var FabricCAServices = class extends BaseClient {
* is provided for this purpose, which can be used on top of any implementation of the {@link KeyValueStore} interface,
* such as a file-based store or a database-based one. The specific implementation is determined by the value of this configuration setting.
*/
constructor(url, tlsOptions, caName, cryptoSuite) {
constructor(url_p, tlsOptions_p, caName_p, cryptoSuite_p) {
super();
let url, tlsOptions, caName, cryptoSuite;
if(typeof url_p === 'object') {
url = url_p.url;
tlsOptions = url_p.tlsOptions;
caName = url_p.caName;
cryptoSuite = url_p.cryptoSuite
} else {
url = url_p;
tlsOptions = tlsOptions_p;
caName = caName_p;
cryptoSuite = cryptoSuite_p;
}

var endpoint = FabricCAServices._parseURL(url);

Expand Down
16 changes: 15 additions & 1 deletion fabric-client/lib/CertificateAuthority.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ var CertificateAuthority = class {
* @returns {CertificateAuthority} The CertificateAuthority instance.
*/
constructor(name, url, connection_options, tlsCACerts, registrar) {
constructor(name, caname, url, connection_options, tlsCACerts, registrar) {
logger.debug('CertificateAuthority.const ');
logger.debug('Organization.const ');
if (typeof name === 'undefined' || name === null) {
Expand All @@ -46,6 +46,11 @@ var CertificateAuthority = class {
throw new Error('Missing url parameter');
}
this._name = name;
if(caname) {
this._caname = caname;
} else {
this._caname = name;
}
this._url = url;
this._connection_options = connection_options;
this._tlsCACerts = tlsCACerts;;
Expand All @@ -61,6 +66,15 @@ var CertificateAuthority = class {
return this._name;
}

/**
* Gets the name of this CertificateAuthority to use in request
*
* @returns {string} The ca name of this CertificateAuthority
*/
getCaName() {
return this._caname;
}

/**
* Gets the url of this CertificateAuthority
*
Expand Down
84 changes: 61 additions & 23 deletions fabric-client/lib/Client.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ var Client = class extends BaseClient {
// an admin defined for the current user's organization.
// This will get set during the setUserFromConfig
this._adminSigningIdentity = null;

this._certificate_authority = null;
}

/**
Expand All @@ -108,6 +110,7 @@ var Client = class extends BaseClient {
if(client._network_config.hasClient()) {
client._setAdminFromConfig();
}

return client;
}

Expand All @@ -126,7 +129,10 @@ var Client = class extends BaseClient {
}
if(this._network_config.hasClient()) {
this._setAdminFromConfig();
// reset the CA incase the org changed
this._certificate_authority = null;
}

}

/**
Expand Down Expand Up @@ -278,6 +284,48 @@ var Client = class extends BaseClient {
return orderer;
}

/**
* Returns a CertificateAuthority implementation as defined by the settings in the
* currently loaded network configuration and the client configuration. A network
* configuration must be loaded for this get method to return a Certificate Authority.
*/
getCertificateAuthority() {
if(this._certificate_authority) {
return this._certificate_authority;
}
if(!this._network_config) {
throw new Error('No network configuration has been loaded');
}
let ca_url, tls_options, ca_name = null;
let client_config = this._network_config.getClientConfig();
if(client_config && client_config.organization) {
let organization_config = this._network_config.getOrganization(client_config.organization);
if(organization_config) {
let cas = organization_config.getCertificateAuthorities();
if(cas.length > 0) {
let ca = cas[0];
tls_options = {
trustedRoots: [ca.getTlsCACerts()], //TODO handle non existent
verify: ca.getConnectionOptions().verify //TODO handle non existent
};
ca_url = ca.getUrl();
ca_name = ca.getCaName();
}
}
}

if(!ca_url) {
throw new Error('Network configuration is missing this client\'s organization and certificate authority');
}

let ca_service_class = Client.getConfigSetting('certificate-authority-client');
let ca_service_impl = require(ca_service_class);
let ca_service = new ca_service_impl( {url : ca_url, tlsOptions : tls_options, caName : ca_name, cryptoSuite : this._crypto_suite});
this._certificate_authority = ca_service;

return ca_service;
}

/**
* Returns a new {@link TransactionID} object. Fabric transaction ids are constructed
* as a hash of a nonce concatenated with the signing identity's serialized bytes. The
Expand Down Expand Up @@ -1058,33 +1106,23 @@ var Client = class extends BaseClient {
return reject( new Error('Missing parameter. Must have a password.'));
}

let ca_url, tls_options, ca_name = null;
let client_config = self._network_config.getClientConfig();
if(client_config && client_config.organization) {
let organization_config = self._network_config.getOrganization(client_config.organization);
if(organization_config) {
mspid = organization_config.getMspid();
let cas = organization_config.getCertificateAuthorities();
if(cas.length > 0) {
let ca = cas[0];
tls_options = {
trustedRoots: [ca.getTlsCACerts()], //TODO handle non existent
verify: ca.getConnectionOptions().verify //TODO handle non existent
};
ca_url = ca.getUrl();
ca_name = ca.getName();
let ca_service, mspid = null;
try {
let client_config = this._network_config.getClientConfig();
if(client_config && client_config.organization) {
let organization_config = this._network_config.getOrganization(client_config.organization);
if(organization_config) {
mspid = organization_config.getMspid();
}
}
if(!mspid) {
throw new Error('Network configuration is missing this client\'s organization and mspid');
}
ca_service = self.getCertificateAuthority();
} catch(err) {
reject(err);
}

if(!ca_url || !tls_options || !mspid) {
return reject(new Error('Configuration is missing this client\'s organization and certificate authority'));
}

let ca_service_class = Client.getConfigSetting('certificate-authority-client');
var ca_service_impl = require(ca_service_class);
var ca_service = new ca_service_impl(ca_url, tls_options, ca_name, self._crypto_suite);

return ca_service.enroll({
enrollmentID: opts.username,
enrollmentSecret: opts.password
Expand Down
2 changes: 2 additions & 0 deletions fabric-client/lib/impl/NetworkConfig_1_0.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ var HTTP_CONNECTION_OPTIONS = 'httpOptions';
var URL = 'url';
var EVENT_URL = 'eventUrl';
var NAME = 'name';
var CANAME = 'caName';
var PEM = 'pem';
var PATH = 'path';
var REGISTRAR = 'registrar';
Expand Down Expand Up @@ -271,6 +272,7 @@ var NetworkConfig_1_0 = class {
if(certificateAuthority_config) {
certificateAuthority = new CertificateAuthority(
name,
certificateAuthority_config[CANAME],
certificateAuthority_config[URL],
certificateAuthority_config[HTTP_CONNECTION_OPTIONS],
getTLSCACert(certificateAuthority_config),
Expand Down
4 changes: 2 additions & 2 deletions test/fixtures/network.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ certificateAuthorities:
- enrollId: admin
enrollSecret: adminpw
# [Optional] The optional name of the CA.
caName: caNameHere
caName: ca-org1

ca-org2:
url: https://localhost:8054
Expand All @@ -228,4 +228,4 @@ certificateAuthorities:
- enrollId: admin
enrollSecret: adminpw
# [Optional] The optional name of the CA.
caName: caNameHere
caName: ca-org2
34 changes: 33 additions & 1 deletion test/integration/network-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -312,11 +312,28 @@ test('\n\n***** use the network configuration file *****\n\n', function(t) {
/*
* S T A R T U S I N G
*/
/*
* switch to organization org2
*/

client.loadFromConfig('test/fixtures/org2.yaml');

return client.initCredentialStores();
}).then((nothing) => {
t.pass('Successfully created the key value store and crypto store based on the config and network config');

let ca = client.getCertificateAuthority();
if(ca) {
t.equals(ca._fabricCAClient._caName,'ca-org2', 'checking that caname is correct for the newly created ca');
} else {
t.fail('Failed - CertificateAuthority should have been created');
}

/*
* switch to organization org1
*/
client.loadFromConfig('test/fixtures/org1.yaml');
t.pass('Successfully loaded \'admin\' for org1');
t.pass('Successfully loaded config for org1');

return client.initCredentialStores();
}).then((nothing) => {
Expand All @@ -326,6 +343,21 @@ test('\n\n***** use the network configuration file *****\n\n', function(t) {
}).then((admin) => {
t.pass('Successfully enrolled user \'admin\' for org1');

let ca = client.getCertificateAuthority();
if(ca) {
t.equals(ca._fabricCAClient._caName,'ca-org1', 'checking that caname is correct after resetting the config');
} else {
t.fail('Failed - CertificateAuthority should have been created');
}

return ca.register({enrollmentID: 'user1', affiliation: 'org1'}, admin);
}).then((secret) => {
t.pass('Successfully registered user \'user1\' for org1');

return client.setUserContext({username:'user1', password:secret});
}).then((user)=> {
t.pass('Successfully enrolled user \'user1\' for org1');

let tx_id = client.newTransactionID(); // get a non admin transaction ID
var request = {
chaincodeId : 'example',
Expand Down
7 changes: 4 additions & 3 deletions test/unit/certificate-authority.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,14 @@ test('\n\n ** CertificateAuthority - constructor set get tests **\n\n', function
'Test Missing url parameter');

t.doesNotThrow(()=>{
new CertificateAuthority('name', 'url');
new CertificateAuthority('name', 'caname', 'url');
},
null,
'Test good construction');

var ca = new CertificateAuthority('name','url','opts', 'certs', 'user');
var ca = new CertificateAuthority('name', 'caname', 'url','opts', 'certs', 'user');
t.equals('name',ca.getName(),'test method getName');
t.equals('caname',ca.getCaName(),'test method getCaName');
t.equals('url',ca.getUrl(),'test method getUrl');
t.equals('opts',ca.getConnectionOptions(),'test method getConnectionOptions');
t.equals('certs',ca.getTlsCACerts(),'test method getTlsCACerts');
Expand All @@ -63,4 +64,4 @@ test('\n\n ** CertificateAuthority - constructor set get tests **\n\n', function
}

t.end();
});
});
14 changes: 14 additions & 0 deletions test/unit/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -1205,3 +1205,17 @@ test('\n\n*** Test per-call timeout support ***\n', function(t) {
t.end();
});
});

test('\n\n*** Test per-call timeout support ***\n', function(t) {
let client = new Client();
t.throws(
() => {

client.getCertificateAuthority();
},
/No network configuration has been loaded/,
'Check that No network configuration has been loaded'
);

t.end();
});
46 changes: 46 additions & 0 deletions test/unit/fabric-ca-client.js
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,52 @@ test('FabricCAServices: Test newCryptoKeyStore() function', function(t) {
}
t.end();
});
// Test optional consturctor
test('FabricCAServices: Test optional consturctor', function(t) {
let opts = {
url : 'http://localhost:7054'
}

t.doesNotThrow(
function () {
let service = new FabricCAServices(opts);
},
null,
'FabricCAServices consturctor with object and just url'
);

opts.caName = 'someca';
t.doesNotThrow(
function () {
let service = new FabricCAServices(opts);
t.equals(service._fabricCAClient._caName,'someca','Caname should have been passed correctly');
},
null,
'FabricCAServices consturctor with object and just url'
);

opts.cryptoSuite = 'somesuite';
t.doesNotThrow(
function () {
let service = new FabricCAServices(opts);
t.equals(service._fabricCAClient._cryptoPrimitives,'somesuite','CryptoSuite should have been passed correctly');
},
null,
'FabricCAServices consturctor with object and just url'
);

opts.tlsOptions = {verify : 'someverify'};
t.doesNotThrow(
function () {
let service = new FabricCAServices(opts);
t.equals(service._fabricCAClient._tlsOptions.verify,'someverify','tlsOptions should have been passed correctly');
},
null,
'FabricCAServices consturctor with object and just url'
);

t.end();
});

// Test getCryptoSuite() function
test('FabricCAServices: Test getCryptoSuite() function', function(t) {
Expand Down
13 changes: 12 additions & 1 deletion test/unit/network-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,16 @@ test('\n\n ** configuration testing **\n\n', function (t) {
'Should be able to instantiate a new instance of "Channel" with blank definition in the network configuration'
);

t.throws(
() => {
var client = new Client();
client._network_config = new NetworkConfig({}, client);
client.getCertificateAuthority();
},
/Network configuration is missing this client\'s organization and certificate authority/,
'Check for Network configuration is missing this client\'s organization and certificate authority'
);

network_config.version = '1.0.0';
network_config.channels = {
'mychannel' : {
Expand Down Expand Up @@ -607,8 +617,9 @@ test('\n\n ** configuration testing **\n\n', function (t) {

t.doesNotThrow(
() => {
var certificateAuthority = new CertificateAuthority('name', 'url', 'connection', 'tlscert', 'registrar');
var certificateAuthority = new CertificateAuthority('name', 'caname', 'url', 'connection', 'tlscert', 'registrar');
t.equals('name',certificateAuthority.getName(), 'check name');
t.equals('caname',certificateAuthority.getCaName(), 'check caname');
t.equals('url',certificateAuthority.getUrl(), 'check url');
t.equals('connection',certificateAuthority.getConnectionOptions(), 'check connection options');
t.equals('tlscert',certificateAuthority.getTlsCACerts(), 'check tlscert');
Expand Down

0 comments on commit 229c0fa

Please sign in to comment.