diff --git a/CHANGES b/CHANGES index 6a8590856..5e8476353 100644 --- a/CHANGES +++ b/CHANGES @@ -2731,4 +2731,5 @@ * dashboard: fix various UI elements hidden for admin user * directoryserver: fix totp validation * email: improve loading of the mail usage to not block other views from loading +* eventlog: add events for directory server and exernal directory configuration diff --git a/dashboard/src/js/client.js b/dashboard/src/js/client.js index ab09372d3..40e5277f0 100644 --- a/dashboard/src/js/client.js +++ b/dashboard/src/js/client.js @@ -3569,6 +3569,8 @@ angular.module('Application').service('Client', ['$http', '$interval', '$timeout var ACTION_DOMAIN_UPDATE = 'domain.update'; var ACTION_DOMAIN_REMOVE = 'domain.remove'; + var ACTION_EXTERNAL_LDAP_CONFIGURE = 'externalldap.configure'; + var ACTION_INSTALL_FINISH = 'cloudron.install.finish'; var ACTION_START = 'cloudron.start'; @@ -3835,6 +3837,13 @@ angular.module('Application').service('Client', ['$http', '$interval', '$timeout case ACTION_DOMAIN_REMOVE: return 'Domain ' + data.domain + ' was removed'; + case ACTION_EXTERNAL_LDAP_CONFIGURE: + if (data.config.provider === 'noop') { + return 'External Directory disabled'; + } else { + return 'External Directory set to ' + data.config.url + ' (' + data.config.provider + ')'; + } + case ACTION_INSTALL_FINISH: return 'Cloudron version ' + data.version + ' installed'; diff --git a/dashboard/src/views/eventlog.js b/dashboard/src/views/eventlog.js index c7bd7f98d..968b178e4 100644 --- a/dashboard/src/views/eventlog.js +++ b/dashboard/src/views/eventlog.js @@ -51,6 +51,7 @@ angular.module('Application').controller('EventLogController', ['$scope', '$loca { name: 'domain.add', value: 'domain.add' }, { name: 'domain.update', value: 'domain.update' }, { name: 'domain.remove', value: 'domain.remove' }, + { name: 'externalldap.configure', value: 'externalldap.configure' }, { name: 'mail.location', value: 'mail.location' }, { name: 'mail.enabled', value: 'mail.enabled' }, { name: 'mail.box.add', value: 'mail.box.add' }, diff --git a/src/eventlog.js b/src/eventlog.js index 33760f357..9585b8b29 100644 --- a/src/eventlog.js +++ b/src/eventlog.js @@ -47,6 +47,8 @@ exports = module.exports = { ACTION_DOMAIN_UPDATE: 'domain.update', ACTION_DOMAIN_REMOVE: 'domain.remove', + ACTION_EXTERNAL_LDAP_CONFIGURE: 'externalldap.configure', + ACTION_INSTALL_FINISH: 'cloudron.install.finish', ACTION_MAIL_LOCATION: 'mail.location', diff --git a/src/externalldap.js b/src/externalldap.js index d1bdb575c..9522e8ec8 100644 --- a/src/externalldap.js +++ b/src/externalldap.js @@ -19,6 +19,7 @@ const assert = require('assert'), BoxError = require('./boxerror.js'), constants = require('./constants.js'), debug = require('debug')('box:externalldap'), + eventlog = require('./eventlog.js'), groups = require('./groups.js'), ldap = require('ldapjs'), once = require('./once.js'), @@ -68,8 +69,9 @@ async function getConfig() { return config; } -async function setConfig(newConfig) { +async function setConfig(newConfig, auditSource) { assert.strictEqual(typeof newConfig, 'object'); + assert(auditSource && typeof auditSource === 'object'); if (constants.DEMO) throw new BoxError(BoxError.BAD_FIELD, 'Not allowed in demo mode'); @@ -83,6 +85,8 @@ async function setConfig(newConfig) { await settings.setJson(settings.EXTERNAL_LDAP_KEY, newConfig); if (newConfig.provider === 'noop') await users.resetSource(); // otherwise, the owner could be 'ldap' source and lock themselves out + + await eventlog.add(eventlog.ACTION_EXTERNAL_LDAP_CONFIGURE, auditSource, { oldConfig: removePrivateFields(currentConfig), config: removePrivateFields(newConfig) }); } // performs service bind if required diff --git a/src/routes/externalldap.js b/src/routes/externalldap.js index 63a7cc284..e677e1327 100644 --- a/src/routes/externalldap.js +++ b/src/routes/externalldap.js @@ -7,6 +7,7 @@ exports = module.exports = { }; const assert = require('assert'), + AuditSource = require('../auditsource.js'), BoxError = require('../boxerror.js'), externalLdap = require('../externalldap.js'), HttpError = require('connect-lastmile').HttpError, @@ -39,7 +40,7 @@ async function setConfig(req, res, next) { if ('bindDn' in req.body && typeof req.body.bindDn !== 'string') return next(new HttpError(400, 'bindDn must be a non empty string')); if ('bindPassword' in req.body && typeof req.body.bindPassword !== 'string') return next(new HttpError(400, 'bindPassword must be a string')); - const [error] = await safe(externalLdap.setConfig(req.body)); + const [error] = await safe(externalLdap.setConfig(req.body, AuditSource.fromRequest(req))); if (error) return next(BoxError.toHttpError(error)); next(new HttpSuccess(200, {})); diff --git a/src/test/externalldap-test.js b/src/test/externalldap-test.js index d0519c89a..965a624aa 100644 --- a/src/test/externalldap-test.js +++ b/src/test/externalldap-test.js @@ -183,7 +183,7 @@ function stopLdapServer(callback) { } describe('External LDAP', function () { - const { setup, cleanup, admin, serverUrl } = common; + const { setup, cleanup, admin, serverUrl, auditSource } = common; before(function (done) { async.series([ @@ -204,7 +204,7 @@ describe('External LDAP', function () { let conf = Object.assign({}, LDAP_CONFIG); delete conf.url; - const [error] = await safe(externalLdap.setConfig(conf)); + const [error] = await safe(externalLdap.setConfig(conf, auditSource)); expect(error.reason).to.equal(BoxError.BAD_FIELD); }); @@ -212,7 +212,7 @@ describe('External LDAP', function () { let conf = Object.assign({}, LDAP_CONFIG); conf.url = ''; - const [error] = await safe(externalLdap.setConfig(conf)); + const [error] = await safe(externalLdap.setConfig(conf, auditSource)); expect(error.reason).to.equal(BoxError.BAD_FIELD); }); @@ -220,7 +220,7 @@ describe('External LDAP', function () { let conf = Object.assign({}, LDAP_CONFIG); delete conf.baseDn; - const [error] = await safe(externalLdap.setConfig(conf)); + const [error] = await safe(externalLdap.setConfig(conf, auditSource)); expect(error.reason).to.equal(BoxError.BAD_FIELD); }); @@ -228,7 +228,7 @@ describe('External LDAP', function () { let conf = Object.assign({}, LDAP_CONFIG); conf.baseDn = ''; - const [error] = await safe(externalLdap.setConfig(conf)); + const [error] = await safe(externalLdap.setConfig(conf, auditSource)); expect(error.reason).to.equal(BoxError.BAD_FIELD); }); @@ -236,7 +236,7 @@ describe('External LDAP', function () { let conf = Object.assign({}, LDAP_CONFIG); delete conf.filter; - const [error] = await safe(externalLdap.setConfig(conf)); + const [error] = await safe(externalLdap.setConfig(conf, auditSource)); expect(error.reason).to.equal(BoxError.BAD_FIELD); }); @@ -244,16 +244,16 @@ describe('External LDAP', function () { let conf = Object.assign({}, LDAP_CONFIG); conf.filter = ''; - const [error] = await safe(externalLdap.setConfig(conf)); + const [error] = await safe(externalLdap.setConfig(conf, auditSource)); expect(error.reason).to.equal(BoxError.BAD_FIELD); }); it('enabling succeeds', async function () { - await externalLdap.setConfig(LDAP_CONFIG); + await externalLdap.setConfig(LDAP_CONFIG, auditSource); }); it('disabling succeeds', async function () { - await externalLdap.setConfig({ provider: 'noop' }); + await externalLdap.setConfig({ provider: 'noop' }, auditSource); }); // now test with groups @@ -262,7 +262,7 @@ describe('External LDAP', function () { conf.syncGroups = true; delete conf.groupBaseDn; - const [error] = await safe(externalLdap.setConfig(conf)); + const [error] = await safe(externalLdap.setConfig(conf, auditSource)); expect(error.reason).to.equal(BoxError.BAD_FIELD); }); @@ -271,7 +271,7 @@ describe('External LDAP', function () { conf.syncGroups = true; conf.groupBaseDn = ''; - const [error] = await safe(externalLdap.setConfig(conf)); + const [error] = await safe(externalLdap.setConfig(conf, auditSource)); expect(error.reason).to.equal(BoxError.BAD_FIELD); }); @@ -280,7 +280,7 @@ describe('External LDAP', function () { conf.syncGroups = true; delete conf.groupFilter; - const [error] = await safe(externalLdap.setConfig(conf)); + const [error] = await safe(externalLdap.setConfig(conf, auditSource)); expect(error.reason).to.equal(BoxError.BAD_FIELD); }); @@ -289,7 +289,7 @@ describe('External LDAP', function () { conf.syncGroups = true; conf.groupFilter = ''; - const [error] = await safe(externalLdap.setConfig(conf)); + const [error] = await safe(externalLdap.setConfig(conf, auditSource)); expect(error.reason).to.equal(BoxError.BAD_FIELD); }); @@ -298,7 +298,7 @@ describe('External LDAP', function () { conf.syncGroups = true; delete conf.groupnameField; - const [error] = await safe(externalLdap.setConfig(conf)); + const [error] = await safe(externalLdap.setConfig(conf, auditSource)); expect(error.reason).to.equal(BoxError.BAD_FIELD); }); @@ -307,7 +307,7 @@ describe('External LDAP', function () { conf.syncGroups = true; conf.groupnameField = ''; - const [error] = await safe(externalLdap.setConfig(conf)); + const [error] = await safe(externalLdap.setConfig(conf, auditSource)); expect(error.reason).to.equal(BoxError.BAD_FIELD); }); @@ -315,13 +315,13 @@ describe('External LDAP', function () { let conf = Object.assign({}, LDAP_CONFIG); conf.syncGroups = true; - await externalLdap.setConfig(conf); + await externalLdap.setConfig(conf, auditSource); }); }); describe('verifyPassword', function () { before(async function () { - await externalLdap.setConfig(LDAP_CONFIG); + await externalLdap.setConfig(LDAP_CONFIG, auditSource); gLdapUsers = [{ username: 'maximus', @@ -375,7 +375,7 @@ describe('External LDAP', function () { }); it('disable sync', async function () { - await externalLdap.setConfig({ provider: 'noop' }); + await externalLdap.setConfig({ provider: 'noop' }, auditSource); }); it('fails if disabled', async function () { @@ -384,7 +384,7 @@ describe('External LDAP', function () { }); it('enable', async function () { - await externalLdap.setConfig(LDAP_CONFIG); + await externalLdap.setConfig(LDAP_CONFIG, auditSource); }); it('succeeds for new users', async function () { @@ -439,7 +439,7 @@ describe('External LDAP', function () { it('enable with groupSync', async function () { let conf = Object.assign({}, LDAP_CONFIG); conf.syncGroups = true; - await externalLdap.setConfig(conf); + await externalLdap.setConfig(conf, auditSource); }); it('succeeds with groups enabled', async function () { @@ -537,7 +537,7 @@ describe('External LDAP', function () { after(server.stop); it('enable', async function () { - await externalLdap.setConfig(LDAP_CONFIG); + await externalLdap.setConfig(LDAP_CONFIG, auditSource); }); it('fails if auto create is disabled', async function () { @@ -562,7 +562,7 @@ describe('External LDAP', function () { it('enable auto create', async function () { let conf = Object.assign({}, LDAP_CONFIG); conf.autoCreate = true; - await externalLdap.setConfig(conf); + await externalLdap.setConfig(conf, auditSource); }); it('fails for unknown user', async function () {