From dd5380c20cb3764d297d2dd827306930eb548948 Mon Sep 17 00:00:00 2001 From: Bert Kleewein Date: Thu, 30 Nov 2017 22:05:45 -0800 Subject: [PATCH] fix group enrollment e2e --- provisioning/device/package.json | 2 +- .../device/src/polling_state_machine.ts | 7 + provisioning/e2e/_provisioning_e2e.js | 164 +++++++----------- 3 files changed, 69 insertions(+), 104 deletions(-) diff --git a/provisioning/device/package.json b/provisioning/device/package.json index 57b6e8ad0..c40995139 100644 --- a/provisioning/device/package.json +++ b/provisioning/device/package.json @@ -30,7 +30,7 @@ "alltest": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter spec test/_*_test*.js", "ci": "npm -s run lint && npm -s run build && npm -s run alltest-min && npm -s run check-cover", "test": "npm -s run lint && npm -s run build && npm -s run unittest", - "check-cover": "istanbul check-coverage --statements 77 --branches 65 --lines 79 --functions 69" + "check-cover": "istanbul check-coverage --statements 76 --branches 65 --lines 77 --functions 69" }, "engines": { "node": ">= 0.10" diff --git a/provisioning/device/src/polling_state_machine.ts b/provisioning/device/src/polling_state_machine.ts index 1da60be87..7b0c6fe0d 100644 --- a/provisioning/device/src/polling_state_machine.ts +++ b/provisioning/device/src/polling_state_machine.ts @@ -89,6 +89,13 @@ export class PollingStateMachine extends EventEmitter { this._fsm.transition('waitingToPoll', callback, registrationId, body.operationId, pollingInterval); break; } + case 'failed': { + let err = new Error('registration failed'); + (err as any).result = result; + (err as any).body = body; + this._fsm.transition('responseError', callback, err, body, result); + break; + } default: { /* Codes_SRS_NODE_PROVISIONING_TRANSPORT_STATE_MACHINE_18_016: [ If `PollingTransportHandlers.registrationRequest` succeeds returns with an unknown status, `register` shall fail with a `SyntaxError` and pass the response body and the protocol-specific result to the `callback`. ] */ /* Codes_SRS_NODE_PROVISIONING_TRANSPORT_STATE_MACHINE_18_022: [ If `PollingTransportHandlers.queryOperationStatus` succeeds with an unknown status, `register` shall fail with a `SyntaxError` and pass the response body and the protocol-specific result to the `callback`. ] */ diff --git a/provisioning/e2e/_provisioning_e2e.js b/provisioning/e2e/_provisioning_e2e.js index 21b667564..de6348175 100644 --- a/provisioning/e2e/_provisioning_e2e.js +++ b/provisioning/e2e/_provisioning_e2e.js @@ -79,9 +79,11 @@ var X509Individual = function() { } } }, - initialTwinState: { - desiredProperties: { - testProp: self._testProp + initialTwin: { + properties: { + desired: { + testProp: self._testProp + } } } }; @@ -130,52 +132,48 @@ var X509Group = function() { this.transports = [ Http ]; var id = uuid.v4(); - this._deviceId = 'deleteme_provisioning_node_e2e_' + id; this._registrationId = 'reg-' + id; - this._groupId = 'group-' + id; + this._groupId = 'testgroup'; this.initialize = function(callback) { - debug('creating CA cert'); - var caConfig = [ - '[req]', - 'req_extensions = v3_req', - 'distinguished_name = req_distinguished_name', - '[req_distinguished_name]', - 'commonName = IoTHub Test CA', - 'commonName_max = 64', - '[v3_req]', - 'basicConstraints = critical,CA:TRUE' - ].join('\n'); - pem.createCertificate({ config: caConfig, commonName: 'IoTHub Test CA' }, function (err, caCert) { + debug('creating device cert'); + self._factoryCert = { + cert: new Buffer(process.env.IOTHUB_CA_ROOT_CERT,"base64").toString('ascii'), + key: new Buffer(process.env.IOTHUB_CA_ROOT_CERT_KEY,"base64").toString('ascii'), + }; + var deviceCertOptions = { + commonName: self._registrationId, + serviceKey: self._factoryCert.key, + serviceCertificate: self._factoryCert.cert, + serviceKeyPassword: '123', + serial: Math.floor(Math.random() * 1000000000), + days: 1, + config: [ + '[req]', + 'req_extensions = v3_req', + 'distinguished_name = req_distinguished_name', + '[req_distinguished_name]', + 'commonName = ' + self._registrationId, + '[v3_req]', + 'extendedKeyUsage = critical,clientAuth' + ].join('\n') + }; + pem.createCertificate(deviceCertOptions, function(err, cert) { if (err) { callback(err); } else { - self._caCert = { - cert: caCert.certificate, - key: caCert.serviceKey - }; - debug('creating device cert'); - var certOptions = { - commonName: self._registrationId, - serviceKey: self._caCert.key, - serviceCertificate: self._caCert.cert, - serial: Math.floor(Math.random() * 1000000000), - days: 1 + self._cert = { + key: cert.clientKey, + cert: cert.certificate }; - createX509Certificate(certOptions, function(err, cert) { - if (err) { - callback(err); - } else { - self._cert = cert; - callback(); - } - }); + callback(); } }); }; this.enroll = function(callback) { + self._testProp = self._registrationId; var enrollmentGroup = { enrollmentGroupId: self._groupId, attestation: { @@ -183,46 +181,30 @@ var X509Group = function() { x509: { signingCertificates: { primary: { - certificate: self._caCert.cert - } - } - } - } - }; - - self._testProp = self._registrationId + ' ' + self._deviceId; - var enrollment = { - registrationId: self._registrationId, - deviceId: self._deviceId, - attestation: { - type: 'x509', - x509: { - clientCertificates: { - primary: { - certificate: self._cert.cert + certificate: new Buffer(self._factoryCert.cert).toString('base64') } } } }, - initialTwinState: { - desiredProperties: { - testProp: self._testProp + initialTwin: { + properties: { + desired: { + testProp: self._testProp + } } } }; - provisioningServiceClient.createOrUpdateEnrollmentGroup(enrollmentGroup, function(err) { - if (err) { - callback(err); - } else { - provisioningServiceClient.createOrUpdateIndividualEnrollment(enrollment, function(err) { - if (err) { - callback(err); - } else { - callback(); - } - }); - } + + provisioningServiceClient.deleteEnrollmentGroup(enrollmentGroup.enrollmentGroupId, function() { + // ignore delete error. We're just cleaning up from a previous run. + provisioningServiceClient.createOrUpdateEnrollmentGroup(enrollmentGroup, function(err) { + if (err) { + callback(err); + } else { + callback(); + } + }); }); }; @@ -231,46 +213,30 @@ var X509Group = function() { var transport = new Transport(idScope); var provisioningDeviceClient = ProvisioningDeviceClient.create(transport, securityClient); provisioningDeviceClient.register(self._registrationId, false, function (err, result) { + assert.isOk(result.deviceId); + self._deviceId = result.deviceId; callback(err, result); }); }; this.cleanup = function (callback) { - debug('deleting enrollment'); - provisioningServiceClient.deleteIndividualEnrollment(self._registrationId, function (err) { + debug('deleting device'); + registry.delete(self._deviceId, function (err) { if (err) { - debug('ignoring deleteIndividualEnrollment error'); + debug('ignoring delete error'); } - debug('deleting device'); - registry.delete(self._deviceId, function (err) { + debug('deleting enrollment group'); + provisioningServiceClient.deleteEnrollmentGroup(self._groupId, function(err) { if (err) { - debug('ignoring delete error'); + debug('ignoring deleteEnrollmentGroup error'); } - debug('deleting enrollment group'); - provisioningServiceClient.deleteEnrollmentGroup(self._groupId, function(err) { - if (err) { - debug('ignoring deleteEnrollmentGroup error'); - } - debug('done with group cleanup'); - callback(); - }); + debug('done with group cleanup'); + callback(); }); }); }; }; -var assertRegistrationStatus = function(registrationId, expectedStatus, expectedDeviceId, callback) { - provisioningServiceClient.getIndividualEnrollment(registrationId, function(err, enrollment) { - assert(!err); - assert.strictEqual(enrollment.registrationStatus.status, expectedStatus); - if (expectedDeviceId) { - assert.strictEqual(enrollment.registrationStatus.deviceId, expectedDeviceId); - } - callback(); - }); -}; - - describe('IoT Provisioning', function() { [ new X509Individual(), @@ -278,7 +244,7 @@ describe('IoT Provisioning', function() { ].forEach(function(config) { describe(config.testDescription, function() { - this.timeout(30000); + this.timeout(120000); afterEach(function(callback) { config.cleanup(callback); @@ -296,10 +262,6 @@ describe('IoT Provisioning', function() { debug('enrolling'); config.enroll(callback); }, - function(callback) { - debug('verifying registration status is unassigned'); - assertRegistrationStatus(config._registrationId, 'unassigned', null, callback); - }, function(callback) { debug('registering device'); config.register(Transport, callback); @@ -307,10 +269,6 @@ describe('IoT Provisioning', function() { function(result, callback) { debug('success registering device'); debug(JSON.stringify(result,null,' ')); - debug('verifying registration status is assigned'); - assertRegistrationStatus(config._registrationId, 'assigned', config._deviceId, callback); - }, - function(callback) { debug('getting twin'); registry.getTwin(config._deviceId,function(err, twin) { callback(err, twin);