Use tasks api for external ldap syncer

This commit is contained in:
Johannes Zellner
2019-08-29 17:19:51 +02:00
parent f8db12346d
commit b9efa8f445
5 changed files with 83 additions and 60 deletions
+68 -59
View File
@@ -4,6 +4,7 @@ exports = module.exports = {
ExternalLdapError: ExternalLdapError,
testConfig: testConfig,
startSyncer: startSyncer,
sync: sync
};
@@ -12,6 +13,7 @@ var assert = require('assert'),
debug = require('debug')('box:ldapclient'),
ldap = require('ldapjs'),
settings = require('./settings.js'),
tasks = require('./tasks.js'),
util = require('util');
function ExternalLdapError(reason, errorOrMessage) {
@@ -41,30 +43,24 @@ ExternalLdapError.BAD_FIELD = 'bad field';
ExternalLdapError.NOT_FOUND = 'not found';
// performs service bind if required
function getClientAndConfig(callback) {
function getClient(externalLdapConfig, callback) {
assert.strictEqual(typeof callback, 'function');
settings.getExternalLdapConfig(function (error, externalLdapConfig) {
if (error) return callback(new ExternalLdapError(ExternalLdapError.INTERNAL_ERROR, error));
var client;
try {
client = ldap.createClient({ url: externalLdapConfig.url });
} catch (e) {
if (e instanceof ldap.ProtocolError) return callback(new ExternalLdapError(ExternalLdapError.BAD_FIELD, 'url protocol is invalid'));
return callback(new ExternalLdapError(ExternalLdapError.INTERNAL_ERROR, e));
}
var client;
try {
client = ldap.createClient({ url: externalLdapConfig.url });
} catch (e) {
if (e instanceof ldap.ProtocolError) return callback(new ExternalLdapError(ExternalLdapError.BAD_FIELD, 'url protocol is invalid'));
return callback(new ExternalLdapError(ExternalLdapError.INTERNAL_ERROR, e));
}
if (!externalLdapConfig.bindDn) return callback(null, client);
if (!externalLdapConfig.bindDn) return callback(null, client);
client.bind(externalLdapConfig.bindDn, externalLdapConfig.bindPassword, function (error) {
if (error instanceof ldap.InvalidCredentialsError) return callback(new ExternalLdapError(ExternalLdapError.INVALID_CREDENTIALS));
if (error) return callback(new ExternalLdapError(ExternalLdapError.EXTERNAL_ERROR, error));
client.bind(externalLdapConfig.bindDn, externalLdapConfig.bindPassword, function (error) {
if (error instanceof ldap.InvalidCredentialsError) return callback(new ExternalLdapError(ExternalLdapError.INVALID_CREDENTIALS));
if (error) return callback(new ExternalLdapError(ExternalLdapError.EXTERNAL_ERROR, error));
debug('getClient: successful');
callback(null, client, externalLdapConfig);
});
callback(null, client, externalLdapConfig);
});
}
@@ -83,26 +79,7 @@ function testConfig(config, callback) {
try { ldap.parseFilter(config.filter); } catch (e) { return callback(new ExternalLdapError(ExternalLdapError.BAD_FIELD, 'invalid filter')); }
if (config.bindDn) try { ldap.parseFilter(config.bindDn); } catch (e) { return callback(new ExternalLdapError(ExternalLdapError.INVALID_CREDENTIALS)); }
var client;
try {
client = ldap.createClient({ url: config.url });
} catch (e) {
if (e instanceof ldap.ProtocolError) return callback(new ExternalLdapError(ExternalLdapError.BAD_FIELD, 'url protocol is invalid'));
return callback(new ExternalLdapError(ExternalLdapError.EXTERNAL_ERROR, e));
}
function bindIfNeeded(callback) {
if (!config.bindDn) return callback();
client.bind(config.bindDn, config.bindPassword, function (error) {
if (error instanceof ldap.InvalidCredentialsError) return callback(new ExternalLdapError(ExternalLdapError.INVALID_CREDENTIALS));
if (error) return callback(new ExternalLdapError(ExternalLdapError.EXTERNAL_ERROR, error));
callback();
});
}
bindIfNeeded(function (error) {
getClient(config, function (error, client) {
if (error) return callback(error);
var opts = {
@@ -120,31 +97,63 @@ function testConfig(config, callback) {
});
}
function sync(callback) {
function startSyncer(callback) {
assert.strictEqual(typeof callback, 'function');
getClientAndConfig(function (error, client, externalLdapConfig) {
if (error) return callback(error);
settings.getExternalLdapConfig(function (error, externalLdapConfig) {
if (error) return callback(new ExternalLdapError(ExternalLdapError.INTERNAL_ERROR, error));
if (!externalLdapConfig.enabled) return callback(new ExternalLdapError(ExternalLdapError.BAD_STATE, 'not enabled'));
var opts = {
filter: externalLdapConfig.filter,
scope: 'sub'
};
tasks.add(tasks.TASK_SYNC_EXTERNAL_LDAP, [], function (error, taskId) {
if (error) return callback(new ExternalLdapError(ExternalLdapError.INTERNAL_ERROR, error));
client.search(externalLdapConfig.baseDn, opts, function(err, res) {
assert.ifError(err);
tasks.startTask(taskId, {}, function (error, result) {
debug('sync: done', error, result);
});
res.on('searchEntry', function(entry) {
console.log('entry: ' + JSON.stringify(entry.object));
});
res.on('searchReference', function(referral) {
console.log('referral: ' + referral.uris.join());
});
res.on('error', function(err) {
console.error('error: ' + err.message);
});
res.on('end', function(result) {
console.log('status: ' + result.status);
callback(null, taskId);
});
});
}
function sync(progressCallback, callback) {
assert.strictEqual(typeof progressCallback, 'function');
assert.strictEqual(typeof callback, 'function');
settings.getExternalLdapConfig(function (error, externalLdapConfig) {
if (error) return callback(new ExternalLdapError(ExternalLdapError.INTERNAL_ERROR, error));
if (!externalLdapConfig.enabled) return callback(new ExternalLdapError(ExternalLdapError.BAD_STATE, 'not enabled'));
// basic validation to not crash
try { ldap.parseDN(externalLdapConfig.baseDn); } catch (e) { return callback(new ExternalLdapError(ExternalLdapError.BAD_FIELD, 'invalid baseDn')); }
try { ldap.parseFilter(externalLdapConfig.filter); } catch (e) { return callback(new ExternalLdapError(ExternalLdapError.BAD_FIELD, 'invalid filter')); }
if (externalLdapConfig.bindDn) try { ldap.parseFilter(externalLdapConfig.bindDn); } catch (e) { return callback(new ExternalLdapError(ExternalLdapError.INVALID_CREDENTIALS)); }
getClient(externalLdapConfig, function (error, client) {
if (error) return callback(error);
var opts = {
filter: externalLdapConfig.filter,
scope: 'sub'
};
client.search(externalLdapConfig.baseDn, opts, function (error, result) {
if (error) return callback(new ExternalLdapError(ExternalLdapError.EXTERNAL_ERROR, error));
result.on('searchEntry', function(entry) {
console.log('entry: ' + JSON.stringify(entry.object));
// TODO ensure db record for user
});
result.on('error', function (error) {
callback(new ExternalLdapError(ExternalLdapError.EXTERNAL_ERROR, error));
});
result.on('end', function(result) {
console.log('status: ' + result.status);
callback();
});
});
});
});