settings: move externaldap setting

This commit is contained in:
Girish Ramakrishnan
2023-08-03 02:06:07 +05:30
parent a19e502198
commit 4a34c390f8
9 changed files with 164 additions and 160 deletions
+88 -63
View File
@@ -1,13 +1,14 @@
'use strict';
exports = module.exports = {
getConfig,
setConfig,
verifyPassword,
maybeCreateUser,
testConfig,
startSyncer,
injectPrivateFields,
removePrivateFields,
sync
@@ -58,25 +59,49 @@ function validUserRequirements(user) {
}
}
async function getConfig() {
const value = await settings.get(settings.EXTERNAL_LDAP_KEY);
if (value === null) return { provider: 'noop', autoCreate: false };
const config = JSON.parse(value);
if (!config.autoCreate) config.autoCreate = false; // ensure new keys
return config;
}
async function setConfig(newConfig) {
assert.strictEqual(typeof newConfig, 'object');
if (settings.isDemo()) throw new BoxError(BoxError.BAD_FIELD, 'Not allowed in demo mode');
const currentConfig = await getConfig();
injectPrivateFields(newConfig, currentConfig);
const error = await testConfig(newConfig);
if (error) throw error;
await settings.set(settings.EXTERNAL_LDAP_KEY, JSON.stringify(newConfig));
}
// performs service bind if required
async function getClient(externalLdapConfig, options) {
assert.strictEqual(typeof externalLdapConfig, 'object');
async function getClient(config, options) {
assert.strictEqual(typeof config, 'object');
assert.strictEqual(typeof options, 'object');
// basic validation to not crash
try { ldap.parseDN(externalLdapConfig.baseDn); } catch (e) { throw new BoxError(BoxError.BAD_FIELD, 'invalid baseDn'); }
try { ldap.parseFilter(externalLdapConfig.filter); } catch (e) { throw new BoxError(BoxError.BAD_FIELD, 'invalid filter'); }
const config = {
url: externalLdapConfig.url,
tlsOptions: {
rejectUnauthorized: externalLdapConfig.acceptSelfSignedCerts ? false : true
}
};
try { ldap.parseDN(config.baseDn); } catch (e) { throw new BoxError(BoxError.BAD_FIELD, 'invalid baseDn'); }
try { ldap.parseFilter(config.filter); } catch (e) { throw new BoxError(BoxError.BAD_FIELD, 'invalid filter'); }
let client;
try {
client = ldap.createClient(config);
const ldapConfig = {
url: config.url,
tlsOptions: {
rejectUnauthorized: config.acceptSelfSignedCerts ? false : true
}
};
client = ldap.createClient(ldapConfig);
} catch (e) {
if (e instanceof ldap.ProtocolError) throw new BoxError(BoxError.BAD_FIELD, 'url protocol is invalid');
throw new BoxError(BoxError.INTERNAL_ERROR, e);
@@ -92,9 +117,9 @@ async function getClient(externalLdapConfig, options) {
});
// skip bind auth if none exist or if not wanted
if (!externalLdapConfig.bindDn || !options.bind) return resolve(client);
if (!config.bindDn || !options.bind) return resolve(client);
client.bind(externalLdapConfig.bindDn, externalLdapConfig.bindPassword, function (error) {
client.bind(config.bindDn, config.bindPassword, function (error) {
if (error instanceof ldap.InvalidCredentialsError) return reject(new BoxError(BoxError.INVALID_CREDENTIALS));
if (error) return reject(new BoxError(BoxError.EXTERNAL_ERROR, error));
@@ -130,8 +155,8 @@ async function clientSearch(client, dn, searchOptions) {
});
}
async function ldapGetByDN(externalLdapConfig, dn) {
assert.strictEqual(typeof externalLdapConfig, 'object');
async function ldapGetByDN(config, dn) {
assert.strictEqual(typeof config, 'object');
assert.strictEqual(typeof dn, 'string');
const searchOptions = {
@@ -141,7 +166,7 @@ async function ldapGetByDN(externalLdapConfig, dn) {
debug(`ldapGetByDN: Get object at ${dn}`);
const client = await getClient(externalLdapConfig, { bind: true });
const client = await getClient(config, { bind: true });
const result = await clientSearch(client, dn, searchOptions);
client.unbind();
if (result.length === 0) throw new BoxError(BoxError.NOT_FOUND);
@@ -149,13 +174,13 @@ async function ldapGetByDN(externalLdapConfig, dn) {
}
// TODO support search by email
async function ldapUserSearch(externalLdapConfig, options) {
assert.strictEqual(typeof externalLdapConfig, 'object');
async function ldapUserSearch(config, options) {
assert.strictEqual(typeof config, 'object');
assert.strictEqual(typeof options, 'object');
const searchOptions = {
paged: true,
filter: ldap.parseFilter(externalLdapConfig.filter),
filter: ldap.parseFilter(config.filter),
scope: 'sub' // We may have to make this configurable
};
@@ -164,14 +189,14 @@ async function ldapUserSearch(externalLdapConfig, options) {
searchOptions.filter = new ldap.AndFilter({ filters: [ extraFilter, searchOptions.filter ] });
}
const client = await getClient(externalLdapConfig, { bind: true });
const result = await clientSearch(client, externalLdapConfig.baseDn, searchOptions);
const client = await getClient(config, { bind: true });
const result = await clientSearch(client, config.baseDn, searchOptions);
client.unbind();
return result;
}
async function ldapGroupSearch(externalLdapConfig, options) {
assert.strictEqual(typeof externalLdapConfig, 'object');
async function ldapGroupSearch(config, options) {
assert.strictEqual(typeof config, 'object');
assert.strictEqual(typeof options, 'object');
const searchOptions = {
@@ -179,15 +204,15 @@ async function ldapGroupSearch(externalLdapConfig, options) {
scope: 'sub' // We may have to make this configurable
};
if (externalLdapConfig.groupFilter) searchOptions.filter = ldap.parseFilter(externalLdapConfig.groupFilter);
if (config.groupFilter) searchOptions.filter = ldap.parseFilter(config.groupFilter);
if (options.filter) { // https://github.com/ldapjs/node-ldapjs/blob/master/docs/filters.md
const extraFilter = ldap.parseFilter(options.filter);
searchOptions.filter = new ldap.AndFilter({ filters: [ extraFilter, searchOptions.filter ] });
}
const client = await getClient(externalLdapConfig, { bind: true });
const result = await clientSearch(client, externalLdapConfig.groupBaseDn, searchOptions);
const client = await getClient(config, { bind: true });
const result = await clientSearch(client, config.groupBaseDn, searchOptions);
client.unbind();
return result;
}
@@ -239,15 +264,15 @@ async function testConfig(config) {
async function maybeCreateUser(identifier) {
assert.strictEqual(typeof identifier, 'string');
const externalLdapConfig = await settings.getExternalLdapConfig();
if (externalLdapConfig.provider === 'noop') throw new BoxError(BoxError.BAD_STATE, 'not enabled');
if (!externalLdapConfig.autoCreate) throw new BoxError(BoxError.BAD_STATE, 'auto create not enabled');
const config = await getConfig();
if (config.provider === 'noop') throw new BoxError(BoxError.BAD_STATE, 'not enabled');
if (!config.autoCreate) throw new BoxError(BoxError.BAD_STATE, 'auto create not enabled');
const ldapUsers = await ldapUserSearch(externalLdapConfig, { filter: `${externalLdapConfig.usernameField}=${identifier}` });
const ldapUsers = await ldapUserSearch(config, { filter: `${config.usernameField}=${identifier}` });
if (ldapUsers.length === 0) throw new BoxError(BoxError.NOT_FOUND);
if (ldapUsers.length > 1) throw new BoxError(BoxError.CONFLICT);
const user = translateUser(externalLdapConfig, ldapUsers[0]);
const user = translateUser(config, ldapUsers[0]);
if (!validUserRequirements(user)) throw new BoxError(BoxError.BAD_FIELD);
return await users.add(user.email, { username: user.username, password: null, displayName: user.displayName, source: 'ldap' }, AuditSource.EXTERNAL_LDAP_AUTO_CREATE);
@@ -258,14 +283,14 @@ async function verifyPassword(user, password, totpToken) {
assert.strictEqual(typeof password, 'string');
assert(totpToken === null || typeof totpToken === 'string');
const externalLdapConfig = await settings.getExternalLdapConfig();
if (externalLdapConfig.provider === 'noop') throw new BoxError(BoxError.BAD_STATE, 'not enabled');
const config = await getConfig();
if (config.provider === 'noop') throw new BoxError(BoxError.BAD_STATE, 'not enabled');
const ldapUsers = await ldapUserSearch(externalLdapConfig, { filter: `${externalLdapConfig.usernameField}=${user.username}` });
const ldapUsers = await ldapUserSearch(config, { filter: `${config.usernameField}=${user.username}` });
if (ldapUsers.length === 0) throw new BoxError(BoxError.NOT_FOUND);
if (ldapUsers.length > 1) throw new BoxError(BoxError.CONFLICT);
const client = await getClient(externalLdapConfig, { bind: false });
const client = await getClient(config, { bind: false });
let userAuthDn;
if (totpToken) {
@@ -281,12 +306,12 @@ async function verifyPassword(user, password, totpToken) {
if (error instanceof ldap.InvalidCredentialsError) throw new BoxError(BoxError.INVALID_CREDENTIALS);
if (error) throw new BoxError(BoxError.EXTERNAL_ERROR, error);
return translateUser(externalLdapConfig, ldapUsers[0]);
return translateUser(config, ldapUsers[0]);
}
async function startSyncer() {
const externalLdapConfig = await settings.getExternalLdapConfig();
if (externalLdapConfig.provider === 'noop') throw new BoxError(BoxError.BAD_STATE, 'not enabled');
const config = await getConfig();
if (config.provider === 'noop') throw new BoxError(BoxError.BAD_STATE, 'not enabled');
const taskId = await tasks.add(tasks.TASK_SYNC_EXTERNAL_LDAP, []);
@@ -297,11 +322,11 @@ async function startSyncer() {
return taskId;
}
async function syncUsers(externalLdapConfig, progressCallback) {
assert.strictEqual(typeof externalLdapConfig, 'object');
async function syncUsers(config, progressCallback) {
assert.strictEqual(typeof config, 'object');
assert.strictEqual(typeof progressCallback, 'function');
const ldapUsers = await ldapUserSearch(externalLdapConfig, {});
const ldapUsers = await ldapUserSearch(config, {});
debug(`syncUsers: Found ${ldapUsers.length} users`);
@@ -310,7 +335,7 @@ async function syncUsers(externalLdapConfig, progressCallback) {
// we ignore all errors here and just log them for now
for (let i = 0; i < ldapUsers.length; i++) {
let ldapUser = translateUser(externalLdapConfig, ldapUsers[i]);
let ldapUser = translateUser(config, ldapUsers[i]);
if (!validUserRequirements(ldapUser)) continue;
percent += step;
@@ -342,17 +367,17 @@ async function syncUsers(externalLdapConfig, progressCallback) {
debug('syncUsers: done');
}
async function syncGroups(externalLdapConfig, progressCallback) {
assert.strictEqual(typeof externalLdapConfig, 'object');
async function syncGroups(config, progressCallback) {
assert.strictEqual(typeof config, 'object');
assert.strictEqual(typeof progressCallback, 'function');
if (!externalLdapConfig.syncGroups) {
if (!config.syncGroups) {
debug('syncGroups: Group sync is disabled');
progressCallback({ percent: 70, message: 'Skipping group sync...' });
return [];
}
const ldapGroups = await ldapGroupSearch(externalLdapConfig, {});
const ldapGroups = await ldapGroupSearch(config, {});
debug(`syncGroups: Found ${ldapGroups.length} groups`);
@@ -361,7 +386,7 @@ async function syncGroups(externalLdapConfig, progressCallback) {
// we ignore all non internal errors here and just log them for now
for (const ldapGroup of ldapGroups) {
let groupName = ldapGroup[externalLdapConfig.groupnameField];
let groupName = ldapGroup[config.groupnameField];
if (!groupName) return;
// some servers return empty array for unknown properties :-/
if (typeof groupName !== 'string') return;
@@ -387,11 +412,11 @@ async function syncGroups(externalLdapConfig, progressCallback) {
debug('syncGroups: sync done');
}
async function syncGroupUsers(externalLdapConfig, progressCallback) {
assert.strictEqual(typeof externalLdapConfig, 'object');
async function syncGroupUsers(config, progressCallback) {
assert.strictEqual(typeof config, 'object');
assert.strictEqual(typeof progressCallback, 'function');
if (!externalLdapConfig.syncGroups) {
if (!config.syncGroups) {
debug('syncGroupUsers: Group users sync is disabled');
progressCallback({ percent: 99, message: 'Skipping group users sync...' });
return [];
@@ -404,7 +429,7 @@ async function syncGroupUsers(externalLdapConfig, progressCallback) {
for (const group of ldapGroups) {
debug(`syncGroupUsers: Sync users for group ${group.name}`);
const result = await ldapGroupSearch(externalLdapConfig, {});
const result = await ldapGroupSearch(config, {});
if (!result || result.length === 0) {
debug(`syncGroupUsers: Unable to find group ${group.name} ignoring for now.`);
continue;
@@ -412,8 +437,8 @@ async function syncGroupUsers(externalLdapConfig, progressCallback) {
// since our group names are lowercase we cannot use potentially case matching ldap filters
let found = result.find(function (r) {
if (!r[externalLdapConfig.groupnameField]) return false;
return r[externalLdapConfig.groupnameField].toLowerCase() === group.name;
if (!r[config.groupnameField]) return false;
return r[config.groupnameField].toLowerCase() === group.name;
});
if (!found) {
@@ -429,7 +454,7 @@ async function syncGroupUsers(externalLdapConfig, progressCallback) {
debug(`syncGroupUsers: Group ${group.name} has ${ldapGroupMembers.length} members.`);
for (const memberDn of ldapGroupMembers) {
const [ldapError, result] = await safe(ldapGetByDN(externalLdapConfig, memberDn));
const [ldapError, result] = await safe(ldapGetByDN(config, memberDn));
if (ldapError) {
debug(`syncGroupUsers: Failed to get ${memberDn}: %o`, ldapError);
continue;
@@ -437,7 +462,7 @@ async function syncGroupUsers(externalLdapConfig, progressCallback) {
debug(`syncGroupUsers: Found member object at ${memberDn} adding to group ${group.name}`);
const username = result[externalLdapConfig.usernameField].toLowerCase();
const username = result[config.usernameField].toLowerCase();
if (!username) continue;
const [getError, userObject] = await safe(users.getByUsername(username));
@@ -459,12 +484,12 @@ async function sync(progressCallback) {
progressCallback({ percent: 10, message: 'Starting ldap user sync' });
const externalLdapConfig = await settings.getExternalLdapConfig();
if (externalLdapConfig.provider === 'noop') throw new BoxError(BoxError.BAD_STATE, 'not enabled');
const config = await getConfig();
if (config.provider === 'noop') throw new BoxError(BoxError.BAD_STATE, 'not enabled');
await syncUsers(externalLdapConfig, progressCallback);
await syncGroups(externalLdapConfig, progressCallback);
await syncGroupUsers(externalLdapConfig, progressCallback);
await syncUsers(config, progressCallback);
await syncGroups(config, progressCallback);
await syncGroupUsers(config, progressCallback);
progressCallback({ percent: 100, message: 'Done' });
-9
View File
@@ -24,7 +24,6 @@ exports = module.exports = {
getServerIpv4,
getServerIpv6,
getLanguages,
syncExternalLdap,
syncDnsRecords,
getSystemGraphs,
getPlatformStatus,
@@ -38,7 +37,6 @@ const assert = require('assert'),
constants = require('../constants.js'),
debug = require('debug')('box:routes/cloudron'),
eventlog = require('../eventlog.js'),
externalLdap = require('../externalldap.js'),
graphs = require('../graphs.js'),
HttpError = require('connect-lastmile').HttpError,
HttpSuccess = require('connect-lastmile').HttpSuccess,
@@ -311,13 +309,6 @@ async function renewCerts(req, res, next) {
next(new HttpSuccess(202, { taskId }));
}
async function syncExternalLdap(req, res, next) {
const [error, taskId] = await safe(externalLdap.startSyncer());
if (error) return next(new HttpError(500, error.message));
next(new HttpSuccess(202, { taskId }));
}
async function getServerIpv4(req, res, next) {
const [error, ipv4] = await safe(sysinfo.getServerIPv4());
if (error) return next(BoxError.toHttpError(error));
+46
View File
@@ -0,0 +1,46 @@
'use strict';
exports = module.exports = {
getConfig,
setConfig,
sync
};
const assert = require('assert'),
BoxError = require('../boxerror.js'),
externalLdap = require('../externalldap.js'),
HttpError = require('connect-lastmile').HttpError,
HttpSuccess = require('connect-lastmile').HttpSuccess,
safe = require('safetydance');
async function sync(req, res, next) {
const [error, taskId] = await safe(externalLdap.startSyncer());
if (error) return next(new HttpError(500, error.message));
next(new HttpSuccess(202, { taskId }));
}
async function getConfig(req, res, next) {
const [error, config] = await safe(externalLdap.getConfig());
if (error) return next(BoxError.toHttpError(error));
next(new HttpSuccess(200, externalLdap.removePrivateFields(config)));
}
async function setConfig(req, res, next) {
assert.strictEqual(typeof req.body, 'object');
if (!req.body.provider || typeof req.body.provider !== 'string') return next(new HttpError(400, 'provider must be a string'));
if ('url' in req.body && typeof req.body.url !== 'string') return next(new HttpError(400, 'url must be a string'));
if ('baseDn' in req.body && typeof req.body.baseDn !== 'string') return next(new HttpError(400, 'baseDn must be a string'));
if ('usernameField' in req.body && typeof req.body.usernameField !== 'string') return next(new HttpError(400, 'usernameField must be a string'));
if ('filter' in req.body && typeof req.body.filter !== 'string') return next(new HttpError(400, 'filter must be a string'));
if ('groupBaseDn' in req.body && typeof req.body.groupBaseDn !== 'string') return next(new HttpError(400, 'groupBaseDn must be a string'));
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));
if (error) return next(BoxError.toHttpError(error));
next(new HttpSuccess(200, {}));
}
+1
View File
@@ -11,6 +11,7 @@ exports = module.exports = {
cloudron: require('./cloudron.js'),
domains: require('./domains.js'),
eventlog: require('./eventlog.js'),
externalLdap: require('./externalldap.js'),
filemanager: require('./filemanager.js'),
groups: require('./groups.js'),
mail: require('./mail.js'),
-28
View File
@@ -12,7 +12,6 @@ const assert = require('assert'),
backups = require('../backups.js'),
BoxError = require('../boxerror.js'),
docker = require('../docker.js'),
externalLdap = require('../externalldap.js'),
HttpError = require('connect-lastmile').HttpError,
HttpSuccess = require('connect-lastmile').HttpSuccess,
safe = require('safetydance'),
@@ -110,31 +109,6 @@ async function setBackupConfig(req, res, next) {
next(new HttpSuccess(200, {}));
}
async function getExternalLdapConfig(req, res, next) {
const [error, config] = await safe(settings.getExternalLdapConfig());
if (error) return next(BoxError.toHttpError(error));
next(new HttpSuccess(200, externalLdap.removePrivateFields(config)));
}
async function setExternalLdapConfig(req, res, next) {
assert.strictEqual(typeof req.body, 'object');
if (!req.body.provider || typeof req.body.provider !== 'string') return next(new HttpError(400, 'provider must be a string'));
if ('url' in req.body && typeof req.body.url !== 'string') return next(new HttpError(400, 'url must be a string'));
if ('baseDn' in req.body && typeof req.body.baseDn !== 'string') return next(new HttpError(400, 'baseDn must be a string'));
if ('usernameField' in req.body && typeof req.body.usernameField !== 'string') return next(new HttpError(400, 'usernameField must be a string'));
if ('filter' in req.body && typeof req.body.filter !== 'string') return next(new HttpError(400, 'filter must be a string'));
if ('groupBaseDn' in req.body && typeof req.body.groupBaseDn !== 'string') return next(new HttpError(400, 'groupBaseDn must be a string'));
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(settings.setExternalLdapConfig(req.body));
if (error) return next(BoxError.toHttpError(error));
next(new HttpSuccess(200, {}));
}
async function getDirectoryServerConfig(req, res, next) {
const [error, config] = await safe(settings.getDirectoryServerConfig());
if (error) return next(BoxError.toHttpError(error));
@@ -278,7 +252,6 @@ function get(req, res, next) {
case settings.BACKUP_POLICY_KEY: return getBackupPolicy(req, res, next);
case settings.IPV6_CONFIG_KEY: return getIPv6Config(req, res, next);
case settings.BACKUP_CONFIG_KEY: return getBackupConfig(req, res, next);
case settings.EXTERNAL_LDAP_KEY: return getExternalLdapConfig(req, res, next);
case settings.DIRECTORY_SERVER_KEY: return getDirectoryServerConfig(req, res, next);
case settings.REGISTRY_CONFIG_KEY: return getRegistryConfig(req, res, next);
case settings.SYSINFO_CONFIG_KEY: return getSysinfoConfig(req, res, next);
@@ -299,7 +272,6 @@ function set(req, res, next) {
switch (req.params.setting) {
case settings.BACKUP_POLICY_KEY: return setBackupPolicy(req, res, next);
case settings.IPV6_CONFIG_KEY: return setIPv6Config(req, res, next);
case settings.EXTERNAL_LDAP_KEY: return setExternalLdapConfig(req, res, next);
case settings.DIRECTORY_SERVER_KEY: return setDirectoryServerConfig(req, res, next);
case settings.REGISTRY_CONFIG_KEY: return setRegistryConfig(req, res, next);
case settings.SYSINFO_CONFIG_KEY: return setSysinfoConfig(req, res, next);
+5 -1
View File
@@ -127,7 +127,6 @@ async function initializeExpressSync() {
router.get ('/api/v1/cloudron/logstream/:unit', token, authorizeAdmin, routes.cloudron.getLogStream);
router.get ('/api/v1/cloudron/eventlog', token, authorizeAdmin, routes.eventlog.list);
router.get ('/api/v1/cloudron/eventlog/:eventId', token, authorizeAdmin, routes.eventlog.get);
router.post('/api/v1/cloudron/sync_external_ldap', json, token, authorizeAdmin, routes.cloudron.syncExternalLdap);
router.get ('/api/v1/cloudron/server_ipv4', token, authorizeAdmin, routes.cloudron.getServerIpv4);
router.get ('/api/v1/cloudron/server_ipv6', token, authorizeAdmin, routes.cloudron.getServerIpv6);
@@ -203,6 +202,11 @@ async function initializeExpressSync() {
router.post('/api/v1/groups/:groupId', json, token, authorizeUserManager, routes.groups.update);
router.del ('/api/v1/groups/:groupId', token, authorizeUserManager, routes.groups.remove);
// External LDAP
router.get ('/api/v1/external_ldap/config', token, authorizeAdmin, routes.externalLdap.getConfig);
router.post('/api/v1/external_ldap/config', json, token, authorizeAdmin, routes.externalLdap.setConfig);
router.post('/api/v1/external_ldap/sync', json, token, authorizeAdmin, routes.externalLdap.sync);
// appstore and subscription routes
router.post('/api/v1/appstore/register_cloudron', json, token, authorizeOwner, routes.appstore.registerCloudron);
router.get ('/api/v1/appstore/web_token', json, token, authorizeOwner, routes.appstore.getWebToken);
+1 -35
View File
@@ -19,9 +19,6 @@ exports = module.exports = {
getServicesConfig,
setServicesConfig,
getExternalLdapConfig,
setExternalLdapConfig,
getDirectoryServerConfig,
setDirectoryServerConfig,
@@ -126,7 +123,6 @@ const assert = require('assert'),
debug = require('debug')('box:settings'),
directoryServer = require('./directoryserver.js'),
docker = require('./docker.js'),
externalLdap = require('./externalldap.js'),
moment = require('moment-timezone'),
mounts = require('./mounts.js'),
paths = require('./paths.js'),
@@ -160,10 +156,6 @@ const gDefaults = (function () {
schedule: '00 00 23 * * *' // every day at 11pm
};
result[exports.SERVICES_CONFIG_KEY] = {};
result[exports.EXTERNAL_LDAP_KEY] = {
provider: 'noop',
autoCreate: false
};
result[exports.DIRECTORY_SERVER_KEY] = {
enabled: false,
secret: '',
@@ -376,32 +368,6 @@ async function setServicesConfig(platformConfig) {
notifyChange(exports.SERVICES_CONFIG_KEY, platformConfig);
}
async function getExternalLdapConfig() {
const value = await get(exports.EXTERNAL_LDAP_KEY);
if (value === null) return gDefaults[exports.EXTERNAL_LDAP_KEY];
const config = JSON.parse(value);
if (!config.autoCreate) config.autoCreate = false; // ensure new keys
return config;
}
async function setExternalLdapConfig(externalLdapConfig) {
assert.strictEqual(typeof externalLdapConfig, 'object');
if (isDemo()) throw new BoxError(BoxError.BAD_FIELD, 'Not allowed in demo mode');
const currentConfig = await getExternalLdapConfig();
externalLdap.injectPrivateFields(externalLdapConfig, currentConfig);
const error = await externalLdap.testConfig(externalLdapConfig);
if (error) throw error;
await set(exports.EXTERNAL_LDAP_KEY, JSON.stringify(externalLdapConfig));
notifyChange(exports.EXTERNAL_LDAP_KEY, externalLdapConfig);
}
async function getDirectoryServerConfig() {
const value = await get(exports.DIRECTORY_SERVER_KEY);
if (value === null) return gDefaults[exports.DIRECTORY_SERVER_KEY];
@@ -534,7 +500,7 @@ async function list() {
// convert JSON objects
[exports.BACKUP_POLICY_KEY, exports.BACKUP_CONFIG_KEY, exports.IPV6_CONFIG_KEY, exports.PROFILE_CONFIG_KEY, exports.SERVICES_CONFIG_KEY,
exports.EXTERNAL_LDAP_KEY, exports.REGISTRY_CONFIG_KEY, exports.SYSINFO_CONFIG_KEY, exports.REVERSE_PROXY_CONFIG_KEY ].forEach(function (key) {
exports.REGISTRY_CONFIG_KEY, exports.SYSINFO_CONFIG_KEY, exports.REVERSE_PROXY_CONFIG_KEY ].forEach(function (key) {
result[key] = typeof result[key] === 'object' ? result[key] : safe.JSON.parse(result[key]);
});
+20 -21
View File
@@ -14,7 +14,6 @@ const async = require('async'),
ldap = require('ldapjs'),
safe = require('safetydance'),
server = require('../server.js'),
settings = require('../settings.js'),
superagent = require('superagent'),
users = require('../users.js');
@@ -195,7 +194,7 @@ describe('External LDAP', function () {
let conf = Object.assign({}, LDAP_CONFIG);
delete conf.url;
const [error] = await safe(settings.setExternalLdapConfig(conf));
const [error] = await safe(externalLdap.setConfig(conf));
expect(error.reason).to.equal(BoxError.BAD_FIELD);
});
@@ -203,7 +202,7 @@ describe('External LDAP', function () {
let conf = Object.assign({}, LDAP_CONFIG);
conf.url = '';
const [error] = await safe(settings.setExternalLdapConfig(conf));
const [error] = await safe(externalLdap.setConfig(conf));
expect(error.reason).to.equal(BoxError.BAD_FIELD);
});
@@ -211,7 +210,7 @@ describe('External LDAP', function () {
let conf = Object.assign({}, LDAP_CONFIG);
delete conf.baseDn;
const [error] = await safe(settings.setExternalLdapConfig(conf));
const [error] = await safe(externalLdap.setConfig(conf));
expect(error.reason).to.equal(BoxError.BAD_FIELD);
});
@@ -219,7 +218,7 @@ describe('External LDAP', function () {
let conf = Object.assign({}, LDAP_CONFIG);
conf.baseDn = '';
const [error] = await safe(settings.setExternalLdapConfig(conf));
const [error] = await safe(externalLdap.setConfig(conf));
expect(error.reason).to.equal(BoxError.BAD_FIELD);
});
@@ -227,7 +226,7 @@ describe('External LDAP', function () {
let conf = Object.assign({}, LDAP_CONFIG);
delete conf.filter;
const [error] = await safe(settings.setExternalLdapConfig(conf));
const [error] = await safe(externalLdap.setConfig(conf));
expect(error.reason).to.equal(BoxError.BAD_FIELD);
});
@@ -235,16 +234,16 @@ describe('External LDAP', function () {
let conf = Object.assign({}, LDAP_CONFIG);
conf.filter = '';
const [error] = await safe(settings.setExternalLdapConfig(conf));
const [error] = await safe(externalLdap.setConfig(conf));
expect(error.reason).to.equal(BoxError.BAD_FIELD);
});
it('enabling succeeds', async function () {
await settings.setExternalLdapConfig(LDAP_CONFIG);
await externalLdap.setConfig(LDAP_CONFIG);
});
it('disabling succeeds', async function () {
await settings.setExternalLdapConfig({ provider: 'noop' });
await externalLdap.setConfig({ provider: 'noop' });
});
// now test with groups
@@ -253,7 +252,7 @@ describe('External LDAP', function () {
conf.syncGroups = true;
delete conf.groupBaseDn;
const [error] = await safe(settings.setExternalLdapConfig(conf));
const [error] = await safe(externalLdap.setConfig(conf));
expect(error.reason).to.equal(BoxError.BAD_FIELD);
});
@@ -262,7 +261,7 @@ describe('External LDAP', function () {
conf.syncGroups = true;
conf.groupBaseDn = '';
const [error] = await safe(settings.setExternalLdapConfig(conf));
const [error] = await safe(externalLdap.setConfig(conf));
expect(error.reason).to.equal(BoxError.BAD_FIELD);
});
@@ -271,7 +270,7 @@ describe('External LDAP', function () {
conf.syncGroups = true;
delete conf.groupFilter;
const [error] = await safe(settings.setExternalLdapConfig(conf));
const [error] = await safe(externalLdap.setConfig(conf));
expect(error.reason).to.equal(BoxError.BAD_FIELD);
});
@@ -280,7 +279,7 @@ describe('External LDAP', function () {
conf.syncGroups = true;
conf.groupFilter = '';
const [error] = await safe(settings.setExternalLdapConfig(conf));
const [error] = await safe(externalLdap.setConfig(conf));
expect(error.reason).to.equal(BoxError.BAD_FIELD);
});
@@ -289,7 +288,7 @@ describe('External LDAP', function () {
conf.syncGroups = true;
delete conf.groupnameField;
const [error] = await safe(settings.setExternalLdapConfig(conf));
const [error] = await safe(externalLdap.setConfig(conf));
expect(error.reason).to.equal(BoxError.BAD_FIELD);
});
@@ -298,7 +297,7 @@ describe('External LDAP', function () {
conf.syncGroups = true;
conf.groupnameField = '';
const [error] = await safe(settings.setExternalLdapConfig(conf));
const [error] = await safe(externalLdap.setConfig(conf));
expect(error.reason).to.equal(BoxError.BAD_FIELD);
});
@@ -306,13 +305,13 @@ describe('External LDAP', function () {
let conf = Object.assign({}, LDAP_CONFIG);
conf.syncGroups = true;
await settings.setExternalLdapConfig(conf);
await externalLdap.setConfig(conf);
});
});
describe('sync', function () {
it('disable sync', async function () {
await settings.setExternalLdapConfig({ provider: 'noop' });
await externalLdap.setConfig({ provider: 'noop' });
});
it('fails if disabled', async function () {
@@ -321,7 +320,7 @@ describe('External LDAP', function () {
});
it('enable', async function () {
await settings.setExternalLdapConfig(LDAP_CONFIG);
await externalLdap.setConfig(LDAP_CONFIG);
});
it('succeeds for new users', async function () {
@@ -376,7 +375,7 @@ describe('External LDAP', function () {
it('enable with groupSync', async function () {
let conf = Object.assign({}, LDAP_CONFIG);
conf.syncGroups = true;
await settings.setExternalLdapConfig(conf);
await externalLdap.setConfig(conf);
});
it('succeeds with groups enabled', async function () {
@@ -474,7 +473,7 @@ describe('External LDAP', function () {
after(server.stop);
it('enable', async function () {
await settings.setExternalLdapConfig(LDAP_CONFIG);
await externalLdap.setConfig(LDAP_CONFIG);
});
it('fails if auto create is disabled', async function () {
@@ -499,7 +498,7 @@ describe('External LDAP', function () {
it('enable auto create', async function () {
let conf = Object.assign({}, LDAP_CONFIG);
conf.autoCreate = true;
await settings.setExternalLdapConfig(conf);
await externalLdap.setConfig(conf);
});
it('fails for unknown user', async function () {