<?xml version="1.0" encoding="UTF-8"?>
<book xmlns:ci="http://apache.org/cocoon/include/1.0">
  <bookinfo>
    <graphic fileref="logo.jpg" />

    <productname>Open Source Native XML Database</productname>
    <title>LDAP Security Manager</title>

    <author>
      <surname>Milowski</surname>

      <firstname>Alex</firstname>

      <email>alexmilowski@users.sourceforge.net</email>
    </author>
  </bookinfo>

  <ci:include src="sidebar.xml" />

  <chapter>
    <title>LDAP Security Manager</title>

    <section>
      <title>Overview</title>

      <para>The LDAP Security Manager provides the ability to pull users and
      groups from LDAP. By default, eXist stores passwords internally. If this
      feature is enabled, the users and groups are pulled from an LDAP
      directory server.</para>

      <para>This implementation currently only supports reading users and
      groups. Creation or modification is not supported.</para>
    </section>

    <section>
      <title>Configuration</title>

      <para>The LDAP Security Manager provides the ability to pull users and
      groups from LDAP. By default, eXist stores passwords internally. If this
      feature is enabled, the users and groups are pulled from an LDAP
      directory server.</para>

      <section>
        <title>Enabling LDAP in conf.xml</title>

        <para>Just place the following <code>security</code> element as a
        child of <code>db-connection</code>:</para>

        <example>
          <title>Example security Element</title>

          <screen>&lt;security class="org.exist.security.LDAPSecurityManager"/&gt;</screen>
        </example>
      </section>

      <section>
        <title>Configure Your LDAP Server</title>

        <para>For the LDAP security manager you need to distinguished names
        (DN)--one for the users and one for the groups. Each user must be
        represented by a single entry under the user DN as an RFC 2307
        <code>posixAccount</code> entry.</para>

        <para>Each group is represented by a single entry under the groupDN as
        a union of RFC 2307 <code>posixGroup</code> and RFC 2256
        <code>groupOfUniqueNames</code>.</para>
      </section>

      <section>
        <title>Set the Java Properties for LDAP</title>

        <para>When eXist is started, you must specify the follow java
        properties:</para>

        <variablelist>
          <varlistentry>
            <term>security.ldap.connection.url</term>

            <listitem>
              <para>The connection URL of the LDAP server.</para>
            </listitem>
          </varlistentry>

          <varlistentry>
            <term>security.ldap.dn.user</term>

            <listitem>
              <para>The user list DN.</para>
            </listitem>
          </varlistentry>

          <varlistentry>
            <term>security.ldap.dn.group</term>

            <listitem>
              <para>The group list DN.</para>
            </listitem>
          </varlistentry>
        </variablelist>

        <para>If you choose not to use the recommended entries under the user
        list DN, you can control each facet location by the following
        properties:</para>

        <variablelist>
          <varlistentry>
            <term>security.ldap.userClass</term>

            <listitem>
              <para>The class name on which to query the user list DN.</para>
            </listitem>
          </varlistentry>

          <varlistentry>
            <term>security.ldap.attr.uid</term>

            <listitem>
              <para>The username.</para>
            </listitem>
          </varlistentry>

          <varlistentry>
            <term>security.ldap.attr.uidNumber</term>

            <listitem>
              <para>The user id number.</para>
            </listitem>
          </varlistentry>

          <varlistentry>
            <term>security.ldap.attr.gidNumber</term>

            <listitem>
              <para>The primary group associated with the user.</para>
            </listitem>
          </varlistentry>

          <varlistentry>
            <term>security.ldap.attr.userPassword</term>

            <listitem>
              <para>The encoded password of the user.</para>
            </listitem>
          </varlistentry>

          <varlistentry>
            <term>security.ldap.attr.userDigestPassword</term>

            <listitem>
              <para>The encoded digest password of the user (for
              WebDAV).</para>
            </listitem>
          </varlistentry>
        </variablelist>

        <para>If you choose not to use the recommended entries under the group
        list DN, you can control each facet location by the following
        properties:</para>

        <variablelist>
          <varlistentry>
            <term>security.ldap.groupClass</term>

            <listitem>
              <para>The class name on which to query the group list DN.</para>
            </listitem>
          </varlistentry>

          <varlistentry>
            <term>security.ldap.attr.groupName</term>

            <listitem>
              <para>The group name.</para>
            </listitem>
          </varlistentry>

          <varlistentry>
            <term>security.ldap.attr.gidNumber</term>

            <listitem>
              <para>The group id. This must be the same in the user and
              group.</para>
            </listitem>
          </varlistentry>

          <varlistentry>
            <term>security.ldap.attr.groupMemberName</term>

            <listitem>
              <para>The name of the member entry which contains the user's
              DN.</para>
            </listitem>
          </varlistentry>
        </variablelist>

        <para>Finally, you can control the LDAP implementation by:</para>

        <variablelist>
          <varlistentry>
            <term>security.ldap.contextFactory</term>

            <listitem>
              <para>The class name of the JNDI context factory for
              LDAP.</para>
            </listitem>
          </varlistentry>
        </variablelist>
      </section>
    </section>

    <section>
      <title>Example LDAP Entries</title>

      <para>In this example exist would use the following DN values:</para>

      <variablelist>
        <varlistentry>
          <term>ou=Users,dc=exist,dc=example, dc=com, dc=authority</term>

          <listitem>
            <para>The user list DN</para>
          </listitem>
        </varlistentry>

        <varlistentry>
          <term>ou=Groups,dc=exist,dc=example, dc=com, dc=authority</term>

          <listitem>
            <para>The group list DN</para>
          </listitem>
        </varlistentry>
      </variablelist>

      <example>
        <title>LDAP Entries in LDIF Format</title>

        <screen>dn: dc=com, dc=authority
dc: com
ou: com
objectClass: dcObject
objectClass: organizationalUnit

dn: dc=example, dc=com, dc=authority
dc: example
objectClass: dcObject
objectClass: organization
o: example

dn: dc=exist,dc=example, dc=com, dc=authority
dc: exist
objectClass: dcObject
objectClass: organization
o: exist

dn: ou=Users,dc=exist,dc=example, dc=com, dc=authority
ou: Users
objectClass: organizationalUnit

dn: uid=jane,ou=Users,dc=exist,dc=example, dc=com, dc=authority
sn: Doe
userPassword:: e01adflsdflsdfasfdsdfasdf=
uidNumber: 100
gidNumber: 100
mail: jane@example.com
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
objectClass: posixAccount
uid: jane
cn: Jane
homeDirectory: /jane

dn: uid=admin,ou=Users,dc=exist,dc=example, dc=com, dc=authority
sn: Administrator
userPassword:: asdfasdfasdfasdfasdf=
uidNumber: 1
gidNumber: 1
mail: admin@example.com
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
objectClass: posixAccount
uid: admin
cn: admin
homeDirectory: /


dn: uid=guest,ou=Users,dc=exist,dc=example, dc=com, dc=authority
sn: guest
userPassword:: e01ENXlsdffsdfllllsdfasdfasdfZ=
uidNumber: 2
gidNumber: 300
mail: exist-guest@example.com
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
objectClass: posixAccount
uid: guest
cn: guest
homeDirectory: /guest

dn: ou=Groups,dc=exist,dc=example, dc=com, dc=authority
ou: Groups
objectClass: organizationalUnit

dn: cn=dba,ou=Groups,dc=exist,dc=example, dc=com, dc=authority
gidNumber: 1
objectClass: groupOfUniqueNames
objectClass: posixGroup
uniqueMember: uid=admin,ou=Users,dc=exist,dc=example,dc=com,dc=authority
cn: dba

dn: cn=guest,ou=Groups,dc=exist,dc=example, dc=com, dc=authority
gidNumber: 300
objectClass: groupOfUniqueNames
objectClass: posixGroup
uniqueMember: uid=admin,ou=Users,dc=exist,dc=example,dc=com,dc=authority
uniqueMember: uid=guest,ou=Users,dc=exist,dc=example,dc=com,dc=authority
cn: guest

dn: cn=exist.users,ou=Groups,dc=exist,dc=example, dc=com, dc=authority
gidNumber: 2001
objectClass: groupOfUniqueNames
objectClass: posixGroup
uniqueMember: uid=jane,ou=Users,dc=exist,dc=example,dc=com,dc=authority
uniqueMember: uid=guest,ou=Users,dc=exist,dc=example,dc=com,dc=authority
uniqueMember: uid=admin,ou=Users,dc=exist,dc=example,dc=com,dc=authority
cn: exist.users

dn: cn=exist.admin,ou=Groups,dc=exist,dc=example, dc=com, dc=authority
gidNumber: 2000
objectClass: groupOfUniqueNames
objectClass: posixGroup
uniqueMember: uid=admin,ou=Users,dc=exist,dc=example,dc=com,dc=authority
cn: exist.admin
</screen>
      </example>
    </section>
  </chapter>
</book>