Skip to content

Commit 1e184e8

Browse files
committed
Merge pull request #2 from codingchili/master
Pulling changes
2 parents 4a5df5f + d72f419 commit 1e184e8

File tree

9 files changed

+155
-95
lines changed

9 files changed

+155
-95
lines changed

config.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"authentication": {
3-
"url": "ldap://localhost:10389",
3+
"url": "ldap://localhost:10388",
44
"admin": {
55
"dn": "uid=admin,ou=system",
66
"password": "secret"

public/script/app.js

-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ app.controller('kbn-authentication-plugin', function ($scope, $http) {
3232
};
3333

3434
$scope.init = function () {
35-
console.log('init');
3635
$http.get('/groups').then(
3736
function success(request) {
3837
$scope.groups = request.data.groups;

src/filter.js

+30-26
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ module.exports = {
5353
*
5454
* @param req the request to be inspected contains user groups and requested index.
5555
* @returns {*}
56-
*/
56+
*/
5757
handleSearch: function (req) {
5858
var query = getQueryList(req.bodyContent);
5959
var response = '';
@@ -64,19 +64,20 @@ module.exports = {
6464
for (var i = 0; i < query.length; i++) {
6565
var search = JSON.parse(query[i]);
6666

67-
if (search.index) {
68-
if (!module.exports.authorizedIndex(search.index, token.groups)) {
69-
authorized = false;
70-
}
71-
}
72-
response += JSON.stringify(search) + '\n';
67+
if (search.index && !authorizedIndex(search.index, token.groups))
68+
authorized = false;
69+
70+
response += JSON.stringify(search);
71+
72+
if (i != query.length - 1)
73+
response += '\n';
7374
}
7475
} catch (err) {
7576
authorized = false;
7677
}
7778

7879
if (authorized) {
79-
req.bodyContent = new Buffer(response, 'utf8')
80+
req.bodyContent = new Buffer(response);
8081
} else {
8182
req.bodyContent = new Buffer('{}');
8283
}
@@ -90,24 +91,9 @@ module.exports = {
9091
* @param index the name of the index.
9192
* @param groups an array of groups to look in.
9293
* @returns {boolean}
93-
*/
94+
*/
9495
authorizedIndex: function (index, groups) {
95-
var authorized = true;
96-
index = (index instanceof Array) ? index : [index];
97-
98-
for (var i = 0; i < index.length; i++) {
99-
var member = false;
100-
101-
for (var k = 0; k < groups.length; k++) {
102-
if (index[i] === groups[k])
103-
member = true;
104-
}
105-
106-
if (!member)
107-
authorized = false;
108-
}
109-
110-
return authorized;
96+
return authorizedIndex(index, groups);
11197
}
11298
};
11399

@@ -124,7 +110,25 @@ function getQueryList(content) {
124110
if (list.length === 0)
125111
return [content.toString()];
126112
else {
127-
list.splice(-1, 1);
128113
return list;
129114
}
130115
}
116+
117+
function authorizedIndex(index, groups) {
118+
var authorized = true;
119+
index = (index instanceof Array) ? index : [index];
120+
121+
for (var i = 0; i < index.length; i++) {
122+
var member = false;
123+
124+
for (var k = 0; k < groups.length; k++) {
125+
if (index[i] === groups[k])
126+
member = true;
127+
}
128+
129+
if (!member)
130+
authorized = false;
131+
}
132+
133+
return authorized;
134+
}

src/twofactor.js

+10-1
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,19 @@
1111
const Speakeasy = require('speakeasy');
1212
const QR = require('qr-image');
1313
const Config = require('./config').load('two-factor');
14-
const User = require('./model/users');
14+
var User = require('./model/users');
1515

1616
module.exports = {
1717

18+
/**
19+
* Override the default data store.
20+
*
21+
* @param store implements model/users.js
22+
*/
23+
init: function (store) {
24+
this.User = store;
25+
},
26+
1827
/**
1928
* Verifies a 2-FA key with the current timeframe and
2029
* the stored secret for the given user.

test/authentication.js

+9-61
Original file line numberDiff line numberDiff line change
@@ -7,91 +7,39 @@
77

88
const Assert = require('assert');
99
const Authentication = require('../src/authentication');
10-
const LDAP = require('ldapjs');
11-
const Server = LDAP.createServer();
12-
13-
const USERNAME = 'username';
14-
const PASSWORD = 'password';
15-
const PASSWORD_WRONG = 'pass-wrong';
16-
10+
const Mock = require('./mock/LDAP');
1711

1812
describe('LDAP Authentication', function () {
1913

20-
before(function () {
21-
Server.listen(10388, '0.0.0.0');
22-
23-
Server.bind('uid=admin,ou=system', function (req, res, next) {
24-
if (req.credentials === PASSWORD_WRONG) {
25-
return next(new LDAP.InvalidCredentialsError());
26-
} else {
27-
res.end();
28-
return next();
29-
}
30-
});
31-
32-
Server.search('ou=users,ou=system', function (req, res, next) {
33-
var entry = {
34-
dn: 'uid=admin, ou=system',
35-
attributes: {
36-
objectclass: ['top', 'organization'],
37-
o: ['system'],
38-
uid: USERNAME
39-
}
40-
};
41-
42-
// Returns an entry for all other searches, simulating a missing entry.
43-
if (req.filter.json.value === 'missing') {
44-
res.end();
45-
return next();
46-
} else {
47-
res.send(entry);
48-
res.end();
49-
return next();
50-
}
51-
});
52-
});
53-
54-
55-
Server.search('ou=groups,ou=system', function (req, res, next) {
56-
var entry = {
57-
dn: 'ou=groups,ou=system',
58-
attributes: {
59-
objectClass: 'groupOfNames',
60-
member: 'uid=' + USERNAME,
61-
cn: 'group-name'
62-
}
63-
};
64-
65-
res.send(entry);
66-
res.end();
67-
return next();
68-
});
14+
before((function () {
15+
Mock.init();
16+
}));
6917

7018
it('Should bind successfully with a client.', function (done) {
71-
Authentication.ldap(USERNAME, PASSWORD, function (err, user) {
72-
Assert.equal(user.uid, USERNAME);
19+
Authentication.ldap(Mock.USERNAME, Mock.PASSWORD, function (err, user) {
20+
Assert.equal(user.uid, Mock.USERNAME);
7321
Assert.equal(err, null);
7422
done();
7523
});
7624
});
7725

7826
it('Should fail to bind with an user using wrong password.', function (done) {
79-
Authentication.ldap(USERNAME, PASSWORD_WRONG, function (err, user) {
27+
Authentication.ldap(Mock.USERNAME, Mock.PASSWORD_WRONG, function (err, user) {
8028
Assert.notEqual(err, null);
8129
done();
8230
});
8331
});
8432

8533
it('Should fail to bind with a user that do not exist.', function (done) {
86-
Authentication.ldap('missing', PASSWORD, function (err, user) {
34+
Authentication.ldap('missing', Mock.PASSWORD, function (err, user) {
8735
Assert.equal(user, null);
8836
Assert.notEqual(err, null);
8937
done();
9038
});
9139
});
9240

9341
it('Should retrieve all the groups an user is member of.', function (done) {
94-
Authentication.ldap(USERNAME, PASSWORD, function (err, user) {
42+
Authentication.ldap(Mock.USERNAME, Mock.PASSWORD, function (err, user) {
9543
Assert.equal(user.groups.length, 1);
9644
Assert.equal(err, null);
9745
done();

test/filter.js

+7-5
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,16 @@ describe('Filter - Route proxying and resource filtering', function () {
1515
});
1616

1717
it('Should accept any searches that do not specify index.', function () {
18+
var token = Authentication.signToken('uid', []);
19+
var payload = new Buffer('{}\n{}');
1820
var request = Filter.handleSearch({
19-
bodyContent: new Buffer("{}\n{}"),
21+
bodyContent: payload,
2022
headers: {
21-
cookie: ""
23+
cookie: 'token=' + token
2224
}
2325
});
2426

25-
Assert.equal(new Buffer('{}').toString(), request.bodyContent.toString());
27+
Assert.equal(request.bodyContent.toString(), payload.toString());
2628
});
2729

2830
it('Should return empty request when token is invalid.', function () {
@@ -34,7 +36,7 @@ describe('Filter - Route proxying and resource filtering', function () {
3436
}
3537
});
3638

37-
Assert.equal(new Buffer('{}').toString(), request.bodyContent.toString());
39+
Assert.equal(request.bodyContent.toString(), '{}');
3840
});
3941

4042
it('Should return request when token is valid for given index', function () {
@@ -47,7 +49,7 @@ describe('Filter - Route proxying and resource filtering', function () {
4749
}
4850
});
4951

50-
Assert.equal(payload.toString() + '\n', request.bodyContent.toString());
52+
Assert.equal(request.bodyContent.toString(), payload.toString());
5153
});
5254

5355
});

test/mock/LDAP.js

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
const LDAP = require('ldapjs');
2+
const Server = LDAP.createServer();
3+
4+
const USERNAME = 'username';
5+
const PASSWORD = 'password';
6+
const PASSWORD_WRONG = 'pass-wrong';
7+
8+
module.exports = {
9+
USERNAME: USERNAME,
10+
PASSWORD: PASSWORD,
11+
PASSWORD_WRONG: PASSWORD_WRONG,
12+
13+
init: function () {
14+
Server.listen(10388, '0.0.0.0');
15+
16+
Server.bind('uid=admin,ou=system', authenticateAdmin);
17+
Server.search('ou=users,ou=system', findUser);
18+
Server.search('ou=groups,ou=system', findGroups);
19+
}
20+
};
21+
22+
function authenticateAdmin (req, res, next) {
23+
if (req.credentials === PASSWORD_WRONG) {
24+
return next(new LDAP.InvalidCredentialsError());
25+
} else {
26+
res.end();
27+
return next();
28+
}
29+
}
30+
31+
function findUser (req, res, next) {
32+
var entry = {
33+
dn: 'uid=admin, ou=system',
34+
attributes: {
35+
objectclass: ['top', 'organization'],
36+
o: ['system'],
37+
uid: USERNAME
38+
}
39+
};
40+
41+
// Returns an entry for all other searches, simulating a missing entry.
42+
if (req.filter.json.value === 'missing') {
43+
res.end();
44+
return next();
45+
} else {
46+
res.send(entry);
47+
res.end();
48+
return next();
49+
}
50+
}
51+
52+
function findGroups (req, res, next) {
53+
var entry = {
54+
dn: 'ou=groups,ou=system',
55+
attributes: {
56+
objectClass: 'groupOfNames',
57+
member: 'uid=' + USERNAME,
58+
cn: 'group-name'
59+
}
60+
};
61+
62+
res.send(entry);
63+
res.end();
64+
return next();
65+
}

test/mock/MongoDB.js

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/**
2+
* @author Robin Duda
3+
*
4+
* Mock implementation of users (MongoDB) for testing
5+
* modules that depend on MongoDB.
6+
*
7+
* For documentation see users.js
8+
*/
9+
10+
var users = {};
11+
12+
module.exports = {
13+
14+
getSecret: function (username, token, callback) {
15+
callback(users[username], users[username].secret);
16+
},
17+
18+
setVerified: function (username, verified) {
19+
users[username].verified = verified;
20+
},
21+
22+
create: function (username, key) {
23+
users[username].secret = {key: key, verified: false};
24+
},
25+
26+
remove: function (username) {
27+
users[username] = null;
28+
}
29+
};

test/twofactor.js

+4
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ const USERNAME = 'test-username';
1111

1212
describe('Two-factor authentication', function () {
1313

14+
before((function () {
15+
TwoFactor.init(require('./mock/mongodb'));
16+
}));
17+
1418
it('Should generate a qr-svg image.', function () {
1519
var svg = TwoFactor.create(USERNAME).svg;
1620
Assert.equal(svg.startsWith('<svg'), true);

0 commit comments

Comments
 (0)