From b57dd10e81f64bf3bb18a741379adefdb3de0bda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Carranza=20V=C3=A9lez?= Date: Tue, 6 Oct 2015 19:55:01 +0000 Subject: [PATCH] Add API endpoint to expire and create new API key --- CHANGELOG.md | 1 + src/api.coffee | 26 +++++++++++++++++++++----- src/app.coffee | 2 +- src/utils.coffee | 35 ++++++++++++++++++++++------------- 4 files changed, 45 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a9451728..0a4657bd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,4 @@ +* Add API endpoint to expire and create new API key [Pablo] * Enable control of API poll interval through Device Variables [Praneeth] * Allow control of VPN + TCP check + Pub nub logs with Device Environment variables [Praneeth] * Add GO api for openvpn control [Praneeth] diff --git a/src/api.coffee b/src/api.coffee index 64605ccb..b5662a63 100644 --- a/src/api.coffee +++ b/src/api.coffee @@ -7,15 +7,21 @@ express = require 'express' bodyParser = require 'body-parser' request = require 'request' config = require './config' +device = require './device' -module.exports = (secret, application) -> +module.exports = (application) -> api = express() api.use(bodyParser()) api.use (req, res, next) -> - if req.query.apikey is secret - next() - else - res.sendStatus(401) + utils.getOrGenerateApiSecret() + .then (secret) -> + if req.query.apikey is secret + next() + else + res.sendStatus(401) + .catch (err) -> + # This should never happen... + res.status(503).send('Invalid API key in supervisor') api.get '/ping', (req, res) -> res.send('OK') @@ -120,4 +126,14 @@ module.exports = (secret, application) -> .catch (err) -> res.status(503).send(err?.message or err or 'Unknown error') + # Expires the supervisor's API key and generates a new one. + # It also communicates the new key to the Resin API. + api.post '/v1/regenerate-api-key', (req, res) -> + utils.newApiSecret() + .then (secret) -> + device.updateState(apikey: secret) + res.status(200).send(secret) + .catch (err) -> + res.status(503).send(err?.message or err or 'Unknown error') + return api diff --git a/src/app.coffee b/src/app.coffee index 294c2876..6a455aa9 100644 --- a/src/app.coffee +++ b/src/app.coffee @@ -25,7 +25,7 @@ knex.init.then -> bootstrap.done .then -> console.log('Starting API server..') - api(secret, application).listen(config.listenPort) + api(application).listen(config.listenPort) # Let API know what version we are, and our api connection info. console.log('Updating supervisor version and api info') device.updateState( diff --git a/src/utils.coffee b/src/utils.coffee index 2d8941b2..270ebe1e 100644 --- a/src/utils.coffee +++ b/src/utils.coffee @@ -101,19 +101,28 @@ exports.connectivityCheck = _.once -> console.log('Waiting for connectivity...') blink.pattern.start(networkPattern) -exports.getOrGenerateApiSecret = do -> - apiSecretPromise = null - return -> - apiSecretPromise ?= Promise.rejected() - apiSecretPromise = apiSecretPromise.catch -> - knex('config').select('value').where(key: 'apiSecret') - .then ([ apiSecret ]) -> - return apiSecret.value if apiSecret? - Promise.try -> - return config.forceApiSecret ? randomHexString.generate() - .then (newSecret) -> - knex('config').insert([{ key: 'apiSecret', value: newSecret }]) - .return(newSecret) + +apiSecretPromise = null +generateApiSecret = -> + Promise.try -> + return config.forceApiSecret ? randomHexString.generate() + .then (newSecret) -> + secretInDB = { key: 'apiSecret', value: newSecret } + knex('config').update(secretInDB).where(key: 'apiSecret') + .then (affectedRows) -> + knex('config').insert(secretInDB) if affectedRows == 0 + .return(newSecret) + +exports.newApiSecret = newApiSecret = -> + apiSecretPromise ?= Promise.resolve() + apiSecretPromise = apiSecretPromise.then -> + generateApiSecret() + +exports.getOrGenerateApiSecret = -> + apiSecretPromise ?= knex('config').select('value').where(key: 'apiSecret').then ([ apiSecret ]) -> + return apiSecret.value if apiSecret? + generateApiSecret() + return apiSecretPromise exports.extendEnvVars = (env, uuid) -> host = '127.0.0.1'