Merge pull request #224 from resin-io/new-device-registering

Use the new device registration endpoint
This commit is contained in:
Page- 2017-04-22 14:58:19 -07:00 committed by GitHub
commit fdcb5f3dff
6 changed files with 100 additions and 41 deletions

View File

@ -16,7 +16,7 @@
"dependencies": {
"JSONStream": "^1.1.2",
"blinking": "~0.0.2",
"bluebird": "^3.0.0",
"bluebird": "^3.5.0",
"body-parser": "^1.12.0",
"buffer-equal-constant-time": "^1.0.1",
"docker-delta": "1.0.1",
@ -37,7 +37,7 @@
"pubnub": "^3.7.13",
"request": "^2.51.0",
"request-progress": "^2.0.1",
"resin-register-device": "^2.0.0",
"resin-register-device": "^3.0.0",
"rimraf": "^2.5.4",
"rwlock": "^5.0.0",
"sqlite3": "^3.1.0",

View File

@ -51,17 +51,17 @@ knex.init.then ->
)
)
updateIpAddr = ->
utils.gosuper.getAsync('/v1/ipaddr', { json: true })
.spread (response, body) ->
if response.statusCode == 200 && body.Data.IPAddresses?
device.updateState(
ip_address: body.Data.IPAddresses.join(' ')
)
.catch(_.noop)
console.log('Starting periodic check for IP addresses..')
setInterval(updateIpAddr, 30 * 1000) # Every 30s
updateIpAddr()
console.log('Starting Apps..')
application.initialize()
updateIpAddr = ->
utils.gosuper.getAsync('/v1/ipaddr', { json: true })
.spread (response, body) ->
if response.statusCode == 200 && body.Data.IPAddresses?
device.updateState(
ip_address: body.Data.IPAddresses.join(' ')
)
.catch(_.noop)
console.log('Starting periodic check for IP addresses..')
setInterval(updateIpAddr, 30 * 1000) # Every 30s
updateIpAddr()

View File

@ -2,17 +2,18 @@ Promise = require 'bluebird'
knex = require './db'
utils = require './utils'
deviceRegister = require 'resin-register-device'
{ resinApi } = require './request'
{ resinApi, request } = require './request'
fs = Promise.promisifyAll(require('fs'))
config = require './config'
configPath = '/boot/config.json'
appsPath = '/boot/apps.json'
_ = require 'lodash'
deviceConfig = require './device-config'
TypedError = require 'typed-error'
userConfig = {}
DuplicateUuidError = (err) ->
return err.message == '"uuid" must be unique.'
DuplicateUuidError = message: '"uuid" must be unique.'
exports.ExchangeKeyError = class ExchangeKeyError extends TypedError
bootstrapper = {}
@ -34,27 +35,71 @@ loadPreloadedApps = ->
.catch (err) ->
utils.mixpanelTrack('Loading preloaded apps failed', { error: err })
exchangeKey = ->
resinApi.get
resource: 'device'
options:
filter:
uuid: userConfig.uuid
customOptions:
apikey: userConfig.apiKey
.catchReturn([])
.timeout(config.apiTimeout)
.then ([ device ]) ->
if not device?
throw new ExchangeKeyError("Couldn't fetch device with provisioning key")
# We found the device, we can try to generate a working device key for it
request.postAsync("#{config.apiEndpoint}/api-key/device/#{device.id}/device-key")
.spread (res, body) ->
if res.status != 200
throw new ExchangeKeyError("Couldn't generate device key with provisioning key")
userConfig.deviceApiKey = body
.return(device)
bootstrap = ->
Promise.try ->
userConfig.deviceType ?= 'raspberry-pi'
if userConfig.registered_at?
return userConfig
deviceRegister.register(resinApi, userConfig)
deviceRegister.register(
userId: userConfig.userId
applicationId: userConfig.applicationId
uuid: userConfig.uuid
deviceType: userConfig.deviceType
deviceApiKey: userConfig.deviceApiKey
provisioningApiKey: userConfig.apiKey
apiEndpoint: config.apiEndpoint
)
.timeout(config.apiTimeout)
.catch DuplicateUuidError, ->
console.log('UUID already registered, checking if our device key is valid for it')
resinApi.get
resource: 'device'
options:
filter:
uuid: userConfig.uuid
customOptions:
apikey: userConfig.apiKey
apikey: userConfig.deviceApiKey
.catchReturn([])
.timeout(config.apiTimeout)
.then ([ device ]) ->
return device
.then (device) ->
if device?
console.log('Fetched device, all is good')
return device
# If we couldn't fetch with the device key then we can try to key exchange in case the provisioning key is an old 'user-api-key'
console.log("Couldn't fetch the device, trying to exchange for a valid key")
exchangeKey()
.tapCatch ExchangeKeyError, (err) ->
# If it fails we just have to reregister as a provisioning key doesn't have the ability to change existing devices
console.log('Exchanging key failed, having to reregister')
generateRegistration(true)
.then (device) ->
.then ({ id }) ->
userConfig.registered_at = Date.now()
userConfig.deviceId = device.id
userConfig.deviceId = id
# Delete the provisioning key now.
delete userConfig.apiKey
fs.writeFileAsync(configPath, JSON.stringify(userConfig))
.return(userConfig)
.then (userConfig) ->
@ -63,7 +108,7 @@ bootstrap = ->
.then ->
knex('config').insert([
{ key: 'uuid', value: userConfig.uuid }
{ key: 'apiKey', value: userConfig.apiKey }
{ key: 'apiKey', value: userConfig.deviceApiKey }
{ key: 'username', value: userConfig.username }
{ key: 'userId', value: userConfig.userId }
{ key: 'version', value: utils.supervisorVersion }
@ -75,19 +120,21 @@ readConfig = ->
fs.readFileAsync(configPath, 'utf8')
.then(JSON.parse)
readConfigAndEnsureUUID = ->
generateRegistration = (forceReregister = false) ->
Promise.try ->
return userConfig.uuid if userConfig.uuid?
deviceRegister.generateUUID()
.then (uuid) ->
userConfig.uuid = uuid
fs.writeFileAsync(configPath, JSON.stringify(userConfig))
.return(uuid)
if forceReregister
userConfig.uuid = deviceRegister.generateUniqueKey()
userConfig.deviceApiKey = deviceRegister.generateUniqueKey()
else
userConfig.uuid ?= deviceRegister.generateUniqueKey()
userConfig.deviceApiKey ?= deviceRegister.generateUniqueKey()
fs.writeFileAsync(configPath, JSON.stringify(userConfig))
.return(userConfig.uuid)
.catch (err) ->
console.log('Error generating and saving UUID: ', err)
Promise.delay(config.bootstrapRetryDelay)
.then ->
readConfigAndEnsureUUID()
generateRegistration()
bootstrapOrRetry = ->
utils.mixpanelTrack('Device bootstrap')
@ -101,6 +148,15 @@ bootstrapper.done = new Promise (resolve) ->
bootstrapper.doneBootstrapping = ->
bootstrapper.bootstrapped = true
resolve(userConfig)
# If we're still using an old api key we can try to exchange it for a valid device key
if userConfig.apiKey?
exchangeKey()
.then ->
delete userConfig.apiKey
knex('config').update(value: userConfig.deviceApiKey).where(key: 'apiKey')
.then ->
fs.writeFileAsync(configPath, JSON.stringify(userConfig))
bootstrapper.bootstrapped = false
bootstrapper.startBootstrapping = ->
@ -115,13 +171,16 @@ bootstrapper.startBootstrapping = ->
bootstrapper.doneBootstrapping() if !bootstrapper.offlineMode
return uuid.value
console.log('New device detected. Bootstrapping..')
readConfigAndEnsureUUID()
generateRegistration()
.tap ->
loadPreloadedApps()
.tap (uuid) ->
if bootstrapper.offlineMode
return knex('config').insert({ key: 'uuid', value: uuid })
else
return bootstrapOrRetry()
bootstrapOrRetry()
# Don't wait on bootstrapping here, bootstrapper.done is for that.
return
module.exports = bootstrapper

View File

@ -21,10 +21,10 @@ exports.getID = memoizePromise ->
bootstrap.done
.then ->
Promise.all([
knex('config').select('value').where(key: 'apiKey')
knex('config').select('value').where(key: 'uuid')
utils.getConfig('apiKey')
utils.getConfig('uuid')
])
.spread ([{ value: apiKey }], [{ value: uuid }]) ->
.spread (apiKey, uuid) ->
resinApi.get(
resource: 'device'
options:
@ -178,9 +178,9 @@ do ->
if _.size(stateDiff) is 0
return
applyPromise = Promise.join(
knex('config').select('value').where(key: 'apiKey')
utils.getConfig('apiKey')
device.getID()
([{ value: apiKey }], deviceID) ->
(apiKey, deviceID) ->
stateDiff = getStateDiff()
if _.size(stateDiff) is 0 || !apiKey?
return

View File

@ -50,9 +50,9 @@ router.post '/v1/devices', (req, res) ->
utils.getConfig('apiKey')
utils.getConfig('userId')
device.getID()
deviceRegister.generateUUID()
randomHexString.generate()
(apiKey, userId, deviceId, uuid, logsChannel) ->
(apiKey, userId, deviceId, logsChannel) ->
uuid = deviceRegister.generateUniqueKey()
d =
user: userId
application: req.body.appId

View File

@ -7,7 +7,7 @@ while true; do
echo "UUID missing from config file, VPN cannot connect"
sleep 2
else
read uuid api_key <<<$(jq -r '.uuid,.apiKey' $CONFIG_PATH)
read uuid api_key <<<$(jq -r '.uuid,.deviceApiKey // .apiKey' $CONFIG_PATH)
mkdir -p /var/volatile/
echo $uuid > /var/volatile/vpnfile
echo $api_key >> /var/volatile/vpnfile