Home | Wiki | OI 1.x Docs | OI 2.x Docs OI logo

OpenInteract and LDAP

With OpenInteract 1.2 and SPOPS 0.50, you can now use LDAP not only as a datastore for your objects, but also for authenticating users and determining group membership. This document explains how.

If you can, read this document and follow its instructions before you install and use OpenInteract. Otherwise actions like schema changes can become more difficult.

The Pieces

Additionally, two packages (base_group and base_user) offer options for storing users and groups in LDAP and doing authentication from there. See below for more.

Overall Configuration

First, install SPOPS version 0.50 or higher and run its tests to ensure that the LDAP portion (SPOPS::LDAP) is functioning properly with your LDAP server.

Next, install OpenInteract 1.2 or higher. This includes functionality to manage multiple datasources and connect to LDAP directories.

Next, make the following modifications to the server configuration file:

You can test your connection information from oi_manage:

$ oi_manage --website_dir=/path/to/mysite test_ldap

This will go through each of the defined datasources and try to connect and bind given the information in the server configuration file.

User/Group Storage and Authentication

Storing users and groups for use in OpenInteract authentication makes things a little trickier. This is supported but still in its infancy, so you might scare up a few gotchas here and there.

You should only need to do the following:

If you're having issues authenticating, try the following simple script, setting the variables to appropriate values:

#!/usr/bin/perl

use strict;
use Net::LDAP;

my $host          = 'localhost';
my $port          = 389;
my $bind_dn       = 'cn=Manager,dc=MyCompany,dc=com';

my $bind_password = 'password';

my $ldap = Net::LDAP->new( $host, port => 389 );
die "Cannot make LDAP connection\n" unless ( $ldap );

my $ldap_msg = $ldap->bind( dn => $bind_dn, password => $bind_password );
if ( my $code = $ldap_msg->code ) {
    die "Error during bind (Code: $code)\n", $ldap_msg->error, "\n";
}
print "Connect/bind ok.";

Object Security

Security for Existing Data

You might be using LDAP because you have a directory of existing information. If you are doing this, then you need to tell OpenInteract about the security for the objects already in the system.

The 'base_security' package has a script for automating this fairly common action. You'll need to run the script 'create_object_security.pl' found in that package. Here's a sample:

 $ export OIWEBSITE=/path/to/mysite
 $ cd pkg/base_security-1.xx/script
 $ perl create_object_security.pl \
      --class=MyClass::User \
      --scope=world \
      --level=read
 $ perl create_object_security.pl \
      --class=MyClass::User \
      --scope=group \
      --scope_id='site admin' \
      --level=write
 $ perl create_object_security.pl \
      --class=MyClass::Group \
      --scope=world \
      --level=read
 $ perl create_object_security.pl \
      --class=MyClass::Group \
      --scope=group \
      --scope_id='site admin' \
      --level=write

You will have to modify 'MyClass::' to your website's namespace and 'site admin' to the ID of your site admin group -- whatever you set in the {default_objects}{site_admin_group} key of your server configuration.

These commands will create entries in the security table so that the 'world' security for all users and groups is 'read' and that the site admin group has read/write privileges to all users and groups.

Run the script with the parameter '--help' to get more information about how to run it.

Object Creation Security

For objects that use security you will need to make a modification to each object's entry in its conf/spops.perl file. For instance, the default security for a lot of objects is specified by something like:

 creation_security => {
    u => undef,
    g => { 3 => 'WRITE' },
    w => 'READ',
 },

The '3' in this refers to the 'site admin' group, which is you use DBI as a backend for users and groups will always be true.

With LDAP, you'll need to change this to be the same as the value you specified in the {default_objects}{site_admin_group} key in your server configuration file.

So assuming you are using 'site admin' as the cn for the site administration group, it might look something like:

 creation_security => {
    u => undef,
    g => { 'site admin' => 'WRITE' },
    w => 'READ',
 },

This will probably be handled automatically in a future OpenInteract release. In the meantime, you'll have to change it manually for every object using security in the system. To get a listing of them, go to the URL /Security/ in your OI site. All the items in the 'Object Classes' list with 'Secure' in the 'Base Security' column need to be modified in this manner.

Server Configuration Examples

The following defines two connections: 'main' and 'auth'. The first describes a connection using an anonymous bind, while the second specifies a bind DN and password. The second also uses a different port than the first.

     'default_connection_ldap' => 'main',
     'ldap_info' => {
           main => {
              host          => 'ldap.myco.com',
              port          => 389,
              bind_dn       => undef,
              bind_password => undef,
              base_dn       => 'dc=MyCo,dc=com',
              timeout       => 120,
              version       => 2,
              sasl          => 0,
              debug         => 0,
           },
           auth => {
              host          => 'ldap.myco.com',
              port          => 3890,
              bind_dn       => 'cn=Manager,dc=MyCo,dc=com',,
              bind_password => 'crystalline',
              base_dn       => 'dc=MyCo,dc=com',
              timeout       => 120,
              version       => 2,
              sasl          => 0,
              debug         => 0,
           },
     },

Object Configuration Examples

Here's a sample configuration, from the 'base_user' package. One important thing to note: you do not need to use a full DN for {ldap_base_dn} -- OpenInteract::SPOPS::LDAP overrides the method base_dn() and prepends the value from {ldap_base_dn} to the value from {base_dn} in your datasource.

So if we were to use the example below with the 'main' datasource, the base DN of these objects would be:

  ou=People                --> From the object
+ dc=MyCo,dc=com           --> From the 'main' datasource
================
  ou=People,dc=MyCo,dc=com --> Base DN used

If you're using multiple datasources, {ldap_base_dn} needs to be a hashref with the keys as datasources and the values as the partial base DN for that datasource. See SPOPS::LDAP::MultiDatasource for more information.

   'user' => {
     class        => 'OpenInteract::User',
     code_class   => 'OpenInteract::User::LDAP',
     isa          => [ qw/ OpenInteract::User OpenInteract::SPOPS::LDAP  
                           SPOPS::Utility SPOPS::Secure SPOPS::LDAP / ],
     field        => [ qw/ cn sn givenname mail userpassword uid objectclass / ],
     field_map    => { 'last_name' => 'sn', 'first_name' => 'givenname',
                       'password' => 'userpassword', 'login_name' => 'uid',
                       'email' => 'mail', user_id => 'uid' },
     multivalue   => [ 'objectclass' ],
     id_field     => 'cn',
     ldap_base_dn => 'ou=People',
     ldap_object_class => [ qw/ top person inetOrgPerson organizationalPerson / ],
     ldap_fetch_object_class => 'person',
     alias        => [],
     has_a        => {},
     links_to     => { 'OpenInteract::Group' => 'uniquemember' },
     fetch_by     => [],
     creation_security => { 
        u => undef,
        g   => { 3 => 'WRITE' },
        w   => 'READ',
     },
     track        => { create => 0, update => 1, remove => 1 },
     display      => { url => '/User/show/' },
     name         => sub { return $_[0]->full_name },
     object_name  => 'User',
  },

Multiple Datasources

You can use multiple datasources in two different ways

  1. Use multiple datasources for the same class. This enables you to search for an entry once and have the search get executed on multiple directories. Read about how this works and how you set it up in SPOPS::LDAP::MultiDatasource
  2. Use a single datasource per a class but have multiple directories available. For instance, you might run one LDAP directory for all equipment in your organization and another for all employees and groups.

    For this, you simply need to configure all datasources in your server configuration, then tell each SPOPS class which datasource it should use. To tell a class, you need to use the {datasource} key in its configuration:

    $config = {
       class      => 'My::Equipment',
       isa        => [ 'SPOPS::LDAP' ],
       datasource => 'equipment',
    };
    

    This class would use the connection information stored under the key 'equipment' in your server configuration.

    There are other configuration details to be aware of -- please see SPOPS::LDAP::MultiDatasource for more infromation.


Home | Wiki | OI 1.x Docs | OI 2.x Docs
SourceForge Logo