remove admin userPassword read permission,

implement user add mod get del endpoints
This commit is contained in:
Arthur Lu 2023-12-15 23:20:43 +00:00
parent ee666f6e08
commit 77c556aa67
3 changed files with 122 additions and 11 deletions

View File

@ -5,7 +5,7 @@ delete: olcAccess
- -
add: olcAccess add: olcAccess
olcAccess: {0}to attrs=userPassword olcAccess: {0}to attrs=userPassword
by group/groupOfNames/member="cn=admins,ou=groups,$BASE_DN" write by group/groupOfNames/member="cn=admins,ou=groups,$BASE_DN" =wcdx
by self write by self write
by anonymous auth by anonymous auth
by * none by * none

View File

@ -16,6 +16,13 @@ export default class LDAP {
this.#groupsdn = `ou=groups,${basedn}`; this.#groupsdn = `ou=groups,${basedn}`;
} }
createUserBind (uid, password) {
return {
dn: `uid=${uid},${this.#peopledn}`,
password
};
}
async addUser (bind, uid, attrs) { async addUser (bind, uid, attrs) {
const logger = new LDAP_MULTIOP_LOGGER(`add ${uid}`); const logger = new LDAP_MULTIOP_LOGGER(`add ${uid}`);
await this.#client.bind(bind.dn, bind.password, logger); await this.#client.bind(bind.dn, bind.password, logger);
@ -23,6 +30,16 @@ export default class LDAP {
return logger; return logger;
} }
const userDN = `uid=${uid},${this.#peopledn}`; const userDN = `uid=${uid},${this.#peopledn}`;
if (!attrs.cn || !attrs.sn || !attrs.userPassword) {
return {
ok: false,
error: {
code: 100,
name: "UndefinedAttributeValueError",
message: "Undefined Attribute Value"
}
};
}
const entry = { const entry = {
objectClass: "inetOrgPerson", objectClass: "inetOrgPerson",
cn: attrs.cn, cn: attrs.cn,
@ -39,7 +56,9 @@ export default class LDAP {
if (!bindResult.ok) { if (!bindResult.ok) {
return bindResult; return bindResult;
} }
return await this.#client.search(`uid=${uid},${this.#peopledn}`, {}); const result = await this.#client.search(`uid=${uid},${this.#peopledn}`, {});
result.user = result.entries[0]; // assume there should only be 1 entry
return result;
} }
async modUser (bind, uid, newAttrs) { async modUser (bind, uid, newAttrs) {
@ -49,7 +68,7 @@ export default class LDAP {
return logger; return logger;
} }
for (const attr of ["cn", "sn", "userPassword"]) { for (const attr of ["cn", "sn", "userPassword"]) {
if (attr in newAttrs) { if (attr in newAttrs && newAttrs[attr]) { // attr should exist and not be undefined or null
const change = new ldap.Change({ const change = new ldap.Change({
operation: "replace", operation: "replace",
modification: { modification: {
@ -232,7 +251,7 @@ class LDAPJS_CLIENT_ASYNC_WRAPPER {
#parseError (err) { #parseError (err) {
if (err) { if (err) {
return {code: err.code, name: err.name, message: err.message}; return { code: err.code, name: err.name, message: err.message };
} }
else { else {
return null; return null;

View File

@ -1,7 +1,6 @@
import express from "express"; import express from "express";
import bodyParser from "body-parser"; import bodyParser from "body-parser";
import cookieParser from "cookie-parser"; import cookieParser from "cookie-parser";
import cors from "cors";
import morgan from "morgan"; import morgan from "morgan";
import LDAP from "./ldap.js"; import LDAP from "./ldap.js";
@ -27,18 +26,111 @@ const ldap = new LDAP(global.argv.ldapURL, global.config.basedn);
const app = express(); const app = express();
app.use(bodyParser.urlencoded({ extended: true })); app.use(bodyParser.urlencoded({ extended: true }));
app.use(cookieParser()); app.use(cookieParser());
app.use(cors({ origin: global.db.hostname }));
app.use(morgan("combined")); app.use(morgan("combined"));
// endpoint handles both adding a new user and updating an existing user including password and groups app.listen(global.argv.listenPort, () => {
app.post("/users/:userid", (req, res) => {}); console.log(`proxmoxaas-api v${global.package.version} listening on port ${global.argv.listenPort}`);
});
app.get("/users/:userid", (req, res) => {}); /**
* GET - get API version
* responses:
* - 200: {version: string}
*/
app.get("/version", (req, res) => {
res.status(200).send({ version: global.package.version });
});
app.delete("/users/:userid", (req, res) => {}); /**
* GET - echo request
* responses:
* - 200: {body: request.body, cookies: request.cookies}
*/
app.get("/echo", (req, res) => {
res.status(200).send({ body: req.body, cookies: req.cookies });
});
/**
* POST - create a new user or modify existing user attributes
*/
app.post("/users/:userid", async (req, res) => {
const params = {
userid: req.params.userid,
bind: ldap.createUserBind(req.body.binduser, req.body.bindpass),
userattrs: {
cn: req.body.usercn,
sn: req.body.usersn,
userPassword: req.body.userpassword
}
};
const checkUser = await ldap.getUser(params.bind, params.userid);
if (!checkUser.ok && checkUser.error.code === 32) { // the user does not exist, create new user
const result = await ldap.addUser(params.bind, params.userid, params.userattrs);
res.send({
ok: result.ok,
error: result.error
});
}
else if (checkUser.ok) { // the user does exist, modify the user entries
const result = await ldap.modUser(params.bind, params.userid, params.userattrs);
res.send({
ok: result.ok,
error: result.error
});
}
else { // some other error happened
res.send({
ok: checkUser.ok,
error: checkUser.error
});
}
});
/**
* GET - get user attributes
*/
app.get("/users/:userid", async (req, res) => {
const params = {
userid: req.params.userid,
bind: ldap.createUserBind(req.body.binduser, req.body.bindpass)
};
const result = await ldap.getUser(params.bind, params.userid);
if (result.ok) {
res.send({
ok: result.ok,
error: result.error,
user: result.user
});
}
else {
res.send({
ok: result.ok,
error: result.error
});
}
});
/**
* DELETE - delete user
*/
app.delete("/users/:userid", async (req, res) => {
const params = {
userid: req.params.userid,
bind: ldap.createUserBind(req.body.binduser, req.body.bindpass)
};
const result = await ldap.delUser(params.bind, params.userid);
res.send({
ok: result.ok,
error: result.error
});
});
app.post("/groups/:groupid", (req, res) => {}); app.post("/groups/:groupid", (req, res) => {});
app.get("/groups/:groupid", (req, res) => {}); app.get("/groups/:groupid", (req, res) => {});
app.delete("/groups/:groupid", (req, res) => {}); app.delete("/groups/:groupid", (req, res) => {});
app.get("/groups/:groupid/members", (req, res) => {});
app.post("/groups/:groupid/members", (req, res) => {});