Compare commits

...

42 Commits

Author SHA1 Message Date
Carpentier Pierre-Francois dd331f948c
Update README.rst 2024-03-13 01:13:02 +01:00
Carpentier Pierre-Francois a2e985576b
Update README.rst 2024-03-13 00:57:26 +01:00
kakwa 6a2e6e56d0 fix CI badge and remove the coverage one 2024-03-13 00:35:48 +01:00
kakwa 5d8fc08f5b re-enable ssl/tls 2024-03-13 00:29:50 +01:00
kakwa 59855f0090 just rename stuff 2024-03-13 00:21:04 +01:00
kakwa d1215bc56f fix package name 2024-03-13 00:18:47 +01:00
kakwa ef11e6a7e3 more deps 2024-03-13 00:17:33 +01:00
kakwa 3596e14249 adding stuff to install 2024-03-13 00:13:11 +01:00
kakwa b94713acb6 sudo for CI 2024-03-13 00:10:06 +01:00
kakwa de16df475f add basic gh action tests 2024-03-13 00:06:44 +01:00
kakwa 242c9ab96e update test ldap configuration 2024-03-13 00:00:14 +01:00
kakwa 48dbff983d update shebang 2024-03-13 00:00:06 +01:00
kakwa 6413b782dd update shebang 2024-03-12 23:59:46 +01:00
Carpentier Pierre-Francois 55c49b4eff
Merge pull request #68 from kakwa/dependabot/pip/python-ldap-3.4.0
Bump python-ldap from 2.4.15 to 3.4.0
2024-03-12 22:39:47 +01:00
Carpentier Pierre-Francois 53a4b6fd5e
Merge pull request #59 from cyberb/master
lcCopy
2024-03-12 22:36:33 +01:00
dependabot[bot] 0ccbe95d9a
Bump python-ldap from 2.4.15 to 3.4.0
Bumps [python-ldap](https://github.com/python-ldap/python-ldap) from 2.4.15 to 3.4.0.
- [Release notes](https://github.com/python-ldap/python-ldap/releases)
- [Commits](https://github.com/python-ldap/python-ldap/commits/python-ldap-3.4.0)

---
updated-dependencies:
- dependency-name: python-ldap
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-29 18:00:11 +00:00
Carpentier Pierre-Francois 4da050236d
Merge pull request #49 from smacz42/andrewcz-ldapcherry-issue34
Add demo backend configuration files in goodies
2020-05-20 19:24:55 +02:00
Carpentier Pierre-Francois 135699bd48
Merge pull request #62 from Sohalt/master
fix typo
2020-04-07 20:58:09 +02:00
sohalt 1549a172f7 fix typo 2020-04-07 19:15:31 +02:00
Boris Rybalkin e2ab3e85d8 lcCopy 2020-01-10 22:10:28 +00:00
Carpentier Pierre-Francois b5907ce340
Merge pull request #55 from StbX/master
add missing import
2019-10-23 21:09:28 +02:00
Steffen Brandemann 791895d4c3 add missing os import 2019-10-21 23:17:20 +02:00
AndrewCz b12add4a0f Add demo backend configuration files in goodies 2019-07-21 20:06:19 -04:00
Carpentier Pierre-Francois 856157af79
Merge pull request #24 from jqueuniet/fix_default_handler
Fix default handler arguments
2019-05-03 12:09:13 +02:00
Carpentier Pierre-Francois b5e7cb6a44
Merge pull request #33 from smacz42/install-in-readme
Add install command to setup in README
2019-04-23 19:56:51 +02:00
smacz d61c89460e Add install command to setup in README 2019-04-23 11:24:17 -04:00
Johann Queuniet 0a96ca61d5
Fix default handler arguments 2019-03-26 11:05:39 +01:00
Carpentier Pierre-Francois 3b58f1464e
Merge pull request #23 from jqueuniet/fix_email_regexp
Change the email regular expression to fix a few validation issues
2019-03-20 18:33:19 +01:00
Johann Queuniet 50c6259035
Fix email regexp 2019-03-20 15:57:45 +01:00
kakwa 245bafb01c typo 2019-02-13 09:44:47 +01:00
kakwa 5ee8a74040 update documentation 2019-02-13 09:41:17 +01:00
kakwa 96acda7aa6 fix formatting 2019-02-13 09:19:08 +01:00
kakwa 30c28c5feb slightly more robust unit tests
pre-cleanup to avoid contamination if other tests fail
2019-02-12 23:28:52 +01:00
kakwa dc60300a29 version + changelog 2019-02-12 23:28:41 +01:00
kakwa 882a303474 fix crash due to encoding in python 2 2019-02-12 23:27:30 +01:00
kakwa d831b09293 improve documentation
* improve documentation for key: True flag in attributes.yml
* improve documentation for the ldap filters and their templating
* improve comment in the .ini file
2019-02-12 23:06:42 +01:00
kakwa 7ac7118c9a adding a debug log to help figure out issues with filters. 2019-02-12 22:43:03 +01:00
kakwa d690bbdc41 passing the correct logger to the backend
previously, the default logger was passed, this logger was using the
default configuration and log level, not honoring log level in
particular.
As a consequence, it was impossible to get debug logs from the backend.
This is now working as expected.
2019-02-12 22:40:42 +01:00
kakwa 73c02ccff4 disable default logger if running in debug mode (-D)
Debug mode can lead to log sensitive data (like password changes).
Having -D to log exclusively to stderr is a safer option.
2019-02-12 22:36:16 +01:00
kakwa 799ca2403f fix the urls for modify and delete
The id of the user is passed through the querystring in this page.
But the id was not properly escaped to be included as a querystring
parameter leading to weird issues like.
2019-02-12 21:24:24 +01:00
kakwa bbafafae60 remove the double escaping.
Now the escaping is done by in the templates.
We need to remove the previous escaping done by hand in the code.
Otherwise, we end-up with double escaping and funky displaying of
fields.
2019-02-12 21:18:45 +01:00
kakwa 0cf5483785 add warning in documentation for log level 'debug' 2019-02-10 18:19:55 +01:00
49 changed files with 468 additions and 253 deletions

19
.github/workflows/tests.yml vendored Normal file
View File

@ -0,0 +1,19 @@
name: CI
on:
push:
pull_request:
workflow_dispatch:
jobs:
build_and_test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install packages and setup ldap/AD
run: sudo ./tests/test_env/deploy.sh
- name: Test
run: python3 setup.py test

View File

@ -1,6 +1,16 @@
Dev
***
Version 1.1.1
*************
* [fix ] fix double escaping issues introduced in 1.0.0
* [fix ] fix missing url escaping in links with querystring parameters (delete and modify page mostly)
* [fix ] fix log level not being honored in the backends
* [impr] clarify the role of 'key: True' of attributes.yml in the documentation
* [impr] add a few more comments in the .ini file to explain better the \*_filter_tmpl and group_attr parameters
* [impr] add debug log to help debug ldap search filters
Version 1.1.0
*************

View File

@ -6,11 +6,9 @@
Nice and simple application to manage users and groups in multiple directory services.
.. image:: https://travis-ci.org/kakwa/ldapcherry.svg?branch=master
:target: https://travis-ci.org/kakwa/ldapcherry
.. image:: https://coveralls.io/repos/kakwa/ldapcherry/badge.svg
:target: https://coveralls.io/r/kakwa/ldapcherry
.. image:: https://github.com/kakwa/ldapcherry/actions/workflows/tests.yml/badge.svg
:target: https://github.com/kakwa/ldapcherry/actions/workflows/tests.yml
:alt: CI
.. image:: https://img.shields.io/pypi/v/ldapcherry.svg
:target: https://pypi.python.org/pypi/ldapcherry
@ -30,21 +28,6 @@ Nice and simple application to manage users and groups in multiple directory ser
----
********
Demo
********
A demo is accessible here: https://ldapcherry.kakwalab.ovh
The credentials are:
* as administrator: admin/admin
* as user: user/user
Please take note that it's not possible to modify/delete the 'admin' and 'user' users.
Also take note that the service will be reseted once per day.
****************
Presentation
****************
@ -90,7 +73,7 @@ The default backend plugins permit to manage Ldap and Active Directory.
$ export DATAROOTDIR=/usr/share/
# install ldapcherry
$ python setup.py
$ python setup.py install
# edit configuration files
$ vi /etc/ldapcherry/ldapcherry.ini
@ -111,7 +94,7 @@ LdapCherry is published under the MIT Public License.
Discussion / Help / Updates
*******************************
* IRC: `Freenode <http://freenode.net/>`_ ``#ldapcherry`` channel
* IRC: `Libera <https://libera.chat/>`_ ``#ldapcherry`` channel
* Bugtracker: `Github <https://github.com/kakwa/ldapcherry/issues>`_
----

View File

@ -106,16 +106,24 @@ ldap.timeout = 1
ldap.groupdn = 'ou=group,dc=example,dc=org'
# users dn
ldap.userdn = 'ou=people,dc=example,dc=org'
# ldapsearch filter to get a user
# ldapsearch filter to get one specific user
# %(username)s is content of the attribute marked 'key: True' in the attributes.file config file
ldap.user_filter_tmpl = '(uid=%(username)s)'
# ldapsearch filter to get groups of a user
# %(username)s is content of the attribute marked 'key: True' in the attributes.file config file
ldap.group_filter_tmpl = '(member=uid=%(username)s,ou=People,dc=example,dc=org)'
# filter to search users
# %(searchstring)s is the content passed through the search box
ldap.search_filter_tmpl = '(|(uid=%(searchstring)s*)(sn=%(searchstring)s*))'
# ldap group attributes and how to fill them
# 'member' is the name of the attribute
# for the template, any of the user's ldap attributes can be user
ldap.group_attr.member = "%(dn)s"
# same with memverUid and the uid user's attribute
#ldap.group_attr.memberUid = "%(uid)s"
# object classes of a user entry
ldap.objectclasses = 'top, person, posixAccount, inetOrgPerson'
# dn entry attribute for an ldap user

View File

@ -25,12 +25,12 @@ admin-lv2:
# ad:
# - Administrators
developpers:
developers:
display_name: Developpers
description: Developpers of the system
backends_groups:
ldap:
- cn=developpers,ou=Group,dc=example,dc=org
- cn=developers,ou=Group,dc=example,dc=org
- cn=users,ou=Group,dc=example,dc=org
users:

View File

@ -47,48 +47,55 @@ Configuration
The ldap backend exposes the following parameters:
+--------------------------+----------+------------------------------------+--------------------------+--------------------------------------------+
| Parameter | Section | Description | Values | Comment |
+==========================+==========+====================================+==========================+============================================+
| uri | backends | The ldap uri to access | ldap uri | * use ldap:// for clear/starttls |
| | | | | * use ldaps:// for ssl |
| | | | | * custom port: ldap://<host>:<port> |
+--------------------------+----------+------------------------------------+--------------------------+--------------------------------------------+
| ca | backends | Path to the CA file | file path | optional |
+--------------------------+----------+------------------------------------+--------------------------+--------------------------------------------+
| starttls | backends | Use starttls | 'on' or 'off' | optional |
+--------------------------+----------+------------------------------------+--------------------------+--------------------------------------------+
| checkcert | backends | Check the server certificat | 'on' or 'off' | optional |
+--------------------------+----------+------------------------------------+--------------------------+--------------------------------------------+
| binddn | backends | The bind dn to use | ldap dn | This dn must have read/write permissions |
+--------------------------+----------+------------------------------------+--------------------------+--------------------------------------------+
| password | backends | The password of the bind dn | password | |
+--------------------------+----------+------------------------------------+--------------------------+--------------------------------------------+
| timeout | backends | Ldap connexion timeout | integer (second) | |
+--------------------------+----------+------------------------------------+--------------------------+--------------------------------------------+
| password | backends | The password of the bind dn | password | |
+--------------------------+----------+------------------------------------+--------------------------+--------------------------------------------+
| groupdn | backends | The ldap dn where groups are | ldap dn | |
+--------------------------+----------+------------------------------------+--------------------------+--------------------------------------------+
| userdn | backends | The ldap dn where users are | ldap dn | |
+--------------------------+----------+------------------------------------+--------------------------+--------------------------------------------+
| user_filter_tmpl | backends | The search filter template | ldap search filter | The user identifier is passed through |
| | | to recover a given user | template | the **username** variable (*%(username)s*).|
+--------------------------+----------+------------------------------------+--------------------------+--------------------------------------------+
| group_filter_tmpl | backends | The search filter template to | ldap search filter | The following variables are usable: |
| | | recover the groups of a given user | template | * **username**: the user key attribute |
| | | | | * **userdn**: the user ldap dn |
+--------------------------+----------+------------------------------------+--------------------------+--------------------------------------------+
| group_attr.<member attr> | backends | Member attribute template value | template | * <member attr> is the member attribute |
| | | | | in groups dn entries |
| | | | | * every user attributes are exposed |
| | | | | in the template |
| | | | | * multiple attributes can be set |
+--------------------------+----------+------------------------------------+--------------------------+--------------------------------------------+
| objectclasses | backends | list of object classes for users | comma separated list | |
+--------------------------+----------+------------------------------------+--------------------------+--------------------------------------------+
| dn_user_attr | backends | attribute used in users dn | dn attribute | |
+--------------------------+----------+------------------------------------+--------------------------+--------------------------------------------+
+--------------------------+----------+------------------------------------+--------------------------+------------------------------------------------+
| Parameter | Section | Description | Values | Comment |
+==========================+==========+====================================+==========================+================================================+
| uri | backends | The ldap uri to access | ldap uri | * use ldap:// for clear/starttls |
| | | | | * use ldaps:// for ssl |
| | | | | * custom port: ldap://<host>:<port> |
+--------------------------+----------+------------------------------------+--------------------------+------------------------------------------------+
| ca | backends | Path to the CA file | file path | optional |
+--------------------------+----------+------------------------------------+--------------------------+------------------------------------------------+
| starttls | backends | Use starttls | 'on' or 'off' | optional |
+--------------------------+----------+------------------------------------+--------------------------+------------------------------------------------+
| checkcert | backends | Check the server certificat | 'on' or 'off' | optional |
+--------------------------+----------+------------------------------------+--------------------------+------------------------------------------------+
| binddn | backends | The bind dn to use | ldap dn | This dn must have read/write permissions |
+--------------------------+----------+------------------------------------+--------------------------+------------------------------------------------+
| password | backends | The password of the bind dn | password | |
+--------------------------+----------+------------------------------------+--------------------------+------------------------------------------------+
| timeout | backends | Ldap connexion timeout | integer (second) | |
+--------------------------+----------+------------------------------------+--------------------------+------------------------------------------------+
| password | backends | The password of the bind dn | password | |
+--------------------------+----------+------------------------------------+--------------------------+------------------------------------------------+
| groupdn | backends | The ldap dn where groups are | ldap dn | |
+--------------------------+----------+------------------------------------+--------------------------+------------------------------------------------+
| userdn | backends | The ldap dn where users are | ldap dn | |
+--------------------------+----------+------------------------------------+--------------------------+------------------------------------------------+
| user_filter_tmpl | backends | The search filter template | ldap search filter | The user identifier is passed through |
| | | to recover a given user | template | the **username** variable (*%(username)s*) |
| | | | | |
| | | | | **username** is the content of the |
| | | | | the attribute marked by '**key: True**' |
| | | | | in the **attributes.yml** file |
+--------------------------+----------+------------------------------------+--------------------------+------------------------------------------------+
| group_filter_tmpl | backends | The search filter template to | ldap search filter | The following variables are usable: |
| | | recover the groups of a given user | template | |
| | | recover the groups of a given user | template | * **username**: the user's key attribute |
| | | | | * **userdn**: the user's ldap dn |
+--------------------------+----------+------------------------------------+--------------------------+------------------------------------------------+
| group_attr.<member attr> | backends | Member attribute template value | template | * <member attr> is the member attribute |
| | | | | in groups dn entries |
| | | | | * every user attributes are exposed |
| | | | | in the template |
| | | | | * multiple <memver attr> attributes |
| | | | | can be set (ex: group_attr.member |
| | | | | (ex: group_attr.member, group_attr.usermemb) |
+--------------------------+----------+------------------------------------+--------------------------+------------------------------------------------+
| objectclasses | backends | list of object classes for users | comma separated list | |
+--------------------------+----------+------------------------------------+--------------------------+------------------------------------------------+
| dn_user_attr | backends | attribute used in users dn | dn attribute | |
+--------------------------+----------+------------------------------------+--------------------------+------------------------------------------------+
Example
@ -96,46 +103,58 @@ Example
.. sourcecode:: ini
[backends]
[backends]
# name of the module
ldap.module = 'ldapcherry.backend.backendLdap'
# display name of the ldap
ldap.display_name = 'My Ldap Directory'
# uri of the ldap directory
ldap.uri = 'ldap://ldap.ldapcherry.org'
# ca to use for ssl/tls connexion
#ldap.ca = '/etc/dnscherry/TEST-cacert.pem'
# use start tls
#ldap.starttls = 'off'
# check server certificate (for tls)
#ldap.checkcert = 'off'
# bind dn to the ldap
ldap.binddn = 'cn=dnscherry,dc=example,dc=org'
# password of the bind dn
ldap.password = 'password'
# timeout of ldap connexion (in second)
ldap.timeout = 1
# groups dn
ldap.groupdn = 'ou=group,dc=example,dc=org'
# users dn
ldap.userdn = 'ou=people,dc=example,dc=org'
# ldapsearch filter to get a user
ldap.user_filter_tmpl = '(uid=%(username)s)'
# ldapsearch filter to get groups of a user
ldap.group_filter_tmpl = '(member=uid=%(username)s,ou=People,dc=example,dc=org)'
# filter to search users
ldap.search_filter_tmpl = '(|(uid=%(searchstring)s*)(sn=%(searchstring)s*))'
# ldap group attributes and how to fill them
ldap.group_attr.member = "%(dn)s"
#ldap.group_attr.memberUid = "%(uid)s"
# object classes of a user entry
ldap.objectclasses = 'top, person, posixAccount, inetOrgPerson'
# dn entry attribute for an ldap user
ldap.dn_user_attr = 'uid'
#####################################
# configuration of ldap backend #
#####################################
# name of the module
ldap.module = 'ldapcherry.backend.backendLdap'
# display name of the ldap
ldap.display_name = 'My Ldap Directory'
# uri of the ldap directory
ldap.uri = 'ldap://ldap.ldapcherry.org'
# ca to use for ssl/tls connexion
#ldap.ca = '/etc/dnscherry/TEST-cacert.pem'
# use start tls
#ldap.starttls = 'off'
# check server certificate (for tls)
#ldap.checkcert = 'off'
# bind dn to the ldap
ldap.binddn = 'cn=dnscherry,dc=example,dc=org'
# password of the bind dn
ldap.password = 'password'
# timeout of ldap connexion (in second)
ldap.timeout = 1
# groups dn
ldap.groupdn = 'ou=group,dc=example,dc=org'
# users dn
ldap.userdn = 'ou=people,dc=example,dc=org'
# ldapsearch filter to get one specific user
# %(username)s is content of the attribute marked 'key: True' in the attributes.file config file
ldap.user_filter_tmpl = '(uid=%(username)s)'
# ldapsearch filter to get groups of a user
# %(username)s is content of the attribute marked 'key: True' in the attributes.file config file
ldap.group_filter_tmpl = '(member=uid=%(username)s,ou=People,dc=example,dc=org)'
# filter to search users
# %(searchstring)s is the content passed through the search box
ldap.search_filter_tmpl = '(|(uid=%(searchstring)s*)(sn=%(searchstring)s*))'
# ldap group attributes and how to fill them
# 'member' is the name of the attribute
# for the template, any of the user's ldap attributes can be user
ldap.group_attr.member = "%(dn)s"
# same with memverUid and the uid user's attribute
#ldap.group_attr.memberUid = "%(uid)s"
# object classes of a user entry
ldap.objectclasses = 'top, person, posixAccount, inetOrgPerson'
# dn entry attribute for an ldap user
ldap.dn_user_attr = 'uid'
Active Directory Backend

View File

@ -112,7 +112,12 @@ If **type** is set to **stringlist** the parameter **values** must be filled wit
Key attribute:
^^^^^^^^^^^^^^
One attribute must be used as a unique key across all backends:
One attribute must be used as a unique key across all backends.
It acts as a reconciliation key.
It also marks which attribute must be used within ldapcherry (ex: querysting parameter in links)
to point to one given user.
To set the key attribute, you must set **key** to **True** on this attribute.
@ -477,6 +482,14 @@ Example:
log.level = 'info'
.. warning::
'debug' should not be used in production.
It tends to log a lot.
More significantly can represent a security issue,
as things like passwords will be logged 'clear text'.
Custom javascript
~~~~~~~~~~~~~~~~~

View File

@ -50,3 +50,17 @@ Basic Lighttpd Vhost
.. literalinclude:: ../goodies/lighttpd.conf
:language: yaml
Demo Backend Configuration Files
--------------------------------
The files here are the ones that are used at the demo site at `ldapcherry.kakwalab.ovh <https://ldapcherry.kakwalab.ovh/>`_ and can be used for a self-hosted demo backend:
.. literalinclude:: ../goodies/demo_backend_configs/attributes.yml
:language: yaml
.. literalinclude:: ../goodies/demo_backend_configs/roles.yml
:language: yaml
.. literalinclude:: ../goodies/demo_backend_configs/ldapcherry.ini
:language: ini

View File

@ -0,0 +1,112 @@
description: "First Name and Display Name"
display_name: "Display Name"
type: string
weight: 30
autofill:
function: lcDisplayName
args:
- $first-name
- $name
backends:
demo: cn
first-name:
description: "First name of the user"
display_name: "First Name"
search_displayed: True
type: string
weight: 20
backends:
demo: givenName
name:
description: "Family name of the user"
display_name: "Name"
search_displayed: True
weight: 10
type: string
backends:
demo: sn
email:
description: "Email of the user"
display_name: "Email"
search_displayed: True
type: email
weight: 40
autofill:
function: lcMail
args:
- $first-name
- $name
- '@example.com'
backends:
demo: mail
uid:
description: "UID of the user"
display_name: "UID"
search_displayed: True
key: True
type: string
weight: 50
autofill:
function: lcUid
args:
- $first-name
- $name
- '10000'
- '40000'
backends:
demo: uid
uidNumber:
description: "User ID Number of the user"
display_name: "UID Number"
weight: 60
type: int
autofill:
function: lcUidNumber
args:
- $first-name
- $name
- '10000'
- '40000'
backends:
demo: uidNumber
gidNumber:
description: "Group ID Number of the user"
display_name: "GID Number"
weight: 70
type: int
default: '10000'
backends:
demo: gidNumber
shell:
description: "Shell of the user"
display_name: "Shell"
weight: 80
self: True
type: stringlist
values:
- /bin/bash
- /bin/zsh
- /bin/sh
backends:
demo: loginShell
home:
description: "Home user path"
display_name: "Home"
weight: 90
type: string
autofill:
function: lcHomeDir
args:
- $first-name
- $name
- /home/
backends:
demo: homeDirectory
password:
description: "Password of the user"
display_name: "Password"
weight: 31
self: True
type: password
backends:
demo: userPassword

View File

@ -0,0 +1,25 @@
[backends]
#####################################
# configuration of demo backend #
#####################################
# Name of the backend
demo.module = 'ldapcherry.backend.backendDemo'
# Display name of the Backend
demo.display_name = 'Demo Backend'
# Groups of admin user
demo.admin.groups = 'SECOFF'
# Groups of basic user
demo.basic.groups = 'Test 2, Test 1'
# Password attribute name
demo.pwd_attr = 'userPassword'
# Attribute to use for the search
demo.search_attributes = 'cn, sn, givenName, uid'
# Login of default admin user
demo.admin.user = 'admin'
# Password of default admin user
demo.admin.password = 'admin'
# Login of default basic user
demo.basic.user = 'user'
# Password of default basic user
demo.basic.password = 'user'

View File

@ -0,0 +1,36 @@
sec-officer:
display_name: Security Officer
description: Security officer of the system
LC_admins: True
backends_groups:
demo:
- SECOFF
admin-lv3:
display_name: Administrators Level 3
description: Super administrators of the system
backends_groups:
demo:
- cn=dns admins,ou=Group,dc=example,dc=org
- cn=nagios admins,ou=Group,dc=example,dc=org
- cn=puppet admins,ou=Group,dc=example,dc=org
- cn=users,ou=Group,dc=example,dc=org
admin-lv2:
display_name: Administrators Level 2
description: Basic administrators of the system
backends_groups:
demo:
- cn=nagios admins,ou=Group,dc=example,dc=org
- cn=users,ou=Group,dc=example,dc=org
developpers:
display_name: Developpers
description: Developpers of the system
backends_groups:
demo:
- cn=developpers,ou=Group,dc=example,dc=org
- cn=users,ou=Group,dc=example,dc=org
users:
display_name: Simple Users
description: Basic users of the system
backends_groups:
demo:
- cn=users,ou=Group,dc=example,dc=org

View File

@ -1,4 +1,3 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# vim:set expandtab tabstop=4 shiftwidth=4:
#
@ -8,6 +7,7 @@
# Generic imports
import sys
import os
import re
import traceback
import json
@ -34,10 +34,8 @@ from mako import exceptions
if sys.version < '3':
from sets import Set as set
from urllib import quote_plus
from cgi import escape as html_escape
else:
from urllib.parse import quote_plus
from html import escape as html_escape
SESSION_KEY = '_cp_username'
@ -62,36 +60,6 @@ class LdapCherry(object):
traceback=True
)
def _escape_list(self, data):
ret = []
for i in data:
ret.append(html_escape(i, True))
return ret
def _escape_dict(self, data):
for d in data:
if isinstance(data[d], list):
data[d] = self._escape_list(data[d])
elif isinstance(data[d], dict):
data[d] = self._escape_dict(data[d])
elif isinstance(data[d], set):
data[d] = set(self._escape_list(data[d]))
else:
data[d] = html_escape(data[d], True)
return data
def _escape(self, data, dtype):
if data is None:
return None
elif dtype == 'search_list':
for d in data:
data[d] = self._escape_dict(data[d])
elif dtype == 'attr_list':
data = self._escape_dict(data)
elif dtype == 'lonely_groups':
data = self._escape_dict(data)
return data
def _get_param(self, section, key, config, default=None):
""" Get configuration parameter "key" from config
@str section: the section of the config file
@ -193,7 +161,7 @@ class LdapCherry(object):
key = self.attributes.get_backend_key(backend)
self.backends[backend] = bc.Backend(
params,
cherrypy.log,
cherrypy.log.error,
backend,
attrslist,
key,
@ -362,6 +330,7 @@ class LdapCherry(object):
cherrypy.log.error_log.setLevel(level)
if debug:
cherrypy.log.error_log.handlers = []
handler = logging.StreamHandler(sys.stderr)
handler.setLevel(logging.DEBUG)
cherrypy.log.error_log.addHandler(handler)
@ -995,7 +964,7 @@ class LdapCherry(object):
return self.temp['index.tmpl'].render(
is_admin=is_admin,
attrs_list=attrs_list,
searchresult=self._escape(user_attrs, 'attr_list'),
searchresult=user_attrs,
notifications=self._empty_notification(),
)
@ -1011,7 +980,7 @@ class LdapCherry(object):
res = None
attrs_list = self.attributes.get_search_attributes()
return self.temp['searchuser.tmpl'].render(
searchresult=self._escape(res, 'search_list'),
searchresult=res,
attrs_list=attrs_list,
is_admin=is_admin,
custom_js=self.custom_js,
@ -1048,7 +1017,7 @@ class LdapCherry(object):
res = None
attrs_list = self.attributes.get_search_attributes()
return self.temp['searchadmin.tmpl'].render(
searchresult=self._escape(res, 'search_list'),
searchresult=res,
attrs_list=attrs_list,
is_admin=is_admin,
custom_js=self.custom_js,
@ -1169,7 +1138,7 @@ class LdapCherry(object):
try:
form = self.temp['form.tmpl'].render(
attributes=self.attributes.attributes,
values=self._escape(user_attrs, 'attr_list'),
values=user_attrs,
modify=True,
keyattr=key,
autofill=False
@ -1187,10 +1156,7 @@ class LdapCherry(object):
form=form,
roles=roles,
is_admin=is_admin,
standalone_groups=self._escape(
standalone_groups,
'lonely_groups'
),
standalone_groups=standalone_groups,
backends_display_names=self.backends_display_names,
custom_js=self.custom_js,
notifications=self._empty_notification(),
@ -1204,7 +1170,7 @@ class LdapCherry(object):
@cherrypy.expose
@exception_decorator
def default(self, attr='', **params):
def default(self, attr='', *args, **params):
cherrypy.response.status = 404
self._check_auth(must_admin=False)
is_admin = self._check_admin()
@ -1245,7 +1211,7 @@ class LdapCherry(object):
form = self.temp['form.tmpl'].render(
attributes=self.attributes.get_selfattributes(),
values=self._escape(user_attrs, 'attr_list'),
values=user_attrs,
modify=True,
autofill=False
)

View File

@ -71,7 +71,7 @@ class Attributes:
raise MissingUserKey()
def _is_email(self, email):
pattern = r'[\.\w]{1,}[@]\w+[.]\w+'
pattern = r'[\+\.\w]+@[-\.\w]+\.\w+'
if re.match(pattern, email):
return True
else:

View File

@ -261,6 +261,16 @@ class Backend(ldapcherry.backend.Backend):
else:
attrlist = None
self._logger(
severity=logging.DEBUG,
msg="%(backend)s: executing search "
"with filter '%(filter)s' in DN '%(dn)s'" % {
'backend': self.backend_name,
'dn': basedn,
'filter': self._uni(searchfilter)
}
)
# bind and search the ldap
ldap_client = self._bind()
try:

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# vim:set expandtab tabstop=4 shiftwidth=4:
# The MIT License (MIT)

View File

@ -1,4 +1,3 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# vim:set expandtab tabstop=4 shiftwidth=4:
#

View File

@ -5,4 +5,4 @@
# ldapCherry
# Copyright (c) 2014 Carpentier Pierre-Francois
version = '1.1.0'
version = '1.1.1'

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from __future__ import with_statement

View File

@ -30,7 +30,7 @@ groups = {
'ad' : ['Domain Users', 'Domain Users 2'],
'ldap': ['cn=users,ou=group,dc=example,dc=com',
'cn=nagios admins,ou=group,dc=example,dc=com',
'cn=developpers,ou=group,dc=example,dc=com',
'cn=developers,ou=group,dc=example,dc=com',
],
'toto': ['not a group'],
}

View File

@ -1,4 +1,4 @@
CherryPy>=3.0.0
PyYAML
Mako
python-ldap==2.4.15
python-ldap==3.4.0

View File

@ -1,4 +1,4 @@
CherryPy>=3.0.0
PyYAML
Mako
python-ldap==2.4.28
python-ldap==3.4.0

View File

@ -30,3 +30,8 @@ function lcUidNumber(firstname, lastname, minuid, maxuid){
function lcHomeDir(firstname, lastname, basedir){
return basedir+lcUid(firstname, lastname);
}
function lcCopy(value){
return value;
}

View File

@ -52,10 +52,10 @@
</td>
% endfor
<td>
<a href="/modify?user=${user}" class="btn btn-xs blue pad" ><span class="glyphicon glyphicon-cog"></span> Modify</a>
<a href="/modify?user=${user | n,u}" class="btn btn-xs blue pad" ><span class="glyphicon glyphicon-cog"></span> Modify</a>
</td>
<td>
<a href="/delete?user=${user}" data-toggle='confirmation-delete' class="btn btn-xs red pad"><span class="glyphicon glyphicon-remove-sign"></span> Delete</a>
<a href="/delete?user=${user | n,u}" data-toggle='confirmation-delete' class="btn btn-xs red pad"><span class="glyphicon glyphicon-remove-sign"></span> Delete</a>
</td>
</tr>
% endfor

View File

@ -5,11 +5,11 @@ Gre='\33[0;32m';
RCol='\33[0m';
cd `dirname $0`
python setup.py test &&\
printf "\nPEP 8 compliance check:\n\n"
pep8 \
--repeat \
--show-source \
--exclude=.venv,.tox,dist,docs,build,*.egg,tests,misc . && \
printf "[${Gre}Passed${RCol}] Yeah! everything is clean\n\n" || \
printf "[${Red}Failed${RCol}] Oh No! there is some mess to fix\n\n"
python3 setup.py test #&&\
#printf "\nPEP 8 compliance check:\n\n"
#pep8 \
# --recurssive ./ \
# --show-source \
# --exclude=.venv,.tox,dist,docs,build,*.egg,tests,misc . && \
# printf "[${Gre}Passed${RCol}] Yeah! everything is clean\n\n" || \
# printf "[${Red}Failed${RCol}] Oh No! there is some mess to fix\n\n"

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# vim:set expandtab tabstop=4 shiftwidth=4:

View File

@ -21,10 +21,10 @@ users:
display_name: Administrators Level 3
description: description
subroles: {}
developpers:
developers:
backends_groups:
ad: [Domain Users]
ldap: ['cn=developpers,ou=group,dc=example,dc=com']
ldap: ['cn=developers,ou=group,dc=example,dc=com']
display_name: Developpers
description: description
subroles: {}

View File

@ -23,12 +23,12 @@ admin-lv2:
ad:
- Domain Users
developpers:
developers:
display_name: Developpers
description: description
backends_groups:
ldap:
- cn=developpers,ou=group,dc=example,dc=com
- cn=developers,ou=group,dc=example,dc=com
- cn=users,ou=group,dc=example,dc=com
ad:
- Domain Users

View File

@ -23,12 +23,12 @@ admin-lv2:
ad:
- Administrators
#developpers:
#developers:
# display_name: Developpers
# description: Developpers of the system
# backends_groups:
# ldap:
# - cn=developpers,ou=Group,dc=example,dc=org
# - cn=developers,ou=Group,dc=example,dc=org
# - cn=users,ou=Group,dc=example,dc=org
#users:

View File

@ -23,12 +23,12 @@ admin -lv2:
ad:
- Domain Users
developpers:
developers:
display_name: Developpers
description: description
backends_groups:
ldap:
- cn=developpers,ou=group,dc=example,dc=com
- cn=developers,ou=group,dc=example,dc=com
- cn=users,ou=group,dc=example,dc=com
ad:
- Domain Users

View File

@ -23,12 +23,12 @@ admin -lv3:
ad:
- Domain Users
developpers:
developers:
display_name: Developpers
description: description
backends_groups:
ldap:
- cn=developpers,ou=group,dc=example,dc=com
- cn=developers,ou=group,dc=example,dc=com
- cn=users,ou=group,dc=example,dc=com
ad:
- Domain Users

View File

@ -17,12 +17,12 @@ admin-lv2:
display_name: Administrators Level 2
description: description
developpers:
developers:
display_name: Developpers
description: description
backends_groups:
ldap:
- cn=developpers,ou=group,dc=example,dc=com
- cn=developers,ou=group,dc=example,dc=com
- cn=users,ou=group,dc=example,dc=com
ad:
- Domain Users

View File

@ -22,12 +22,12 @@ admin-lv2:
ad:
- Domain Users
developpers:
developers:
display_name: Developpers
description: description
backends_groups:
ldap:
- cn=developpers,ou=group,dc=example,dc=com
- cn=developers,ou=group,dc=example,dc=com
- cn=users,ou=group,dc=example,dc=com
ad:
- Domain Users

View File

@ -17,12 +17,12 @@ admin-lv2:
- cn=nagios admins,ou=Group,dc=example,dc=org
- cn=users,ou=Group,dc=example,dc=org
developpers:
developers:
display_name: Developpers
description: Developpers of the system
backends_groups:
ldap:
- cn=developpers,ou=Group,dc=example,dc=org
- cn=developers,ou=Group,dc=example,dc=org
- cn=users,ou=Group,dc=example,dc=org
users:

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from __future__ import with_statement

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from __future__ import with_statement
@ -119,10 +119,15 @@ class TestError(object):
@travis_disabled
def testSearchUser(self):
inv = Backend(cfg, cherrypy.log, u'test☭', attr, 'sAMAccountName')
try:
inv.del_user(u'☭default_user')
except: pass
try:
inv.del_user(u'☭default_user2')
except: pass
try:
inv.add_user(default_user.copy())
except:
pass
except: pass
inv.add_user(default_user2.copy())
ret = inv.search(u'test☭')
expected = [u'☭default_user', u'☭default_user2']

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from __future__ import with_statement

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from __future__ import with_statement

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from __future__ import with_statement

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from __future__ import with_statement
@ -107,10 +107,10 @@ class TestError(object):
'description': 'description',
'display_name': 'Administrators Level 3'
},
'developpers': {
'developers': {
'backends_groups': {
'ad': ['Domain Users'],
'ldap': ['cn=developpers,ou=group,dc=example,dc=com',
'ldap': ['cn=developers,ou=group,dc=example,dc=com',
'cn=users,ou=group,dc=example,dc=com']},
'description': 'description',
'display_name': 'Developpers'
@ -152,7 +152,7 @@ class TestError(object):
def testGetAllRoles(self):
inv = Roles('./tests/cfg/roles.yml')
res = inv.get_allroles()
expected = ['developpers', 'admin-lv3', 'admin-lv2', 'users']
expected = ['developers', 'admin-lv3', 'admin-lv2', 'users']
assert res == expected
def testGetAllRoles(self):
@ -187,9 +187,9 @@ class TestError(object):
'ad' : ['Domain Users', 'Domain Users 2'],
'ldap': ['cn=users,ou=group,dc=example,dc=com',
'cn=nagios admins,ou=group,dc=example,dc=com',
'cn=developpers,ou=group,dc=example,dc=com',
'cn=developers,ou=group,dc=example,dc=com',
],
'toto': ['not a group'],
}
expected = {'unusedgroups': {'toto': set(['not a group']), 'ad': set(['Domain Users 2'])}, 'roles': set(['developpers', 'admin-lv2', 'users'])}
expected = {'unusedgroups': {'toto': set(['not a group']), 'ad': set(['Domain Users 2'])}, 'roles': set(['developers', 'admin-lv2', 'users'])}
assert inv.get_roles(groups) == expected

View File

@ -5,6 +5,7 @@ apt update
DEBIAN_FRONTEND=noninteractive apt-get install ldap-utils slapd -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" -f -q -y
DEBIAN_FRONTEND=noninteractive apt-get install samba-dsdb-modules samba-vfs-modules samba -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" -f -q -y
DEBIAN_FRONTEND=noninteractive apt-get install winbind -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" -f -q -y
DEBIAN_FRONTEND=noninteractive apt-get install build-essential python3-dev libsasl2-dev slapd ldap-utils tox lcov valgrind libtidy-dev libldap-dev python3-cherrypy3 python3-ldap python3-mako -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" -f -q -y
[ -e '/etc/default/slapd' ] && rm -rf /etc/default/slapd
cp -r `dirname $0`/etc/default/slapd /etc/default/slapd
@ -18,7 +19,6 @@ sudo sed -i "s%template_dir.*%template_dir = '`pwd`/resources/templates/'%" /etc
sudo sed -i "s%tools.staticdir.dir.*%tools.staticdir.dir = '`pwd`/resources/static/'%" /etc/ldapcherry/ldapcherry.ini
chown -R openldap:openldap /etc/ldap/
rm /etc/ldap/slapd.d/cn\=config/*mdb*
/etc/init.d/slapd restart
ldapadd -c -H ldap://localhost:390 -x -D "cn=admin,dc=example,dc=org" -f /etc/ldap/content.ldif -w password
if grep -q '127.0.0.1' /etc/hosts && ! grep -q 'ldap.ldapcherry.org' /etc/hosts

View File

@ -103,9 +103,9 @@ cn: users
description: Basic Users
member: cn=Sheri Smith,ou=people,dc=example,dc=org
dn: cn=developpers,ou=group,dc=example,dc=org
dn: cn=developers,ou=group,dc=example,dc=org
objectclass: groupofnames
cn: developpers
cn: developers
description: Developpers
member: cn=Sheri Smith,ou=people,dc=example,dc=org

View File

@ -1,4 +1,5 @@
# AUTO-GENERATED FILE - DO NOT EDIT!! Use ldapmodify.
# CRC32 7a6099db
dn: cn=config
objectClass: olcGlobal
cn: config
@ -7,12 +8,12 @@ olcLogLevel: none
olcPidFile: /var/run/slapd/slapd.pid
olcToolThreads: 1
structuralObjectClass: olcGlobal
entryUUID: 2964261c-6754-1033-8d48-1703270f04bd
entryUUID: 38579c70-750a-103e-8489-9578878139e2
creatorsName: cn=config
createTimestamp: 20140503211805Z
entryCSN: 20140503211805.658522Z#000000#000#000000
createTimestamp: 20240312221838Z
entryCSN: 20240312221838.644900Z#000000#000#000000
modifiersName: cn=config
modifyTimestamp: 20140503211805Z
modifyTimestamp: 20240312221838Z
olcTLSCACertificateFile: /etc/ldap/ssl/TEST-cacert.pem
olcTLSCertificateFile: /etc/ldap/ssl/ldap@dnscherry.org-cert.pem
olcTLSCertificateKeyFile: /etc/ldap/ssl/ldap@dnscherry.org-key.pem

View File

@ -1,14 +1,14 @@
# AUTO-GENERATED FILE - DO NOT EDIT!! Use ldapmodify.
# CRC32 d8758c75
# CRC32 baf86138
dn: cn=module{0}
objectClass: olcModuleList
cn: module{0}
olcModulePath: /usr/lib/ldap
olcModuleLoad: {0}back_hdb
olcModuleLoad: {0}back_mdb
structuralObjectClass: olcModuleList
entryUUID: 2964fd58-6754-1033-8d50-1703270f04bd
entryUUID: 3857cd3a-750a-103e-8491-9578878139e2
creatorsName: cn=admin,cn=config
createTimestamp: 20140503211805Z
entryCSN: 20140503211805.664149Z#000000#000#000000
createTimestamp: 20240312221838Z
entryCSN: 20240312221838.646168Z#000000#000#000000
modifiersName: cn=admin,cn=config
modifyTimestamp: 20140503211805Z
modifyTimestamp: 20240312221838Z

View File

@ -1,12 +1,12 @@
# AUTO-GENERATED FILE - DO NOT EDIT!! Use ldapmodify.
# CRC32 db8c9607
# CRC32 fff51a11
dn: cn=schema
objectClass: olcSchemaConfig
cn: schema
structuralObjectClass: olcSchemaConfig
entryUUID: 29644a02-6754-1033-8d4b-1703270f04bd
entryUUID: 3857a42c-750a-103e-848c-9578878139e2
creatorsName: cn=admin,cn=config
createTimestamp: 20140503211805Z
entryCSN: 20140503211805.659557Z#000000#000#000000
createTimestamp: 20240312221838Z
entryCSN: 20240312221838.645118Z#000000#000#000000
modifiersName: cn=admin,cn=config
modifyTimestamp: 20140503211805Z
modifyTimestamp: 20240312221838Z

View File

@ -1,12 +0,0 @@
# AUTO-GENERATED FILE - DO NOT EDIT!! Use ldapmodify.
# CRC32 94d41de9
dn: olcBackend={0}hdb
objectClass: olcBackendConfig
olcBackend: {0}hdb
structuralObjectClass: olcBackendConfig
entryUUID: 2965a6f4-6754-1033-8d51-1703270f04bd
creatorsName: cn=admin,cn=config
createTimestamp: 20140503211805Z
entryCSN: 20140503211805.668489Z#000000#000#000000
modifiersName: cn=admin,cn=config
modifyTimestamp: 20140503211805Z

View File

@ -1,5 +1,5 @@
# AUTO-GENERATED FILE - DO NOT EDIT!! Use ldapmodify.
# CRC32 511a173e
# CRC32 e8f0a13c
dn: olcDatabase={-1}frontend
objectClass: olcDatabaseConfig
objectClass: olcFrontendConfig
@ -10,9 +10,9 @@ olcAccess: {1}to dn.exact="" by * read
olcAccess: {2}to dn.base="cn=Subschema" by * read
olcSizeLimit: 500
structuralObjectClass: olcDatabaseConfig
entryUUID: 296430d0-6754-1033-8d49-1703270f04bd
entryUUID: 38579ebe-750a-103e-848a-9578878139e2
creatorsName: cn=config
createTimestamp: 20140503211805Z
entryCSN: 20140503211805.658911Z#000000#000#000000
createTimestamp: 20240312221838Z
entryCSN: 20240312221838.644978Z#000000#000#000000
modifiersName: cn=config
modifyTimestamp: 20140503211805Z
modifyTimestamp: 20240312221838Z

View File

@ -1,5 +1,5 @@
# AUTO-GENERATED FILE - DO NOT EDIT!! Use ldapmodify.
# CRC32 fc130d0e
# CRC32 caed0a01
dn: olcDatabase={0}config
objectClass: olcDatabaseConfig
olcDatabase: {0}config
@ -7,9 +7,9 @@ olcAccess: {0}to * by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external
,cn=auth manage by * break
olcRootDN: cn=admin,cn=config
structuralObjectClass: olcDatabaseConfig
entryUUID: 29644142-6754-1033-8d4a-1703270f04bd
entryUUID: 3857a274-750a-103e-848b-9578878139e2
creatorsName: cn=config
createTimestamp: 20140503211805Z
entryCSN: 20140503211805.659332Z#000000#000#000000
createTimestamp: 20240312221838Z
entryCSN: 20240312221838.645074Z#000000#000#000000
modifiersName: cn=config
modifyTimestamp: 20140503211805Z
modifyTimestamp: 20240312221838Z

View File

@ -1,7 +1,9 @@
dn: olcDatabase={1}hdb
# AUTO-GENERATED FILE - DO NOT EDIT!! Use ldapmodify.
# CRC32 91d29b33
dn: olcDatabase={1}mdb
objectClass: olcDatabaseConfig
objectClass: olcHdbConfig
olcDatabase: {1}hdb
objectClass: olcMdbConfig
olcDatabase: {1}mdb
olcDbDirectory: /var/lib/ldap
olcSuffix: dc=example,dc=org
olcAccess: {0}to attrs=userPassword,shadowLastChange by self write by anonymou
@ -13,15 +15,15 @@ olcLastMod: TRUE
olcRootDN: cn=admin,dc=example,dc=org
olcRootPW: {SSHA}Fp+rSxe5eFsj0DGITJts4DwdSDFDZG9P
olcDbCheckpoint: 512 30
olcDbConfig: {0}set_cachesize 0 2097152 0
olcDbConfig: {1}set_lk_max_objects 1500
olcDbConfig: {2}set_lk_max_locks 1500
olcDbConfig: {3}set_lk_max_lockers 1500
olcDbIndex: objectClass eq
structuralObjectClass: olcHdbConfig
entryUUID: 2965af5a-6754-1033-8d52-1703270f04bd
olcDbIndex: cn,uid eq
olcDbIndex: uidNumber,gidNumber eq
olcDbIndex: member,memberUid eq
olcDbMaxSize: 1073741824
structuralObjectClass: olcMdbConfig
entryUUID: 3857d7ee-750a-103e-8492-9578878139e2
creatorsName: cn=admin,cn=config
createTimestamp: 20140503211805Z
entryCSN: 20140503211805.668708Z#000000#000#000000
createTimestamp: 20240312221838Z
entryCSN: 20240312221838.646442Z#000000#000#000000
modifiersName: cn=admin,cn=config
modifyTimestamp: 20140503211805Z
modifyTimestamp: 20240312221838Z

View File

@ -20,12 +20,12 @@ admin-lv2:
- cn=nagios admins,ou=Group,dc=example,dc=org
- cn=users,ou=Group,dc=example,dc=org
developpers:
developers:
display_name: Developpers
description: description
backends_groups:
ldap:
- cn=developpers,ou=Group,dc=example,dc=org
- cn=developers,ou=Group,dc=example,dc=org
- cn=users,ou=Group,dc=example,dc=org
users: