Closed christophe-lejeune closed 2 years ago
The scope
is a an option of ldap.js search
. By default, is is set to base
but could be set to sub
. It is called from our Ldap
module in the method searchAndBind
.
The new scope could be hard coded, or (preferably) changed in the config file.
I suggest to have the scope hard coded with sub
BUT also that administrators would use the greatest common search path (e.g. : ou=people,dc=acme,dc=edu
for classic AD-like directory and dc=acme,dc=edu
for a directory with multiple subtrees).
searchAndBind
has two steps: search
and bind
.
search
can be applied recursively from any broader node.
bind
must be applied to the exact node.
@christophe-lejeune I will share a small node program so that you can check that your LDAP server is able to generate on first step the input needed in the second step.
Testable on any computer that can connect to your LDAP server and on which you can have Node.js installed.
In a new folder.
Copy-paste in a new file package.json
:
{
"name": "ldaptest",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"ldapjs": "^2.3.1",
"minimist": "^1.2.5"
}
}
Copy-paste in a new file named index.js
:
const LDAP = require("ldapjs");
const {filter, url, searchBase} = require('minimist')(process.argv.slice(2));
let close = (ldap) => {
if (ldap._socket) {
ldap._socket.end()
}
}
let ldap = LDAP.createClient({url});
ldap.search(searchBase, {scope: 'sub', filter, attributes: ['dn']}, (tcpError, res) => {
if (tcpError) {
close(ldap);
console.log('TCP error');
} else {
let dn;
res.on('searchEntry', (entry) => {
dn = entry.object.dn;
});
res.on('end', () => {
close(ldap);
console.log({dn});
});
}
});
Install dependencies:
npm install
Launch the program to test your LDAP server ability to search for the complete path ("distinguished name") of a user from his/her ID :
node index.js --url ldap://ldap.acme.fr --searchBase dc=acme,dc=fr --filter uid=benel
You'll get for example:
uid=benel,ou=people,dc=acme,dc=fr
Test it on IDs of people with different status.
Dear @benel
Thank you very much for this node program, super easy to deploy within seconds on a test machine.
The issues of this test seems to confirm that the my university's LDAP accepts "recursive" requests
Indeed, it have results with id belonging to different status:
{ dn: 'uid=lejeune,ou=people,dc=acme,dc=fr' }
{ dn: 'uid=benel,ou=people,dc=master,dc=acme,dc=fr' }
And, when the id is unknown :
{ dn: undefined }
Are these results sufficient to make a try with scope: "sub"
or does the two steps (search
and bind
) require additional developments prior to make such tests.
Again many thank for your helps in deploying/adapting AAAforREST for my needs !
Are these results sufficient to make a try with scope: "sub" or does the two steps (search and bind) require additional developments prior to make such tests.
Additional (small)) developments are necessary to inject the resulted DN into the bind.
And here is a new version that searches AND binds:
const LDAP = require("ldapjs");
const {filter, url, searchBase, password} = require('minimist')(process.argv.slice(2));
let close = (ldap) => {
if (ldap._socket) {
ldap._socket.end()
}
}
let ldap = LDAP.createClient({url});
ldap.search(searchBase, {scope: 'sub', filter, attributes: ['dn']}, (tcpError, res) => {
if (tcpError) {
close(ldap);
console.log('TCP error');
} else {
let dn;
res.on('searchEntry', (entry) => {
dn = entry.object.dn;
});
res.on('end', () => {
console.log({dn});
ldap.bind(dn, password, (badPassword) => {
close(ldap);
console.log({logged: !badPassword});
});
});
}
});
node index.js --url ldap://ldap.acme.fr --searchBase dc=acme,dc=fr --filter uid=benel --password "p8ssW0rd"
{ dn: 'uid=benel,ou=people,dc=acme,dc=fr' }
{ logged: true }
I confirm the messages are different when the id and the password matches { logged: true }
, when the password does not match the id { logged: false }
and when the id does not belong to the ldap { dn: undefined }
.
In the latter case, an exception is raised, but if does not invalidate the test.
I published a temporary container image named "aaaforrest:dev". If you have time to test it, please tell me if it works in your settings.
For now, the existing tests do not pass . Sorry for that.
A side effect has just been fixed. Tests are passing again. The new container image (aaaforrest:dev
) can be pulled for testing.
This temporary container (with the fixed side effect) works for me ! Thanks to this code and configuration, users from different nodes can log in !
Thank you very much and congratulations for this great work !
Great!
The new container image is now published on DockerHub as aaaforrest
(latest)!
Thank you very much for the great work done on AAAforREST !
I would like to use it with my university's LDAP. My first attempt was successful. That'a already great !
However, I realized that my LDAP have "subdomains" for different types of students. In the example provided in
conf/config.yml
, we would have two different search bases, one withdc=example,dc=com
and the other withdc=master,dc=example,dc=com
. Each configuration works if it is used alone. But I fail to use it altogether.As you can see, the search bases have
dc=example,dc=com
in common. Unfortunately, queries ondc=example,dc=com
gives no answer concerningdc=master,dc=example,dc=com
. Do you think it would be possible to generate "recursive" queries to this LDAP ? Or should we consider these two search bases as two different LDAP, as in first version of AAAforREST ?I would be happy to conduct tests under your direction.
Again many thanks and best wishes !