diff --git a/build/tasks/eslint.js b/build/tasks/eslint.js index 0f229879ac..c5f927c4a0 100644 --- a/build/tasks/eslint.js +++ b/build/tasks/eslint.js @@ -8,6 +8,8 @@ gulp.task('lint', function () { 'fabric-ca-client/lib/*.js', 'examples/**/*.js', '!node_modules/**', + '!fabric-client/node_modules/**', + '!fabric-ca-client/node_modules/**', '!docs/**', '!coverage/**', '!tmp/**' diff --git a/fabric-ca-client/lib/FabricCAClientImpl.js b/fabric-ca-client/lib/FabricCAClientImpl.js index 12550c44a9..e76de7219d 100644 --- a/fabric-ca-client/lib/FabricCAClientImpl.js +++ b/fabric-ca-client/lib/FabricCAClientImpl.js @@ -76,7 +76,8 @@ var FabricCAServices = class { * @param {Object} req Registration request with the following fields: *
- enrollmentID {string}. ID which will be used for enrollment *
- role {string}. An arbitrary string representing a role value for the user - *
- group {string}. Group to which this user will be assigned, like a company or an organization + *
- affiliation {string}. Affiliation with which this user will be associated, like a company or an organization + *
- maxEnrollments {number}. The maximum number of times this user will be permitted to enroll *
- attrs {{@link KeyValueAttribute}[]}. Array of key/value attributes to assign to the user. * @param registrar {User}. The identity of the registrar (i.e. who is performing the registration) * @returns {Promise} The enrollment secret to use when this user enrolls @@ -90,9 +91,15 @@ var FabricCAServices = class { throw new Error('Missing required argument "request.enrollmentID"'); } + if (typeof req.maxEnrollments === 'undefined' || req.maxEnrollments === null) { + // set maxEnrollments to 1 + req.maxEnrollments = 1; + } + checkRegistrar(registrar); - return this._fabricCAClient.register(req.enrollmentID, req.role, req.group, req.attrs, registrar.getSigningIdentity()); + return this._fabricCAClient.register(req.enrollmentID, req.role, req.affiliation, req.maxEnrollments, req.attrs, + registrar.getSigningIdentity()); } /** @@ -128,10 +135,11 @@ var FabricCAServices = class { var csr = privateKey.generateCSR('CN=' + req.enrollmentID); self._fabricCAClient.enroll(req.enrollmentID, req.enrollmentSecret, csr) .then( - function (csrPEM) { + function (enrollResponse) { return resolve({ key: privateKey, - certificate: csrPEM + certificate: enrollResponse.enrollmentCert, + rootCertificate: enrollResponse.caCertChain }); }, function (err) { @@ -298,19 +306,20 @@ var FabricCAClient = class { * Register a new user and return the enrollment secret * @param {string} enrollmentID ID which will be used for enrollment * @param {string} role Type of role for this user - * @param {string} group Group to which this user will be assigned + * @param {string} affiliation Affiliation with which this user will be associated + * @param {number} maxEnrollments The maximum number of times the user is permitted to enroll * @param {KeyValueAttribute[]} attrs Array of key/value attributes to assign to the user * @param {SigningIdentity} signingIdentity The instance of a SigningIdentity encapsulating the * signing certificate, hash algorithm and signature algorithm * @returns {Promise} The enrollment secret to use when this user enrolls */ - register(enrollmentID, role, group, attrs, signingIdentity) { + register(enrollmentID, role, affiliation, maxEnrollments, attrs, signingIdentity) { var self = this; var numArgs = arguments.length; //all arguments are required if (numArgs < 5) { - throw new Error('Missing required parameters. \'enrollmentID\', \'role\', \'group\', \'attrs\', \ + throw new Error('Missing required parameters. \'enrollmentID\', \'role\', \'affiliation\', \'attrs\', \ and \'signingIdentity\' are all required.'); } @@ -318,13 +327,14 @@ var FabricCAClient = class { var regRequest = { 'id': enrollmentID, 'type': role ? role : 'client', - 'group': group, + 'affiliation': affiliation, + 'max_enrollments': maxEnrollments, 'attrs': attrs }; return self.post('register', regRequest, signingIdentity) .then(function (response) { - return resolve(response.result.credential); + return resolve(response.result.secret); }).catch(function (err) { return reject(err); }); @@ -358,10 +368,15 @@ var FabricCAClient = class { return new Promise(function (resolve, reject) { + if (serial!=null){ + if (serial.length < 80){ + serial = '0' + serial; + } + } var regRequest = { 'id': enrollmentID, 'aki': aki, - 'serial': parseInt(serial, 16) + '', // per CFSSL, serial numbers are saved as decimals instead of hex strings in cert database + 'serial': serial, 'reason': reason }; @@ -446,12 +461,19 @@ var FabricCAClient = class { return cert + '.' + b64Sign; } + /** + * @typedef {Object} EnrollmentResponse + * @property {string} enrollmentCert PEM-encoded X509 enrollment certificate + * @property {string} caCertChain PEM-encoded X509 certificate chain for the issuing + * certificate authority + */ + /** * Enroll a registered user in order to receive a signed X509 certificate * @param {string} enrollmentID The registered ID to use for enrollment * @param {string} enrollmentSecret The secret associated with the enrollment ID * @param {string} csr PEM-encoded PKCS#10 certificate signing request - * @returns {Promise} PEM-encoded X509 certificate + * @returns {Promise} {@link EnrollmentResponse} * @throws Will throw an error if all parameters are not provided * @throws Will throw an error if calling the enroll API fails for any reason */ @@ -495,10 +517,14 @@ var FabricCAClient = class { } //response should be JSON try { - var enrollResponse = JSON.parse(payload); - if (enrollResponse.success) { + var res = JSON.parse(payload); + if (res.success) { //we want the result field which is Base64-encoded PEM - return resolve(new Buffer.from(enrollResponse.result, 'base64').toString()); + var enrollResponse = new Object(); + // Cert field is Base64-encoded PEM + enrollResponse.enrollmentCert = new Buffer.from(res.result.Cert, 'base64').toString(); + enrollResponse.caCertChain = new Buffer.from(res.result.ServerInfo.CAChain, 'base64').toString(); + return resolve(enrollResponse); } else { return reject(new Error( util.format('Enrollment failed with errors [%s]', JSON.stringify(enrollResponse.errors)))); diff --git a/fabric-ca-client/package.json b/fabric-ca-client/package.json index 850d9b6954..fad324e774 100644 --- a/fabric-ca-client/package.json +++ b/fabric-ca-client/package.json @@ -28,8 +28,10 @@ "winston": "^2.2.0" }, "license": "Apache-2.0", - "licenses": [{ - "type": "Apache-2.0", - "url": "https://github.com/hyperledger/fabric/blob/master/LICENSE" - }] + "licenses": [ + { + "type": "Apache-2.0", + "url": "https://github.com/hyperledger/fabric/blob/master/LICENSE" + } + ] } diff --git a/test/integration/fabric-ca-services-tests.js b/test/integration/fabric-ca-services-tests.js index 8f5bc59897..4897a1fe3a 100644 --- a/test/integration/fabric-ca-services-tests.js +++ b/test/integration/fabric-ca-services-tests.js @@ -85,11 +85,12 @@ test('FabricCAServices: Test enroll() With Dynamic CSR', function (t) { var signingIdentity = new SigningIdentity('testSigningIdentity', eResult.certificate, pubKey, msp, new Signer(msp.cryptoSuite, eResult.key)); - return cop._fabricCAClient.register(enrollmentID, 'client', 'org1', [], signingIdentity); + return cop._fabricCAClient.register(enrollmentID, 'client', 'org1', 1, [], signingIdentity); },(err) => { t.fail('Failed to import the public key from the enrollment certificate. ' + err.stack ? err.stack : err); t.end(); }).then((secret) => { + console.log('secret: ' + JSON.stringify(secret)); t.comment(secret); enrollmentSecret = secret; // to be used in the next test case @@ -110,17 +111,16 @@ test('FabricCAServices: Test enroll() With Dynamic CSR', function (t) { return member.setEnrollment(eResult.key, eResult.certificate); }).then(() => { t.comment('Successfully constructed a user object based on the enrollment'); - - return cop.register({enrollmentID: 'testUserX', group: 'bank_X'}, member); + return cop.register({enrollmentID: 'testUserX', affiliation: 'bank_X'}, member); }).then((secret) => { - t.fail('Should not have been able to register user of a group "bank_X" because "admin" does not belong to that group'); + t.fail('Should not have been able to register user of a affiliation "bank_X" because "admin" does not belong to that affiliation'); t.end(); },(err) => { - t.pass('Successfully rejected registration request "testUserX" in group "bank_X"'); + t.pass('Successfully rejected registration request "testUserX" in affiliation "bank_X"'); - return cop.register({enrollmentID: 'testUserX', group: 'org1'}, member); + return cop.register({enrollmentID: 'testUserX', affiliation: 'org1'}, member); }).then((secret) => { - t.pass('Successfully registered "testUserX" in group "org1" with enrollment secret returned: ' + secret); + t.pass('Successfully registered "testUserX" in affiliation "org1" with enrollment secret returned: ' + secret); return cop.revoke({enrollmentID: 'testUserX'}, member); },(err) => { @@ -129,7 +129,7 @@ test('FabricCAServices: Test enroll() With Dynamic CSR', function (t) { }).then((response) => { t.equal(response.success, true, 'Successfully revoked "testUserX"'); - return cop.register({enrollmentID: 'testUserY', group: 'org2.department1'}, member); + return cop.register({enrollmentID: 'testUserY', affiliation: 'org2.department1'}, member); },(err) => { t.fail('Failed to revoke "testUserX". ' + err.stack ? err.stack : err); t.end(); @@ -148,11 +148,12 @@ test('FabricCAServices: Test enroll() With Dynamic CSR', function (t) { t.comment(util.format('Ready to revoke certificate serial # "%s" with aki "%s"', serial, aki)); return cop.revoke({serial: serial, aki: aki}, member); + //return; }).then((response) => { t.equal(response.success, true, 'Successfully revoked "testUserY" using serial number and AKI'); // register a new user 'webAdmin' that can register other users of the role 'client' - return cop.register({enrollmentID: 'webAdmin', group: 'org1.department2', attrs: [{name: 'hf.Registrar.Roles', value: 'client'}]}, member); + return cop.register({enrollmentID: 'webAdmin', affiliation: 'org1.department2', attrs: [{name: 'hf.Registrar.Roles', value: 'client'}]}, member); }).then((secret) => { t.pass('Successfully registered "webAdmin" who can register other users of the "client" role'); @@ -175,7 +176,7 @@ test('FabricCAServices: Test enroll() With Dynamic CSR', function (t) { },(err) => { t.pass('Successfully rejected attempt to register a user of invalid role. ' + err); - return cop.register({enrollmentID: 'auditor', role: 'client', group: 'org2.department1'}, webAdmin); + return cop.register({enrollmentID: 'auditor', role: 'client', affiliation: 'org2.department1'}, webAdmin); }).then(() => { t.pass('Successfully registered "auditor" of role "client" from "webAdmin"'); t.end(); @@ -195,12 +196,12 @@ test('FabricCAClient: Test enroll With Static CSR', function (t) { t.comment(util.format('Sending enroll request for user %s with enrollment secret %s', enrollmentID, enrollmentSecret)); return client.enroll(enrollmentID, enrollmentSecret, csr.toString()) - .then(function (pem) { - t.comment(pem); + .then(function (enrollResponse) { + t.comment(enrollResponse.enrollmentCert); t.pass('Successfully invoked enroll API with enrollmentID \'' + enrollmentID + '\''); //check that we got back the expected certificate var cert = new X509(); - cert.readCertPEM(pem); + cert.readCertPEM(enrollResponse.enrollmentCert); t.comment(cert.getSubjectString()); t.equal(cert.getSubjectString(), '/CN=' + enrollmentID, 'Subject should be /CN=' + enrollmentID); t.end();