/
createUser.ts
142 lines (108 loc) · 4.35 KB
/
createUser.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
import { parsePlaceholder } from "@scow/lib-config";
import { FastifyRequest } from "fastify";
import ldapjs from "ldapjs";
import { CreateUserInfo, CreateUserResult } from "src/auth/AuthProvider";
import { searchOne, useLdap } from "src/auth/ldap/helpers";
import { modifyPassword } from "src/auth/ldap/password";
import { AuthConfigSchema, NewUserGroupStrategy } from "src/config/auth";
import { promisify } from "util";
/*
* Apply extra props.
* @param obj the object to apply extra props
* @param extraProps the extraProps config
* @param placeholderObj the object where the values of placeholders ({{ }}) are from
*/
const applyExtraProps = (obj: object, extraProps: Record<string, string | string[]>, placeholderObj: object) => {
for (const key in extraProps) {
const value = extraProps[key];
if (Array.isArray(value)) {
obj[key] = value.map((x) => parsePlaceholder(x, placeholderObj));
} else {
obj[key] = parsePlaceholder(value, placeholderObj);
}
}
};
export async function createUser(
info: CreateUserInfo, req: FastifyRequest, ldap: NonNullable<AuthConfigSchema["ldap"]>,
): Promise<CreateUserResult> {
const id = info.id + ldap.addUser.uidStart;
await useLdap(req.log, ldap)(async (client) => {
const userDn =
`${ldap.addUser.userIdDnKey ?? ldap.attrs.uid}=${info.identityId},` +
`${ldap.addUser.userBase}`;
const userEntry: Record<string, string | string[] | number> = {
[ldap.attrs.uid]: info.identityId,
sn: info.identityId,
loginShell: "/bin/bash",
objectClass: ["inetOrgPerson", "posixAccount", "shadowAccount"],
homeDirectory: parsePlaceholder(ldap.addUser.homeDir, { userId: info.identityId }),
uidNumber: id,
gidNumber: id,
};
if (ldap.attrs.name) {
userEntry[ldap.attrs.name] = info.name;
}
if (ldap.attrs.mail) {
userEntry[ldap.attrs.mail] = info.mail;
}
// parse attributes
if (ldap.addUser.extraProps) {
applyExtraProps(userEntry, ldap.addUser.extraProps, userEntry);
}
const add = promisify(client.add.bind(client));
if (ldap.addUser.groupStrategy === NewUserGroupStrategy.newGroupPerUser) {
req.log.info("ldap.addUser.groupStrategy is newGroupPerUser. Creating new group for the user.");
const config = ldap.addUser.newGroupPerUser!;
const groupDn = `${config.groupIdDnKey ?? ldap.attrs.uid}=${info.identityId},${config.groupBase}`;
const groupEntry = {
objectClass: ["posixGroup"],
memberUid: info.identityId,
gidNumber: id,
};
userEntry["gidNumber"] = id;
if (config.extraProps) {
applyExtraProps(groupEntry, config.extraProps, userEntry);
}
req.log.info("Adding group %s with entry info %o", groupDn, groupEntry);
await add(groupDn, groupEntry);
}
if (ldap.addUser.groupStrategy === NewUserGroupStrategy.oneGroupForAllUsers) {
const config = ldap.addUser.oneGroupForAllUsers!;
req.log.info("ldap.addUser.groupStrategy is one-group-for-all-users.");
req.log.info("Using existing group %s for the user", config.gidNumber);
userEntry["gidNumber"] = config.gidNumber;
}
req.log.info("Adding people %s with entry info %o", userDn, userEntry);
await add(userDn, userEntry);
// set password as admin user
await modifyPassword(userDn, undefined, info.password, client);
// Add user to ldap group
const addUserToLdapGroup = ldap.addUser.addUserToLdapGroup;
if (addUserToLdapGroup) {
// get existing members
req.log.info("Adding %s to group %s", userDn, addUserToLdapGroup);
const members = await searchOne(req.log, client, addUserToLdapGroup, {
attributes: ["member"],
}, (entry) => {
const member = entry.attributes.find((x) => x.json.type === "member");
if (!member) {
return undefined;
}
return { members: member.json.vals };
});
if (!members) {
req.log.error("Didn't find LDAP group %s", addUserToLdapGroup);
throw { code: "INTERNAL_ERROR" };
}
// add the dn of the new user to the value
const modify = promisify(client.modify.bind(client));
await modify(addUserToLdapGroup, new ldapjs.Change({
operation: "add",
modification: {
"member": members.members.concat(userDn),
},
}));
}
});
return "OK";
}