2018 LDAP(2)NodeJS and LDAP

2018 LDAP(2)NodeJS and LDAP

Set up LDAP Server
Install LDAPJS
> npm install ldapjs

I suppose to have OpenLDAP CLI on my machine, check it out.
> ldapsearch -H

> ldapsearch -V
ldapsearch: @(#) $OpenLDAP: ldapsearch 2.4.28 (Jul 15 2017 15:44:01) $

Set Up a Simple Project as follow: package.json
{
"devDependencies": {
"gulp": "3.9.0",
"gulp-jshint": "1.12.0",
"gulp-mocha": "2.1.3",
"gulp-nodemon": "2.0.4",
"gulp-util": "3.0.7",
"gulp-concat": "2.6.0",
"gulp-tar": "1.5.0",
"gulp-gzip": "1.2.0",
"gulp-artifactory-upload": "1.2.0",
"gulp-jsdoc": "0.1.5",
"gulp-stubby-server": "0.1.5",
"gulp-help": "1.6.1",
"ldapjs": "1.0.2"
},
"engines": {
"node": ">=0.12.0"
},
"name": "ldap-server",
"private": true,
"version": "1.0.0"
}

password-app.js
/*jslint node: true */
'use strict';

var ldap = require('ldapjs');

var server = ldap.createServer();

server.listen(1389, function(){
console.log('/etc/passwd LDAP server up at: %s', server.url);
});

NPM install and run with command
> node password-app.js

Run the client to connect to that
> ldapsearch -H ldap://localhost:1389 -x -b "o=myhost" objectclass=*
# extended LDIF
#
# LDAPv3
# base <o=myhost> with scope subtree
# filter: objectclass=*
# requesting: ALL
#
# search result
search: 2
result: 32 No such object
text: No tree found for: o=myhost
# numResponses: 1

Add this binding to the server
server.bind('cn=root', function(req, res, next) {
if (req.dn.toString() !== 'cn=root' || req.credentials !== 'secret')
return next(new ldap.InvalidCredentialsError());

res.end();
return next();
});

We will have the password to verified.
> ldapsearch -H ldap://localhost:1389 -x -D cn=root -w foo -b "o=myhost" objectclass=*
ldap_bind: Invalid credentials (49)
matched DN: cn=root
additional info: InvalidCredentialsError

> ldapsearch -H ldap://localhost:1389 -x -D cn=root -w secret -LLL -b "o=myhost" objectclass=*
No such object (32)
Additional information: No tree found for: o=myhost

The format for /etc/passwd is as follow:
jsmith:x:1001:1000:Joe Smith,Room 1007,(234)555-8910,(234)555-0044,email:/home/jsmith:/bin/sh
jsmith - Username
x - password hash
1001 - Numeric UID
1000 - Numeric Primary GID
‘Joe Smith, …’ - DisplayName and Other information
/home/jsmith. Home directory
/bin/sh Shell

Load and Parse all the Data into req.users
function loadPasswdFile(req, res, next) {
fs.readFile('/etc/passwd', 'utf8', function(err, data) {
if (err)
return next(new ldap.OperationsError(err.message));

req.users = {};

var lines = data.split('\n');
for (var i = 0; i < lines.length; i++) {
if (!lines[i] || /^#/.test(lines[i])) // empty line or start with #, ignore
continue;

var record = lines[i].split(':');
if (!record || !record.length) //no :, ignore
continue;

req.users[record[0]] = {
dn: 'cn=' + record[0] + ', ou=users, o=myhost',
attributes: {
cn: record[0],
uid: record[2],
gid: record[3],
description: record[4],
homedirectory: record[5],
shell: record[6] || '',
objectclass: 'unixUser'
}
};
}

return next();
});
}

Add this to the binding
var pre = [authorize, loadPasswdFile];

server.search('o=myhost', pre, function(req, res, next) {
Object.keys(req.users).forEach(function(k) {
if (req.filter.matches(req.users[k].attributes))
res.send(req.users[k]);
});

res.end();
return next();
});

Search for root user
> ldapsearch -H ldap://localhost:1389 -x -D cn=root -w secret -LLL -b "o=myhost" cn=root
dn: cn=root, ou=users, o=myhost
cn: root
uid: 0
gid: 0
description: System Administrator
homedirectory: /var/root
shell: /bin/sh
objectclass: unixUser

List all the user information
> ldapsearch -H ldap://localhost:1389 -x -D cn=root -w secret -LLL -b "o=myhost" objectclass=*

CN start with r*
> ldapsearch -H ldap://localhost:1389 -x -D cn=root -w secret -LLL -b "o=myhost" cn=r*
dn: cn=root, ou=users, o=myhost
cn: root
uid: 0
gid: 0
description: System Administrator
homedirectory: /var/root
shell: /bin/sh
objectclass: unixUser

Server Add
server.add('ou=users, o=myhost', pre, function(req, res, next) {
if (!req.dn.rdns[0].cn)
return next(new ldap.ConstraintViolationError('cn required'));

if (req.users[req.dn.rdns[0].cn])
return next(new ldap.EntryAlreadyExistsError(req.dn.toString()));

var entry = req.toObject().attributes;

if (entry.objectclass.indexOf('unixUser') === -1)
return next(new ldap.ConstraintViolation('entry must be a unixUser'));

var opts = ['-m'];
if (entry.description) {
opts.push('-c');
opts.push(entry.description[0]);
}
if (entry.homedirectory) {
opts.push('-d');
opts.push(entry.homedirectory[0]);
}
if (entry.gid) {
opts.push('-g');
opts.push(entry.gid[0]);
}
if (entry.shell) {
opts.push('-s');
opts.push(entry.shell[0]);
}
if (entry.uid) {
opts.push('-u');
opts.push(entry.uid[0]);
}
opts.push(entry.cn[0]);
var useradd = spawn('useradd', opts);

var messages = [];

useradd.stdout.on('data', function(data) {
messages.push(data.toString());
});
useradd.stderr.on('data', function(data) {
messages.push(data.toString());
});

useradd.on('exit', function(code) {
if (code !== 0) {
var msg = '' + code;
if (messages.length)
msg += ': ' + messages.join();
return next(new ldap.OperationsError(msg));
}

res.end();
return next();
});
});

Execute the command useradd

Modify User
server.modify('ou=users, o=myhost', pre, function(req, res, next) {
if (!req.dn.rdns[0].cn || !req.users[req.dn.rdns[0].cn])
return next(new ldap.NoSuchObjectError(req.dn.toString()));

if (!req.changes.length)
return next(new ldap.ProtocolError('changes required'));

var user = req.users[req.dn.rdns[0].cn].attributes;
var mod;

for (var i = 0; i < req.changes.length; i++) {
mod = req.changes[i].modification;
switch (req.changes[i].operation) {
case 'replace':
if (mod.type !== 'userpassword' || !mod.vals || !mod.vals.length)
return next(new ldap.UnwillingToPerformError('only password updates ' +
'allowed'));
break;
case 'add':
case 'delete':
return next(new ldap.UnwillingToPerformError('only replace allowed'));
}
}

var passwd = spawn('chpasswd', ['-c', 'MD5']);
passwd.stdin.end(user.cn + ':' + mod.vals[0], 'utf8');

passwd.on('exit', function(code) {
if (code !== 0)
return next(new ldap.OperationsError('' + code));

res.end();
return next();
});
});

Create a file user.ldif
dn: cn=ldapjs, ou=users, o=myhost
objectClass: unixUser
cn: ldapjs
shell: /bin/bash
description: Created via ldapadd

Add User
>ldapadd -H ldap://localhost:1389 -x -D cn=root -w secret -f ./user.ldif

Change Password passwd.ldif
dn: cn=ldapjs, ou=users, o=myhost
changetype: modify
replace: userPassword
userPassword: secret
>ldapmodify -H ldap://localhost:1389 -x -D cn=root -w secret -f ./passwd.ldif

Delete User
>ldapdelete -H ldap://localhost:1389 -x -D cn=root -w secret "cn=ldapjs, ou=users, o=myhost"

It seems that the ldapJS will handle the protocol things, everything under that, our solution can store the data in DB or file system.

References:
http://ldapjs.org/guide.html
http://sillycat.iteye.com/blog/2414080
http://ldapjs.org/examples.html
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值