diff --git a/migrations/schema.sql b/migrations/schema.sql index c43afff35..9ac57a539 100644 --- a/migrations/schema.sql +++ b/migrations/schema.sql @@ -72,7 +72,6 @@ CREATE TABLE IF NOT EXISTS apps( createdAt TIMESTAMP(2) NOT NULL DEFAULT CURRENT_TIMESTAMP, updatedAt TIMESTAMP(2) NOT NULL DEFAULT CURRENT_TIMESTAMP, memoryLimit BIGINT DEFAULT 0, - altDomain VARCHAR(256), xFrameOptions VARCHAR(512), sso BOOLEAN DEFAULT 1, // whether user chose to enable SSO debugModeJson TEXT, // options for development mode diff --git a/src/addons.js b/src/addons.js index cab10e836..e9709e67c 100644 --- a/src/addons.js +++ b/src/addons.js @@ -250,7 +250,7 @@ function setupOauth(app, options, callback) { if (!app.sso) return callback(null); var appId = app.id; - var redirectURI = 'https://' + (app.altDomain || app.intrinsicFqdn); + var redirectURI = 'https://' + app.intrinsicFqdn; var scope = 'profile'; clients.delByAppIdAndType(appId, clients.TYPE_OAUTH, function (error) { // remove existing creds diff --git a/src/appdb.js b/src/appdb.js index 7588d7d73..2fe06ceb9 100644 --- a/src/appdb.js +++ b/src/appdb.js @@ -61,7 +61,7 @@ var assert = require('assert'), var APPS_FIELDS_PREFIXED = [ 'apps.id', 'apps.appStoreId', 'apps.installationState', 'apps.installationProgress', 'apps.runState', 'apps.health', 'apps.containerId', 'apps.manifestJson', 'apps.httpPort', 'apps.location', 'apps.domain', 'apps.dnsRecordId', 'apps.accessRestrictionJson', 'apps.restoreConfigJson', 'apps.oldConfigJson', 'apps.updateConfigJson', 'apps.memoryLimit', - 'apps.altDomain', 'apps.xFrameOptions', 'apps.sso', 'apps.debugModeJson', 'apps.robotsTxt', 'apps.enableBackup', + 'apps.xFrameOptions', 'apps.sso', 'apps.debugModeJson', 'apps.robotsTxt', 'apps.enableBackup', 'apps.creationTime', 'apps.updateTime' ].join(','); var PORT_BINDINGS_FIELDS = [ 'hostPort', 'environmentVariable', 'appId' ].join(','); @@ -196,7 +196,6 @@ function add(id, appStoreId, manifest, location, domain, portBindings, data, cal var accessRestriction = data.accessRestriction || null; var accessRestrictionJson = JSON.stringify(accessRestriction); var memoryLimit = data.memoryLimit || 0; - var altDomain = data.altDomain || null; var xFrameOptions = data.xFrameOptions || ''; var installationState = data.installationState || exports.ISTATE_PENDING_INSTALL; var restoreConfigJson = data.restoreConfig ? JSON.stringify(data.restoreConfig) : null; // used when cloning @@ -205,8 +204,8 @@ function add(id, appStoreId, manifest, location, domain, portBindings, data, cal var queries = []; queries.push({ - query: 'INSERT INTO apps (id, appStoreId, manifestJson, installationState, location, domain, accessRestrictionJson, memoryLimit, altDomain, xFrameOptions, restoreConfigJson, sso, debugModeJson) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', - args: [ id, appStoreId, manifestJson, installationState, location, domain, accessRestrictionJson, memoryLimit, altDomain, xFrameOptions, restoreConfigJson, sso, debugModeJson ] + query: 'INSERT INTO apps (id, appStoreId, manifestJson, installationState, location, domain, accessRestrictionJson, memoryLimit, xFrameOptions, restoreConfigJson, sso, debugModeJson) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', + args: [ id, appStoreId, manifestJson, installationState, location, domain, accessRestrictionJson, memoryLimit, xFrameOptions, restoreConfigJson, sso, debugModeJson ] }); Object.keys(portBindings).forEach(function (env) { diff --git a/src/apps.js b/src/apps.js index 29860370b..4481504ec 100644 --- a/src/apps.js +++ b/src/apps.js @@ -315,8 +315,7 @@ function getAppConfig(app) { accessRestriction: app.accessRestriction, portBindings: app.portBindings, memoryLimit: app.memoryLimit, - xFrameOptions: app.xFrameOptions || 'SAMEORIGIN', - altDomain: app.altDomain + xFrameOptions: app.xFrameOptions || 'SAMEORIGIN' }; } @@ -364,8 +363,7 @@ function get(appId, callback) { app.intrinsicFqdn = domains.fqdn(app.location, app.domain, result.provider); app.iconUrl = getIconUrlSync(app); - app.fqdn = app.altDomain || app.intrinsicFqdn; - app.cnameTarget = app.altDomain ? app.intrinsicFqdn : null; + app.fqdn = app.intrinsicFqdn; callback(null, app); }); @@ -388,8 +386,7 @@ function getByIpAddress(ip, callback) { app.intrinsicFqdn = domains.fqdn(app.location, app.domain, result.provider); app.iconUrl = getIconUrlSync(app); - app.fqdn = app.altDomain || app.intrinsicFqdn; - app.cnameTarget = app.altDomain ? app.intrinsicFqdn : null; + app.fqdn = app.intrinsicFqdn; callback(null, app); }); @@ -409,8 +406,7 @@ function getAll(callback) { app.intrinsicFqdn = domains.fqdn(app.location, app.domain, result.provider); app.iconUrl = getIconUrlSync(app); - app.fqdn = app.altDomain || app.intrinsicFqdn; - app.cnameTarget = app.altDomain ? app.intrinsicFqdn : null; + app.fqdn = app.intrinsicFqdn; iteratorDone(); }); @@ -468,7 +464,6 @@ function install(data, auditSource, callback) { cert = data.cert || null, key = data.key || null, memoryLimit = data.memoryLimit || 0, - altDomain = data.altDomain || null, xFrameOptions = data.xFrameOptions || 'SAMEORIGIN', sso = 'sso' in data ? data.sso : null, debugMode = data.debugMode || null, @@ -513,8 +508,6 @@ function install(data, auditSource, callback) { // if sso was unspecified, enable it by default if possible if (sso === null) sso = !!manifest.addons['ldap'] || !!manifest.addons['oauth']; - if (altDomain !== null && !validator.isFQDN(altDomain)) return callback(new AppsError(AppsError.BAD_FIELD, 'Invalid external domain')); - var appId = uuid.v4(); if (icon) { @@ -550,7 +543,6 @@ function install(data, auditSource, callback) { var data = { accessRestriction: accessRestriction, memoryLimit: memoryLimit, - altDomain: altDomain, xFrameOptions: xFrameOptions, sso: sso, debugMode: debugMode, @@ -605,11 +597,6 @@ function configure(appId, data, auditSource, callback) { if (error) return callback(error); } - if ('altDomain' in data) { - values.altDomain = data.altDomain; - if (values.altDomain !== null && !validator.isFQDN(values.altDomain)) return callback(new AppsError(AppsError.BAD_FIELD, 'Invalid external domain')); - } - if ('portBindings' in data) { portBindings = values.portBindings = data.portBindings; error = validatePortBindings(values.portBindings, app.manifest.tcpPorts); @@ -653,9 +640,9 @@ function configure(appId, data, auditSource, callback) { // save cert to boxdata/certs. TODO: move this to apptask when we have a real task queue if ('cert' in data && 'key' in data) { - if (data.cert && data.key) { - var vhost = values.altDomain || intrinsicFqdn; + var vhost = intrinsicFqdn; + if (data.cert && data.key) { error = reverseProxy.validateCertificate(vhost, data.cert, data.key); if (error) return callback(new AppsError(AppsError.BAD_CERTIFICATE, error.message)); diff --git a/src/apptask.js b/src/apptask.js index 7c72fdbab..c57ba5d2c 100644 --- a/src/apptask.js +++ b/src/apptask.js @@ -15,8 +15,7 @@ exports = module.exports = { _verifyManifest: verifyManifest, _registerSubdomain: registerSubdomain, _unregisterSubdomain: unregisterSubdomain, - _waitForDnsPropagation: waitForDnsPropagation, - _waitForAltDomainDnsPropagation: waitForAltDomainDnsPropagation + _waitForDnsPropagation: waitForDnsPropagation }; require('supererror')({ splatchError: true }); @@ -347,23 +346,6 @@ function waitForDnsPropagation(app, callback) { }); } -function waitForAltDomainDnsPropagation(app, callback) { - if (!app.altDomain) return callback(null); - - // try for 10 minutes before giving up. this allows the user to "reconfigure" the app in the case where - // an app has an external domain and cloudron is migrated to custom domain. - var isNakedDomain = tld.getDomain(app.altDomain) === app.altDomain; - if (isNakedDomain) { // check naked domains with A record since CNAME records don't work there - sysinfo.getPublicIp(function (error, ip) { - if (error) return callback(error); - - domains.waitForDNSRecord(app.altDomain, tld.getDomain(app.altDomain), ip, 'A', { interval: 10000, times: 60 }, callback); - }); - } else { - domains.waitForDNSRecord(app.altDomain, tld.getDomain(app.altDomain), app.intrinsicFqdn + '.', 'CNAME', { interval: 10000, times: 60 }, callback); - } -} - // Ordering is based on the following rationale: // - configure nginx, icon, oauth // - register subdomain. @@ -446,9 +428,6 @@ function install(app, callback) { updateApp.bind(null, app, { installationProgress: '85, Waiting for DNS propagation' }), exports._waitForDnsPropagation.bind(null, app), - updateApp.bind(null, app, { installationProgress: '90, Waiting for External Domain setup' }), - exports._waitForAltDomainDnsPropagation.bind(null, app), // required when restoring and !restoreConfig - updateApp.bind(null, app, { installationProgress: '95, Configuring reverse proxy' }), configureReverseProxy.bind(null, app), @@ -541,9 +520,6 @@ function configure(app, callback) { updateApp.bind(null, app, { installationProgress: '80, Waiting for DNS propagation' }), exports._waitForDnsPropagation.bind(null, app), - updateApp.bind(null, app, { installationProgress: '85, Waiting for External Domain setup' }), - exports._waitForAltDomainDnsPropagation.bind(null, app), - updateApp.bind(null, app, { installationProgress: '90, Configuring reverse proxy' }), configureReverseProxy.bind(null, app), diff --git a/src/backups.js b/src/backups.js index 2943cca62..6d9f037bb 100644 --- a/src/backups.js +++ b/src/backups.js @@ -720,7 +720,7 @@ function backupApp(app, callback) { const timestamp = (new Date()).toISOString().replace(/[T.]/g, '-').replace(/[:Z]/g,''); safe.fs.unlinkSync(paths.BACKUP_LOG_FILE); // start fresh log file - progress.set(progress.BACKUP, 10, 'Backing up ' + (app.altDomain || app.intrinsicFqdn)); + progress.set(progress.BACKUP, 10, 'Backing up ' + app.intrinsicFqdn); backupAppWithTimestamp(app, timestamp, function (error) { progress.set(progress.BACKUP, 100, error ? error.message : ''); @@ -747,12 +747,12 @@ function backupBoxAndApps(auditSource, callback) { var step = 100/(allApps.length+2); async.mapSeries(allApps, function iterator(app, iteratorCallback) { - progress.set(progress.BACKUP, step * processed, 'Backing up ' + (app.altDomain || app.intrinsicFqdn)); + progress.set(progress.BACKUP, step * processed, 'Backing up ' + app.intrinsicFqdn); ++processed; if (!app.enableBackup) { - progress.set(progress.BACKUP, step * processed, 'Skipped backup ' + (app.altDomain || app.intrinsicFqdn)); + progress.set(progress.BACKUP, step * processed, 'Skipped backup ' + app.intrinsicFqdn); return iteratorCallback(null, null); // nothing to backup } @@ -762,7 +762,7 @@ function backupBoxAndApps(auditSource, callback) { return iteratorCallback(error); } - progress.set(progress.BACKUP, step * processed, 'Backed up ' + (app.altDomain || app.intrinsicFqdn)); + progress.set(progress.BACKUP, step * processed, 'Backed up ' + app.intrinsicFqdn); iteratorCallback(null, backupId || null); // clear backupId if is in BAD_STATE and never backed up }); diff --git a/src/clients.js b/src/clients.js index a31488dcd..102efc250 100644 --- a/src/clients.js +++ b/src/clients.js @@ -191,7 +191,7 @@ function getAll(callback) { if (record.type === exports.TYPE_PROXY) record.name = result.manifest.title + ' Website Proxy'; if (record.type === exports.TYPE_OAUTH) record.name = result.manifest.title + ' OAuth'; - record.domain = result.altDomain || result.intrinsicFqdn; + record.domain = result.intrinsicFqdn; tmp.push(record); diff --git a/src/docker.js b/src/docker.js index b698d7b35..1e8dcbed4 100644 --- a/src/docker.js +++ b/src/docker.js @@ -129,7 +129,7 @@ function createSubcontainer(app, name, cmd, options, callback) { var manifest = app.manifest; var exposedPorts = {}, dockerPortBindings = { }; - var domain = app.altDomain || app.intrinsicFqdn; + var domain = app.intrinsicFqdn; var stdEnv = [ 'CLOUDRON=1', 'WEBADMIN_ORIGIN=' + config.adminOrigin(), diff --git a/src/domains.js b/src/domains.js index 5f5d6306b..72f3790ab 100644 --- a/src/domains.js +++ b/src/domains.js @@ -322,13 +322,9 @@ function waitForDNSRecord(fqdn, domain, value, type, options, callback) { assert.strictEqual(typeof callback, 'function'); get(domain, function (error, result) { - // domain can be not found when waiting for altDomain. When we migrate altDomain, this can never happen - if (error && error.reason !== DomainError.NOT_FOUND) return callback(new DomainError(DomainError.INTERNAL_ERROR, error)); + if (error) return callback(error); - // hack for lack of provider with altDomain. When we migrate altDomain, this will be automatically "manual" - const provider = result ? result.provider : 'manual'; - - api(provider).waitForDns(fqdn, result ? result.zoneName : domain, value, type, options, callback); + api(result.provider).waitForDns(fqdn, result ? result.zoneName : domain, value, type, options, callback); }); } diff --git a/src/reverseproxy.js b/src/reverseproxy.js index 61d40edec..ce085b81a 100644 --- a/src/reverseproxy.js +++ b/src/reverseproxy.js @@ -84,12 +84,11 @@ function getApi(app, callback) { if (domain.tlsConfig.provider === 'fallback') return callback(null, fallback, {}); - // use acme if we have altDomain or the tlsConfig is not caas - var api = (app.altDomain || domain.tlsConfig.provider !== 'caas') ? acme : caas; + var api = domain.tlsConfig.provider === 'caas' ? caas : acme; var options = { }; if (domain.tlsConfig.provider === 'caas') { - options.prod = true; // with altDomain, we will choose acme setting based on this + options.prod = true; } else { // acme options.prod = domain.tlsConfig.provider.match(/.*-prod/) !== null; // matches 'le-prod' or 'letsencrypt-prod' } @@ -220,7 +219,7 @@ function getCertificate(app, callback) { assert.strictEqual(typeof app, 'object'); assert.strictEqual(typeof callback, 'function'); - var vhost = app.altDomain || app.intrinsicFqdn; + var vhost = app.intrinsicFqdn; var certFilePath = path.join(paths.APP_CERTS_DIR, `${vhost}.user.cert`); var keyFilePath = path.join(paths.APP_CERTS_DIR, `${vhost}.user.key`); @@ -240,7 +239,7 @@ function ensureCertificate(app, auditSource, callback) { assert.strictEqual(typeof auditSource, 'object'); assert.strictEqual(typeof callback, 'function'); - var vhost = app.altDomain || app.intrinsicFqdn; + var vhost = app.intrinsicFqdn; var certFilePath = path.join(paths.APP_CERTS_DIR, `${vhost}.user.cert`); var keyFilePath = path.join(paths.APP_CERTS_DIR, `${vhost}.user.key`); @@ -278,7 +277,7 @@ function ensureCertificate(app, auditSource, callback) { eventlog.add(eventlog.ACTION_CERTIFICATE_RENEWAL, auditSource, { domain: vhost, errorMessage: errorMessage }); // if no cert was returned use fallback. the fallback/caas provider will not provide any for example - if (!certFilePath || !keyFilePath) return getFallbackCertificate(app.altDomain ? tld.getDomain(app.altDomain) : app.domain, callback); + if (!certFilePath || !keyFilePath) return getFallbackCertificate(app.domain, callback); callback(null, { certFilePath, keyFilePath, reason: 'new-le' }); }); @@ -329,7 +328,7 @@ function configureAppInternal(app, bundle, callback) { var sourceDir = path.resolve(__dirname, '..'); var endpoint = 'app'; - var vhost = app.altDomain || app.intrinsicFqdn; + var vhost = app.intrinsicFqdn; var data = { sourceDir: sourceDir, @@ -372,7 +371,7 @@ function unconfigureApp(app, callback) { assert.strictEqual(typeof app, 'object'); assert.strictEqual(typeof callback, 'function'); - var vhost = app.altDomain || app.intrinsicFqdn; + var vhost = app.intrinsicFqdn; var nginxConfigFilename = path.join(paths.NGINX_APPCONFIG_DIR, app.id + '.conf'); if (!safe.fs.unlinkSync(nginxConfigFilename)) { diff --git a/src/routes/apps.js b/src/routes/apps.js index bac1ccede..bbec688d1 100644 --- a/src/routes/apps.js +++ b/src/routes/apps.js @@ -58,8 +58,6 @@ function removeInternalAppFields(app) { iconUrl: app.iconUrl, fqdn: app.fqdn, memoryLimit: app.memoryLimit, - altDomain: app.altDomain, - cnameTarget: app.cnameTarget, xFrameOptions: app.xFrameOptions, sso: app.sso, debugMode: app.debugMode, @@ -134,9 +132,6 @@ function installApp(req, res, next) { if ('memoryLimit' in data && typeof data.memoryLimit !== 'number') return next(new HttpError(400, 'memoryLimit is not a number')); - // falsy value in altDomain unsets it - if (data.altDomain && typeof data.altDomain !== 'string') return next(new HttpError(400, 'altDomain must be a string')); - if (data.xFrameOptions && typeof data.xFrameOptions !== 'string') return next(new HttpError(400, 'xFrameOptions must be a string')); if ('sso' in data && typeof data.sso !== 'boolean') return next(new HttpError(400, 'sso must be a boolean')); @@ -181,7 +176,6 @@ function configureApp(req, res, next) { if (!data.cert && data.key) return next(new HttpError(400, 'cert must be provided')); if ('memoryLimit' in data && typeof data.memoryLimit !== 'number') return next(new HttpError(400, 'memoryLimit is not a number')); - if (data.altDomain && typeof data.altDomain !== 'string') return next(new HttpError(400, 'altDomain must be a string')); if (data.xFrameOptions && typeof data.xFrameOptions !== 'string') return next(new HttpError(400, 'xFrameOptions must be a string')); if ('enableBackup' in data && typeof data.enableBackup !== 'boolean') return next(new HttpError(400, 'enableBackup must be a boolean')); diff --git a/src/routes/oauth2.js b/src/routes/oauth2.js index 1dc6b4576..58741baa6 100644 --- a/src/routes/oauth2.js +++ b/src/routes/oauth2.js @@ -239,7 +239,7 @@ function loginForm(req, res) { apps.get(result.appId, function (error, result) { if (error) return sendErrorPageOrRedirect(req, res, 'Unknown Application for those OAuth credentials'); - var applicationName = result.altDomain || result.intrinsicFqdn; + var applicationName = result.intrinsicFqdn; render(applicationName, '/api/v1/apps/' + result.id + '/icon'); }); });