diff --git a/bin/load_gen b/bin/load_gen index 479504930ddd06db10c15c6e7c5b5c279af89042..07c1081c6a7c6bb2843d9acbec6f36b07d07ddb0 100755 --- a/bin/load_gen +++ b/bin/load_gen @@ -329,44 +329,53 @@ if (args.m) outputActiveUserSummary(args.m); const userdb = require("../lib/load_gen/user_db.js"); -if (args.u) { - // parse args.u - var start, end; - try { - var r = args.u.split('/'); - if (r.length != 2) throw "expected format ##/##"; - start = parseInt(r[0], 10); - end = parseInt(r[1], 10); - if (start >= end) throw "first number must be smaller than the second"; - } catch(e) { - console.log("your -u argument is poorly formated: " + e.toString()); +const lg_crypto = require("../lib/load_gen/crypto.js"); + +lg_crypto.init(function(err) { + if (err) { + process.stderr.write('error initializing crypto module: ' + err); process.exit(1); } - // now create all them users! - console.log("Runing with", (end - start + 1), "pre-created users (XXX@loadtest.domain)"); - for (var i = start; i < end; i++) { - userdb.addNewUser(userdb.getNewUser(i + "@loadtest.domain", "THE PASSWORD")); - } - console.log("users created! applying load..."); - poll(); -} else { - console.log("To start, let's create " + NUM_INITIAL_USERS + " users via the API. One moment please..."); - - var createUser = require("../lib/load_gen/activities/signup.js").startFunc; - var created = 0; - for (var i = 0; i < NUM_INITIAL_USERS; i++) { - createUser(configuration, function(err) { - if (err) { - console.log("failed to create initial users! tragedy! run away!:", err); - process.exit(1); - } - process.stdout.write("."); - if (++created == NUM_INITIAL_USERS) { - process.stdout.write("\n\n"); - console.log("Average active users simulated over the last 1s/5s/60s:"); - poll(); - } - }); + if (args.u) { + // parse args.u + var start, end; + try { + var r = args.u.split('/'); + if (r.length != 2) throw "expected format ##/##"; + start = parseInt(r[0], 10); + end = parseInt(r[1], 10); + if (start >= end) throw "first number must be smaller than the second"; + } catch(e) { + console.log("your -u argument is poorly formated: " + e.toString()); + process.exit(1); + } + + // now create all them users! + console.log("Runing with", (end - start + 1), "pre-created users (XXX@loadtest.domain)"); + for (var i = start; i < end; i++) { + userdb.addNewUser(userdb.getNewUser(i + "@loadtest.domain", "THE PASSWORD")); + } + console.log("users created! applying load..."); + poll(); + } else { + console.log("To start, let's create " + NUM_INITIAL_USERS + " users via the API. One moment please..."); + + var createUser = require("../lib/load_gen/activities/signup.js").startFunc; + var created = 0; + for (var i = 0; i < NUM_INITIAL_USERS; i++) { + createUser(configuration, function(err) { + if (err) { + console.log("failed to create initial users! tragedy! run away!:", err); + process.exit(1); + } + process.stdout.write("."); + if (++created == NUM_INITIAL_USERS) { + process.stdout.write("\n\n"); + console.log("Average active users simulated over the last 1s/5s/60s:"); + poll(); + } + }); + } } -} +}); diff --git a/lib/load_gen/activities/signup.js b/lib/load_gen/activities/signup.js index 60b4edb514f3ad5151ae9a9f9c989c648835ad34..d628756660aef5bcddd024b478e40844defe0e8a 100644 --- a/lib/load_gen/activities/signup.js +++ b/lib/load_gen/activities/signup.js @@ -61,7 +61,8 @@ exports.startFunc = function(cfg, cb) { // stage them wcli.post(cfg, '/wsapi/stage_user', context, { email: email, - site: userdb.any(user.sites) + site: userdb.any(user.sites), + pass: user.password }, function (err, r) { if (err) return cb(err); if (r.code !== 200) return cb("can't stage user, non-200 response: " + r.code); @@ -74,7 +75,6 @@ exports.startFunc = function(cfg, cb) { // and simulate clickthrough wcli.post(cfg, '/wsapi/complete_user_creation', context, { token: r.body, - pass: user.password, ephemeral: false }, function (err, r) { try { diff --git a/lib/load_gen/common.js b/lib/load_gen/common.js index 1808e76f38347c7fe9d95890bf7b03c8640b6cca..59758e21e0bcb92fff08a0a4394bfb470a640dd8 100644 --- a/lib/load_gen/common.js +++ b/lib/load_gen/common.js @@ -80,27 +80,31 @@ exports.genAssertionAndVerify = function(cfg, user, ctx, email, audience, cb) { return cb(e.toString() + (r ? (" - " + r.body) : "")); } - var assertion = crypto.getAssertion({ + crypto.getAssertion({ now: t, secretKey: ctx.keys[email].keyPair.secretKey, cert: ctx.keys[email].cert, audience: audience, email: email - }); - - wcli.post(cfg, '/verify', {}, { - audience: assertion.audience, - assertion: assertion.assertion - }, function (err, r) { - try { - if (err) throw err; - if (r.code !== 200) throw "non-200 status: " + resp.code; - if (!JSON.parse(r.body).status === 'okay') throw "verification failed with: " + r.reason; - cb(undefined); - } catch(e) { - return cb("can't verify: " + e.toString()); + }, function(err, assertion) { + if (err) { + return cb("error getting assertion: " + err); } + + wcli.post(cfg, '/verify', {}, { + audience: assertion.audience, + assertion: assertion.assertion + }, function (err, r) { + try { + if (err) throw err; + if (r.code !== 200) throw "non-200 status: " + resp.code; + if (!JSON.parse(r.body).status === 'okay') throw "verification failed with: " + r.reason; + cb(undefined); + } catch(e) { + return cb("can't verify: " + e.toString()); + } + }); }); }); -} +}; diff --git a/lib/load_gen/crypto.js b/lib/load_gen/crypto.js index 85c00a77aeef641781a76fba878a278349e87389..8f4e220b8082d0d4130b7db256ac2b84687be257 100644 --- a/lib/load_gen/crypto.js +++ b/lib/load_gen/crypto.js @@ -7,25 +7,36 @@ const userDB = require('./user_db.js'), -jwk = require('jwcrypto/jwk.js'), -jwt = require('jwcrypto/jwt.js'), -vep = require('jwcrypto/vep.js'); +jwcrypto = require('jwcrypto'); -const NUM_KEYPAIRS = 5; +// load algorithms +require("jwcrypto/lib/algs/rs"); +require("jwcrypto/lib/algs/ds"); -process.stdout.write("generating " + NUM_KEYPAIRS + - " keypairs to be (re)used during load generation: "); +const NUM_KEYPAIRS = 5; var keyPairs = []; -while (keyPairs.length < NUM_KEYPAIRS) -{ - keyPairs.push(jwk.KeyPair.generate("DS", 256)); - process.stdout.write("."); -} - -process.stdout.write("\n"); - +exports.init = function(cb) { + process.stdout.write("generating " + NUM_KEYPAIRS + + " keypairs to be (re)used during load generation: "); + function next() { + if (keyPairs.length < NUM_KEYPAIRS) { + jwcrypto.generateKeypair( + {algorithm: "DS", keysize: 256}, + function(err, kp) { + if (err) return cb(err); + keyPairs.push(kp); + process.stdout.write("."); + next(); + }); + } else { + process.stdout.write("\n"); + cb(null); + } + } + next(); +}; exports.getKeyPair = function() { return userDB.any(keyPairs); @@ -33,7 +44,7 @@ exports.getKeyPair = function() { var assertions = []; -exports.getAssertion = function(obj) { +exports.getAssertion = function(obj, cb) { // we can memoize here, returning existing assertions to reduce // compute cost of loadgen client, to simulate more load on servers @@ -41,16 +52,23 @@ exports.getAssertion = function(obj) { // what email or RP is associated with the assertion, just that // it applies load. - function genAssertion() { + function genAssertion(cb) { var expirationDate = new Date(obj.now.getTime() + (2 * 60 * 1000)); - var tok = new jwt.JWT(null, expirationDate, obj.audience); - var assertion = vep.bundleCertsAndAssertion([obj.cert], tok.sign(obj.secretKey)); - - return { - audience: obj.audience, - assertion: assertion, - expirationDate: expirationDate - }; + jwcrypto.assertion.sign( + {}, + { + audience: obj.audience, + expiresAt: expirationDate + }, obj.secretKey, function(err, assertion) { + if (err) cb(err); + else { + cb(null, { + audience: obj.audience, + assertion: assertion, + expirationDate: expirationDate + }); + } + }); } if (assertions.length >= 30) { @@ -58,12 +76,16 @@ exports.getAssertion = function(obj) { var assertion = assertions[which]; // consider assertions which expire in the next minute stale if ((assertion.expirationDate - new Date()) < (60 * 1000)) { - assertion = assertions[which] = genAssertion(); + assertions.splice(which, 1); + } else { + return process.nextTick(function() { + return cb(null, assertions[which]); + }); } - return assertions[which]; } - var a = genAssertion(); - assertions.push(a); - return a; + genAssertion(function(err, a) { + assertions.push(a); + cb(err, a); + }); };