.. Copyright (C)  2014 Champs Libres Cooperative SCRLFS
   Permission is granted to copy, distribute and/or modify this document
   under the terms of the GNU Free Documentation License, Version 1.3
   or any later version published by the Free Software Foundation;
   with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
   A copy of the license is included in the section entitled "GNU
   Free Documentation License".

.. _ldap-bundle:

LDAP bundle
###########

This bundle binds the database with an ldap directory.

The bundle synchronize the ldap directory with users in the database. It also
provides a way to check user credentials against the ldap directory.


.. contents:: Table of content
   :local:

Current limitations
*******************

- The length of the ldap dn must be < 255 characters
- if the username extracted from the ldap is updated, the changes are not reflected in the database and remains the same


Entities provided
*****************

This bundle provides only one entity : :class:`Chill\\LdapBundle\\Entity\\UserLdapBinding`

How the synchronizer works ?
****************************

#. The synchronizer performs a query on :code:`dn` and :code:`query` defined in the :ref:`configuration <configuration>`.
#. For each entry returned by the query, it looks if the :code:`dn` exists in the database

   #. If the entry does not exists :

      #. the synchronizer looks for user with same username as defined by :code:`username_attr`, and bind it with the :code:`dn` if it exists.
      #. else, a user is created with username defined by :code:`username_attr` (if the ldap contains more than one attribute, the first attribute returned is used)

   #. if a user exists which is already binded with the :code:`dn`, the entry is ignored.

#. The synchronizer looks for dn existing in database and which were not returned by the query performed in 1. 

   #. If they exists, those user are set to :code:`enabled=false`: they are not allowed to login.

Installation
************

This bundle requires : 

- PHP LDAP ext
- :code:`symfony/ldap` with minimal version 3.1. Note that, currently, Chill uses Symfony 2.8: you should add the dependency on this single package manually

In your composer.json, for stable version : 

.. code-block:: json

   "require": {
           // .. other dependencies 
           "symfony/ldap" : "~3.1",
           "chill-project/ldap": "~1.0"
   }



And for dev version :

.. code-block:: json

   "require": {
           // .. other dependencies 
           "symfony/ldap" : "~3.1",
           "chill-project/ldap": "dev-master@dev"
   }


.. _configuration:

Configuration
**************

Configuration of the bundle
============================

.. code-block:: yaml

   # Default configuration for extension with alias: "chill_ldap"
   chill_ldap:
       server:               # Required

           # the host of the ldap directory
           host:                 ~ # Required, Example: localhost

           # the port to reach the ldap directory
           port:                 389

           # the version of the ldap directory
           version:              3

           # Is the use of ssl required to establish connection
           use_ssl:              false

           # Is the use of startssl required to establish connection
           use_starttls:         false

           # the user to bind to dn directory. Required for searching existing users.
           bind_dn:              ~ # Required, Example: cn=user,dn=chill,dn=social

           # the user's password to bind to dn directory.
           bind_password:        ~ # Required, Example: paSSw0rD
       user_query:           # Required

           # The DN where the query is executed
           dn:                   ~ # Example: ou=People,dc=champs-libres,dc=coop

           # The query which will allow to retrieve users
           query:                ~ # Example: (&(objectClass=inetOrgPerson)(userPassword=*))

           # The attribute which will provide username (=login)
           username_attr:        cn


Example : 

.. code-block:: yaml

   chill_ldap:
       server:
           # host, bind_dn and bind_password are imported from parameters.yml
           host: "%ldap_host%"
           bind_dn: "%ldap_bind_dn%"
           bind_password: "%ldap_bind_password%"
       user_query:
           dn: dc=champs-libres,dc=coop
           query: "(&(objectClass=inetOrgPerson)(userPassword=*))"


Configuration of the security part of chill
============================================

Simply add the following config in the firewall of the security bundle :
`chill_ldap_form_login: ~`. This config is located in `app/config/security.yml`

Example of a configuration : 

.. code-block:: yaml

   # in app/config/security.yml

       firewalls:
           dev:
               pattern: ^/(_(profiler|wdt)|css|images|js)/
               security: false

           default:
               anonymous: ~
               # enable the login check by a form, agaisnt the database
               form_login:
                   csrf_parameter: _csrf_token
                   csrf_token_id: authenticate
                   csrf_provider: form.csrf_provider
               # enable the login check by a form, against the ldap
               chill_ldap_form_login: ~ # this is the line you should add


Note that, if you enable the login check by form **and** by the ldap, 
the password will be checked against the database **and** against the ldap.
If one of them match, the login will succeed.

If you want to completely disable login check against the database, 
simply remove the :code:`form_login` entry and all his options.

.. _command-and-crontab:

Command and crontab
===================

Synchronize the database : 

.. code-block:: bash

   php app/console chill:ldap:synchronize


For getting more debug message : 

.. code-block:: bash

   php app/console chill:ldap:synchronize -vvv



You should run this command regularly (using crontab or 
`systemd timer <https://www.freedesktop.org/software/systemd/man/systemd.timer.html#>`_)
to synchronize ldap and database automatically.



