fix openldap init script paas user token saving,
add config file with BASE_DN, add async wrapper class for ldap client, implement addUser getUser delUser, add and implement addGroup delGroup methods
This commit is contained in:
parent
0896ea4c81
commit
10116da900
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,3 +1,4 @@
|
||||
**/package-lock.json
|
||||
**/node_modules
|
||||
**/*.token
|
||||
**/*.token
|
||||
**/config.json
|
3
config/config.template.json
Normal file
3
config/config.template.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"basedn": "dc=example,dc=com"
|
||||
}
|
@ -2,7 +2,7 @@ export BASE_DN=''
|
||||
read -p "Base DN: " BASE_DN
|
||||
|
||||
export PAAS_PASSWD=$(tr -dc 'A-Za-z0-9!"#$%&'\''()*+,-./:;<=>?@[\]^_`{|}~' </dev/urandom | head -c 256; echo)
|
||||
echo "$PAAS_PASSWD" > paas.token
|
||||
echo "$PAAS_PASSWD" -n > paas.token
|
||||
echo "Saved PAAS Authentication Token (password) to paas.token"
|
||||
|
||||
envsubst '$BASE_DN' < auth.template.ldif > auth.ldif
|
||||
|
11
src/config.js
Normal file
11
src/config.js
Normal file
@ -0,0 +1,11 @@
|
||||
import { readFileSync } from "fs";
|
||||
import { exit } from "process";
|
||||
export default () => {
|
||||
try {
|
||||
return JSON.parse(readFileSync(global.argv.configPath));
|
||||
}
|
||||
catch (e) {
|
||||
console.log(`Error: ${global.argv.configPath} was not found. Please follow the directions in the README to initialize localdb.json.`);
|
||||
exit(1);
|
||||
}
|
||||
};
|
184
src/ldap.js
184
src/ldap.js
@ -1,31 +1,179 @@
|
||||
import ldap from "ldapjs";
|
||||
import { exit } from "process";
|
||||
|
||||
export class LDAP {
|
||||
export default class LDAP {
|
||||
#client = null;
|
||||
#paasBind = null;
|
||||
#baseDN = null;
|
||||
#basedn = null;
|
||||
#peopledn = null;
|
||||
#groupsdn = null;
|
||||
|
||||
constructor (url, paasBind, baseDN) {
|
||||
constructor (url, basedn) {
|
||||
const opts = {
|
||||
url
|
||||
};
|
||||
this.#client = ldap.createClient(opts);
|
||||
this.#client.on("connectError", (err) => {
|
||||
console.err(`Error: could not establish connection to ${url}`);
|
||||
console.err(err);
|
||||
exit(1);
|
||||
});
|
||||
|
||||
this.#paasBind = paasBind;
|
||||
this.#baseDN = baseDN;
|
||||
this.#client = new LDAPJS_CLIENT_ASYNC_WRAPPER(opts);
|
||||
this.#basedn = basedn;
|
||||
this.#peopledn = `ou=people,${basedn}`;
|
||||
this.#groupsdn = `ou=groups,${basedn}`;
|
||||
}
|
||||
|
||||
addUser (uid, entry) {}
|
||||
async addUser (bind, uid, attrs) {
|
||||
const result = await this.#client.bind(bind.dn, bind.password);
|
||||
if (!result.ok) {
|
||||
return result;
|
||||
}
|
||||
const userDN = `uid=${uid},${this.#peopledn}`;
|
||||
const entry = {
|
||||
objectClass: "inetOrgPerson",
|
||||
cn: attrs.cn,
|
||||
sn: attrs.sn,
|
||||
uid,
|
||||
userPassword: attrs.userPassword
|
||||
};
|
||||
return await this.#client.add(userDN, entry);
|
||||
}
|
||||
|
||||
getUser (uid) {}
|
||||
async getUser (bind, uid) {
|
||||
const result = await this.#client.bind(bind.dn, bind.password);
|
||||
if (!result.ok) {
|
||||
return result;
|
||||
}
|
||||
const opts = {
|
||||
filter: `(uid=${uid})`,
|
||||
scope: "sub"
|
||||
};
|
||||
return await this.#client.search(this.#peopledn, opts);
|
||||
}
|
||||
|
||||
modUser (uid, entry) {}
|
||||
async modUser (bind, uid, attrs) { }
|
||||
|
||||
delUser (uid) {}
|
||||
async delUser (bind, uid) {
|
||||
const result = await this.#client.bind(bind.dn, bind.password);
|
||||
if (!result.ok) {
|
||||
return result;
|
||||
}
|
||||
const userDN = `uid=${uid},${this.#peopledn}`;
|
||||
return await this.#client.del(userDN);
|
||||
}
|
||||
|
||||
async addGroup (bind, gid, attrs) {
|
||||
const result = await this.#client.bind(bind.dn, bind.password);
|
||||
if (!result.ok) {
|
||||
return result;
|
||||
}
|
||||
const groupDN = `cn=${gid},${this.#groupsdn}`;
|
||||
const entry = {
|
||||
objectClass: "groupOfNames",
|
||||
member: "",
|
||||
cn: gid
|
||||
};
|
||||
return await this.#client.add(groupDN, entry);
|
||||
}
|
||||
|
||||
async delGroup (bind, gid) {
|
||||
const result = await this.#client.bind(bind.dn, bind.password);
|
||||
if (!result.ok) {
|
||||
return result;
|
||||
}
|
||||
const groupDN = `cn=${gid},${this.#groupsdn}`;
|
||||
return await this.#client.del(groupDN);
|
||||
}
|
||||
|
||||
async addUserToGroup (bind, uid, gid) {
|
||||
|
||||
}
|
||||
|
||||
async delUserFromGroup (bind, uid, gid) { }
|
||||
}
|
||||
|
||||
class LDAPJS_CLIENT_ASYNC_WRAPPER {
|
||||
#client = null;
|
||||
constructor (opts) {
|
||||
this.#client = ldap.createClient(opts);
|
||||
this.#client.on("error", (err) => {
|
||||
console.error(`An error occured:\n${err}`);
|
||||
});
|
||||
this.#client.on("connectError", (err) => {
|
||||
console.error(`Unable to connect to ${opts.url}:\n${err}`);
|
||||
});
|
||||
}
|
||||
|
||||
bind (dn, password) {
|
||||
return new Promise((resolve) => {
|
||||
this.#client.bind(dn, password, (err) => {
|
||||
if (err) {
|
||||
resolve({ ok: false, error: err });
|
||||
}
|
||||
else {
|
||||
resolve({ ok: true });
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
add (dn, entry) {
|
||||
return new Promise((resolve) => {
|
||||
this.#client.add(dn, entry, (err) => {
|
||||
if (err) {
|
||||
resolve({ ok: false, error: err });
|
||||
}
|
||||
else {
|
||||
resolve({ ok: true });
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
search (base, options) {
|
||||
return new Promise((resolve) => {
|
||||
this.#client.search(base, options, (err, res) => {
|
||||
if (err) {
|
||||
return resolve({ ok: false, error: err });
|
||||
}
|
||||
const results = { ok: false, status: 1, message: "", entries: [] };
|
||||
res.on("searchRequest", (searchRequest) => { });
|
||||
res.on("searchEntry", (entry) => {
|
||||
results.entries.push({ dn: entry.pojo.objectName, attributes: entry.pojo.attributes });
|
||||
});
|
||||
res.on("searchReference", (referral) => { });
|
||||
res.on("error", (error) => {
|
||||
results.ok = error.status === 0;
|
||||
results.status = error.status;
|
||||
results.message = error.message;
|
||||
resolve(results);
|
||||
});
|
||||
res.on("end", (result) => {
|
||||
results.ok = result.status === 0;
|
||||
results.status = result.status;
|
||||
results.message = result.message;
|
||||
resolve(results);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
modify (name, changes) {
|
||||
return new Promise((resolve) => {
|
||||
this.#client.modify(name, changes, (err) => {
|
||||
if (err) {
|
||||
resolve({ ok: false, error: err });
|
||||
}
|
||||
else {
|
||||
resolve({ ok: true });
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
del (dn) {
|
||||
return new Promise((resolve) => {
|
||||
this.#client.del(dn, (err) => {
|
||||
if (err) {
|
||||
resolve({ ok: false, error: err });
|
||||
}
|
||||
else {
|
||||
resolve({ ok: true });
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
49
src/main.js
49
src/main.js
@ -2,29 +2,56 @@ import express from "express";
|
||||
import bodyParser from "body-parser";
|
||||
import cookieParser from "cookie-parser";
|
||||
import morgan from "morgan";
|
||||
import LDAP from "ldap.js";
|
||||
|
||||
import LDAP from "./ldap.js";
|
||||
import _config from "./config.js";
|
||||
import _package from "./package.js";
|
||||
|
||||
import parseArgs from "minimist";
|
||||
|
||||
global.argv = parseArgs(process.argv.slice(2), {
|
||||
default: {
|
||||
package: "package.json",
|
||||
listenPort: 8082,
|
||||
ldapURL: "ldap://localhost",
|
||||
configPath: "config/config.json"
|
||||
}
|
||||
});
|
||||
|
||||
global.package = _package(global.argv.package);
|
||||
global.config = _config(global.argv.configPath);
|
||||
|
||||
const ldap = new LDAP(global.argv.ldapURL, global.config.basedn);
|
||||
|
||||
/* import { readFileSync } from "fs";
|
||||
const paas = {
|
||||
dn: `uid=paas,ou=people,${global.config.basedn}`,
|
||||
password: readFileSync("paas.token").toString()
|
||||
};
|
||||
console.log(await ldap.addUser(paas, "testuser", { cn: "test", sn: "test", userPassword: "test" }));
|
||||
console.log((await ldap.getUser(paas, "testuser")).entries[0].attributes);
|
||||
console.log(await ldap.delUser(paas, "testuser"));
|
||||
console.log(await ldap.addGroup(paas, "testgroup"));
|
||||
console.log(await ldap.delGroup(paas, "testgroup"));
|
||||
exit(0); */
|
||||
|
||||
const app = express();
|
||||
app.use(bodyParser.urlencoded({ extended: true }));
|
||||
app.use(cookieParser());
|
||||
app.use(morgan("combined"));
|
||||
|
||||
app.listen(global.db.listenPort, () => {
|
||||
console.log(`proxmoxaas-api v${global.api.version} listening on port ${global.db.listenPort}`);
|
||||
app.listen(global.argv.listenPort, () => {
|
||||
console.log(`proxmoxaas-ldap v${global.package.version} listening on port ${global.argv.listenPort}`);
|
||||
});
|
||||
|
||||
app.get("/:user", (req, res) => {
|
||||
|
||||
app.get("/:user", async (req, res) => {
|
||||
});
|
||||
|
||||
app.post("/:user", (req, res) => {
|
||||
|
||||
app.post("/:user", async (req, res) => {
|
||||
});
|
||||
|
||||
app.delete("/:user", (req, res) => {
|
||||
|
||||
app.delete("/:user", async (req, res) => {
|
||||
});
|
||||
|
||||
app.post("/:user/password", (req, res) => {
|
||||
|
||||
app.post("/:user/password", async (req, res) => {
|
||||
});
|
||||
|
11
src/package.js
Normal file
11
src/package.js
Normal file
@ -0,0 +1,11 @@
|
||||
import { readFileSync } from "fs";
|
||||
import { exit } from "process";
|
||||
export default (path) => {
|
||||
try {
|
||||
return JSON.parse(readFileSync(path));
|
||||
}
|
||||
catch (e) {
|
||||
console.log(`Error: ${path} was not found.`);
|
||||
exit(1);
|
||||
}
|
||||
};
|
Loading…
Reference in New Issue
Block a user