ldap-rest 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/index.mjs +8 -7
- package/dist/abstract/ldapFlat.js +1 -1
- package/dist/abstract/plugin.js +1 -1
- package/dist/abstract/twakePlugin.js +1 -1
- package/dist/bin/index.js +1 -1
- package/dist/config/args.js +1 -1
- package/dist/config/schema.js +1 -1
- package/dist/lib/changeContext.js +1 -1
- package/dist/lib/entitySchema/validator.js +1 -0
- package/dist/lib/expressFormatedResponses.js +1 -1
- package/dist/lib/health.js +1 -0
- package/dist/lib/instanceProviders.js +1 -1
- package/dist/lib/ldapActions.js +1 -1
- package/dist/lib/metrics.js +1 -0
- package/dist/lib/requestContext.js +1 -1
- package/dist/lib/shutdown.js +1 -0
- package/dist/lib/staticFiles.js +1 -0
- package/dist/lib/storage/store.js +1 -1
- package/dist/lib/utils.js +1 -1
- package/dist/logger/winston.js +1 -1
- package/dist/plugins/auth/crowdsec.js +1 -1
- package/dist/plugins/auth/openidconnect.js +1 -1
- package/dist/plugins/demo/helloworld.js +1 -1
- package/dist/plugins/ldap/bulkImport.js +1 -1
- package/dist/plugins/ldap/flatGeneric.js +1 -1
- package/dist/plugins/ldap/groups.js +1 -1
- package/dist/plugins/ldap/organizations.js +1 -1
- package/dist/plugins/metrics.js +1 -0
- package/dist/plugins/rabbitmq.js +1 -1
- package/dist/plugins/scim/scim.js +1 -1
- package/dist/plugins/static.js +1 -1
- package/dist/plugins/storage/file.js +1 -1
- package/dist/plugins/storage/postgres.js +1 -1
- package/dist/plugins/storage/valkey.js +1 -1
- package/dist/plugins/storage.js +1 -1
- package/dist/plugins/twake/calendar.js +1 -1
- package/dist/plugins/twake/clouderyProvision.js +1 -1
- package/dist/plugins/twake/cozyProvision.js +1 -1
- package/dist/plugins/twake/drive.js +1 -1
- package/dist/plugins/twake/james.js +1 -1
- package/dist/plugins/twake/migrationProxy.js +1 -0
- package/dist/plugins/weblogs.js +1 -1
- package/dist/src/abstract/ldapFlat.d.ts +3 -13
- package/dist/src/abstract/plugin.d.ts +20 -0
- package/dist/src/abstract/twakePlugin.d.ts +23 -1
- package/dist/src/bin/index.d.ts +46 -1
- package/dist/src/config/args.d.ts +12 -1
- package/dist/src/lib/changeContext.d.ts +11 -0
- package/dist/src/lib/entitySchema/validator.d.ts +64 -0
- package/dist/src/lib/expressFormatedResponses.d.ts +19 -0
- package/dist/src/lib/health.d.ts +63 -0
- package/dist/src/lib/instanceProviders.d.ts +4 -0
- package/dist/src/lib/ldapActions.d.ts +28 -0
- package/dist/src/lib/metrics.d.ts +44 -0
- package/dist/src/lib/requestContext.d.ts +40 -0
- package/dist/src/lib/shutdown.d.ts +20 -0
- package/dist/src/lib/staticFiles.d.ts +33 -0
- package/dist/src/lib/storage/store.d.ts +8 -0
- package/dist/src/lib/utils.d.ts +9 -0
- package/dist/src/logger/winston.d.ts +4 -0
- package/dist/src/plugins/ldap/groups.d.ts +18 -3
- package/dist/src/plugins/ldap/organizations.d.ts +3 -5
- package/dist/src/plugins/metrics.d.ts +17 -0
- package/dist/src/plugins/rabbitmq.d.ts +37 -1
- package/dist/src/plugins/static.d.ts +12 -0
- package/dist/src/plugins/storage/file.d.ts +4 -0
- package/dist/src/plugins/storage/postgres.d.ts +7 -14
- package/dist/src/plugins/storage/valkey.d.ts +2 -15
- package/dist/src/plugins/storage.d.ts +8 -0
- package/dist/src/plugins/twake/drive.d.ts +8 -0
- package/dist/src/plugins/twake/james.d.ts +2 -0
- package/dist/src/plugins/twake/migrationProxy.d.ts +71 -0
- package/docs/client-development/api/reference.md +5 -9
- package/docs/client-development/api/rest-api.md +4 -10
- package/docs/client-development/schemas/README.md +60 -21
- package/docs/plugin-development/README.md +15 -13
- package/docs/plugin-development/dependencies.md +8 -0
- package/docs/plugin-development/hooks.md +1 -1
- package/docs/usage/README.md +1 -0
- package/docs/usage/configuration.md +49 -11
- package/docs/usage/operations.md +193 -0
- package/docs/usage/plugins/README.md +2 -0
- package/docs/usage/plugins/auth/authz-per-branch.md +2 -1
- package/docs/usage/plugins/integrations/README.md +8 -4
- package/docs/usage/plugins/integrations/mail-migration.md +102 -0
- package/docs/usage/plugins/integrations/scim.md +4 -2
- package/docs/usage/plugins/ldap/bulk-import.md +3 -1
- package/docs/usage/plugins/ldap/flat-generic.md +5 -2
- package/docs/usage/plugins/ldap/on-change.md +2 -1
- package/docs/usage/plugins/ldap/organizations.md +7 -7
- package/docs/usage/plugins/utilities/metrics.md +21 -0
- package/docs/usage/plugins/utilities/static.md +16 -8
- package/docs/usage/plugins/utilities/storage.md +7 -0
- package/docs/usage/plugins/utilities/weblogs.md +51 -30
- package/docs/usage/upgrading.md +71 -0
- package/package.json +11 -2
- package/static/schemas/example/README.md +1 -0
|
@@ -18,6 +18,9 @@ No additional configuration required.
|
|
|
18
18
|
|
|
19
19
|
### Request Logging
|
|
20
20
|
|
|
21
|
+
Each line carries the `requestId` of the answer's `X-Request-Id`, see
|
|
22
|
+
[operations](../../operations.md#request-id).
|
|
23
|
+
|
|
21
24
|
Each request is logged when it arrives:
|
|
22
25
|
|
|
23
26
|
```
|
|
@@ -31,26 +34,31 @@ Each response is logged when completed at **notice** level (between info and war
|
|
|
31
34
|
```json
|
|
32
35
|
{
|
|
33
36
|
"level": "notice",
|
|
34
|
-
"message":
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
"message": {
|
|
38
|
+
"requestId": "6effd260-b079-4335-b727-544189ed33a6",
|
|
39
|
+
"method": "GET",
|
|
40
|
+
"url": "/api/v1/ldap/users",
|
|
41
|
+
"status": 200,
|
|
42
|
+
"duration": 45,
|
|
43
|
+
"ip": "10.0.9.12",
|
|
44
|
+
"user": "admin"
|
|
45
|
+
},
|
|
46
|
+
"requestId": "6effd260-b079-4335-b727-544189ed33a6",
|
|
47
|
+
"timestamp": "2026-10-26T18:07:03.286Z"
|
|
40
48
|
}
|
|
41
49
|
```
|
|
42
50
|
|
|
43
51
|
## Log Fields
|
|
44
52
|
|
|
45
|
-
| Field
|
|
46
|
-
|
|
|
47
|
-
| `
|
|
48
|
-
| `
|
|
49
|
-
| `method`
|
|
50
|
-
| `url`
|
|
51
|
-
| `status`
|
|
52
|
-
| `
|
|
53
|
-
| `error`
|
|
53
|
+
| Field | Description | Example |
|
|
54
|
+
| ----------- | ------------------------------- | ------------------------------ |
|
|
55
|
+
| `user` | Authenticated user (if any) | `admin` |
|
|
56
|
+
| `requestId` | The answer's `X-Request-Id` | `6effd260-b079-…` |
|
|
57
|
+
| `method` | HTTP method | `GET`, `POST`, `PUT`, `DELETE` |
|
|
58
|
+
| `url` | Full URL including query params | `/api/v1/ldap/users?match=*` |
|
|
59
|
+
| `status` | HTTP status code | `200`, `404`, `500` |
|
|
60
|
+
| `duration` | Request duration, in ms | `45`, `123` |
|
|
61
|
+
| `error` | Error message (if applicable) | `Connection timeout` |
|
|
54
62
|
|
|
55
63
|
## Enriching the Log Line From Another Plugin
|
|
56
64
|
|
|
@@ -77,6 +85,7 @@ Output:
|
|
|
77
85
|
"level": "notice",
|
|
78
86
|
"message": {
|
|
79
87
|
"uids": ["jdoe", "asmith"],
|
|
88
|
+
"requestId": "6effd260-b079-4335-b727-544189ed33a6",
|
|
80
89
|
"method": "POST",
|
|
81
90
|
"url": "/api/_getldapentries",
|
|
82
91
|
"status": 200,
|
|
@@ -89,7 +98,7 @@ Output:
|
|
|
89
98
|
|
|
90
99
|
Notes:
|
|
91
100
|
|
|
92
|
-
- Core fields (`method`, `url`, `status`, `duration`, `ip`, `user`, `error`)
|
|
101
|
+
- Core fields (`requestId`, `method`, `url`, `status`, `duration`, `ip`, `user`, `error`)
|
|
93
102
|
always take precedence: a plugin cannot overwrite them.
|
|
94
103
|
- The value must be set **before** the response completes (i.e. before
|
|
95
104
|
`res.json()` / `res.end()`), since the entry is written on the `finish` event.
|
|
@@ -319,27 +328,40 @@ res.on('close', () => {
|
|
|
319
328
|
Logs are in JSON format for easy parsing:
|
|
320
329
|
|
|
321
330
|
```bash
|
|
322
|
-
cat app.log | jq 'select(.status >= 400)'
|
|
331
|
+
cat app.log | jq 'select(.message.status? >= 400)'
|
|
323
332
|
```
|
|
324
333
|
|
|
325
334
|
Filters 4xx and 5xx responses:
|
|
326
335
|
|
|
327
336
|
```json
|
|
328
337
|
{
|
|
329
|
-
"level": "
|
|
330
|
-
"message":
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
338
|
+
"level": "notice",
|
|
339
|
+
"message": {
|
|
340
|
+
"requestId": "6effd260-b079-4335-b727-544189ed33a6",
|
|
341
|
+
"method": "GET",
|
|
342
|
+
"url": "/api/v1/ldap/users/notfound",
|
|
343
|
+
"status": 404,
|
|
344
|
+
"duration": 12,
|
|
345
|
+
"ip": "10.0.9.12"
|
|
346
|
+
},
|
|
347
|
+
"requestId": "6effd260-b079-4335-b727-544189ed33a6",
|
|
348
|
+
"timestamp": "2026-10-26T18:07:03.286Z"
|
|
334
349
|
}
|
|
335
350
|
```
|
|
336
351
|
|
|
352
|
+
The lines of one request, the access line and what the server logged while
|
|
353
|
+
serving it:
|
|
354
|
+
|
|
355
|
+
```bash
|
|
356
|
+
cat app.log | jq 'select(.requestId == "6effd260-b079-4335-b727-544189ed33a6")'
|
|
357
|
+
```
|
|
358
|
+
|
|
337
359
|
### Statistics
|
|
338
360
|
|
|
339
361
|
Generate request statistics:
|
|
340
362
|
|
|
341
363
|
```bash
|
|
342
|
-
cat app.log | jq -r '.message
|
|
364
|
+
cat app.log | jq -r 'select(.message.method?) | .message.method' | sort | uniq -c
|
|
343
365
|
```
|
|
344
366
|
|
|
345
367
|
Output:
|
|
@@ -356,8 +378,7 @@ Output:
|
|
|
356
378
|
Average response time per endpoint:
|
|
357
379
|
|
|
358
380
|
```bash
|
|
359
|
-
cat app.log | jq -r 'select(.
|
|
360
|
-
sed 's/ms$//' | \
|
|
381
|
+
cat app.log | jq -r 'select(.message.duration?) | "\(.message.url) \(.message.duration)"' | \
|
|
361
382
|
awk '{sum[$1]+=$2; count[$1]++} END {for (url in sum) print url, sum[url]/count[url] "ms"}'
|
|
362
383
|
```
|
|
363
384
|
|
|
@@ -377,16 +398,16 @@ For high-traffic deployments:
|
|
|
377
398
|
|
|
378
399
|
## Log Rotation
|
|
379
400
|
|
|
380
|
-
|
|
401
|
+
Rotate the log file with external tools:
|
|
381
402
|
|
|
382
|
-
###
|
|
403
|
+
### Writing to a file
|
|
383
404
|
|
|
384
405
|
```bash
|
|
385
|
-
--log-file ./logs/ldap-rest.log
|
|
386
|
-
--log-max-size 10485760 \ # 10MB
|
|
387
|
-
--log-max-files 5
|
|
406
|
+
--logger file --log-file ./logs/ldap-rest.log
|
|
388
407
|
```
|
|
389
408
|
|
|
409
|
+
The server does not rotate the file itself.
|
|
410
|
+
|
|
390
411
|
### Using logrotate (Linux)
|
|
391
412
|
|
|
392
413
|
```
|
package/docs/usage/upgrading.md
CHANGED
|
@@ -4,6 +4,77 @@ What to check before deploying, newest first. Only releases that need a
|
|
|
4
4
|
decision or a configuration change appear here; see the
|
|
5
5
|
[CHANGELOG](../../CHANGELOG.md) for everything else.
|
|
6
6
|
|
|
7
|
+
## From 1.1 to 1.2.0
|
|
8
|
+
|
|
9
|
+
### The process stops on an uncaught exception
|
|
10
|
+
|
|
11
|
+
**Who is affected:** every deployment; a supervisor, Kubernetes or systemd,
|
|
12
|
+
restarts the process, as it should.
|
|
13
|
+
|
|
14
|
+
An exception nothing caught was logged and the process kept serving in a
|
|
15
|
+
state nobody knew. The binary now shuts down and exits with 1. On
|
|
16
|
+
`SIGTERM` it also drains what is in flight within `--shutdown-timeout`
|
|
17
|
+
(20 s) and closes its connections before the signal ends it, where the
|
|
18
|
+
signal ended the process at once, the broker connection closed first when
|
|
19
|
+
`core/rabbitmq` was loaded. A host assembling the server in its own
|
|
20
|
+
process gets neither unless it asks: `run()` no longer installs the handlers
|
|
21
|
+
that logged an uncaught exception or an unhandled rejection and kept the
|
|
22
|
+
process alive, so without `exitOnCrash()` or handlers of its own, Node's
|
|
23
|
+
action applies and the process ends on either. See
|
|
24
|
+
[shutdown](operations.md#shutdown).
|
|
25
|
+
|
|
26
|
+
### The readiness of a pod follows the directory
|
|
27
|
+
|
|
28
|
+
**Who is affected:** a deployment of the Helm chart, whose probes now call
|
|
29
|
+
`GET /healthz` and `GET /readyz` instead of opening the listen port.
|
|
30
|
+
|
|
31
|
+
A pod leaves the endpoints while the directory does not answer, where it
|
|
32
|
+
kept receiving requests and answering 500; a rollout started during a
|
|
33
|
+
directory outage waits for the directory. Both routes are served without
|
|
34
|
+
authentication: an Ingress routing `/` exposes them, keep the two paths to
|
|
35
|
+
the cluster. See [operations](operations.md#health-and-readiness).
|
|
36
|
+
|
|
37
|
+
### `--ldap-dn` and `--ldap-pwd` are required
|
|
38
|
+
|
|
39
|
+
**Who is affected:** a deployment that left one of them unset, and so bound
|
|
40
|
+
as `cn=admin,dc=example,dc=com` or with the password `admin`; the published
|
|
41
|
+
Docker image carried both in its `ENV`, and the Helm chart's example only set
|
|
42
|
+
the password.
|
|
43
|
+
|
|
44
|
+
The server now stops at startup naming the missing option. Set `DM_LDAP_DN`
|
|
45
|
+
and `DM_LDAP_PWD` (or `--ldap-dn` and `--ldap-pwd`) to the values that were
|
|
46
|
+
implied.
|
|
47
|
+
|
|
48
|
+
### Every entity route checks the shape of a value
|
|
49
|
+
|
|
50
|
+
**Who is affected:** a script or connector writing through `/api/v1/ldap/<entity>`,
|
|
51
|
+
`/api/v1/ldap/groups` or `/api/v1/ldap/organizations` text that is not a
|
|
52
|
+
number for a `number` or `integer`, a `delete` of a `required` attribute as
|
|
53
|
+
a whole, or a change naming an attribute a strict schema does not declare;
|
|
54
|
+
one writing through `/api/v1/ldap/<entity>` several values for an attribute
|
|
55
|
+
the schema does not type `array`; and one changing a `fixed` attribute of a
|
|
56
|
+
group, which the server dropped from the change and answered 200. The
|
|
57
|
+
server now answers 400, naming the attribute. A group creation sending a
|
|
58
|
+
value under a `fixed` attribute now writes the schema's default, or the
|
|
59
|
+
value when the schema gives none, where it wrote nothing. The shipped LSC connector sends shapes that stay
|
|
60
|
+
accepted, a list of one in a `replace` and one value for an `array` on a
|
|
61
|
+
creation; its whole-attribute delete is refused for a `required` attribute,
|
|
62
|
+
as any, and a group synchronisation that forces `objectClass` or another
|
|
63
|
+
`fixed` attribute now has the whole update refused: keep those attributes
|
|
64
|
+
out of the group updates.
|
|
65
|
+
|
|
66
|
+
Send one value for a single-valued attribute, a list for an `array` (one
|
|
67
|
+
value, or a list of one, is taken either way), numbers as numbers or digits,
|
|
68
|
+
and `null` or `[]` in a `replace` to clear an attribute. The rules are in
|
|
69
|
+
[what a value must look like](../client-development/schemas/README.md#what-a-value-must-look-like).
|
|
70
|
+
|
|
71
|
+
### `--logger`: `console` or `file`
|
|
72
|
+
|
|
73
|
+
A `DM_LOGGER` set to anything else wrote `error.log` in the working
|
|
74
|
+
directory; the server now stops at startup. Set `DM_LOGGER=file` to keep
|
|
75
|
+
that file, and `DM_LOG_FILE` to name another one. An empty `DM_LOGGER` is
|
|
76
|
+
`console`.
|
|
77
|
+
|
|
7
78
|
## From 1.0 to 1.1.0
|
|
8
79
|
|
|
9
80
|
### The static files can no longer be framed by another origin
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ldap-rest",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Light directory manager",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Identity-Manager"
|
|
@@ -160,6 +160,10 @@
|
|
|
160
160
|
"types": "./dist/src/plugins/ldap/trash.d.ts",
|
|
161
161
|
"import": "./dist/plugins/ldap/trash.js"
|
|
162
162
|
},
|
|
163
|
+
"./plugin-metrics": {
|
|
164
|
+
"types": "./dist/src/plugins/metrics.d.ts",
|
|
165
|
+
"import": "./dist/plugins/metrics.js"
|
|
166
|
+
},
|
|
163
167
|
"./plugin-rabbitmq": {
|
|
164
168
|
"types": "./dist/src/plugins/rabbitmq.d.ts",
|
|
165
169
|
"import": "./dist/plugins/rabbitmq.js"
|
|
@@ -288,6 +292,10 @@
|
|
|
288
292
|
"types": "./dist/src/plugins/twake/lifecycleEvents.d.ts",
|
|
289
293
|
"import": "./dist/plugins/twake/lifecycleEvents.js"
|
|
290
294
|
},
|
|
295
|
+
"./plugin-twake-migrationproxy": {
|
|
296
|
+
"types": "./dist/src/plugins/twake/migrationProxy.d.ts",
|
|
297
|
+
"import": "./dist/plugins/twake/migrationProxy.js"
|
|
298
|
+
},
|
|
291
299
|
"./plugin-twake-spaces": {
|
|
292
300
|
"types": "./dist/src/plugins/twake/spaces.d.ts",
|
|
293
301
|
"import": "./dist/plugins/twake/spaces.js"
|
|
@@ -754,6 +762,7 @@
|
|
|
754
762
|
"multer": "^2.0.2",
|
|
755
763
|
"node-fetch": "^3.3.2",
|
|
756
764
|
"p-limit": "^7.1.1",
|
|
765
|
+
"prom-client": "^15.1.3",
|
|
757
766
|
"winston": "^3.17.0"
|
|
758
767
|
},
|
|
759
768
|
"devDependencies": {
|
|
@@ -795,7 +804,7 @@
|
|
|
795
804
|
"typescript": "^5.9.2"
|
|
796
805
|
},
|
|
797
806
|
"optionalDependencies": {
|
|
798
|
-
"@linagora/rabbitmq-client": "^0.
|
|
807
|
+
"@linagora/rabbitmq-client": "^0.7.2",
|
|
799
808
|
"express-openid-connect": "^2.19.2",
|
|
800
809
|
"iovalkey": "^0.4.0",
|
|
801
810
|
"lemonldap-ng-handler": "^0.7.3",
|
|
@@ -20,6 +20,7 @@ Point a server at them with:
|
|
|
20
20
|
```sh
|
|
21
21
|
node bin/index.mjs \
|
|
22
22
|
--ldap-base dc=example,dc=org \
|
|
23
|
+
--ldap-dn cn=admin,dc=example,dc=org --ldap-pwd secret \
|
|
23
24
|
--ldap-top-organization ou=organization,dc=example,dc=org \
|
|
24
25
|
--ldap-group-base ou=lists,ou=groups,dc=example,dc=org \
|
|
25
26
|
--group-schema static/schemas/example/groups.json \
|