mirror of
https://github.com/balena-os/balena-supervisor.git
synced 2024-12-25 16:31:05 +00:00
Auto-merge for PR #463 via VersionBot
Allow registering the deviceApiKey in a non-compatible OS by making the apiKey equal the deviceApiKey, and add an fsync to all config.json writes
This commit is contained in:
commit
a6409f0e12
@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file
|
|||||||
automatically by Versionist. DO NOT EDIT THIS FILE MANUALLY!
|
automatically by Versionist. DO NOT EDIT THIS FILE MANUALLY!
|
||||||
This project adheres to [Semantic Versioning](http://semver.org/).
|
This project adheres to [Semantic Versioning](http://semver.org/).
|
||||||
|
|
||||||
|
## v5.0.1 - 2017-07-01
|
||||||
|
|
||||||
|
* Allow registering the deviceApiKey in a non-compatible OS by making the apiKey equal the deviceApiKey, and add an fsync to all config.json writes [Pablo Carranza Velez]
|
||||||
|
|
||||||
## v5.0.0 - 2017-06-26
|
## v5.0.0 - 2017-06-26
|
||||||
|
|
||||||
* Remove the undocumented and unused sideload and compose APIs [Pablo Carranza Velez]
|
* Remove the undocumented and unused sideload and compose APIs [Pablo Carranza Velez]
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "resin-supervisor",
|
"name": "resin-supervisor",
|
||||||
"description": "This is resin.io's Supervisor, a program that runs on IoT devices and has the task of running user Apps (which are Docker containers), and updating them as Resin's API informs it to.",
|
"description": "This is resin.io's Supervisor, a program that runs on IoT devices and has the task of running user Apps (which are Docker containers), and updating them as Resin's API informs it to.",
|
||||||
"version": "5.0.0",
|
"version": "5.0.1",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
@ -21,6 +21,15 @@ exports.ExchangeKeyError = class ExchangeKeyError extends TypedError
|
|||||||
|
|
||||||
bootstrapper = {}
|
bootstrapper = {}
|
||||||
|
|
||||||
|
writeAndSyncFile = (path, data) ->
|
||||||
|
fs.openAsync(path, 'w')
|
||||||
|
.then (fd) ->
|
||||||
|
fs.writeAsync(fd, data, 0, 'utf8')
|
||||||
|
.then ->
|
||||||
|
fs.fsyncAsync(fd)
|
||||||
|
.then ->
|
||||||
|
fs.closeAsync(fd)
|
||||||
|
|
||||||
loadPreloadedApps = ->
|
loadPreloadedApps = ->
|
||||||
devConfig = {}
|
devConfig = {}
|
||||||
knex('app').truncate()
|
knex('app').truncate()
|
||||||
@ -64,12 +73,16 @@ exchangeKey = ->
|
|||||||
.then (device) ->
|
.then (device) ->
|
||||||
if not device?
|
if not device?
|
||||||
throw new ExchangeKeyError("Couldn't fetch device with provisioning key")
|
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
|
# We found the device, we can try to register a working device key for it
|
||||||
request.postAsync("#{config.apiEndpoint}/api-key/device/#{device.id}/device-key?apikey=#{userConfig.apiKey}")
|
userConfig.deviceApiKey ?= deviceRegister.generateUniqueKey()
|
||||||
|
request.postAsync("#{config.apiEndpoint}/api-key/device/#{device.id}/device-key?apikey=#{userConfig.apiKey}", {
|
||||||
|
json: true
|
||||||
|
body:
|
||||||
|
apiKey: userConfig.deviceApiKey
|
||||||
|
})
|
||||||
.spread (res, body) ->
|
.spread (res, body) ->
|
||||||
if res.status != 200
|
if res.statusCode != 200
|
||||||
throw new ExchangeKeyError("Couldn't generate device key with provisioning key")
|
throw new ExchangeKeyError("Couldn't register device key with provisioning key")
|
||||||
userConfig.deviceApiKey = body
|
|
||||||
.return(device)
|
.return(device)
|
||||||
|
|
||||||
bootstrap = ->
|
bootstrap = ->
|
||||||
@ -100,9 +113,15 @@ bootstrap = ->
|
|||||||
.then ({ id }) ->
|
.then ({ id }) ->
|
||||||
userConfig.registered_at = Date.now()
|
userConfig.registered_at = Date.now()
|
||||||
userConfig.deviceId = id
|
userConfig.deviceId = id
|
||||||
# Delete the provisioning key now.
|
osRelease.getOSVersion(config.hostOSVersionPath)
|
||||||
delete userConfig.apiKey
|
.then (osVersion) ->
|
||||||
fs.writeFileAsync(configPath, JSON.stringify(userConfig))
|
# Delete the provisioning key now, only if the OS supports it
|
||||||
|
hasSupport = hasDeviceApiKeySupport(osVersion)
|
||||||
|
if hasSupport
|
||||||
|
delete userConfig.apiKey
|
||||||
|
else
|
||||||
|
userConfig.apiKey = userConfig.deviceApiKey
|
||||||
|
writeAndSyncFile(configPath, JSON.stringify(userConfig))
|
||||||
.return(userConfig)
|
.return(userConfig)
|
||||||
.then (userConfig) ->
|
.then (userConfig) ->
|
||||||
console.log('Finishing bootstrapping')
|
console.log('Finishing bootstrapping')
|
||||||
@ -132,7 +151,7 @@ generateRegistration = (forceReregister = false) ->
|
|||||||
else
|
else
|
||||||
userConfig.uuid ?= deviceRegister.generateUniqueKey()
|
userConfig.uuid ?= deviceRegister.generateUniqueKey()
|
||||||
userConfig.deviceApiKey ?= deviceRegister.generateUniqueKey()
|
userConfig.deviceApiKey ?= deviceRegister.generateUniqueKey()
|
||||||
fs.writeFileAsync(configPath, JSON.stringify(userConfig))
|
writeAndSyncFile(configPath, JSON.stringify(userConfig))
|
||||||
.return(userConfig.uuid)
|
.return(userConfig.uuid)
|
||||||
.catch (err) ->
|
.catch (err) ->
|
||||||
console.log('Error generating and saving UUID: ', err)
|
console.log('Error generating and saving UUID: ', err)
|
||||||
@ -148,26 +167,43 @@ bootstrapOrRetry = ->
|
|||||||
utils.mixpanelTrack('Device bootstrap failed, retrying', { error: err, delay: config.bootstrapRetryDelay })
|
utils.mixpanelTrack('Device bootstrap failed, retrying', { error: err, delay: config.bootstrapRetryDelay })
|
||||||
setTimeout(bootstrapOrRetry, config.bootstrapRetryDelay)
|
setTimeout(bootstrapOrRetry, config.bootstrapRetryDelay)
|
||||||
|
|
||||||
|
hasDeviceApiKeySupport = (osVersion) ->
|
||||||
|
try
|
||||||
|
!/^Resin OS /.test(osVersion) or semver.gte(semverRegex.test(osVersion), '2.0.2')
|
||||||
|
catch err
|
||||||
|
console.error('Unable to determine if device has deviceApiKey support', err, err.stack)
|
||||||
|
false
|
||||||
|
|
||||||
bootstrapper.done = new Promise (resolve) ->
|
bootstrapper.done = new Promise (resolve) ->
|
||||||
bootstrapper.doneBootstrapping = ->
|
bootstrapper.doneBootstrapping = ->
|
||||||
bootstrapper.bootstrapped = true
|
bootstrapper.bootstrapped = true
|
||||||
resolve(userConfig)
|
resolve(userConfig)
|
||||||
# If we're still using an old api key we can try to exchange it for a valid device key
|
# If we're still using an old api key we can try to exchange it for a valid device key
|
||||||
|
# This will only be the case when the supervisor/OS has been updated.
|
||||||
if userConfig.apiKey?
|
if userConfig.apiKey?
|
||||||
Promise.join(
|
# Only do a key exchange and delete the provisioning key if we're on a Resin OS version
|
||||||
osRelease.getOSVersion(config.hostOSVersionPath)
|
# that supports using the deviceApiKey (2.0.2 and above)
|
||||||
exchangeKey()
|
# or if we're in a non-Resin OS (which is assumed to be updated enough).
|
||||||
(osVersion) ->
|
# Otherwise VPN and other host services that use an API key will break.
|
||||||
# Only delete the provisioning key if we're on a Resin OS version that supports using the deviceApiKey (2.0.2 and above)
|
#
|
||||||
# or if we're in a non-Resin OS (which is assumed to be updated enough).
|
# In other cases, we make the apiKey equal the deviceApiKey instead.
|
||||||
# Otherwise VPN and other host services that use an API key will break.
|
osRelease.getOSVersion(config.hostOSVersionPath)
|
||||||
hasDeviceApiKeySupport = !/^Resin OS /.test(osVersion) or semver.gte(semverRegex.test(osVersion), '2.0.2')
|
.then (osVersion) ->
|
||||||
delete userConfig.apiKey if hasDeviceApiKeySupport
|
hasSupport = hasDeviceApiKeySupport(osVersion)
|
||||||
utils.setConfig('apiKey', userConfig.deviceApiKey)
|
if hasSupport or userConfig.apiKey != userConfig.deviceApiKey
|
||||||
|
console.log('Attempting key exchange')
|
||||||
|
exchangeKey()
|
||||||
.then ->
|
.then ->
|
||||||
fs.writeFileAsync(configPath, JSON.stringify(userConfig))
|
console.log('Key exchange succeeded, starting to use deviceApiKey')
|
||||||
)
|
if hasSupport
|
||||||
return
|
delete userConfig.apiKey
|
||||||
|
else
|
||||||
|
userConfig.apiKey = userConfig.deviceApiKey
|
||||||
|
utils.setConfig('apiKey', userConfig.deviceApiKey)
|
||||||
|
.then ->
|
||||||
|
writeAndSyncFile(configPath, JSON.stringify(userConfig))
|
||||||
|
# We return immediately, and eventually the API key will be exchanged and replaced.
|
||||||
|
return
|
||||||
|
|
||||||
bootstrapper.bootstrapped = false
|
bootstrapper.bootstrapped = false
|
||||||
bootstrapper.startBootstrapping = ->
|
bootstrapper.startBootstrapping = ->
|
||||||
|
Loading…
Reference in New Issue
Block a user