#!/usr/bin/env node 'use strict'; var url = require('url'); var fs = require('fs'); var path = require('path'); var argv = process.argv.slice(2); var Wreck = require('wreck'); var _ = require('lodash'); var pg = require('pg'); var uuid = require('node-uuid'); var async = require('async'); var raqiaPath = path.join(__dirname, '..', 'raqia.json'); var code = argv[0]; if (!code) { console.log('Registers your machines with the Lamassu raqia.is API.'); console.log('Usage: ssu-raqia \n'); console.log('Please supply the code sent to you by Lamassu support.'); process.exit(1); } var apiKey, apiSecret; try { var buf = new Buffer(code, 'hex'); apiKey = uuid.unparse(buf); apiSecret = uuid.unparse(buf, 16); } catch(ex) { console.log('There was a problem with the code. Please contact Lamassu support.'); process.exit(2); } var psqlUrl; try { psqlUrl = process.env.DATABASE_URL || JSON.parse(fs.readFileSync('/etc/lamassu.json')).postgresql; } catch (ex) { psqlUrl = 'psql://lamassu:lamassu@localhost/lamassu'; } var client = new pg.Client(psqlUrl); client.connect(function(err) { if (err) return console.log(err); var sql = 'SELECT * FROM devices ORDER BY id'; client.query(sql, function(err, res) { if (err) return console.log(err); client.end(); var machines = _.pluck(res.rows, 'fingerprint'); var uri = url.format({ protocol: 'https', host: 'api.raqia.is', pathname: '/auth/users' }); var opts = { headers: headers(apiKey, apiSecret), json:true }; Wreck.get(uri, opts, function(err, res, payload) { if (err) return console.log(err.message); if (res.statusCode !== 200) return console.log('Could not connect to raqia.is: %d', res.statusCode); var configuredMachines = _(payload).pluck('fingerprint').compact().value(); var remainingMachines = _.difference(machines, configuredMachines); var users = {}; var zcUsers = _.filter(payload, zeroConfScopeOnly); if (zcUsers.length < remainingMachines.length) bail('You need more raqia users for your account. Please contact Lamassu support.'); _.forEach(configuredMachines, function(fingerprint) { var user = _.find(payload, {fingerprint: fingerprint}); users[fingerprint] = user; }); async.each(remainingMachines, function(fingerprint, cb) { var zcUser = zcUsers.pop(); users[fingerprint] = zcUser; updateUser(zcUser, fingerprint, cb); }, function(err) { if (err) bail(err.message); fs.writeFileSync(raqiaPath, JSON.stringify(users)); console.log('Success.'); } ); }); }); }); function updateUser(user, fingerprint, cb) { var uri = 'https://api.raqia.is/auth/users/' + user.userId; var opts = { json: true, payload: JSON.stringify({fingerprint: fingerprint}), headers: headers(apiKey, apiSecret) }; Wreck.post(uri, opts, function(err, res) { if (err) return cb(err); if (res.statusCode !== 200) return cb(new Error('Could not connect to raqia.is: ' + res.statusCode)); cb(); }); } function zeroConfScopeOnly(user) { return user.apiKeys[0].scope[0] === 'zero-conf' && user.apiKeys[0].scope.length === 1 && !user.fingerprint; } function headers(apiKey, apiSecret) { return { 'request-id': uuid.v4(), Authorization: 'Basic ' + buildAuth(apiKey, apiSecret) }; } function buildAuth(apiKey, apiSecret) { return new Buffer([apiKey, apiSecret].join(':')).toString('base64'); } function bail(msg) { console.log(msg); process.exit(1); }