Skip to content

Commit

Permalink
version: 6.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
maxime-beguin committed Nov 10, 2022
1 parent 0e16f1e commit 504c845
Show file tree
Hide file tree
Showing 14 changed files with 252 additions and 0 deletions.
4 changes: 4 additions & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export { LdapServerMockConfiguration } from './lib/configuration';
export { LdapServerMockLogger } from './lib/logger';
export { LdapServerMock } from './lib/server';
export { LdapUser } from './lib/user';
7 changes: 7 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.LdapServerMock = exports.LdapServerMockLogger = void 0;
var logger_1 = require("./lib/logger");
Object.defineProperty(exports, "LdapServerMockLogger", { enumerable: true, get: function () { return logger_1.LdapServerMockLogger; } });
var server_1 = require("./lib/server");
Object.defineProperty(exports, "LdapServerMock", { enumerable: true, get: function () { return server_1.LdapServerMock; } });
6 changes: 6 additions & 0 deletions lib/configuration.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export interface LdapServerMockConfiguration {
readonly certPath?: string;
readonly certKeyPath?: string;
readonly port?: number;
readonly searchBase?: string;
}
2 changes: 2 additions & 0 deletions lib/configuration.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
35 changes: 35 additions & 0 deletions lib/ldapTypes.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/// <reference types="node" />
import { Socket } from 'node:net';
import { DN, Filter } from 'ldapjs';
export interface LdapState {
readonly bindDN: DN;
}
export interface LdapRequest {
readonly connection: Socket & LdapState;
readonly dn: DN;
readonly logId: string;
}
export interface LdapResponse {
readonly end: (code?: number) => void;
}
export interface LdapBindRequest extends LdapRequest {
readonly authentication: string;
readonly credentials: string;
readonly name: DN;
readonly version: string;
}
export interface LdapSearchRequest extends LdapRequest {
readonly attributes: string[];
readonly baseObject: DN;
readonly filter: Filter;
readonly scope: 'base' | 'one' | 'sub';
readonly sizeLimit: number;
readonly timeLimit: number;
readonly typesOnly: boolean;
}
export interface LdapBindResponse extends LdapResponse {
}
export interface LdapSearchResponse extends LdapResponse {
readonly send: (entry: any) => void;
}
export declare type LdapNext = (error?: Error) => void;
2 changes: 2 additions & 0 deletions lib/ldapTypes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
3 changes: 3 additions & 0 deletions lib/logger.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export declare class LdapServerMockLogger {
info(...args: any[]): void;
}
9 changes: 9 additions & 0 deletions lib/logger.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.LdapServerMockLogger = void 0;
class LdapServerMockLogger {
info(...args) {
console.info(...args);
}
}
exports.LdapServerMockLogger = LdapServerMockLogger;
16 changes: 16 additions & 0 deletions lib/server.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/// <reference types="node" />
import { LdapServerMockConfiguration } from './configuration';
import { LdapServerMockLogger } from './logger';
import { LdapUser } from './user';
export declare class LdapServerMock {
private _users;
private _connectedSockets;
private _port;
private _ldapServer;
private _logger;
private _searchBase;
private _server?;
constructor(_users: LdapUser[], serverConfiguration: LdapServerMockConfiguration, certificatePublicKey?: Buffer, certificatePrivateKey?: Buffer, logger?: LdapServerMockLogger);
start(): Promise<void>;
stop(): Promise<void>;
}
66 changes: 66 additions & 0 deletions lib/server.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.LdapServerMock = void 0;
const ldapjs_1 = require("ldapjs");
const logger_1 = require("./logger");
class LdapServerMock {
constructor(_users, serverConfiguration, certificatePublicKey, certificatePrivateKey, logger) {
this._users = _users;
this._connectedSockets = new Set();
this._port = serverConfiguration.port ?? 3004;
this._searchBase = serverConfiguration.searchBase ?? 'dc=test';
this._ldapServer = (0, ldapjs_1.createServer)({
...(certificatePublicKey && { certificate: certificatePublicKey }),
...(certificatePrivateKey && { key: certificatePrivateKey })
});
this._logger = logger ?? new logger_1.LdapServerMockLogger();
}
async start() {
return new Promise((resolve, reject) => {
this._ldapServer.bind(this._searchBase, (request, response, next) => {
response.end();
});
this._ldapServer.search(this._searchBase, (request, response, next) => {
for (const user of this._users) {
if (request.filter.matches(user.attributes)) {
response.send(user);
}
}
response.end();
});
this._logger.info('starting');
this._server = this._ldapServer.listen(this._port, () => {
const info = this._server?.address();
this._logger.info('started on port %i', info.port);
if (process.connected && process.send) {
process.send({ status: 'started' });
}
resolve();
});
this._server.on('connection', (socket) => {
this._connectedSockets.add(socket);
socket.on('close', () => {
this._connectedSockets.delete(socket);
});
});
});
}
async stop() {
return new Promise((resolve, reject) => {
this._logger.info('stopping');
if (this._server) {
for (const socket of this._connectedSockets.values()) {
socket.destroy();
}
this._server.close(() => {
this._logger.info('stopped');
resolve();
});
}
else {
resolve();
}
});
}
}
exports.LdapServerMock = LdapServerMock;
6 changes: 6 additions & 0 deletions lib/user.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export interface LdapUser {
readonly dn: string;
readonly attributes: {
[key: string]: boolean | string | number | string[] | number[] | boolean[];
};
}
2 changes: 2 additions & 0 deletions lib/user.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
2 changes: 2 additions & 0 deletions server.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/usr/bin/env node
export {};
92 changes: 92 additions & 0 deletions server.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
#!/usr/bin/env node
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const fs = tslib_1.__importStar(require("node:fs/promises"));
const node_path_1 = tslib_1.__importDefault(require("node:path"));
const server_1 = require("./lib/server");
function exit(error, code = 1) {
if (error) {
console.log('error: %s', error);
}
printHelp();
process.exitCode = 1;
}
function getArguments() {
let confFilePath = '';
let databaseFilePath = '';
for (let i = 2; i < process.argv.length; i++) {
const argChunks = process.argv[i].match(/--(conf|database)=(.*)/);
if (!argChunks) {
break;
}
switch (argChunks[1]) {
case 'conf':
confFilePath = node_path_1.default.resolve(argChunks[2]);
break;
case 'database':
databaseFilePath = node_path_1.default.resolve(argChunks[2]);
break;
default:
throw new Error(`unexpected option ${argChunks[1]}`);
break;
}
}
if (!confFilePath) {
throw new Error('missing --conf option');
}
if (!databaseFilePath) {
throw new Error('missing --database option');
}
return { confFilePath, databaseFilePath };
}
async function main() {
let args;
try {
args = getArguments();
}
catch (error) {
exit(error.message);
return;
}
let configurationFilePath = args.confFilePath;
let databaseFilePath = args.databaseFilePath;
process.on('SIGTERM', async () => {
if (server) {
await server.stop();
}
});
let serverConfiguration;
let users = [];
try {
serverConfiguration = require(configurationFilePath);
users = require(databaseFilePath);
}
catch (error) {
exit(error.message);
return;
}
let certificatePublicKey;
let certificatePrivateKey;
if (serverConfiguration.certPath && serverConfiguration.certKeyPath) {
try {
certificatePublicKey = await fs.readFile(node_path_1.default.resolve(serverConfiguration.certPath));
certificatePrivateKey = await fs.readFile(node_path_1.default.resolve(serverConfiguration.certKeyPath));
}
catch (error) {
exit(error.message);
return;
}
}
const server = new server_1.LdapServerMock(users, serverConfiguration, certificatePublicKey, certificatePrivateKey);
await server.start();
}
function printHelp() {
console.log(`
usage: npx ldap-server-mock options
options:
--conf="file" relative or absolute path to the server configuration file
--database="file" relative or absolute path to the file containing LDAP users in JSON format
`);
}
main();

0 comments on commit 504c845

Please sign in to comment.