Deploy ====== LdapCherry aims to be as simple as possible to deploy. The Application is constituted of: * ldapcherryd: the daemon to lauch LdapCherry. * one ini file (ldapcherry.ini by default): the entry point for the configuration, containing all the "technical" attributes. * two yaml files (roles.yml and attributes by default): the files containing the roles and attributes definition. The default configuration directory is **/etc/ldapcherry/**. Launch ------ LdapCherry is launched using the internal cherrypy server: .. sourcecode:: bash # ldapcherryd help $ ldapcherryd -h # launching ldapcherryd in the foreground $ ldapcherryd -c /etc/ldapcherry/ldapcherry.ini # launching ldapcherryd in the foreground in debug mode $ ldapcherryd -c /etc/ldapcherry/ldapcherry.ini -D # launching ldapcherryd as a daemon $ ldapcherryd -c /etc/ldapcherry/ldapcherry.ini -p /var/run/ldapcherry/ldapcherry.pid -d Roles and Attributes Configuration ---------------------------------- Entry point in main configuration ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The main configuration file (**ldapcherry.ini** by default) contains two parameters locating the roles and attributes configuration files: +-----------------+------------+-------------------------------+-------------------+ | Parameter | Section | Description | Values | +=================+============+===============================+===================+ | attributes.file | attributes | Attributes configuration file | Path to conf file | +-----------------+------------+-------------------------------+-------------------+ | roles.file | roles | Roles configuration file | Path to conf file | +-----------------+------------+-------------------------------+-------------------+ Attributes Configuration ~~~~~~~~~~~~~~~~~~~~~~~~ The attributes configuration is done in a yaml file (**attributes.yml** by default). Mandatory parameters ^^^^^^^^^^^^^^^^^^^^ The mandatory parameters for an attribute, and their format are the following: .. sourcecode:: yaml : description: # (free text) display_name: # (free text) weight: # (integer) type: # (in ['int', 'string', 'email', 'stringlist', 'fix', 'textfield']) backends: # (list of backend attributes name) - : - : .. warning:: (the attribute id) must be unique, LdapCherry won't start if it's not. .. warning:: (the backend id) must be defined in main ini configuration file. LdapCherry won't start if it's not. Type listing ^^^^^^^^^^^^ The following **type** are supported: * **int**: an integer (ex: uid) * **string**: a string (ex: first name) * **stringlist**: a string to choose from a given list of strings (ex: one of /bin/sh, /bin/bash /bin/zsh for a shell) * **textfield**: free multiline text (ex: an SSH key) * **email**: an email address * **fix**: a fix value, only present shown information purposes Type stringlist values ^^^^^^^^^^^^^^^^^^^^^^ If **type** is set to **stringlist** the parameter **values** must be filled with the list of possible values: .. sourcecode:: yaml : description: display_name: weight: : Key attribute: ^^^^^^^^^^^^^^ One attribute must be used as a unique key across all backends: To set the key attribute, you must set **key** to **True** on this attribute. Example: .. sourcecode:: yaml uid: description: "UID of the user" display_name: "UID" search_displayed: True key: True # defining the attribute as "key" type: string weight: 50 backends: ldap: uid ad: sAMAccountName Authorize self modification ^^^^^^^^^^^^^^^^^^^^^^^^^^^ A user can modify some of his attributes (self modification). In such case, the parameter **self** must set to **True**: .. sourcecode:: yaml : description: display_name: weight: self: True backends: - : - : Autofill ^^^^^^^^ LdapCherry has the possibility to auto-fill fields from other fields, to use this functionnality **autofill** must be set. Example: .. sourcecode:: yaml gidNumber: description: "Group ID Number of the user" display_name: "GID Number" weight: 70 type: int autofill: function: lcUidNumber # name of the function to call args: # list of arguments - $first-name # - $name - '10000' - '40000' backends: ldap: gidNumber Arguments of the **autofill** function work as follow: * if argument starts with **$**, for example **$my_field**, the value of form input **my_field** will be passed to the function. * otherwise, it will be treated as a fixed argument. Available **autofill** functions: * lcUid: generate 8 characters ascii uid from 2 other fields (first letter of the first field, 7 first letters of the second): .. sourcecode:: yaml autofill: function: lcUid args: - $first-name - $name * lcDisplayName: concatenate two fields (with a space as separator): .. sourcecode:: yaml autofill: function: lcDisplayName args: - $first-name - $name * lcMail: generate an email address from 2 other fields and a domain (+domain): .. sourcecode:: yaml autofill: function: lcMail args: - $first-name - $name - '@example.com' * lcUidNumber: generate an uid number from 2 other fields and between a minimum and maximum value: .. sourcecode:: yaml autofill: function: lcUidNumber args: - $first-name - $name - '10000' - '40000' * lcHomeDir: generate an home directory from 2 other fields and a root (+): .. sourcecode:: yaml autofill: function: lcHomeDir args: - $first-name - $name - /home/ Roles Configuration ~~~~~~~~~~~~~~~~~~~ The roles configuration is done in a yaml file (**roles.yml** by default). Mandatory parameters ^^^^^^^^^^^^^^^^^^^^ Roles are seen as an aggregate of groups: .. sourcecode:: yaml : display_name: description: backends_groups: # list of backends : # list of groups in backend - - : - - .. warning:: must be unique, LdapCherry won't start if it's not Defining LdapCherry Administrator role ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ At least one of the declared roles must be tagged to be LdapCherry administrators. Doing so is done by setting **LC_admins** to **True** for the selected role: .. sourcecode:: yaml : display_name: description: LC_admins: True backends_groups: # list of backends : # list of groups in backend - - : - - Nesting roles ^^^^^^^^^^^^^ LdapCherry handles roles nesting: .. sourcecode:: yaml parent_role: display_name: Role parent description: The parent role backends_groups: backend_id_1: - b1_group_1 - b1_group_2 backend_id_2: - b2_group_1 - b2_group_2 subroles: child_role_1: display_name: Child role 1 description: The first Child Role backends_groups: backend_id_1: - b1_group_3 child_role_2: display_name: Child role 2 description: The second Child Role backends_groups: backend_id_1: - b1_group_4 In that case, child_role_1 and child_role_2 will contain all groups of parent_role plus their own specific groups. Main Configuration ------------------ Webserver ~~~~~~~~~ LdapCherry uses the embedded http server of CherryPy, however it has some limitations: * no listening on port 80/443 (unless run as root, which is strongly discourage) * no https The simpler way to properly deploy LdapCherry is to run it listening only on localhost with a port above 1024 and put it behind an http server like nginx, apache or lighttpd acting as a reverse http(s) proxy. +---------------------+---------+------------------------------------+--------------------------+--------------------------------------------+ | Parameter | Section | Description | Values | Comment | +=====================+=========+====================================+==========================+============================================+ | server.socket_host | global | Listening IP | IP on which to listen | Use '0.0.0.0' to listen on any interfaces. | +---------------------+---------+------------------------------------+--------------------------+--------------------------------------------+ | server.socket_port | global | Listening Port | TCP Port | | +---------------------+---------+------------------------------------+--------------------------+--------------------------------------------+ | server.thread_pool | global | Number of threads created | Number of threads | | | | | by the CherryPy server | threads | | +---------------------+---------+------------------------------------+--------------------------+--------------------------------------------+ | tools.staticdir.on | /static | Serve static files through | True, False | These files could be server directly by an | | | | LdapCherry | | HTTP server for better performance. | +---------------------+---------+------------------------------------+--------------------------+--------------------------------------------+ | tools.staticdir.dir | /static | Directory containing LdapCherry | Path to static resources | | | | | static resources (js, css, img...) | | | +---------------------+---------+------------------------------------+--------------------------+--------------------------------------------+ example: .. sourcecode:: ini [global] # listing interface server.socket_host = '127.0.0.1' # port server.socket_port = 8080 # number of threads server.thread_pool = 8 # enable cherrypy static handling # to comment if static content are handled otherwise [/static] tools.staticdir.on = True tools.staticdir.dir = '/usr/share/ldapcherry/static/' Backends ~~~~~~~~ Backends are configure in the **backends** section, the format is the following: .. sourcecode:: ini [backends] # backend python module path .module = # display name of the backend in forms .display_name = # parameters of the module instance for backend . . = It's possible to instanciate the same module several times. Authentication and sessions ~~~~~~~~~~~~~~~~~~~~~~~~~~~ LdapCherry supports several authentication modes: +------------------------+---------+---------------------+------------------------------------------------+---------------------------------+ | Parameter | Section | Description | Values | Comment | +========================+=========+=====================+================================================+=================================+ | auth.mode | auth | Authentication mode | * 'and' (user must auth on all backends) | | | | | | * 'or' (user must auth on one of the backends) | | | | | | * 'none' (disable auth) | | | | | | * 'custom' (use custom auth module) | | +------------------------+---------+---------------------+------------------------------------------------+---------------------------------+ | auth.module | auth | Custom auth module | python class path to module | only used if auth.mode='custom' | +------------------------+---------+---------------------+------------------------------------------------+---------------------------------+ | tools.sessions.timeout | global | Session timeout in | Number of minutes | | | | | minutes | | | +------------------------+---------+---------------------+------------------------------------------------+---------------------------------+ Different session backends can also be configured (see CherryPy documentation for details) .. sourcecode:: ini [global] # session configuration # activate session tools.sessions.on = True # session timeout in minutes tools.sessions.timeout = 10 # file session storage(to use if multiple processes, # default is in RAM and per process) #tools.sessions.storage_type = "file" # session #tools.sessions.storage_path = "/var/lib/ldapcherry/sessions" [auth] # Auth mode # * and: user must authenticate on all backends # * or: user must authenticate on one of the backend # * none: disable authentification # * custom: custom authentification module (need auth.module param) auth.mode = 'or' # custom auth module to load #auth.module = 'ldapcherry.auth.modNone' Logging ~~~~~~~ LdapCherry has two loggers, one for errors and applicative actions (login, del/add, logout...) and one for access logs. Each logger can be configured to log to syslog, file or be disabled. Logging parameters: +--------------------+---------+---------------------------------+-------------------------------------------------+----------------------------------------+ | Parameter | Section | Description | Values | Comment | +====================+=========+=================================+=================================================+========================================+ | log.access_handler | global | Logger type for access log | 'syslog', 'file', 'none' | | +--------------------+---------+---------------------------------+-------------------------------------------------+----------------------------------------+ | log.error_handler | global | Logger type for applicative log | 'syslog', 'file', 'none' | | +--------------------+---------+---------------------------------+-------------------------------------------------+----------------------------------------+ | log.access_file | global | log file for access log | path to log file | only used if log.access_handler='file' | +--------------------+---------+---------------------------------+-------------------------------------------------+----------------------------------------+ | log.error_file | global | log file for applicative log | path to log file | only used if log.error_handler='file' | +--------------------+---------+---------------------------------+-------------------------------------------------+----------------------------------------+ | log.level | global | log level of LdapCherry | 'debug', 'info', 'warning', 'error', 'critical' | | +--------------------+---------+---------------------------------+-------------------------------------------------+----------------------------------------+ Example: .. sourcecode:: ini [global] # logger syslog for access log log.access_handler = 'syslog' # logger syslog for error and ldapcherry log log.error_handler = 'syslog' # log level log.level = 'info' Custom javascript ~~~~~~~~~~~~~~~~~ It's possible to add custom javascript to LdapCherry, mainly to add custom autofill functions. Configuration: +---------------------+---------+--------------------------------+--------------------------+------------------------------------------------------------+ | Parameter | Section | Description | Values | Comment | +=====================+=========+================================+==========================+============================================================+ | tools.staticdir.on | /custom | Serve custom js files through | True, False | These files could be server directly by an | | | | LdapCherry | | HTTP server for better performance. | +---------------------+---------+--------------------------------+--------------------------+------------------------------------------------------------+ | tools.staticdir.dir | /custom | Directory containing custom js | Path to static resources | * custom js files must be put at the root if the directory | | | | files | | * only files ending with ".js" are taken into account | +---------------------+---------+--------------------------------+--------------------------+------------------------------------------------------------+ Other LdapCherry parameters ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +---------------+-----------+--------------------------------+------------------------+ | Parameter | Section | Description | Values | +===============+===========+================================+========================+ | template_dir | resources | LdapCherry template directory | path to template dir | +---------------+-----------+--------------------------------+------------------------+ .. sourcecode:: ini # resources parameters [resources] # templates directory template_dir = '/usr/share/ldapcherry/templates/'