Filtering Customer Search from Active Directory

Moderator: crythias

Locked
dceotrs
Znuny newbie
Posts: 4
Joined: 18 Sep 2013, 01:02
Znuny Version: 3.2.10
Real Name: Lamar Newton
Company: Brigham Young University

Filtering Customer Search from Active Directory

Post by dceotrs »

I'm brand new to OTRS so please forgive my ignorance.

I have been trying to setup a proof of concept OTRS implementation so that we can evaluate OTRS as a replacement for our current helpdesk system. This system will be used as an internal Helpdesk environment, so both the agents and customers are within our own organization. Our organization uses a Microsoft Active Directory of which I want to use to authenticate both our agents and customers against in OTRS.

So far I have been able to achieve the goal of authenticating both agents and Customers against our Active Directory. The problem is that it isn't working exactly the way that we would like. The current problem that I am trying to resolve is in relation to customer searches. Our Active Directory is an directory that is used by multiple departments within our University which contains upwards of 40,000 objects, but our department that I want to limit the scope of OTRS to only has about 500 people. So far I have been able to create a group in AD that OTRS uses for login (which works), but if an Agent is creating a ticket for a customer and does a customer search it is still searching all 40,000 plus objects. I'm looking for a way to make it so that customer searches are also restricted by the AD customer group that I created and it needs to be able to deal with nested groups.

Can someone suggest a way to make this work???

Below is Agent and Customer sections of my config.pm file:

Code: Select all

    # This is an example configuration for an LDAP auth. backend.
    # (take care that Net::LDAP is installed!)
   $Self->{AuthModule1} = 'Kernel::System::Auth::LDAP';
   $Self->{'AuthModule::LDAP::Host1'} = 'byu.local';
   $Self->{'AuthModule::LDAP::BaseDN1'} = 'dc=byu,dc=local';
   $Self->{'AuthModule::LDAP::UID1'} = 'sAMAccountName';

    # Check if the user is allowed to auth in a posixGroup
    # (e. g. user needs to be in a group xyz to use otrs)
   $Self->{'AuthModule::LDAP::GroupDN1'} = 'CN=OTRSAgents,OU=DCE,DC=byu,DC=local';
   $Self->{'AuthModule::LDAP::AccessAttr1'} = 'member';
    # for ldap posixGroups objectclass (just uid)
   # $Self->{'AuthModule::LDAP::UserAttr1'} = 'UID';
    # for non ldap posixGroups objectclass (with full user dn)
    # $Self->{'AuthModule::LDAP::UserAttr1'} = 'DN';

    # The following is valid but would only be necessary if the
    # anonymous user do NOT have permission to read from the LDAP tree
   $Self->{'AuthModule::LDAP::SearchUserDN1'} = 'CN=OTRS Search,OU=DCE,DC=byu,DC=local';
   $Self->{'AuthModule::LDAP::SearchUserPw1'} = 'mypassword';

    # in case you want to add always one filter to each ldap query, use
    # this option. e. g. AlwaysFilter => '(mail=*)' or AlwaysFilter => '(objectclass=user)'
#    $Self->{'AuthModule::LDAP::AlwaysFilter'} = '';

    # in case you want to add a suffix to each login name, then
    # you can use this option. e. g. user just want to use user but
    # in your ldap directory exists user@domain.
#    $Self->{'AuthModule::LDAP::UserSuffix'} = '@domain.com';

    # In case you want to convert all given usernames to lower letters you
    # should activate this option. It might be helpfull if databases are
    # in use that do not distinguish selects for upper and lower case letters
    # (Oracle, postgresql). User might be synched twice, if this option
    # is not in use.
#    $Self->{'AuthModule::LDAP::UserLowerCase'} = 0;

    # In case you need to use OTRS in iso-charset, you can define this
    # by using this option (converts utf-8 data from LDAP to iso).
#    $Self->{'AuthModule::LDAP::Charset'} = 'iso-8859-1';

    # Net::LDAP new params (if needed - for more info see perldoc Net::LDAP)
   $Self->{'AuthModule::LDAP::Params'} = {
       port    => 389,
       timeout => 120,
       async   => 0,
       version => 3,
   };
    # --------------------------------------------------- #
    # authentication sync settings                        #
    # (enable agent data sync. after succsessful          #
    # authentication)                                     #
    # --------------------------------------------------- #
    # This is an example configuration for an LDAP auth sync. backend.
    # (take care that Net::LDAP is installed!)
   $Self->{AuthSyncModule1} = 'Kernel::System::Auth::Sync::LDAP';
   $Self->{'AuthSyncModule::LDAP::Host1'} = 'byu.local';
   $Self->{'AuthSyncModule::LDAP::BaseDN1'} = 'dc=byu,dc=local';
   $Self->{'AuthSyncModule::LDAP::UID1'} = 'sAMAccountName';

    # The following is valid but would only be necessary if the
    # anonymous user do NOT have permission to read from the LDAP tree
   $Self->{'AuthSyncModule::LDAP::SearchUserDN1'} = 'CN=OTRS Search,OU=DCE,DC=byu,DC=local';
   $Self->{'AuthSyncModule::LDAP::SearchUserPw1'} = 'mypassword';

    # in case you want to add always one filter to each ldap query, use
    # this option. e. g. AlwaysFilter => '(mail=*)' or AlwaysFilter => '(objectclass=user)'
#    $Self->{'AuthSyncModule::LDAP::AlwaysFilter'} = '';

    # AuthSyncModule::LDAP::UserSyncMap
    # (map if agent should create/synced from LDAP to DB after successful login)
   $Self->{'AuthSyncModule::LDAP::UserSyncMap1'} = {
       # DB -> LDAP
       UserFirstname => 'givenName',
       UserLastname  => 'sn',
       UserEmail     => 'mail',
   };

    # In case you need to use OTRS in iso-charset, you can define this
    # by using this option (converts utf-8 data from LDAP to iso).
#    $Self->{'AuthSyncModule::LDAP::Charset'} = 'iso-8859-1';

    # Net::LDAP new params (if needed - for more info see perldoc Net::LDAP)
   $Self->{'AuthSyncModule::LDAP::Params'} = {
       port    => 389,
       timeout => 120,
       async   => 0,
       version => 3,
   };

    # Die if backend can't work, e. g. can't connect to server.
#    $Self->{'AuthSyncModule::LDAP::Die'} = 1;

    # Die if backend can't work, e. g. can't connect to server.
#    $Self->{'AuthModule::LDAP::Die'} = 1;
# End Agent Configuration

# Begin of Customer LDAP configuration

$Self->{'Customer::AuthModule'} = 'Kernel::System::CustomerAuth::ConnectAD';
$Self->{'Customer::AuthModule::ConnectAD::Host'} = 'byu.local';
$Self->{'Customer::AuthModule::ConnectAD::BaseDN'} = 'dc=byu,dc=local';
$Self->{'Customer::AuthModule::ConnectAD::UID'} = 'sAMAccountName';
# Group membership filtering start
$Self->{'Customer::AuthModule::ConnectAD::GroupDN'} = 'CN=OTRSCustomers,OU=DCE,DC=byu,DC=local';
$Self->{'Customer::AuthModule::ConnectAD::AccessAttr'} = 'member';
# only Member of this group are allowed to login, erase the commentsymbol(#) to enable filtering
$Self->{'Customer::AuthModule::ConnectAD::SearchUserDN'} = 'CN=OTRS Search,OU=DCE,DC=byu,DC=local';
$Self->{'Customer::AuthModule::ConnectAD::SearchUserPw'} = 'my password'; 

$Self->{CustomerUser} = {
   Name => 'otrs ldap1',
   Module => 'Kernel::System::CustomerUser::LDAP',
   Params => {
      Host => 'byu.local',
      BaseDN => 'dc=byu,dc=local',
      SSCOPE => 'sub',
      UserDN => 'CN=OTRS Search,OU=DCE,DC=byu,DC=local',
      UserPw => 'mypassword',
      AlwaysFilter => '',
   },
   CustomerKey => 'sAMAccountName',
   CustomerID => 'mail',
   CustomerUserListFields => ['UserFirstname', 'UserLastname', 'sAMAccountName', 'cn', 'mail'],
# original line  CustomerUserListFields => ['sAMAccountName', 'cn', 'mail'],
   CustomerUserSearchFields => ['UserFirstname', 'UserLastname', 'sAMAccountName', 'cn', 'mail'],
# original line  CustomerUserSearchFields => ['sAMAccountName', 'cn', 'mail'],
   CustomerUserPostMasterSearchFields => ['UserFirstname', 'UserLastname', 'mail'],
   CustomerUserNameFields => ['UserFirstname', 'UserLastname', 'sn'],
# original line  CustomerUserPostMasterSearchFields => ['mail'],
# original line  CustomerUserNameFields => ['givenname', 'sn'],
   Map => [
      #['UserSalutation', 'Title', 'title', '1', '0', 'var'],
      ['UserFirstname', 'Firstname', 'givenname', '1', '1', 'var'],
      ['UserLastname', 'Lastname', 'sn', '1', '1', 'var'],
      ['UserLogin', 'Login', 'sAMAccountName', '1', '1', 'var'],
      ['UserEmail', 'Email', 'mail', '1', '1', 'var'],
      ['UserCustomerID', 'CustomerID', 'mail', '0', '1', 'var'],
      #['UserPhone', 'Phone', 'telephonenumber', '1', '0', 'var'],
      #['UserAddress', 'Address', 'postaladdress', '1', '0', 'var'],
      #['UserComment', 'Comment', 'description', '1', '0', 'var'],
   ],
}; 
# End of Customer LDAP configuration
crythias
Moderator
Posts: 10170
Joined: 04 May 2010, 18:38
Znuny Version: 5.0.x
Location: SouthWest Florida, USA
Contact:

Re: Filtering Customer Search from Active Directory

Post by crythias »

use ldapsearch criteria in "always filter"
OTRS 6.0.x (private/testing/public) on Linux with MySQL database.
Please edit your signature to include your OTRS version, Operating System, and database type.
Click Subscribe Topic below to get notifications. Consider amending your topic title to include [SOLVED] if it is so.
Need help? Before you ask
dceotrs
Znuny newbie
Posts: 4
Joined: 18 Sep 2013, 01:02
Znuny Version: 3.2.10
Real Name: Lamar Newton
Company: Brigham Young University

Re: Filtering Customer Search from Active Directory

Post by dceotrs »

Thank You! Is there somewhere that I can get information on how to configure the "Always filter"?
crythias
Moderator
Posts: 10170
Joined: 04 May 2010, 18:38
Znuny Version: 5.0.x
Location: SouthWest Florida, USA
Contact:

Re: Filtering Customer Search from Active Directory

Post by crythias »

OTRS 6.0.x (private/testing/public) on Linux with MySQL database.
Please edit your signature to include your OTRS version, Operating System, and database type.
Click Subscribe Topic below to get notifications. Consider amending your topic title to include [SOLVED] if it is so.
Need help? Before you ask
dceotrs
Znuny newbie
Posts: 4
Joined: 18 Sep 2013, 01:02
Znuny Version: 3.2.10
Real Name: Lamar Newton
Company: Brigham Young University

Re: Filtering Customer Search from Active Directory

Post by dceotrs »

Okay, that link was helpful. Below is the change that I made to the Customer section of the config.pm file (I bolded the significant line). The change causes it to only show customers who are directly members of the group "OTRSCustomers". The problem is that the group "OTRSCustomers" contains nested groups and the filter is ignoring those who are members of the nested groups. The ConnectAD module fixes this problem for authentication but it doesn't seem to be working for the filter.

Any Ideas? Thank You!

# Begin of Customer LDAP configuration

$Self->{'Customer::AuthModule'} = 'Kernel::System::CustomerAuth::ConnectAD';
$Self->{'Customer::AuthModule::ConnectAD::Host'} = 'byu.local';
$Self->{'Customer::AuthModule::ConnectAD::BaseDN'} = 'dc=byu,dc=local';
$Self->{'Customer::AuthModule::ConnectAD::UID'} = 'sAMAccountName';
# Group membership filtering start
$Self->{'Customer::AuthModule::ConnectAD::GroupDN'} = 'CN=OTRSCustomers,OU=DCE,DC=byu,DC=local';
$Self->{'Customer::AuthModule::ConnectAD::AccessAttr'} = 'member';
# only Member of this group are allowed to login, erase the commentsymbol(#) to enable filtering
$Self->{'Customer::AuthModule::ConnectAD::SearchUserDN'} = 'CN=OTRS Search,OU=DCE,DC=byu,DC=local';
$Self->{'Customer::AuthModule::ConnectAD::SearchUserPw'} = 'mypassword';

$Self->{CustomerUser} = {
Name => 'otrs ldap1',
Module => 'Kernel::System::CustomerUser::ConnectAD',
Params => {
Host => 'byu.local',
BaseDN => 'dc=byu,dc=local',
SSCOPE => 'sub',
UserDN => 'CN=OTRS Search,OU=DCE,DC=byu,DC=local',
UserPw => 'dceotrs1',
AlwaysFilter => '(objectclass=user)(memberOf=CN=OTRSCustomers,OU=DCE,DC=byu,DC=local)',
},
CustomerKey => 'sAMAccountName',
CustomerID => 'mail',
CustomerUserListFields => ['givenname', 'sn', 'sAMAccountName', 'cn', 'mail'],
# original line CustomerUserListFields => ['sAMAccountName', 'cn', 'mail'],
CustomerUserSearchFields => ['givenname', 'sn', 'sAMAccountName', 'cn', 'mail'],
# original line CustomerUserSearchFields => ['sAMAccountName', 'cn', 'mail'],
CustomerUserPostMasterSearchFields => ['givenname', 'sn', 'mail'],
CustomerUserNameFields => ['givenname', 'sn'],
# original line CustomerUserPostMasterSearchFields => ['mail'],
# original line CustomerUserNameFields => ['givenname', 'sn'],
Map => [
#['UserSalutation', 'Title', 'title', '1', '0', 'var'],
['UserFirstname', 'Firstname', 'givenname', '1', '1', 'var'],
['UserLastname', 'Lastname', 'sn', '1', '1', 'var'],
['UserLogin', 'Login', 'sAMAccountName', '1', '1', 'var'],
['UserEmail', 'Email', 'mail', '1', '1', 'var'],
['UserCustomerID', 'CustomerID', 'mail', '0', '1', 'var'],
#['UserPhone', 'Phone', 'telephonenumber', '1', '0', 'var'],
#['UserAddress', 'Address', 'postaladdress', '1', '0', 'var'],
#['UserComment', 'Comment', 'description', '1', '0', 'var'],
],
};

# End of Customer LDAP configuration
dceotrs
Znuny newbie
Posts: 4
Joined: 18 Sep 2013, 01:02
Znuny Version: 3.2.10
Real Name: Lamar Newton
Company: Brigham Young University

Re: Filtering Customer Search from Active Directory

Post by dceotrs »

Based on the information that crythias provided (THANK YOU!!) I have been able to solve most of the problems that I was having, but it requires WAY more finagling than it should in my opinion.

- 1st I needed to install a third party plugin in order to get the customer login to filter properly on a group which contains nested groups. The module is called ConnectAD which can be found on the OPMZone website.
- 2nd for some reason I could never get ConnectAD to work with Agent logins, so all of our agents will have to be located directly in the control group
- 3rd Although I was able to get ConnectAD against a nested AD group to work for Customer logins, I was not able to get it to work in the alwaysfilter so that when agents are searching customers it only shows the customers that are in the AD group. I therefore had to resort to using a lot of OR conditions in the filter to look in all of the nested groups.

I think it incredible that this hasn't been a big enough issue that the OTRS development community hasn't resolved LDAP lookups to deal with nested groups in AD!! The ConnectAD module works to a point, but it still needs a LOT of work - unless, of course, I'm missing something in my implementation.


To help those who follow, I have included below my resultant config.pm file as an example of what I did to get it to work - to a point.


#Agent Authentication section
# (take care that Net::LDAP is installed!)
# Note: the 1's in the following lines which allow for agent information being stored in both AD and the local DB
$Self->{AuthModule1} = 'Kernel::System::Auth::LDAP';
$Self->{'AuthModule::LDAP::Host1'} = 'byu.local';
$Self->{'AuthModule::LDAP::BaseDN1'} = 'dc=byu,dc=local';
$Self->{'AuthModule::LDAP::UID1'} = 'sAMAccountName';

# This section provides group membership requirements before an agent can login
$Self->{'AuthModule::LDAP::GroupDN1'} = 'CN=OTRSAgents,OU=DCE,DC=byu,DC=local';
$Self->{'AuthModule::LDAP::AccessAttr1'} = 'member';

# This is the AD user that has rights to browse the AD tree for agent authentication
$Self->{'AuthModule::LDAP::SearchUserDN1'} = 'CN=OTRS Search,OU=DCE,DC=byu,DC=local';
$Self->{'AuthModule::LDAP::SearchUserPw1'} = 'mypassword';

# Net::LDAP new params (if needed - for more info see perldoc Net::LDAP)
$Self->{'AuthModule::LDAP::Params'} = {
port => 389,
timeout => 120,
async => 0,
version => 3,
};
# --------------------------------------------------- #
# authentication sync settings #
# (enable agent data sync. after succsessful #
# authentication) #
# --------------------------------------------------- #
# This is an example configuration for an LDAP auth sync. backend.
# (take care that Net::LDAP is installed!)
$Self->{AuthSyncModule1} = 'Kernel::System::Auth::Sync::LDAP';
$Self->{'AuthSyncModule::LDAP::Host1'} = 'byu.local';
$Self->{'AuthSyncModule::LDAP::BaseDN1'} = 'dc=byu,dc=local';
$Self->{'AuthSyncModule::LDAP::UID1'} = 'sAMAccountName';

# The following is valid but would only be necessary if the
# anonymous user do NOT have permission to read from the LDAP tree
$Self->{'AuthSyncModule::LDAP::SearchUserDN1'} = 'CN=OTRS Search,OU=DCE,DC=byu,DC=local';
$Self->{'AuthSyncModule::LDAP::SearchUserPw1'} = 'mypassword';

# AuthSyncModule::LDAP::UserSyncMap
# (map if agent should create/synced from LDAP to DB after successful login)
$Self->{'AuthSyncModule::LDAP::UserSyncMap1'} = {
# DB -> LDAP
UserFirstname => 'givenName',
UserLastname => 'sn',
UserEmail => 'mail',
};

# Net::LDAP new params (if needed - for more info see perldoc Net::LDAP)
$Self->{'AuthSyncModule::LDAP::Params'} = {
port => 389,
timeout => 120,
async => 0,
version => 3,
};

# Die if backend can't work, e. g. can't connect to server.
# $Self->{'AuthSyncModule::LDAP::Die'} = 1;

# Die if backend can't work, e. g. can't connect to server.
# $Self->{'AuthModule::LDAP::Die'} = 1;
# End Agent Configuration

# Begin of Customer LDAP configuration

$Self->{'Customer::AuthModule'} = 'Kernel::System::CustomerAuth::ConnectAD';
$Self->{'Customer::AuthModule::ConnectAD::Host'} = 'byu.local';
$Self->{'Customer::AuthModule::ConnectAD::BaseDN'} = 'dc=byu,dc=local';
$Self->{'Customer::AuthModule::ConnectAD::UID'} = 'sAMAccountName';
# Group membership filtering start
$Self->{'Customer::AuthModule::ConnectAD::GroupDN'} = 'CN=OTRSCustomers,OU=DCE,DC=byu,DC=local';
$Self->{'Customer::AuthModule::ConnectAD::AccessAttr'} = 'member';
# only Member of this group are allowed to login, erase the commentsymbol(#) to enable filtering
$Self->{'Customer::AuthModule::ConnectAD::SearchUserDN'} = 'CN=OTRS Search,OU=DCE,DC=byu,DC=local';
$Self->{'Customer::AuthModule::ConnectAD::SearchUserPw'} = 'mypassword';

$Self->{CustomerUser} = {
Name => 'otrs ldap1',
Module => 'Kernel::System::CustomerUser::LDAP',
Params => {
Host => 'byu.local',
BaseDN => 'dc=byu,dc=local',
SSCOPE => 'sub',
UserDN => 'CN=OTRS Search,OU=DCE,DC=byu,DC=local',
UserPw => 'mypassword',
AlwaysFilter => '(objectclass=user)(|(memberOf=CN=OTRSCustomers,OU=DCE,DC=byu,DC=local)
(memberOf=CN=DCE-DomainUsers,OU=SecurityGroups,OU=DCE,DC=byu,DC=local)
(memberOf=CN=DCE-DomainUsers,OU=SecurityGroups,OU=DCE,DC=byu,DC=local)
(memberOf=CN=DCE.Accounting.AllUsers,OU=Accounting,OU=SecurityGroups,OU=DCE,DC=byu,DC=local)
(memberOf=CN=DCE.BGS.AllUsers,OU=BGS,OU=SecurityGroups,OU=DCE,DC=byu,DC=local)
(memberOf=CN=DCE.ED.AllUsers,OU=CES,OU=SecurityGroups,OU=DCE,DC=byu,DC=local)
(memberOf=CN=DCE.CMP.AllUsers,OU=CMP,OU=SecurityGroups,OU=DCE,DC=byu,DC=local)
(memberOf=CN=DCE.CWAllUsers,OU=CW,OU=SecurityGroups,OU=DCE,DC=byu,DC=local)
(memberOf=CN=DCE.DN.AllUsers,OU=DN,OU=SecurityGroups,OU=DCE,DC=byu,DC=local)
(memberOf=CN=DCE.EV.AllUsers,OU=EV,OU=SecurityGroups,OU=DCE,DC=byu,DC=local)
(memberOf=CN=DCE.HR.AllUsers,OU=HR,OU=SecurityGroups,OU=DCE,DC=byu,DC=local)
(memberOf=CN=DCE.IS.AllUsers,OU=IS,OU=SecurityGroups,OU=DCE,DC=byu,DC=local)
(memberOf=CN=DCE.REG.AllUsers,OU=REG,OU=SecurityGroups,OU=DCE,DC=byu,DC=local)
(memberOf=CN=DCE.Viscom.AllUsers,OU=Viscom,OU=SecurityGroups,OU=DCE,DC=byu,DC=local)
(memberOf=CN=DCE.YP.AllUsers,OU=YP,OU=SecurityGroups,OU=DCE,DC=byu,DC=local))',
},
CustomerKey => 'sAMAccountName',
CustomerID => 'mail',
CustomerUserListFields => ['givenname', 'sn', 'sAMAccountName', 'cn', 'mail'],
CustomerUserSearchFields => ['givenname', 'sn', 'sAMAccountName', 'cn', 'mail'],
CustomerUserPostMasterSearchFields => ['givenname', 'sn', 'mail'],
CustomerUserNameFields => ['givenname', 'sn'],
Map => [
#['UserSalutation', 'Title', 'title', '1', '0', 'var'],
['UserFirstname', 'Firstname', 'givenname', '1', '1', 'var'],
['UserLastname', 'Lastname', 'sn', '1', '1', 'var'],
['UserLogin', 'Login', 'sAMAccountName', '1', '1', 'var'],
['UserEmail', 'Email', 'mail', '1', '1', 'var'],
['UserCustomerID', 'CustomerID', 'mail', '0', '1', 'var'],
#['UserPhone', 'Phone', 'telephonenumber', '1', '0', 'var'],
#['UserAddress', 'Address', 'postaladdress', '1', '0', 'var'],
#['UserComment', 'Comment', 'description', '1', '0', 'var'],
],
};

# End of Customer LDAP configuration
Locked