diff --git a/setup/start/sudoers b/setup/start/sudoers index 54edb4dbc..3f41023d6 100644 --- a/setup/start/sudoers +++ b/setup/start/sudoers @@ -25,9 +25,6 @@ yellowtent ALL=(root) NOPASSWD: /home/yellowtent/box/src/scripts/reboot.sh Defaults!/home/yellowtent/box/src/scripts/update.sh env_keep="HOME BOX_ENV" yellowtent ALL=(root) NOPASSWD: /home/yellowtent/box/src/scripts/update.sh -Defaults!/home/yellowtent/box/src/scripts/remotesupport.sh env_keep="HOME BOX_ENV" -yellowtent ALL=(root) NOPASSWD: /home/yellowtent/box/src/scripts/remotesupport.sh - Defaults!/home/yellowtent/box/src/scripts/configurelogrotate.sh env_keep="HOME BOX_ENV" yellowtent ALL=(root) NOPASSWD: /home/yellowtent/box/src/scripts/configurelogrotate.sh diff --git a/src/constants.js b/src/constants.js index 9c9cb8912..9741f694a 100644 --- a/src/constants.js +++ b/src/constants.js @@ -80,16 +80,13 @@ exports = module.exports = { SECRET_PLACEHOLDER: String.fromCharCode(0x25CF).repeat(8), // also used in dashboard client.js - CLOUDRON: CLOUDRON, - TEST: TEST, + CLOUDRON, + TEST, PORT25_CHECK_SERVER: 'port25check.cloudron.io', FORUM_URL: 'https://forum.cloudron.io', - SUPPORT_USERNAME: 'cloudron-support', - SUPPORT_EMAIL: 'support@cloudron.io', - USER_DIRECTORY_LDAP_DN: 'cn=admin,ou=system,dc=cloudron', FOOTER: '© %YEAR%   [Cloudron](https://cloudron.io)       [Forum ](https://forum.cloudron.io)', diff --git a/src/routes/index.js b/src/routes/index.js index 06e77fc16..349bc4935 100644 --- a/src/routes/index.js +++ b/src/routes/index.js @@ -28,7 +28,6 @@ exports = module.exports = { provision: require('./provision.js'), reverseProxy: require('./reverseproxy.js'), services: require('./services.js'), - support: require('./support.js'), system: require('./system.js'), tasks: require('./tasks.js'), tokens: require('./tokens.js'), diff --git a/src/routes/support.js b/src/routes/support.js deleted file mode 100644 index 9c8604a64..000000000 --- a/src/routes/support.js +++ /dev/null @@ -1,31 +0,0 @@ -'use strict'; - -exports = module.exports = { - getRemoteSupport, - enableRemoteSupport, -}; - -const assert = require('assert'), - AuditSource = require('../auditsource.js'), - HttpError = require('@cloudron/connect-lastmile').HttpError, - HttpSuccess = require('@cloudron/connect-lastmile').HttpSuccess, - safe = require('safetydance'), - support = require('../support.js'); - -async function enableRemoteSupport(req, res, next) { - assert.strictEqual(typeof req.body, 'object'); - - if (typeof req.body.enabled !== 'boolean') return next(new HttpError(400, 'enabled is required')); - - const [error] = await safe(support.enableRemoteSupport(req.body.enabled, AuditSource.fromRequest(req))); - if (error) return next(new HttpError(503, 'Error enabling remote support. Try running "cloudron-support --enable-remote-support" on the server')); - - next(new HttpSuccess(202, {})); -} - -async function getRemoteSupport(req, res, next) { - const [error, enabled] = await safe(support.getRemoteSupport()); - if (error) return next(new HttpError(500, error)); - - next(new HttpSuccess(200, { enabled })); -} diff --git a/src/routes/test/common.js b/src/routes/test/common.js index bd12ab3df..6e29807d8 100644 --- a/src/routes/test/common.js +++ b/src/routes/test/common.js @@ -14,7 +14,6 @@ const apps = require('../../apps.js'), safe = require('safetydance'), server = require('../../server.js'), settings = require('../../settings.js'), - support = require('../../support.js'), superagent = require('@cloudron/superagent'), tasks = require('../../tasks.js'), timers = require('timers/promises'), @@ -127,7 +126,6 @@ async function setup() { const owner = exports.owner, serverUrl = exports.serverUrl, user = exports.user, admin = exports.admin; await setupServer(); - await safe(fs.promises.unlink(support._sshInfo().filePath)); // setup let response = await superagent.post(`${serverUrl}/api/v1/provision/setup`) diff --git a/src/routes/test/support-test.js b/src/routes/test/support-test.js deleted file mode 100644 index ed2bbbbcd..000000000 --- a/src/routes/test/support-test.js +++ /dev/null @@ -1,86 +0,0 @@ -/* global it:false */ -/* global describe:false */ -/* global before:false */ -/* global after:false */ - -'use strict'; - -const common = require('./common.js'), - expect = require('expect.js'), - fs = require('fs'), - nock = require('nock'), - support = require('../../support.js'), - superagent = require('@cloudron/superagent'); - -describe('Support API', function () { - const { setup, cleanup, serverUrl, owner, mockApiServerOrigin, appstoreToken, user, admin } = common; - - before(setup); - before(() => { if (!nock.isActive()) nock.activate(); }); - after(cleanup); - - const authorizedKeysFile = support._sshInfo().filePath; - - describe('remote support', function () { - it('get remote support', async function () { - const response = await superagent.get(`${serverUrl}/api/v1/support/remote_support`) - .query({ access_token: owner.token }); - expect(response.status).to.equal(200); - expect(response.body.enabled).to.be(false); - }); - - it('enable remote support', async function () { - const response = await superagent.post(`${serverUrl}/api/v1/support/remote_support`) - .query({ access_token: owner.token }) - .send({ enabled: true }); - - expect(response.status).to.equal(202); - - let data = await fs.promises.readFile(authorizedKeysFile, 'utf8'); - let count = (data.match(/support@cloudron.io/g) || []).length; - expect(count).to.be(1); - }); - - it('returns true when remote support enabled', async function () { - const response = await superagent.get(`${serverUrl}/api/v1/support/remote_support`) - .query({ access_token: owner.token }); - expect(response.status).to.equal(200); - expect(response.body.enabled).to.be(true); - }); - - it('enable remote support (again)', async function () { - const response = await superagent.post(`${serverUrl}/api/v1/support/remote_support`) - .query({ access_token: owner.token }) - .send({ enabled: true }); - expect(response.status).to.equal(202); - - let data = await fs.promises.readFile(authorizedKeysFile, 'utf8'); - let count = (data.match(/support@cloudron.io/g) || []).length; - expect(count).to.be(1); - }); - - it('disable remote support', async function () { - const response = await superagent.post(`${serverUrl}/api/v1/support/remote_support`) - .query({ access_token: owner.token }) - .send({ enabled: false }); - - expect(response.status).to.equal(202); - - let data = await fs.promises.readFile(authorizedKeysFile, 'utf8'); - let count = (data.match(/support@cloudron.io/g) || []).length; - expect(count).to.be(0); - }); - - it('disable remote support (again)', async function () { - const response = await superagent.post(`${serverUrl}/api/v1/support/remote_support`) - .query({ access_token: owner.token }) - .send({ enabled: false }); - - expect(response.status).to.equal(202); - - const data = await fs.promises.readFile(authorizedKeysFile, 'utf8'); - const count = (data.match(/support@cloudron.io/g) || []).length; - expect(count).to.be(0); - }); - }); -}); diff --git a/src/scripts/remotesupport.sh b/src/scripts/remotesupport.sh deleted file mode 100755 index b74a2f4a4..000000000 --- a/src/scripts/remotesupport.sh +++ /dev/null @@ -1,45 +0,0 @@ -#!/bin/bash - -set -eu -o pipefail - -if [[ ${EUID} -ne 0 ]]; then - echo "This script should be run as root." > /dev/stderr - exit 1 -fi - -if [[ $# -eq 0 ]]; then - echo "No arguments supplied" - exit 1 -fi - -if [[ "$1" == "--check" ]]; then - echo "OK" - exit 0 -fi - -CLOUDRON_SUPPORT_PUBLIC_KEY="ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGWS+930b8QdzbchGljt3KSljH9wRhYvht8srrtQHdzg support@cloudron.io" - -cmd="$1" -keys_file="$2" -user="${3:-1000}" - -if [[ "$1" == "is-enabled" ]]; then - if grep -q "${CLOUDRON_SUPPORT_PUBLIC_KEY}" "${keys_file}"; then - echo "true" - else - echo "false" - fi -elif [[ "$1" == "enable" ]]; then - mkdir -p $(dirname "${keys_file}") # .ssh does not exist sometimes - touch "${keys_file}" # required for concat to work - if ! grep -q "${CLOUDRON_SUPPORT_PUBLIC_KEY}" "${keys_file}"; then - echo -e "\n${CLOUDRON_SUPPORT_PUBLIC_KEY}" >> "${keys_file}" - chmod 600 "${keys_file}" - chown "${user}" "${keys_file}" - fi -elif [[ "$1" == "disable" ]]; then - if [[ -f "${keys_file}" ]]; then - sed -e "/ support@cloudron.io$/d" -i "${keys_file}" - fi -fi - diff --git a/src/server.js b/src/server.js index 6e4d8a8d7..5602b229d 100644 --- a/src/server.js +++ b/src/server.js @@ -405,10 +405,6 @@ async function initializeExpressSync() { router.post('/api/v1/mail/:domain/lists/:name', json, token, authorizeMailManager, routes.mail.updateList); router.del ('/api/v1/mail/:domain/lists/:name', token, authorizeMailManager, routes.mail.delList); - // support routes - router.get ('/api/v1/support/remote_support', token, authorizeOwner, routes.support.getRemoteSupport); - router.post('/api/v1/support/remote_support', json, token, authorizeOwner, routes.support.enableRemoteSupport); - // domain routes router.post('/api/v1/domains', json, token, authorizeAdmin, routes.domains.add); router.post('/api/v1/domains/sync_dns', json, token, authorizeAdmin, routes.domains.syncDnsRecords); diff --git a/src/support.js b/src/support.js deleted file mode 100644 index aecb9ae07..000000000 --- a/src/support.js +++ /dev/null @@ -1,52 +0,0 @@ -'use strict'; - -exports = module.exports = { - getRemoteSupport, - enableRemoteSupport, - - _sshInfo: sshInfo -}; - -const assert = require('assert'), - BoxError = require('./boxerror.js'), - constants = require('./constants.js'), - eventlog = require('./eventlog.js'), - path = require('path'), - paths = require('./paths.js'), - safe = require('safetydance'), - shell = require('./shell.js')('support'); - -// the logic here is also used in the cloudron-support tool -const AUTHORIZED_KEYS_CMD = path.join(__dirname, 'scripts/remotesupport.sh'); - -function sshInfo() { - let filePath, user; - - if (constants.TEST) { - filePath = path.join(paths.baseDir(), 'authorized_keys'); - user = process.getuid(); - } else { - filePath = `/home/${constants.SUPPORT_USERNAME}/.ssh/authorized_keys`; - user = constants.SUPPORT_USERNAME; - } - - return { filePath, user }; -} - -async function getRemoteSupport() { - const [error, stdoutResult] = await safe(shell.promises.sudo([ AUTHORIZED_KEYS_CMD, 'is-enabled', sshInfo().filePath ], { captureStdout: true })); - if (error) throw new BoxError(BoxError.FS_ERROR, error); - - return stdoutResult.trim() === 'true'; -} - -async function enableRemoteSupport(enable, auditSource) { - assert.strictEqual(typeof enable, 'boolean'); - assert.strictEqual(typeof auditSource, 'object'); - - const si = sshInfo(); - const [error] = await safe(shell.promises.sudo([ AUTHORIZED_KEYS_CMD, enable ? 'enable' : 'disable', si.filePath, si.user ], {})); - if (error) throw new BoxError(BoxError.FS_ERROR, error); - - await eventlog.add(eventlog.ACTION_SUPPORT_SSH, auditSource, { enable }); -}