Strengthen password in LDAP using SHA512 crypt algorithm
Uses the crypt() function to do password encryption. This function handles several schemes such as: MD5, Blowfish, SHA1, SHA2. SHA-512 is used in Authelia for best security. The algorithm is fully described in https://www.akkadia.org/drepper/SHA-crypt.txt The 'crypt3' npm package has been added as a dependency to use the crypt() function. The package needs to be compiled in order to call the c function, that's why python, make and C++ compiler are installed temporarily in the Docker image.pull/168/head
parent
b9b0973488
commit
462418e123
|
@ -1,9 +1,14 @@
|
||||||
FROM node:7-alpine
|
FROM node:8.7.0-alpine
|
||||||
|
|
||||||
WORKDIR /usr/src
|
WORKDIR /usr/src
|
||||||
|
|
||||||
COPY package.json /usr/src/package.json
|
COPY package.json /usr/src/package.json
|
||||||
|
|
||||||
|
RUN apk update
|
||||||
|
RUN apk add make g++ python
|
||||||
|
|
||||||
RUN npm install --production
|
RUN npm install --production
|
||||||
|
RUN apk del python make g++ && rm -f /var/cache/apk/*
|
||||||
|
|
||||||
COPY dist/server /usr/src/server
|
COPY dist/server /usr/src/server
|
||||||
COPY dist/shared /usr/src/shared
|
COPY dist/shared /usr/src/shared
|
||||||
|
|
|
@ -5,7 +5,6 @@ services:
|
||||||
- ./test:/usr/src/test
|
- ./test:/usr/src/test
|
||||||
- ./dist/server:/usr/src/server
|
- ./dist/server:/usr/src/server
|
||||||
- ./dist/shared:/usr/src/shared
|
- ./dist/shared:/usr/src/shared
|
||||||
- ./node_modules:/usr/src/node_modules
|
|
||||||
- ./config.template.yml:/etc/authelia/config.yml:ro
|
- ./config.template.yml:/etc/authelia/config.yml:ro
|
||||||
networks:
|
networks:
|
||||||
- example-network
|
- example-network
|
||||||
|
|
|
@ -2,3 +2,6 @@ olcAccess: {0}to attrs=userPassword,shadowLastChange by self write by anonymou
|
||||||
s auth by * none
|
s auth by * none
|
||||||
# olcAccess: {1}to dn.base="" by * read
|
# olcAccess: {1}to dn.base="" by * read
|
||||||
# olcAccess: {2}to * by * read
|
# olcAccess: {2}to * by * read
|
||||||
|
|
||||||
|
olcPasswordHash: {CRYPT}
|
||||||
|
olcPasswordCryptSaltFormat: $6$rounds=50000$%.16s
|
||||||
|
|
|
@ -27,7 +27,7 @@ objectclass: inetOrgPerson
|
||||||
objectclass: top
|
objectclass: top
|
||||||
mail: john.doe@authelia.com
|
mail: john.doe@authelia.com
|
||||||
sn: John Doe
|
sn: John Doe
|
||||||
userpassword: {SHA}W6ph5Mm5Pz8GgiULbPgzG37mj9g=
|
userpassword: {CRYPT}$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/
|
||||||
|
|
||||||
dn: cn=harry,ou=users,dc=example,dc=com
|
dn: cn=harry,ou=users,dc=example,dc=com
|
||||||
cn: harry
|
cn: harry
|
||||||
|
@ -35,7 +35,7 @@ objectclass: inetOrgPerson
|
||||||
objectclass: top
|
objectclass: top
|
||||||
mail: harry.potter@authelia.com
|
mail: harry.potter@authelia.com
|
||||||
sn: Harry Potter
|
sn: Harry Potter
|
||||||
userpassword: {SHA}W6ph5Mm5Pz8GgiULbPgzG37mj9g=
|
userpassword: {CRYPT}$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/
|
||||||
|
|
||||||
dn: cn=bob,ou=users,dc=example,dc=com
|
dn: cn=bob,ou=users,dc=example,dc=com
|
||||||
cn: bob
|
cn: bob
|
||||||
|
@ -43,7 +43,7 @@ objectclass: inetOrgPerson
|
||||||
objectclass: top
|
objectclass: top
|
||||||
mail: bob.dylan@authelia.com
|
mail: bob.dylan@authelia.com
|
||||||
sn: Bob Dylan
|
sn: Bob Dylan
|
||||||
userpassword: {SHA}W6ph5Mm5Pz8GgiULbPgzG37mj9g=
|
userpassword: {CRYPT}$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/
|
||||||
|
|
||||||
dn: cn=james,ou=users,dc=example,dc=com
|
dn: cn=james,ou=users,dc=example,dc=com
|
||||||
cn: james
|
cn: james
|
||||||
|
@ -51,7 +51,7 @@ objectclass: inetOrgPerson
|
||||||
objectclass: top
|
objectclass: top
|
||||||
mail: james.dean@authelia.com
|
mail: james.dean@authelia.com
|
||||||
sn: James Dean
|
sn: James Dean
|
||||||
userpassword: {SHA}W6ph5Mm5Pz8GgiULbPgzG37mj9g=
|
userpassword: {CRYPT}$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/
|
||||||
|
|
||||||
dn: cn=blackhat,ou=users,dc=example,dc=com
|
dn: cn=blackhat,ou=users,dc=example,dc=com
|
||||||
cn: blackhat
|
cn: blackhat
|
||||||
|
@ -59,4 +59,4 @@ objectclass: inetOrgPerson
|
||||||
objectclass: top
|
objectclass: top
|
||||||
mail: billy.blackhat@authelia.com
|
mail: billy.blackhat@authelia.com
|
||||||
sn: Billy BlackHat
|
sn: Billy BlackHat
|
||||||
userpassword: {SHA}W6ph5Mm5Pz8GgiULbPgzG37mj9g=
|
userpassword: {CRYPT}$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
"bluebird": "3.5.0",
|
"bluebird": "3.5.0",
|
||||||
"body-parser": "^1.15.2",
|
"body-parser": "^1.15.2",
|
||||||
"connect-redis": "^3.3.0",
|
"connect-redis": "^3.3.0",
|
||||||
"dovehash": "0.0.5",
|
"crypt3": "^1.0.0",
|
||||||
"ejs": "^2.5.5",
|
"ejs": "^2.5.5",
|
||||||
"express": "^4.14.0",
|
"express": "^4.14.0",
|
||||||
"express-request-id": "^1.4.0",
|
"express-request-id": "^1.4.0",
|
||||||
|
|
|
@ -15,7 +15,6 @@ const yamlContent = YAML.load(configurationFilepath);
|
||||||
|
|
||||||
const deps: GlobalDependencies = {
|
const deps: GlobalDependencies = {
|
||||||
u2f: require("u2f"),
|
u2f: require("u2f"),
|
||||||
dovehash: require("dovehash"),
|
|
||||||
ldapjs: require("ldapjs"),
|
ldapjs: require("ldapjs"),
|
||||||
session: require("express-session"),
|
session: require("express-session"),
|
||||||
winston: require("winston"),
|
winston: require("winston"),
|
||||||
|
|
|
@ -7,7 +7,6 @@ import Exceptions = require("./Exceptions");
|
||||||
import fs = require("fs");
|
import fs = require("fs");
|
||||||
import ejs = require("ejs");
|
import ejs = require("ejs");
|
||||||
import { IUserDataStore } from "./storage/IUserDataStore";
|
import { IUserDataStore } from "./storage/IUserDataStore";
|
||||||
import { Winston } from "../../types/Dependencies";
|
|
||||||
import express = require("express");
|
import express = require("express");
|
||||||
import ErrorReplies = require("./ErrorReplies");
|
import ErrorReplies = require("./ErrorReplies");
|
||||||
import AuthenticationSessionHandler = require("./AuthenticationSession");
|
import AuthenticationSessionHandler = require("./AuthenticationSession");
|
||||||
|
|
|
@ -69,7 +69,8 @@ export class ServerVariablesInitializer {
|
||||||
const mailSenderBuilder = new MailSenderBuilder(Nodemailer);
|
const mailSenderBuilder = new MailSenderBuilder(Nodemailer);
|
||||||
const notifier = NotifierFactory.build(config.notifier, mailSenderBuilder);
|
const notifier = NotifierFactory.build(config.notifier, mailSenderBuilder);
|
||||||
const ldapClientFactory = new LdapClientFactory(config.ldap, deps.ldapjs);
|
const ldapClientFactory = new LdapClientFactory(config.ldap, deps.ldapjs);
|
||||||
const clientFactory = new ClientFactory(config.ldap, ldapClientFactory, deps.dovehash, deps.winston);
|
const clientFactory = new ClientFactory(config.ldap, ldapClientFactory,
|
||||||
|
deps.winston);
|
||||||
|
|
||||||
const ldapAuthenticator = new Authenticator(config.ldap, clientFactory);
|
const ldapAuthenticator = new Authenticator(config.ldap, clientFactory);
|
||||||
const ldapPasswordUpdater = new PasswordUpdater(config.ldap, clientFactory);
|
const ldapPasswordUpdater = new PasswordUpdater(config.ldap, clientFactory);
|
||||||
|
@ -97,5 +98,5 @@ export class ServerVariablesInitializer {
|
||||||
};
|
};
|
||||||
return BluebirdPromise.resolve(variables);
|
return BluebirdPromise.resolve(variables);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,5 @@
|
||||||
|
|
||||||
import util = require("util");
|
|
||||||
import BluebirdPromise = require("bluebird");
|
import BluebirdPromise = require("bluebird");
|
||||||
import exceptions = require("../Exceptions");
|
import exceptions = require("../Exceptions");
|
||||||
import Dovehash = require("dovehash");
|
|
||||||
|
|
||||||
import { EventEmitter } from "events";
|
import { EventEmitter } from "events";
|
||||||
import { IClient, GroupsAndEmails } from "./IClient";
|
import { IClient, GroupsAndEmails } from "./IClient";
|
||||||
import { ILdapClient } from "./ILdapClient";
|
import { ILdapClient } from "./ILdapClient";
|
||||||
|
@ -11,20 +7,18 @@ import { ILdapClientFactory } from "./ILdapClientFactory";
|
||||||
import { LdapConfiguration } from "../configuration/Configuration";
|
import { LdapConfiguration } from "../configuration/Configuration";
|
||||||
import { Winston } from "../../../types/Dependencies";
|
import { Winston } from "../../../types/Dependencies";
|
||||||
import Util = require("util");
|
import Util = require("util");
|
||||||
|
import { HashGenerator } from "../utils/HashGenerator";
|
||||||
|
|
||||||
export class Client implements IClient {
|
export class Client implements IClient {
|
||||||
private userDN: string;
|
private userDN: string;
|
||||||
private password: string;
|
private password: string;
|
||||||
private ldapClient: ILdapClient;
|
private ldapClient: ILdapClient;
|
||||||
private logger: Winston;
|
private logger: Winston;
|
||||||
private dovehash: typeof Dovehash;
|
|
||||||
private options: LdapConfiguration;
|
private options: LdapConfiguration;
|
||||||
|
|
||||||
constructor(userDN: string, password: string, options: LdapConfiguration,
|
constructor(userDN: string, password: string, options: LdapConfiguration,
|
||||||
ldapClientFactory: ILdapClientFactory, dovehash: typeof Dovehash, logger: Winston) {
|
ldapClientFactory: ILdapClientFactory, logger: Winston) {
|
||||||
this.options = options;
|
this.options = options;
|
||||||
this.dovehash = dovehash;
|
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
this.userDN = userDN;
|
this.userDN = userDN;
|
||||||
this.password = password;
|
this.password = password;
|
||||||
|
@ -128,18 +122,22 @@ export class Client implements IClient {
|
||||||
|
|
||||||
modifyPassword(username: string, newPassword: string): BluebirdPromise<void> {
|
modifyPassword(username: string, newPassword: string): BluebirdPromise<void> {
|
||||||
const that = this;
|
const that = this;
|
||||||
const encodedPassword = this.dovehash.encode("SSHA", newPassword);
|
|
||||||
const change = {
|
|
||||||
operation: "replace",
|
|
||||||
modification: {
|
|
||||||
userPassword: encodedPassword
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
this.logger.debug("LDAP: update password of user '%s'", username);
|
this.logger.debug("LDAP: update password of user '%s'", username);
|
||||||
return this.searchUserDn(username)
|
return this.searchUserDn(username)
|
||||||
.then(function (userDN: string) {
|
.then(function (userDN: string) {
|
||||||
that.ldapClient.modifyAsync(userDN, change);
|
return BluebirdPromise.join(
|
||||||
|
HashGenerator.ssha512(newPassword),
|
||||||
|
BluebirdPromise.resolve(userDN));
|
||||||
|
})
|
||||||
|
.then(function (res: string[]) {
|
||||||
|
const change = {
|
||||||
|
operation: "replace",
|
||||||
|
modification: {
|
||||||
|
userPassword: res[0]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
that.logger.debug("Password new='%s'", change.modification.userPassword);
|
||||||
|
return that.ldapClient.modifyAsync(res[1], change);
|
||||||
})
|
})
|
||||||
.then(function () {
|
.then(function () {
|
||||||
return that.ldapClient.unbindAsync();
|
return that.ldapClient.unbindAsync();
|
||||||
|
|
|
@ -4,27 +4,24 @@ import { Client } from "./Client";
|
||||||
import { SanitizedClient } from "./SanitizedClient";
|
import { SanitizedClient } from "./SanitizedClient";
|
||||||
import { ILdapClientFactory } from "./ILdapClientFactory";
|
import { ILdapClientFactory } from "./ILdapClientFactory";
|
||||||
import { LdapConfiguration } from "../configuration/Configuration";
|
import { LdapConfiguration } from "../configuration/Configuration";
|
||||||
|
|
||||||
import Ldapjs = require("ldapjs");
|
import Ldapjs = require("ldapjs");
|
||||||
import Dovehash = require("dovehash");
|
|
||||||
import Winston = require("winston");
|
import Winston = require("winston");
|
||||||
|
|
||||||
export class ClientFactory implements IClientFactory {
|
export class ClientFactory implements IClientFactory {
|
||||||
private config: LdapConfiguration;
|
private config: LdapConfiguration;
|
||||||
private ldapClientFactory: ILdapClientFactory;
|
private ldapClientFactory: ILdapClientFactory;
|
||||||
private dovehash: typeof Dovehash;
|
|
||||||
private logger: typeof Winston;
|
private logger: typeof Winston;
|
||||||
|
|
||||||
constructor(ldapConfiguration: LdapConfiguration, ldapClientFactory: ILdapClientFactory,
|
constructor(ldapConfiguration: LdapConfiguration,
|
||||||
dovehash: typeof Dovehash, logger: typeof Winston) {
|
ldapClientFactory: ILdapClientFactory,
|
||||||
|
logger: typeof Winston) {
|
||||||
this.config = ldapConfiguration;
|
this.config = ldapConfiguration;
|
||||||
this.ldapClientFactory = ldapClientFactory;
|
this.ldapClientFactory = ldapClientFactory;
|
||||||
this.dovehash = dovehash;
|
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
create(userDN: string, password: string): IClient {
|
create(userDN: string, password: string): IClient {
|
||||||
return new SanitizedClient(new Client(userDN, password, this.config, this.ldapClientFactory,
|
return new SanitizedClient(new Client(userDN, password,
|
||||||
this.dovehash, this.logger));
|
this.config, this.ldapClientFactory, this.logger));
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
import BluebirdPromise = require("bluebird");
|
||||||
|
import RandomString = require("randomstring");
|
||||||
|
import Util = require("util");
|
||||||
|
import Crypto = require("crypto");
|
||||||
|
const crypt = require("crypt3");
|
||||||
|
const shacrypt = require("shacrypt");
|
||||||
|
|
||||||
|
export class HashGenerator {
|
||||||
|
static ssha512(password: string, salt?: string): BluebirdPromise<string> {
|
||||||
|
const rounds = 500000;
|
||||||
|
const saltSize = 16;
|
||||||
|
// $6 means SHA512
|
||||||
|
const _salt = Util.format("$6$rounds=%d$%s", rounds,
|
||||||
|
(salt) ? salt : RandomString.generate(16));
|
||||||
|
|
||||||
|
const cryptAsync = BluebirdPromise.promisify<string, string, string>(crypt);
|
||||||
|
|
||||||
|
return cryptAsync(password, _salt)
|
||||||
|
.then(function (hash: string) {
|
||||||
|
return BluebirdPromise.resolve(Util.format("{CRYPT}%s", hash));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,7 +7,6 @@ import winston = require("winston");
|
||||||
import speakeasy = require("speakeasy");
|
import speakeasy = require("speakeasy");
|
||||||
import u2f = require("u2f");
|
import u2f = require("u2f");
|
||||||
import session = require("express-session");
|
import session = require("express-session");
|
||||||
|
|
||||||
import { AppConfiguration, UserConfiguration } from "../src/lib/configuration/Configuration";
|
import { AppConfiguration, UserConfiguration } from "../src/lib/configuration/Configuration";
|
||||||
import { GlobalDependencies } from "../types/Dependencies";
|
import { GlobalDependencies } from "../types/Dependencies";
|
||||||
import Server from "../src/lib/Server";
|
import Server from "../src/lib/Server";
|
||||||
|
@ -34,8 +33,7 @@ describe("test server configuration", function () {
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
session: sessionMock as any,
|
session: sessionMock as any,
|
||||||
ConnectRedis: Sinon.spy(),
|
ConnectRedis: Sinon.spy()
|
||||||
dovehash: Sinon.spy() as any
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -62,8 +62,7 @@ describe("test session configuration builder", function () {
|
||||||
session: Sinon.spy() as any,
|
session: Sinon.spy() as any,
|
||||||
speakeasy: Sinon.spy() as any,
|
speakeasy: Sinon.spy() as any,
|
||||||
u2f: Sinon.spy() as any,
|
u2f: Sinon.spy() as any,
|
||||||
winston: Sinon.spy() as any,
|
winston: Sinon.spy() as any
|
||||||
dovehash: Sinon.spy() as any
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const options = SessionConfigurationBuilder.build(configuration, deps);
|
const options = SessionConfigurationBuilder.build(configuration, deps);
|
||||||
|
@ -144,8 +143,7 @@ describe("test session configuration builder", function () {
|
||||||
session: Sinon.spy() as any,
|
session: Sinon.spy() as any,
|
||||||
speakeasy: Sinon.spy() as any,
|
speakeasy: Sinon.spy() as any,
|
||||||
u2f: Sinon.spy() as any,
|
u2f: Sinon.spy() as any,
|
||||||
winston: Sinon.spy() as any,
|
winston: Sinon.spy() as any
|
||||||
dovehash: Sinon.spy() as any
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const options = SessionConfigurationBuilder.build(configuration, deps);
|
const options = SessionConfigurationBuilder.build(configuration, deps);
|
||||||
|
|
|
@ -7,7 +7,6 @@ import { LdapClientStub } from "../mocks/ldap/LdapClientStub";
|
||||||
import Sinon = require("sinon");
|
import Sinon = require("sinon");
|
||||||
import BluebirdPromise = require("bluebird");
|
import BluebirdPromise = require("bluebird");
|
||||||
import Assert = require("assert");
|
import Assert = require("assert");
|
||||||
import Dovehash = require("dovehash");
|
|
||||||
import Winston = require("winston");
|
import Winston = require("winston");
|
||||||
|
|
||||||
describe("test authelia ldap client", function () {
|
describe("test authelia ldap client", function () {
|
||||||
|
@ -34,7 +33,7 @@ describe("test authelia ldap client", function () {
|
||||||
ldapClient.searchAsyncStub.returns(BluebirdPromise.resolve([{
|
ldapClient.searchAsyncStub.returns(BluebirdPromise.resolve([{
|
||||||
cn: "group1"
|
cn: "group1"
|
||||||
}]));
|
}]));
|
||||||
const client = new Client(ADMIN_USER_DN, ADMIN_PASSWORD, options, factory, Dovehash, Winston);
|
const client = new Client(ADMIN_USER_DN, ADMIN_PASSWORD, options, factory, Winston);
|
||||||
|
|
||||||
return client.searchGroups("user1")
|
return client.searchGroups("user1")
|
||||||
.then(function () {
|
.then(function () {
|
||||||
|
@ -80,7 +79,7 @@ describe("test authelia ldap client", function () {
|
||||||
cn: "group1"
|
cn: "group1"
|
||||||
}]));
|
}]));
|
||||||
|
|
||||||
const client = new Client(ADMIN_USER_DN, ADMIN_PASSWORD, options, factory, Dovehash, Winston);
|
const client = new Client(ADMIN_USER_DN, ADMIN_PASSWORD, options, factory, Winston);
|
||||||
|
|
||||||
return client.searchGroups("user1")
|
return client.searchGroups("user1")
|
||||||
.then(function (groups: string[]) {
|
.then(function (groups: string[]) {
|
||||||
|
|
|
@ -1,13 +1,11 @@
|
||||||
|
|
||||||
import { PasswordUpdater } from "../../src/lib/ldap/PasswordUpdater";
|
|
||||||
import { LdapConfiguration } from "../../src/lib/configuration/Configuration";
|
|
||||||
|
|
||||||
import Sinon = require("sinon");
|
import Sinon = require("sinon");
|
||||||
import BluebirdPromise = require("bluebird");
|
import BluebirdPromise = require("bluebird");
|
||||||
import Assert = require("assert");
|
import Assert = require("assert");
|
||||||
|
import { PasswordUpdater } from "../../src/lib/ldap/PasswordUpdater";
|
||||||
|
import { LdapConfiguration } from "../../src/lib/configuration/Configuration";
|
||||||
import { ClientFactoryStub } from "../mocks/ldap/ClientFactoryStub";
|
import { ClientFactoryStub } from "../mocks/ldap/ClientFactoryStub";
|
||||||
import { ClientStub } from "../mocks/ldap/ClientStub";
|
import { ClientStub } from "../mocks/ldap/ClientStub";
|
||||||
|
import { HashGenerator } from "../../src/lib/utils/HashGenerator";
|
||||||
|
|
||||||
describe("test password update", function () {
|
describe("test password update", function () {
|
||||||
const USERNAME = "username";
|
const USERNAME = "username";
|
||||||
|
@ -18,10 +16,9 @@ describe("test password update", function () {
|
||||||
|
|
||||||
let clientFactoryStub: ClientFactoryStub;
|
let clientFactoryStub: ClientFactoryStub;
|
||||||
let adminClientStub: ClientStub;
|
let adminClientStub: ClientStub;
|
||||||
|
|
||||||
let passwordUpdater: PasswordUpdater;
|
let passwordUpdater: PasswordUpdater;
|
||||||
let ldapConfig: LdapConfiguration;
|
let ldapConfig: LdapConfiguration;
|
||||||
let dovehash: any;
|
let ssha512HashGenerator: Sinon.SinonStub;
|
||||||
|
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
clientFactoryStub = new ClientFactoryStub();
|
clientFactoryStub = new ClientFactoryStub();
|
||||||
|
@ -39,19 +36,20 @@ describe("test password update", function () {
|
||||||
users_filter: "cn={0}"
|
users_filter: "cn={0}"
|
||||||
};
|
};
|
||||||
|
|
||||||
dovehash = {
|
ssha512HashGenerator = Sinon.stub(HashGenerator, "ssha512");
|
||||||
encode: Sinon.stub()
|
|
||||||
};
|
|
||||||
|
|
||||||
passwordUpdater = new PasswordUpdater(ldapConfig, clientFactoryStub);
|
passwordUpdater = new PasswordUpdater(ldapConfig, clientFactoryStub);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
afterEach(function () {
|
||||||
|
ssha512HashGenerator.restore();
|
||||||
|
});
|
||||||
|
|
||||||
describe("success", function () {
|
describe("success", function () {
|
||||||
it("should update the password successfully", function () {
|
it("should update the password successfully", function () {
|
||||||
clientFactoryStub.createStub.withArgs(ADMIN_USER_DN, ADMIN_PASSWORD)
|
clientFactoryStub.createStub.withArgs(ADMIN_USER_DN, ADMIN_PASSWORD)
|
||||||
.returns(adminClientStub);
|
.returns(adminClientStub);
|
||||||
|
|
||||||
dovehash.encode.returns("{SSHA}AQmxaKfobGY9HSQa6aDYkAWOgPGNhGYn");
|
ssha512HashGenerator.returns("{CRYPT}$6$abcdefghijklm$AQmxaKfobGY9HSQa6aDYkAWOgPGNhGYn");
|
||||||
adminClientStub.modifyPasswordStub.withArgs(USERNAME, NEW_PASSWORD).returns(BluebirdPromise.resolve());
|
adminClientStub.modifyPasswordStub.withArgs(USERNAME, NEW_PASSWORD).returns(BluebirdPromise.resolve());
|
||||||
adminClientStub.openStub.returns(BluebirdPromise.resolve());
|
adminClientStub.openStub.returns(BluebirdPromise.resolve());
|
||||||
adminClientStub.closeStub.returns(BluebirdPromise.resolve());
|
adminClientStub.closeStub.returns(BluebirdPromise.resolve());
|
||||||
|
@ -65,7 +63,7 @@ describe("test password update", function () {
|
||||||
clientFactoryStub.createStub.withArgs(ADMIN_USER_DN, ADMIN_PASSWORD)
|
clientFactoryStub.createStub.withArgs(ADMIN_USER_DN, ADMIN_PASSWORD)
|
||||||
.returns(adminClientStub);
|
.returns(adminClientStub);
|
||||||
|
|
||||||
dovehash.encode.returns("{SSHA}AQmxaKfobGY9HSQa6aDYkAWOgPGNhGYn");
|
ssha512HashGenerator.returns("{CRYPT}$6$abcdefghijklm$AQmxaKfobGY9HSQa6aDYkAWOgPGNhGYn");
|
||||||
adminClientStub.modifyPasswordStub.withArgs(USERNAME, NEW_PASSWORD)
|
adminClientStub.modifyPasswordStub.withArgs(USERNAME, NEW_PASSWORD)
|
||||||
.returns(BluebirdPromise.reject(new Error("Error while updating password")));
|
.returns(BluebirdPromise.reject(new Error("Error while updating password")));
|
||||||
adminClientStub.openStub.returns(BluebirdPromise.resolve());
|
adminClientStub.openStub.returns(BluebirdPromise.resolve());
|
||||||
|
|
|
@ -115,8 +115,7 @@ describe("Private pages of the server must not be accessible without session", f
|
||||||
session: ExpressSession,
|
session: ExpressSession,
|
||||||
winston: Winston,
|
winston: Winston,
|
||||||
speakeasy: speakeasy,
|
speakeasy: speakeasy,
|
||||||
ConnectRedis: Sinon.spy(),
|
ConnectRedis: Sinon.spy()
|
||||||
dovehash: Sinon.spy() as any
|
|
||||||
};
|
};
|
||||||
|
|
||||||
server = new Server(deps);
|
server = new Server(deps);
|
||||||
|
|
|
@ -115,8 +115,7 @@ describe("Public pages of the server must be accessible without session", functi
|
||||||
session: ExpressSession,
|
session: ExpressSession,
|
||||||
winston: Winston,
|
winston: Winston,
|
||||||
speakeasy: speakeasy,
|
speakeasy: speakeasy,
|
||||||
ConnectRedis: Sinon.spy(),
|
ConnectRedis: Sinon.spy()
|
||||||
dovehash: Sinon.spy() as any
|
|
||||||
};
|
};
|
||||||
|
|
||||||
server = new Server(deps);
|
server = new Server(deps);
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
import Assert = require("assert");
|
||||||
|
import { HashGenerator } from "../../src/lib/utils/HashGenerator";
|
||||||
|
|
||||||
|
describe("test HashGenerator", function () {
|
||||||
|
it("should compute correct ssha512 (password)", function () {
|
||||||
|
return HashGenerator.ssha512("password", "jgiCMRyGXzoqpxS3")
|
||||||
|
.then(function (hash: string) {
|
||||||
|
Assert.equal(hash, "{CRYPT}$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should compute correct ssha512 (test)", function () {
|
||||||
|
return HashGenerator.ssha512("test", "abcdefghijklmnop")
|
||||||
|
.then(function (hash: string) {
|
||||||
|
Assert.equal(hash, "{CRYPT}$6$rounds=500000$abcdefghijklmnop$sTlNGf0VO/HTQIOXemmaBbV28HUch/qhWOA1/4dsDj6CDQYhUgXbYSPL6gccAsWMr2zD5fFWwhKmPdG.yxphs.");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -6,9 +6,7 @@ import nedb = require("nedb");
|
||||||
import ldapjs = require("ldapjs");
|
import ldapjs = require("ldapjs");
|
||||||
import u2f = require("u2f");
|
import u2f = require("u2f");
|
||||||
import RedisSession = require("connect-redis");
|
import RedisSession = require("connect-redis");
|
||||||
import dovehash = require("dovehash");
|
|
||||||
|
|
||||||
export type Dovehash = typeof dovehash;
|
|
||||||
export type Speakeasy = typeof speakeasy;
|
export type Speakeasy = typeof speakeasy;
|
||||||
export type Winston = typeof winston;
|
export type Winston = typeof winston;
|
||||||
export type Session = typeof session;
|
export type Session = typeof session;
|
||||||
|
@ -19,7 +17,6 @@ export type ConnectRedis = typeof RedisSession;
|
||||||
|
|
||||||
export interface GlobalDependencies {
|
export interface GlobalDependencies {
|
||||||
u2f: U2f;
|
u2f: U2f;
|
||||||
dovehash: Dovehash;
|
|
||||||
ldapjs: Ldapjs;
|
ldapjs: Ldapjs;
|
||||||
session: Session;
|
session: Session;
|
||||||
ConnectRedis: ConnectRedis;
|
ConnectRedis: ConnectRedis;
|
||||||
|
|
Loading…
Reference in New Issue