Ensure preloaded apps get the deviceApiKey in the env vars, and apps never get the provisioning key, and improve detection of cases when the device has been pre-provisioned

It appears preloaded apps have been getting restarted because the "apiKey" configuration value was only available after provisioning succeeded. This change ensures the
deviceApiKey that the device will use is injected into the env vars of preloaded apps, ensuring the app is not restarted (unless provisioning fails and the uuid and deviceApiKey are
regenerated, but this should be rare).

We also ensure that whenever an app's RESIN_API_KEY env var is populated, it is *always* done with the deviceApiKey and never with the provisioning apiKey.

Closes #457
Change-Type: patch
Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
This commit is contained in:
Pablo Carranza Velez 2017-10-20 13:47:19 -07:00
parent 99019c9034
commit d98897cdcf
3 changed files with 11 additions and 6 deletions

View File

@ -633,9 +633,9 @@ getRemoteState = (uuid, apiKey) ->
throw err
# TODO: Actually store and use app.environment and app.config separately
parseEnvAndFormatRemoteApps = (remoteApps, uuid, apiKey) ->
parseEnvAndFormatRemoteApps = (remoteApps, uuid, deviceApiKey) ->
appsWithEnv = _.mapValues remoteApps, (app, appId) ->
utils.extendEnvVars(app.environment, uuid, appId, app.name, app.commit)
utils.extendEnvVars(app.environment, uuid, deviceApiKey, appId, app.name, app.commit)
.then (env) ->
app.config ?= {}
return {
@ -716,7 +716,9 @@ application.update = update = (force, scheduled = false) ->
.then ->
utils.setConfig('name', local.name) if local.name != deviceName
.then ->
parseEnvAndFormatRemoteApps(local.apps, uuid, apiKey)
utils.getConfig('deviceApiKey')
.then (deviceApiKey) ->
parseEnvAndFormatRemoteApps(local.apps, uuid, deviceApiKey)
.then (remoteApps) ->
localApps = formatLocalApps(apps)
resourcesForUpdate = compareForUpdate(localApps, remoteApps)

View File

@ -40,7 +40,7 @@ loadPreloadedApps = ->
fs.readFileAsync(appsPath, 'utf8')
.then(JSON.parse)
.map (app) ->
utils.extendEnvVars(app.env, userConfig.uuid, app.appId, app.name, app.commit)
utils.extendEnvVars(app.env, userConfig.uuid, userConfig.deviceApiKey, app.appId, app.name, app.commit)
.then (extendedEnv) ->
app.env = JSON.stringify(extendedEnv)
_.merge(devConfig, app.config)
@ -135,6 +135,7 @@ bootstrap = ->
# We use the provisioning/user `apiKey` if it still exists because if it does it means we were already registered
# using that key and have to rely on the exchange key mechanism to swap the keys as appropriate later
{ key: 'apiKey', value: userConfig.apiKey ? userConfig.deviceApiKey }
{ key: 'deviceApiKey', value: userConfig.deviceApiKey }
{ key: 'username', value: userConfig.username }
{ key: 'userId', value: userConfig.userId }
{ key: 'version', value: utils.supervisorVersion }
@ -202,6 +203,8 @@ bootstrapper.done = new Promise (resolve) ->
delete userConfig.apiKey
else
userConfig.apiKey = userConfig.deviceApiKey
utils.setConfig('deviceApiKey', userConfig.deviceApiKey)
.then ->
utils.setConfig('apiKey', userConfig.deviceApiKey)
.then ->
writeAndSyncFile(configPath, JSON.stringify(userConfig))

View File

@ -155,7 +155,7 @@ exports.setConfig = (key, value = null) ->
.then (n) ->
knex('config').insert({ key, value }) if n == 0
exports.extendEnvVars = (env, uuid, appId, appName, commit) ->
exports.extendEnvVars = (env, uuid, apiKey, appId, appName, commit) ->
host = '127.0.0.1'
newEnv =
RESIN_APP_ID: appId.toString()
@ -170,7 +170,7 @@ exports.extendEnvVars = (env, uuid, appId, appName, commit) ->
RESIN_SUPERVISOR_PORT: config.listenPort
RESIN_SUPERVISOR_API_KEY: exports.getOrGenerateSecret('api')
RESIN_SUPERVISOR_VERSION: exports.supervisorVersion
RESIN_API_KEY: getConfig('apiKey')
RESIN_API_KEY: apiKey
RESIN: '1'
USER: 'root'
if env?