diff --git a/src/apps.js b/src/apps.js index df54ecd6e..9a8d04ec8 100644 --- a/src/apps.js +++ b/src/apps.js @@ -296,7 +296,7 @@ function purchase(appStoreId, callback) { }); } -function install(appId, appStoreId, manifest, location, portBindings, accessRestriction, oauthProxy, icon, callback) { +function install(appId, appStoreId, manifest, location, portBindings, accessRestriction, oauthProxy, icon, cert, key, callback) { assert.strictEqual(typeof appId, 'string'); assert.strictEqual(typeof appStoreId, 'string'); assert(manifest && typeof manifest === 'object'); @@ -305,6 +305,8 @@ function install(appId, appStoreId, manifest, location, portBindings, accessRest assert.strictEqual(typeof accessRestriction, 'object'); assert.strictEqual(typeof oauthProxy, 'boolean'); assert(!icon || typeof icon === 'string'); + assert(cert === null || typeof cert === 'string'); + assert(key === null || typeof key === 'string'); assert.strictEqual(typeof callback, 'function'); var error = manifestFormat.parse(manifest); @@ -334,6 +336,9 @@ function install(appId, appStoreId, manifest, location, portBindings, accessRest } } + error = settings.validateCertificate(cert, key, config.appFqdn(location)); + if (error) return callback(new AppsError(AppsError.BAD_CERTIFICATE, error.message)); + debug('Will install app with id : ' + appId); purchase(appStoreId, function (error) { @@ -343,6 +348,12 @@ function install(appId, appStoreId, manifest, location, portBindings, accessRest if (error && error.reason === DatabaseError.ALREADY_EXISTS) return callback(getDuplicateErrorDetails(location.toLowerCase(), portBindings, error)); if (error) return callback(new AppsError(AppsError.INTERNAL_ERROR, error)); + // save cert to data/box/certs + if (cert && key) { + if (!safe.fs.writeFileSync(path.join(paths.APP_CERTS_DIR, config.appFqdn(location) + '.cert'), cert)) return callback(new AppsError(AppsError.INTERNAL_ERROR, 'Error saving cert: ' + safe.error.message)); + if (!safe.fs.writeFileSync(path.join(paths.APP_CERTS_DIR, config.appFqdn(location) + '.key'), key)) return callback(new AppsError(AppsError.INTERNAL_ERROR, 'Error saving key: ' + safe.error.message)); + } + taskmanager.restartAppTask(appId); callback(null); diff --git a/src/routes/apps.js b/src/routes/apps.js index 5d70d6aa4..22b344f6a 100644 --- a/src/routes/apps.js +++ b/src/routes/apps.js @@ -117,18 +117,23 @@ function installApp(req, res, next) { if (typeof data.accessRestriction !== 'object') return next(new HttpError(400, 'accessRestriction is required')); if (typeof data.oauthProxy !== 'boolean') return next(new HttpError(400, 'oauthProxy must be a boolean')); if ('icon' in data && typeof data.icon !== 'string') return next(new HttpError(400, 'icon is not a string')); + if (data.cert && typeof data.cert !== 'string') return next(new HttpError(400, 'cert must be a string')); + if (data.key && typeof data.key !== 'string') return next(new HttpError(400, 'key must be a string')); + if (data.cert && !data.key) return next(new HttpError(400, 'key must be provided')); + if (!data.cert && data.key) return next(new HttpError(400, 'cert must be provided')); // allow tests to provide an appId for testing var appId = (process.env.BOX_ENV === 'test' && typeof data.appId === 'string') ? data.appId : uuid.v4(); debug('Installing app id:%s storeid:%s loc:%s port:%j accessRestriction:%j oauthproxy:%s manifest:%j', appId, data.appStoreId, data.location, data.portBindings, data.accessRestriction, data.oauthProxy, data.manifest); - apps.install(appId, data.appStoreId, data.manifest, data.location, data.portBindings || null, data.accessRestriction, data.oauthProxy, data.icon || null, function (error) { + apps.install(appId, data.appStoreId, data.manifest, data.location, data.portBindings || null, data.accessRestriction, data.oauthProxy, data.icon || null, data.cert || null, data.key || null, function (error) { if (error && error.reason === AppsError.ALREADY_EXISTS) return next(new HttpError(409, error.message)); if (error && error.reason === AppsError.PORT_RESERVED) return next(new HttpError(409, 'Port ' + error.message + ' is reserved.')); if (error && error.reason === AppsError.PORT_CONFLICT) return next(new HttpError(409, 'Port ' + error.message + ' is already in use.')); if (error && error.reason === AppsError.BAD_FIELD) return next(new HttpError(400, error.message)); if (error && error.reason === AppsError.BILLING_REQUIRED) return next(new HttpError(402, 'Billing required')); + if (error && error.reason === AppsError.BAD_CERTIFICATE) return next(new HttpError(400, error.message)); if (error && error.reason === AppsError.USER_REQUIRED) return next(new HttpError(400, 'accessRestriction must specify one user')); if (error) return next(new HttpError(500, error));