ldap-rest 0.0.1
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/LICENSE +661 -0
- package/README.md +48 -0
- package/bin/cleanup-external-users.mjs +219 -0
- package/bin/index.mjs +54 -0
- package/bin/sync-james.mjs +190 -0
- package/dist/abstract/ldapFlat.js +1 -0
- package/dist/abstract/plugin.js +1 -0
- package/dist/abstract/twakePlugin.js +1 -0
- package/dist/bin/index.js +1 -0
- package/dist/config/args.js +1 -0
- package/dist/lib/auth/base.js +1 -0
- package/dist/lib/authz/base.js +1 -0
- package/dist/lib/expressFormatedResponses.js +1 -0
- package/dist/lib/ldapActions.js +1 -0
- package/dist/lib/parseConfig.js +1 -0
- package/dist/lib/utils.js +1 -0
- package/dist/logger/winston.js +1 -0
- package/dist/plugins/auth/authzLinid1.js +1 -0
- package/dist/plugins/auth/authzPerBranch.js +1 -0
- package/dist/plugins/auth/crowdsec.js +1 -0
- package/dist/plugins/auth/llng.js +1 -0
- package/dist/plugins/auth/openidconnect.js +1 -0
- package/dist/plugins/auth/rateLimit.js +1 -0
- package/dist/plugins/auth/token.js +1 -0
- package/dist/plugins/configApi.js +1 -0
- package/dist/plugins/demo/helloworld.js +1 -0
- package/dist/plugins/ldap/bulkImport.js +1 -0
- package/dist/plugins/ldap/departmentSync.js +1 -0
- package/dist/plugins/ldap/externalUsersInGroups.js +1 -0
- package/dist/plugins/ldap/flatGeneric.js +1 -0
- package/dist/plugins/ldap/groups.js +1 -0
- package/dist/plugins/ldap/onChange.js +1 -0
- package/dist/plugins/ldap/organization.js +1 -0
- package/dist/plugins/ldap/trash.js +1 -0
- package/dist/plugins/priority.json.js +1 -0
- package/dist/plugins/static.js +1 -0
- package/dist/plugins/twake/calendarResources.js +1 -0
- package/dist/plugins/twake/james.js +1 -0
- package/dist/plugins/weblogs.js +1 -0
- package/dist/src/abstract/ldapFlat.d.ts +94 -0
- package/dist/src/abstract/plugin.d.ts +43 -0
- package/dist/src/abstract/twakePlugin.d.ts +90 -0
- package/dist/src/bin/index.d.ts +43 -0
- package/dist/src/browser/ldap-group-editor/LdapGroupEditor.d.ts +31 -0
- package/dist/src/browser/ldap-group-editor/api/GroupApiClient.d.ts +23 -0
- package/dist/src/browser/ldap-group-editor/components/CreateGroupModal.d.ts +19 -0
- package/dist/src/browser/ldap-group-editor/components/GroupPropertyEditor.d.ts +30 -0
- package/dist/src/browser/ldap-group-editor/components/GroupTree.d.ts +17 -0
- package/dist/src/browser/ldap-group-editor/components/MoveGroupModal.d.ts +20 -0
- package/dist/src/browser/ldap-group-editor/index.d.ts +6 -0
- package/dist/src/browser/ldap-group-editor/types.d.ts +58 -0
- package/dist/src/browser/ldap-resource-editor/api/ResourceApiClient.d.ts +53 -0
- package/dist/src/browser/ldap-resource-editor/cache/CacheManager.d.ts +65 -0
- package/dist/src/browser/ldap-resource-editor/index.d.ts +6 -0
- package/dist/src/browser/ldap-resource-editor/types.d.ts +78 -0
- package/dist/src/browser/ldap-tree-viewer/LdapTreeViewer.d.ts +26 -0
- package/dist/src/browser/ldap-tree-viewer/api/LdapApiClient.d.ts +30 -0
- package/dist/src/browser/ldap-tree-viewer/components/TreeNode.d.ts +17 -0
- package/dist/src/browser/ldap-tree-viewer/components/TreeRoot.d.ts +14 -0
- package/dist/src/browser/ldap-tree-viewer/index.d.ts +7 -0
- package/dist/src/browser/ldap-tree-viewer/store/Store.d.ts +18 -0
- package/dist/src/browser/ldap-tree-viewer/store/actions.d.ts +28 -0
- package/dist/src/browser/ldap-tree-viewer/store/reducers.d.ts +7 -0
- package/dist/src/browser/ldap-tree-viewer/types.d.ts +34 -0
- package/dist/src/browser/ldap-unit-editor/LdapUnitEditor.d.ts +27 -0
- package/dist/src/browser/ldap-unit-editor/api/UnitApiClient.d.ts +24 -0
- package/dist/src/browser/ldap-unit-editor/components/MoveUnitModal.d.ts +28 -0
- package/dist/src/browser/ldap-unit-editor/components/UnitPropertyEditor.d.ts +28 -0
- package/dist/src/browser/ldap-unit-editor/components/UnitTree.d.ts +18 -0
- package/dist/src/browser/ldap-unit-editor/index.d.ts +6 -0
- package/dist/src/browser/ldap-unit-editor/types.d.ts +55 -0
- package/dist/src/browser/ldap-user-editor/LdapUserEditor.d.ts +32 -0
- package/dist/src/browser/ldap-user-editor/api/UserApiClient.d.ts +55 -0
- package/dist/src/browser/ldap-user-editor/cache/CacheManager.d.ts +65 -0
- package/dist/src/browser/ldap-user-editor/components/MoveUserModal.d.ts +28 -0
- package/dist/src/browser/ldap-user-editor/components/PointerField.d.ts +22 -0
- package/dist/src/browser/ldap-user-editor/components/UserEditor.d.ts +46 -0
- package/dist/src/browser/ldap-user-editor/components/UserList.d.ts +24 -0
- package/dist/src/browser/ldap-user-editor/components/UserTree.d.ts +24 -0
- package/dist/src/browser/ldap-user-editor/index.d.ts +7 -0
- package/dist/src/browser/ldap-user-editor/types.d.ts +67 -0
- package/dist/src/browser/shared/components/Modal.d.ts +38 -0
- package/dist/src/browser/shared/components/StatusMessage.d.ts +48 -0
- package/dist/src/browser/shared/index.d.ts +10 -0
- package/dist/src/browser/shared/types/index.d.ts +65 -0
- package/dist/src/browser/shared/utils/dom.d.ts +33 -0
- package/dist/src/browser/shared/utils/form.d.ts +28 -0
- package/dist/src/browser/shared/utils/schema.d.ts +29 -0
- package/dist/src/config/args.d.ts +128 -0
- package/dist/src/config/schema.d.ts +18 -0
- package/dist/src/hooks.d.ts +76 -0
- package/dist/src/lib/auth/base.d.ts +9 -0
- package/dist/src/lib/authz/base.d.ts +63 -0
- package/dist/src/lib/expressFormatedResponses.d.ts +26 -0
- package/dist/src/lib/ldapActions.d.ts +91 -0
- package/dist/src/lib/parseConfig.d.ts +23 -0
- package/dist/src/lib/utils.d.ts +73 -0
- package/dist/src/logger/winston.d.ts +3 -0
- package/dist/src/plugins/auth/authzLinid1.d.ts +46 -0
- package/dist/src/plugins/auth/authzPerBranch.d.ts +59 -0
- package/dist/src/plugins/auth/crowdsec.d.ts +29 -0
- package/dist/src/plugins/auth/llng.d.ts +8 -0
- package/dist/src/plugins/auth/openidconnect.d.ts +11 -0
- package/dist/src/plugins/auth/rateLimit.d.ts +24 -0
- package/dist/src/plugins/auth/token.d.ts +17 -0
- package/dist/src/plugins/configApi.d.ts +24 -0
- package/dist/src/plugins/demo/helloworld.d.ts +12 -0
- package/dist/src/plugins/ldap/bulkImport.d.ts +48 -0
- package/dist/src/plugins/ldap/departmentSync.d.ts +35 -0
- package/dist/src/plugins/ldap/externalUsersInGroups.d.ts +21 -0
- package/dist/src/plugins/ldap/flatGeneric.d.ts +31 -0
- package/dist/src/plugins/ldap/groups.d.ts +95 -0
- package/dist/src/plugins/ldap/onChange.d.ts +32 -0
- package/dist/src/plugins/ldap/organization.d.ts +65 -0
- package/dist/src/plugins/ldap/trash.d.ts +52 -0
- package/dist/src/plugins/static.d.ts +7 -0
- package/dist/src/plugins/twake/calendarResources.d.ts +31 -0
- package/dist/src/plugins/twake/james.d.ts +83 -0
- package/dist/src/plugins/weblogs.d.ts +8 -0
- package/docs/DEVELOPER_GUIDE.md +298 -0
- package/docs/OPENAPI.md +440 -0
- package/docs/PLUGIN_DEPENDENCIES.md +612 -0
- package/docs/README.md +466 -0
- package/docs/api/REFERENCE.md +983 -0
- package/docs/api/REST_API.md +1237 -0
- package/docs/authentication.md +469 -0
- package/docs/authzLinid1.md +521 -0
- package/docs/authzPerBranch.md +596 -0
- package/docs/browser/LIBRARIES.md +1196 -0
- package/docs/examples/EXAMPLES.md +1659 -0
- package/docs/examples/twake-mailbox-type-nomenclature.ldif +37 -0
- package/docs/examples/twake-mailbox-type-schema-amendment.ldif +30 -0
- package/docs/jamesTeamMailboxes.md +343 -0
- package/docs/ldapBulkImport.md +722 -0
- package/docs/ldapExternalUsersInGroups.md +325 -0
- package/docs/ldapFlatGeneric.md +444 -0
- package/docs/ldapGroups.md +589 -0
- package/docs/ldapOrganizations.md +659 -0
- package/docs/ldapTrash.md +260 -0
- package/docs/linagora.png +0 -0
- package/docs/onChange.md +318 -0
- package/docs/plugins/DEVELOPMENT.md +1219 -0
- package/docs/presenterm-fr.md +721 -0
- package/docs/presenterm.md +721 -0
- package/docs/schemas/SCHEMAS.md +1212 -0
- package/docs/static.md +410 -0
- package/docs/twakeCalendarResources.md +148 -0
- package/docs/twakeJames.md +661 -0
- package/docs/weblogs.md +399 -0
- package/examples/web/ldap-group-editor.html +113 -0
- package/examples/web/ldap-tree-viewer.html +368 -0
- package/examples/web/ldap-unit-editor.html +108 -0
- package/examples/web/ldap-user-editor.html +412 -0
- package/package.json +458 -0
- package/static/browser/common-demo.css +450 -0
- package/static/browser/ldap-group-editor/LdapGroupEditor.js +207 -0
- package/static/browser/ldap-group-editor/LdapGroupEditor.js.map +1 -0
- package/static/browser/ldap-group-editor/api/GroupApiClient.js +112 -0
- package/static/browser/ldap-group-editor/api/GroupApiClient.js.map +1 -0
- package/static/browser/ldap-group-editor/components/CreateGroupModal.js +212 -0
- package/static/browser/ldap-group-editor/components/CreateGroupModal.js.map +1 -0
- package/static/browser/ldap-group-editor/components/GroupPropertyEditor.js +497 -0
- package/static/browser/ldap-group-editor/components/GroupPropertyEditor.js.map +1 -0
- package/static/browser/ldap-group-editor/components/GroupTree.js +153 -0
- package/static/browser/ldap-group-editor/components/GroupTree.js.map +1 -0
- package/static/browser/ldap-group-editor/components/MoveGroupModal.js +235 -0
- package/static/browser/ldap-group-editor/components/MoveGroupModal.js.map +1 -0
- package/static/browser/ldap-group-editor/index.js +2 -0
- package/static/browser/ldap-group-editor/index.js.map +1 -0
- package/static/browser/ldap-group-editor/types.js +2 -0
- package/static/browser/ldap-group-editor/types.js.map +1 -0
- package/static/browser/ldap-group-editor.esm.js +1399 -0
- package/static/browser/ldap-group-editor.esm.js.map +1 -0
- package/static/browser/ldap-group-editor.js +1407 -0
- package/static/browser/ldap-group-editor.js.map +1 -0
- package/static/browser/ldap-group-editor.min.js +2 -0
- package/static/browser/ldap-group-editor.min.js.map +1 -0
- package/static/browser/ldap-resource-editor/api/ResourceApiClient.js +226 -0
- package/static/browser/ldap-resource-editor/api/ResourceApiClient.js.map +1 -0
- package/static/browser/ldap-resource-editor/cache/CacheManager.js +123 -0
- package/static/browser/ldap-resource-editor/cache/CacheManager.js.map +1 -0
- package/static/browser/ldap-resource-editor/index.js +2 -0
- package/static/browser/ldap-resource-editor/index.js.map +1 -0
- package/static/browser/ldap-resource-editor/types.js +2 -0
- package/static/browser/ldap-resource-editor/types.js.map +1 -0
- package/static/browser/ldap-tree-viewer/LdapTreeViewer.js +187 -0
- package/static/browser/ldap-tree-viewer/LdapTreeViewer.js.map +1 -0
- package/static/browser/ldap-tree-viewer/api/LdapApiClient.js +50 -0
- package/static/browser/ldap-tree-viewer/api/LdapApiClient.js.map +1 -0
- package/static/browser/ldap-tree-viewer/components/TreeNode.js +140 -0
- package/static/browser/ldap-tree-viewer/components/TreeNode.js.map +1 -0
- package/static/browser/ldap-tree-viewer/components/TreeRoot.js +98 -0
- package/static/browser/ldap-tree-viewer/components/TreeRoot.js.map +1 -0
- package/static/browser/ldap-tree-viewer/index.js +2 -0
- package/static/browser/ldap-tree-viewer/index.js.map +1 -0
- package/static/browser/ldap-tree-viewer/store/Store.js +29 -0
- package/static/browser/ldap-tree-viewer/store/Store.js.map +1 -0
- package/static/browser/ldap-tree-viewer/store/actions.js +53 -0
- package/static/browser/ldap-tree-viewer/store/actions.js.map +1 -0
- package/static/browser/ldap-tree-viewer/store/reducers.js +79 -0
- package/static/browser/ldap-tree-viewer/store/reducers.js.map +1 -0
- package/static/browser/ldap-tree-viewer/types.js +2 -0
- package/static/browser/ldap-tree-viewer/types.js.map +1 -0
- package/static/browser/ldap-tree-viewer.css +2 -0
- package/static/browser/ldap-tree-viewer.css.map +1 -0
- package/static/browser/ldap-tree-viewer.esm.js +606 -0
- package/static/browser/ldap-tree-viewer.esm.js.map +1 -0
- package/static/browser/ldap-tree-viewer.js +614 -0
- package/static/browser/ldap-tree-viewer.js.map +1 -0
- package/static/browser/ldap-tree-viewer.min.js +2 -0
- package/static/browser/ldap-tree-viewer.min.js.map +1 -0
- package/static/browser/ldap-unit-editor/LdapUnitEditor.js +119 -0
- package/static/browser/ldap-unit-editor/LdapUnitEditor.js.map +1 -0
- package/static/browser/ldap-unit-editor/api/UnitApiClient.js +95 -0
- package/static/browser/ldap-unit-editor/api/UnitApiClient.js.map +1 -0
- package/static/browser/ldap-unit-editor/components/MoveUnitModal.js +295 -0
- package/static/browser/ldap-unit-editor/components/MoveUnitModal.js.map +1 -0
- package/static/browser/ldap-unit-editor/components/UnitPropertyEditor.js +321 -0
- package/static/browser/ldap-unit-editor/components/UnitPropertyEditor.js.map +1 -0
- package/static/browser/ldap-unit-editor/components/UnitTree.js +197 -0
- package/static/browser/ldap-unit-editor/components/UnitTree.js.map +1 -0
- package/static/browser/ldap-unit-editor/index.js +2 -0
- package/static/browser/ldap-unit-editor/index.js.map +1 -0
- package/static/browser/ldap-unit-editor/types.js +2 -0
- package/static/browser/ldap-unit-editor/types.js.map +1 -0
- package/static/browser/ldap-unit-editor.esm.js +1013 -0
- package/static/browser/ldap-unit-editor.esm.js.map +1 -0
- package/static/browser/ldap-unit-editor.js +1021 -0
- package/static/browser/ldap-unit-editor.js.map +1 -0
- package/static/browser/ldap-unit-editor.min.js +2 -0
- package/static/browser/ldap-unit-editor.min.js.map +1 -0
- package/static/browser/ldap-user-editor/LdapUserEditor.js +184 -0
- package/static/browser/ldap-user-editor/LdapUserEditor.js.map +1 -0
- package/static/browser/ldap-user-editor/api/UserApiClient.js +209 -0
- package/static/browser/ldap-user-editor/api/UserApiClient.js.map +1 -0
- package/static/browser/ldap-user-editor/cache/CacheManager.js +123 -0
- package/static/browser/ldap-user-editor/cache/CacheManager.js.map +1 -0
- package/static/browser/ldap-user-editor/components/MoveUserModal.js +302 -0
- package/static/browser/ldap-user-editor/components/MoveUserModal.js.map +1 -0
- package/static/browser/ldap-user-editor/components/PointerField.js +152 -0
- package/static/browser/ldap-user-editor/components/PointerField.js.map +1 -0
- package/static/browser/ldap-user-editor/components/UserEditor.js +608 -0
- package/static/browser/ldap-user-editor/components/UserEditor.js.map +1 -0
- package/static/browser/ldap-user-editor/components/UserList.js +181 -0
- package/static/browser/ldap-user-editor/components/UserList.js.map +1 -0
- package/static/browser/ldap-user-editor/components/UserTree.js +164 -0
- package/static/browser/ldap-user-editor/components/UserTree.js.map +1 -0
- package/static/browser/ldap-user-editor/index.js +2 -0
- package/static/browser/ldap-user-editor/index.js.map +1 -0
- package/static/browser/ldap-user-editor/types.js +2 -0
- package/static/browser/ldap-user-editor/types.js.map +1 -0
- package/static/browser/ldap-user-editor.css +2 -0
- package/static/browser/ldap-user-editor.css.map +1 -0
- package/static/browser/ldap-user-editor.esm.js +1897 -0
- package/static/browser/ldap-user-editor.esm.js.map +1 -0
- package/static/browser/ldap-user-editor.js +1905 -0
- package/static/browser/ldap-user-editor.js.map +1 -0
- package/static/browser/ldap-user-editor.min.js +2 -0
- package/static/browser/ldap-user-editor.min.js.map +1 -0
- package/static/browser/shared/components/Modal.js +121 -0
- package/static/browser/shared/components/Modal.js.map +1 -0
- package/static/browser/shared/components/StatusMessage.js +119 -0
- package/static/browser/shared/components/StatusMessage.js.map +1 -0
- package/static/browser/shared/index.js +7 -0
- package/static/browser/shared/index.js.map +1 -0
- package/static/browser/shared/types/index.js +37 -0
- package/static/browser/shared/types/index.js.map +1 -0
- package/static/browser/shared/utils/dom.js +78 -0
- package/static/browser/shared/utils/dom.js.map +1 -0
- package/static/browser/shared/utils/form.js +234 -0
- package/static/browser/shared/utils/form.js.map +1 -0
- package/static/browser/shared/utils/schema.js +121 -0
- package/static/browser/shared/utils/schema.js.map +1 -0
- package/static/browser/shared.esm.js +694 -0
- package/static/browser/shared.esm.js.map +1 -0
- package/static/browser/shared.js +723 -0
- package/static/browser/shared.js.map +1 -0
- package/static/browser/shared.min.js +2 -0
- package/static/browser/shared.min.js.map +1 -0
- package/static/schemas/ad/computers.json +92 -0
- package/static/schemas/ad/groups.json +55 -0
- package/static/schemas/ad/organizations.json +66 -0
- package/static/schemas/ad/users.json +116 -0
- package/static/schemas/standard/devices.json +72 -0
- package/static/schemas/standard/groups.json +54 -0
- package/static/schemas/standard/organizations.json +49 -0
- package/static/schemas/standard/users.json +86 -0
- package/static/schemas/twake/groups.json +75 -0
- package/static/schemas/twake/nomenclature/twakeAccountStatus.json +31 -0
- package/static/schemas/twake/nomenclature/twakeDeliveryMode.json +31 -0
- package/static/schemas/twake/nomenclature/twakeListType.json +31 -0
- package/static/schemas/twake/nomenclature/twakeMailboxType.json +31 -0
- package/static/schemas/twake/nomenclature/twakeTitle.json +31 -0
- package/static/schemas/twake/organizations.json +52 -0
- package/static/schemas/twake/positions.json +32 -0
- package/static/schemas/twake/users.json +112 -0
|
@@ -0,0 +1,521 @@
|
|
|
1
|
+
# Authorization Plugin: authzLinid1
|
|
2
|
+
|
|
3
|
+
LDAP-based authorization plugin that grants permissions based on the `twakeLocalAdminLink` attribute in organizational units.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The `authzLinid1` plugin provides dynamic, LDAP-driven access control by reading permissions directly from LDAP organizational units. It supports:
|
|
8
|
+
|
|
9
|
+
- **LDAP-based permissions** - No configuration files needed, permissions stored in LDAP
|
|
10
|
+
- **Organization-centric** - Users listed in `twakeLocalAdminLink` manage the organization
|
|
11
|
+
- **Full CRUD rights** - Local admins get read, write, and delete permissions
|
|
12
|
+
- **Sub-branch inheritance** - Permissions apply recursively to sub-branches
|
|
13
|
+
- **Cross-branch access** - Users/groups can be managed if their `twakeDepartmentLink` points to an authorized organization
|
|
14
|
+
- **Permission caching** - Configurable TTL reduces LDAP queries (default: 5 minutes)
|
|
15
|
+
|
|
16
|
+
## How It Works
|
|
17
|
+
|
|
18
|
+
### twakeLocalAdminLink Attribute
|
|
19
|
+
|
|
20
|
+
Organizations in LDAP can have a `twakeLocalAdminLink` attribute listing user DNs who manage that organization:
|
|
21
|
+
|
|
22
|
+
```ldif
|
|
23
|
+
dn: ou=HR,ou=organization,dc=example,dc=com
|
|
24
|
+
objectClass: organizationalUnit
|
|
25
|
+
ou: HR
|
|
26
|
+
twakeLocalAdminLink: uid=hr-admin,ou=users,dc=example,dc=com
|
|
27
|
+
twakeLocalAdminLink: uid=hr-manager,ou=users,dc=example,dc=com
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Users listed in `twakeLocalAdminLink` automatically get full permissions (read, write, delete) for:
|
|
31
|
+
|
|
32
|
+
- The organization itself (`ou=HR,ou=organization,dc=example,dc=com`)
|
|
33
|
+
- All sub-organizations (`ou=Payroll,ou=HR,ou=organization,dc=example,dc=com`)
|
|
34
|
+
- All users/groups with `twakeDepartmentLink` pointing to this organization
|
|
35
|
+
|
|
36
|
+
### Cross-Branch Access
|
|
37
|
+
|
|
38
|
+
Users and groups can exist in different LDAP branches but belong to specific organizations via `twakeDepartmentLink`:
|
|
39
|
+
|
|
40
|
+
```ldif
|
|
41
|
+
# User in global users branch
|
|
42
|
+
dn: uid=john,ou=users,dc=example,dc=com
|
|
43
|
+
objectClass: twakeAccount
|
|
44
|
+
uid: john
|
|
45
|
+
cn: John Doe
|
|
46
|
+
twakeDepartmentLink: ou=HR,ou=organization,dc=example,dc=com
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
The HR admin (listed in `ou=HR`'s `twakeLocalAdminLink`) can manage John even though he's in `ou=users` because his `twakeDepartmentLink` points to the HR organization.
|
|
50
|
+
|
|
51
|
+
## Configuration
|
|
52
|
+
|
|
53
|
+
No configuration file needed - permissions are read from LDAP. Simply load the plugin:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
--plugin core/auth/authzLinid1
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
**Optional Cache Configuration:**
|
|
60
|
+
|
|
61
|
+
The plugin caches permissions for 5 minutes by default. This is hardcoded but can be modified in the source if needed.
|
|
62
|
+
|
|
63
|
+
## Permission Resolution
|
|
64
|
+
|
|
65
|
+
For each LDAP operation, the plugin:
|
|
66
|
+
|
|
67
|
+
1. **Resolves user DN** - Converts username to LDAP DN
|
|
68
|
+
2. **Searches for permissions** - Finds all organizations where user is in `twakeLocalAdminLink`
|
|
69
|
+
3. **Caches results** - Stores permissions for 5 minutes
|
|
70
|
+
4. **Checks branch access** - Verifies if requested branch matches authorized organizations
|
|
71
|
+
5. **Checks link attributes** - For entries with `twakeDepartmentLink`, checks if link points to authorized org
|
|
72
|
+
|
|
73
|
+
### Permission Inheritance
|
|
74
|
+
|
|
75
|
+
Permissions apply to the organization and all descendants:
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
ou=organization,dc=example,dc=com
|
|
79
|
+
├── ou=Main Unit [admin1 has twakeLocalAdminLink here]
|
|
80
|
+
│ ├── ou=Sub Unit 1 [admin1 can access]
|
|
81
|
+
│ │ └── ou=Department1 [admin1 can access]
|
|
82
|
+
│ └── ou=Sub Unit 2 [admin1 can access]
|
|
83
|
+
└── ou=Private [admin1 cannot access]
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Cross-Branch Examples
|
|
87
|
+
|
|
88
|
+
**Scenario 1: User in authorized branch**
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
Organization: ou=HR,ou=organization,dc=example,dc=com
|
|
92
|
+
twakeLocalAdminLink: uid=admin,ou=users,dc=example,dc=com
|
|
93
|
+
|
|
94
|
+
User: uid=john,ou=users,ou=HR,ou=organization,dc=example,dc=com
|
|
95
|
+
|
|
96
|
+
Result: admin can manage john (user is in HR branch)
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
**Scenario 2: User with department link**
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
Organization: ou=HR,ou=organization,dc=example,dc=com
|
|
103
|
+
twakeLocalAdminLink: uid=admin,ou=users,dc=example,dc=com
|
|
104
|
+
|
|
105
|
+
User: uid=john,ou=users,dc=example,dc=com
|
|
106
|
+
twakeDepartmentLink: ou=HR,ou=organization,dc=example,dc=com
|
|
107
|
+
|
|
108
|
+
Result: admin can manage john (twakeDepartmentLink points to HR)
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
**Scenario 3: User without link in wrong branch**
|
|
112
|
+
|
|
113
|
+
```
|
|
114
|
+
Organization: ou=HR,ou=organization,dc=example,dc=com
|
|
115
|
+
twakeLocalAdminLink: uid=admin,ou=users,dc=example,dc=com
|
|
116
|
+
|
|
117
|
+
User: uid=john,ou=users,dc=example,dc=com
|
|
118
|
+
(no twakeDepartmentLink)
|
|
119
|
+
|
|
120
|
+
Result: admin cannot manage john (not in HR branch, no link)
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## Hooks
|
|
124
|
+
|
|
125
|
+
### ldapaddrequest Hook
|
|
126
|
+
|
|
127
|
+
Intercepts all LDAP add operations:
|
|
128
|
+
|
|
129
|
+
1. Checks if request has authenticated user
|
|
130
|
+
2. Resolves user's DN from username
|
|
131
|
+
3. Determines which branch to check:
|
|
132
|
+
- If entry has `twakeDepartmentLink`, use that organization
|
|
133
|
+
- Otherwise, use parent DN of the entry being added
|
|
134
|
+
4. Verifies user has write permission for that branch
|
|
135
|
+
5. Throws error if access denied
|
|
136
|
+
|
|
137
|
+
**Special allowances:**
|
|
138
|
+
|
|
139
|
+
- Unauthenticated requests pass through (for internal operations)
|
|
140
|
+
|
|
141
|
+
### ldapsearchrequest Hook
|
|
142
|
+
|
|
143
|
+
Intercepts all LDAP search operations:
|
|
144
|
+
|
|
145
|
+
1. Checks if request has authenticated user
|
|
146
|
+
2. Resolves user's DN from username
|
|
147
|
+
3. Allows base scope searches on top organization (for navigation)
|
|
148
|
+
4. Allows searches for `twakeLocalAdminLink` (for permission refresh)
|
|
149
|
+
5. Verifies user has read permission for search base
|
|
150
|
+
6. Throws error if access denied
|
|
151
|
+
|
|
152
|
+
**Special allowances:**
|
|
153
|
+
|
|
154
|
+
- Base scope on `ldap_top_organization` (e.g., for getOrganisationTop API)
|
|
155
|
+
- Filters containing `twakeLocalAdminLink` (permission refresh queries)
|
|
156
|
+
|
|
157
|
+
### getOrganisationTop Hook
|
|
158
|
+
|
|
159
|
+
Modifies the organization tree API:
|
|
160
|
+
|
|
161
|
+
1. Returns organizations where user is local admin
|
|
162
|
+
2. Replaces default top organization with authorized branches
|
|
163
|
+
3. Enables UI to show only manageable organizations
|
|
164
|
+
|
|
165
|
+
**Behavior:**
|
|
166
|
+
|
|
167
|
+
- If user manages multiple orgs, returns the first one
|
|
168
|
+
- If user manages one org, returns that org
|
|
169
|
+
- If user manages no orgs, returns default top organization
|
|
170
|
+
|
|
171
|
+
## API Integration
|
|
172
|
+
|
|
173
|
+
### Organization Tree API
|
|
174
|
+
|
|
175
|
+
The plugin automatically filters the organization tree API:
|
|
176
|
+
|
|
177
|
+
**Global admin (manages top organization):**
|
|
178
|
+
|
|
179
|
+
```
|
|
180
|
+
GET /api/v1/ldap/organizations/top
|
|
181
|
+
Authorization: Bearer <token>
|
|
182
|
+
|
|
183
|
+
Response:
|
|
184
|
+
{
|
|
185
|
+
"dn": "ou=organization,dc=example,dc=com",
|
|
186
|
+
"ou": "organization"
|
|
187
|
+
}
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
**Local admin (manages specific organization):**
|
|
191
|
+
|
|
192
|
+
```
|
|
193
|
+
GET /api/v1/ldap/organizations/top
|
|
194
|
+
Authorization: Bearer <token>
|
|
195
|
+
|
|
196
|
+
Response:
|
|
197
|
+
{
|
|
198
|
+
"dn": "ou=HR,ou=organization,dc=example,dc=com",
|
|
199
|
+
"ou": "HR"
|
|
200
|
+
}
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### Add User Example
|
|
204
|
+
|
|
205
|
+
**Success - User with department link to authorized org:**
|
|
206
|
+
|
|
207
|
+
```
|
|
208
|
+
POST /api/v1/users
|
|
209
|
+
Authorization: Bearer <hr-admin-token>
|
|
210
|
+
|
|
211
|
+
{
|
|
212
|
+
"uid": "newuser",
|
|
213
|
+
"cn": "New User",
|
|
214
|
+
"twakeDepartmentLink": ["ou=HR,ou=organization,dc=example,dc=com"]
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
Response: 201 Created
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
**Failure - User with link to unauthorized org:**
|
|
221
|
+
|
|
222
|
+
```
|
|
223
|
+
POST /api/v1/users
|
|
224
|
+
Authorization: Bearer <hr-admin-token>
|
|
225
|
+
|
|
226
|
+
{
|
|
227
|
+
"uid": "newuser",
|
|
228
|
+
"cn": "New User",
|
|
229
|
+
"twakeDepartmentLink": ["ou=IT,ou=organization,dc=example,dc=com"]
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
Response: 403 Forbidden
|
|
233
|
+
{
|
|
234
|
+
"error": "User hr-admin does not have write permission for branch ou=IT,ou=organization,dc=example,dc=com"
|
|
235
|
+
}
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
## Performance
|
|
239
|
+
|
|
240
|
+
### Permission Caching
|
|
241
|
+
|
|
242
|
+
Permissions are cached to reduce LDAP queries:
|
|
243
|
+
|
|
244
|
+
- **Cache TTL**: 5 minutes (hardcoded)
|
|
245
|
+
- **Per-user cache**: Each user's permissions cached separately
|
|
246
|
+
- **Automatic refresh**: Cache expires after TTL
|
|
247
|
+
- **On-demand refresh**: New permissions fetched on cache miss
|
|
248
|
+
|
|
249
|
+
**Cache structure:**
|
|
250
|
+
|
|
251
|
+
```javascript
|
|
252
|
+
{
|
|
253
|
+
"uid=admin,ou=users,dc=example,dc=com": {
|
|
254
|
+
branches: Map([
|
|
255
|
+
["ou=HR,ou=organization,dc=example,dc=com", {read: true, write: true, delete: true}],
|
|
256
|
+
["ou=Finance,ou=organization,dc=example,dc=com", {read: true, write: true, delete: true}]
|
|
257
|
+
]),
|
|
258
|
+
timestamp: 1696512000000
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### LDAP Query Optimization
|
|
264
|
+
|
|
265
|
+
The plugin minimizes LDAP queries:
|
|
266
|
+
|
|
267
|
+
1. **User DN resolution** - Cached implicitly by permission cache
|
|
268
|
+
2. **Permission search** - Single query for all organizations with user in `twakeLocalAdminLink`
|
|
269
|
+
3. **No recursive searches** - Uses DN suffix matching for sub-branch checks
|
|
270
|
+
|
|
271
|
+
**Typical query pattern:**
|
|
272
|
+
|
|
273
|
+
```
|
|
274
|
+
User makes request → Check cache → (if expired) Search LDAP once → Cache for 5 min
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
## LDAP Schema Requirements
|
|
278
|
+
|
|
279
|
+
### Required Attributes
|
|
280
|
+
|
|
281
|
+
**Organizations:**
|
|
282
|
+
|
|
283
|
+
- `twakeLocalAdminLink` (multi-valued) - DNs of local administrators
|
|
284
|
+
|
|
285
|
+
**Users/Groups:**
|
|
286
|
+
|
|
287
|
+
- `twakeDepartmentLink` (single-valued) - DN of parent organization
|
|
288
|
+
|
|
289
|
+
### Example Schema
|
|
290
|
+
|
|
291
|
+
```ldif
|
|
292
|
+
# Organization with local admins
|
|
293
|
+
dn: ou=HR,ou=organization,dc=example,dc=com
|
|
294
|
+
objectClass: organizationalUnit
|
|
295
|
+
objectClass: twakeOrganization
|
|
296
|
+
ou: HR
|
|
297
|
+
twakeLocalAdminLink: uid=hr-admin,ou=users,dc=example,dc=com
|
|
298
|
+
twakeLocalAdminLink: uid=hr-manager,ou=users,dc=example,dc=com
|
|
299
|
+
|
|
300
|
+
# User with department link
|
|
301
|
+
dn: uid=employee1,ou=users,dc=example,dc=com
|
|
302
|
+
objectClass: inetOrgPerson
|
|
303
|
+
objectClass: twakeAccount
|
|
304
|
+
uid: employee1
|
|
305
|
+
cn: Employee One
|
|
306
|
+
twakeDepartmentLink: ou=HR,ou=organization,dc=example,dc=com
|
|
307
|
+
|
|
308
|
+
# Group with department link
|
|
309
|
+
dn: cn=hr-staff,ou=groups,dc=example,dc=com
|
|
310
|
+
objectClass: groupOfNames
|
|
311
|
+
objectClass: twakeGroup
|
|
312
|
+
cn: hr-staff
|
|
313
|
+
twakeDepartmentLink: ou=HR,ou=organization,dc=example,dc=com
|
|
314
|
+
member: uid=employee1,ou=users,dc=example,dc=com
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
## Security Considerations
|
|
318
|
+
|
|
319
|
+
### LDAP-Driven Security
|
|
320
|
+
|
|
321
|
+
- **Centralized control** - All permissions in LDAP, no config files to sync
|
|
322
|
+
- **Audit trail** - LDAP modifications can be logged/audited
|
|
323
|
+
- **Consistency** - Single source of truth for permissions
|
|
324
|
+
- **Real-time updates** - Changes effective after cache expiry (5 min max)
|
|
325
|
+
|
|
326
|
+
### Permission Model
|
|
327
|
+
|
|
328
|
+
- **Local admins get full access** - Read, write, and delete
|
|
329
|
+
- **No granular permissions** - Cannot grant read-only local admin
|
|
330
|
+
- **Inheritance always applies** - Cannot restrict sub-branches
|
|
331
|
+
- **Cross-branch by design** - Department links intentionally allow cross-branch access
|
|
332
|
+
|
|
333
|
+
### Authentication Required
|
|
334
|
+
|
|
335
|
+
This plugin only handles **authorization**. Combine with an authentication plugin:
|
|
336
|
+
|
|
337
|
+
```bash
|
|
338
|
+
--plugin core/auth/token \
|
|
339
|
+
--plugin core/auth/authzLinid1 \
|
|
340
|
+
--auth-token "secret-token"
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
### Cache Security
|
|
344
|
+
|
|
345
|
+
- **Cache delays permission revocation** - Up to 5 minutes after removing user from `twakeLocalAdminLink`
|
|
346
|
+
- **Cache per user** - Removing one user doesn't invalidate others
|
|
347
|
+
- **No cache persistence** - Cache cleared on server restart
|
|
348
|
+
|
|
349
|
+
## Troubleshooting
|
|
350
|
+
|
|
351
|
+
### Problem: Access Denied
|
|
352
|
+
|
|
353
|
+
**Symptoms:**
|
|
354
|
+
|
|
355
|
+
```json
|
|
356
|
+
{
|
|
357
|
+
"error": "User jdoe does not have write permission for branch ou=HR,ou=organization,dc=example,dc=com"
|
|
358
|
+
}
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
**Solutions:**
|
|
362
|
+
|
|
363
|
+
1. Verify user is in organization's `twakeLocalAdminLink`:
|
|
364
|
+
|
|
365
|
+
```bash
|
|
366
|
+
ldapsearch -x -b "ou=organization,dc=example,dc=com" "(twakeLocalAdminLink=uid=jdoe,*)"
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
2. Check user DN matches exactly (spaces, case, order)
|
|
370
|
+
|
|
371
|
+
3. Wait up to 5 minutes for cache to expire after adding user
|
|
372
|
+
|
|
373
|
+
4. Check user is authenticated (verify `req.user` is set)
|
|
374
|
+
|
|
375
|
+
### Problem: Cannot Manage User in Different Branch
|
|
376
|
+
|
|
377
|
+
**Symptoms:**
|
|
378
|
+
User exists in `ou=users,dc=example,dc=com` but local admin cannot manage them.
|
|
379
|
+
|
|
380
|
+
**Solutions:**
|
|
381
|
+
|
|
382
|
+
1. Add `twakeDepartmentLink` to user:
|
|
383
|
+
|
|
384
|
+
```ldif
|
|
385
|
+
dn: uid=user,ou=users,dc=example,dc=com
|
|
386
|
+
changetype: modify
|
|
387
|
+
add: twakeDepartmentLink
|
|
388
|
+
twakeDepartmentLink: ou=HR,ou=organization,dc=example,dc=com
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
2. Or move user to organization branch:
|
|
392
|
+
```
|
|
393
|
+
From: uid=user,ou=users,dc=example,dc=com
|
|
394
|
+
To: uid=user,ou=users,ou=HR,ou=organization,dc=example,dc=com
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
### Problem: Permissions Not Updating
|
|
398
|
+
|
|
399
|
+
**Symptoms:**
|
|
400
|
+
Added user to `twakeLocalAdminLink` but they still get access denied.
|
|
401
|
+
|
|
402
|
+
**Solutions:**
|
|
403
|
+
|
|
404
|
+
1. Wait up to 5 minutes for cache to expire
|
|
405
|
+
2. Restart server to clear all caches immediately
|
|
406
|
+
3. Verify LDAP modification succeeded:
|
|
407
|
+
```bash
|
|
408
|
+
ldapsearch -x -b "ou=HR,ou=organization,dc=example,dc=com" "(objectClass=*)" twakeLocalAdminLink
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
### Problem: User Not Found
|
|
412
|
+
|
|
413
|
+
**Symptoms:**
|
|
414
|
+
|
|
415
|
+
```
|
|
416
|
+
User jdoe not found in LDAP
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
**Solutions:**
|
|
420
|
+
|
|
421
|
+
1. Verify user exists in LDAP:
|
|
422
|
+
|
|
423
|
+
```bash
|
|
424
|
+
ldapsearch -x -b "dc=example,dc=com" "(uid=jdoe)"
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
2. Check `ldap_user_main_attribute` configuration (default: `uid`)
|
|
428
|
+
|
|
429
|
+
3. Verify authentication plugin sets `req.user` correctly
|
|
430
|
+
|
|
431
|
+
### Problem: Cannot Search Top Organization
|
|
432
|
+
|
|
433
|
+
**Symptoms:**
|
|
434
|
+
|
|
435
|
+
```json
|
|
436
|
+
{
|
|
437
|
+
"error": "User admin does not have read permission for branch ou=organization,dc=example,dc=com"
|
|
438
|
+
}
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
**Solutions:**
|
|
442
|
+
|
|
443
|
+
This is expected behavior - users can only see organizations they manage. To grant access to top organization:
|
|
444
|
+
|
|
445
|
+
```bash
|
|
446
|
+
ldapsearch -x -b "ou=organization,dc=example,dc=com" -s base "(objectClass=*)"
|
|
447
|
+
# Modify to add user:
|
|
448
|
+
ldapmodify <<EOF
|
|
449
|
+
dn: ou=organization,dc=example,dc=com
|
|
450
|
+
changetype: modify
|
|
451
|
+
add: twakeLocalAdminLink
|
|
452
|
+
twakeLocalAdminLink: uid=admin,ou=users,dc=example,dc=com
|
|
453
|
+
EOF
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
## Integration Examples
|
|
457
|
+
|
|
458
|
+
### With Token Authentication
|
|
459
|
+
|
|
460
|
+
```bash
|
|
461
|
+
--plugin core/auth/token \
|
|
462
|
+
--plugin core/auth/authzLinid1 \
|
|
463
|
+
--auth-token "admin-token" \
|
|
464
|
+
--ldap-top-organization "ou=organization,dc=example,dc=com"
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
### With OpenID Connect
|
|
468
|
+
|
|
469
|
+
```bash
|
|
470
|
+
--plugin core/auth/openidconnect \
|
|
471
|
+
--plugin core/auth/authzLinid1 \
|
|
472
|
+
--oidc-server "https://auth.example.com" \
|
|
473
|
+
--oidc-client-id "ldap-rest" \
|
|
474
|
+
--oidc-client-secret "secret" \
|
|
475
|
+
--base-url "https://api.example.com" \
|
|
476
|
+
--ldap-top-organization "ou=organization,dc=example,dc=com"
|
|
477
|
+
```
|
|
478
|
+
|
|
479
|
+
### With LemonLDAP::NG
|
|
480
|
+
|
|
481
|
+
```bash
|
|
482
|
+
--plugin core/auth/llng \
|
|
483
|
+
--plugin core/auth/authzLinid1 \
|
|
484
|
+
--llng-ini /etc/lemonldap-ng/lemonldap-ng.ini \
|
|
485
|
+
--ldap-top-organization "ou=organization,dc=example,dc=com"
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
## Comparison with authzPerBranch
|
|
489
|
+
|
|
490
|
+
| Feature | authzLinid1 | authzPerBranch |
|
|
491
|
+
| ----------------- | ---------------------------------- | -------------------------------- |
|
|
492
|
+
| Configuration | LDAP-based | Config file/env |
|
|
493
|
+
| Permission source | `twakeLocalAdminLink` attribute | JSON configuration |
|
|
494
|
+
| Granularity | Organization-level | Per-branch, per-user/group |
|
|
495
|
+
| Read-only access | No (always full access) | Yes (separate read/write/delete) |
|
|
496
|
+
| Cross-branch | Yes (via `twakeDepartmentLink`) | Yes (if configured) |
|
|
497
|
+
| Dynamic updates | Yes (via LDAP) | No (requires restart) |
|
|
498
|
+
| Cache | 5 min (hardcoded) | Configurable TTL |
|
|
499
|
+
| Use case | Organization-based delegated admin | Fine-grained access control |
|
|
500
|
+
|
|
501
|
+
**When to use authzLinid1:**
|
|
502
|
+
|
|
503
|
+
- Organizations manage themselves
|
|
504
|
+
- LDAP is source of truth
|
|
505
|
+
- Full admin access is acceptable
|
|
506
|
+
- Department-based delegation
|
|
507
|
+
|
|
508
|
+
**When to use authzPerBranch:**
|
|
509
|
+
|
|
510
|
+
- Need read-only access
|
|
511
|
+
- Complex permission matrix
|
|
512
|
+
- Config-driven permissions
|
|
513
|
+
- Different rights per branch
|
|
514
|
+
|
|
515
|
+
## See Also
|
|
516
|
+
|
|
517
|
+
- [authzPerBranch Plugin](authzPerBranch.md) - Configuration-based authorization
|
|
518
|
+
- [Authentication Plugins](authentication.md) - Setup authentication
|
|
519
|
+
- [LDAP Organizations](ldapOrganizations.md) - Organization tree management
|
|
520
|
+
- [LDAP Users](ldapFlatGeneric.md) - User management
|
|
521
|
+
- [LDAP Groups](ldapGroups.md) - Group management
|