LDAP Troubleshooting, Info

Dont create your support topics here! No new topics with questions allowed!

Moderator: crythias

Forum rules
Dont create your support topics here! No new topics with questions allowed!
Post Reply
crythias
Moderator
Posts: 10169
Joined: 04 May 2010, 18:38
Znuny Version: 5.0.x
Location: SouthWest Florida, USA
Contact:

LDAP Troubleshooting, Info

Post by crythias »

{a German user named boris has a different howto on LDAP. Check it out (German)}
If you're looking for some help with LDAP, here are some error messages to look for and what they mean:

Quick super hint: You need to set up at least one admin account that's not root@localhost to get started with ldap. If you "forget", there's an easy way to get that user setup after LDAP is set up:

Code: Select all

bin/otrs.AddUser.pl -f firstname -l lastname -p password -g admin -e user@example.com username
The username should match something in ldap, and being a member of "admin" means it's just like root@localhost.

Look at your logs (otrs.log or var/log/messages or Admin System Log). There is important information that the following won't make sense unless you see these logs.

ERRORS
Can't locate Net/LDAP.pm in @INC
This means it isn't installed. You did run otrs.CheckModules, right?

Code: Select all

cpan Net::LDAP
or

Code: Select all

ppm install Net::LDAP
might be of use.

http://wiki.servicenow.com/index.php?ti ... rror_Codes
first bind failed
Almost always SearchUser credentials, password. Invalid syntax means poorly formatted dn/distinguished name. 52e is password/credentials. If you doubt this, then it's related to the ldap host not accepting/validating the credentials. This could be for several different reasons, but it is not something OTRS can fix.
See this thread for discussion
Note that Active Directory by default needs a SearchUser and SearchPw for every bind. (A bind is simply the authority/permission to perform a search). The user to perform an LDAP lookup should not be a domain admin. It should be a basic user.

First bind failed! Bad file descriptor
This is because IPv6 is being attempted. The best way to get around this is to add the following to your Params (changed because it makes more sense):

Code: Select all

  inet4 => 1,

Code: Select all

  inet6 => 0,
"No LDAP entry found!"
This means you've successfully queried (logged in to query) the LDAP server, but the request doesn't return a result. Usually, this means you're trying to ask for a username in the wrong field or basedn.
You'll see Filter='(Param1=Param2Param3)'
Param1 is uid or the value of UserAttr
Param2 is the submitted username/login entry
Param3 is the UserSuffix, if provided

If you have an additional filter, it may show up as
Filter='(&(Param1=Param2Param3)(Param4))'
In which Param4 will be your filter parameters.

SETUP
First thing: Read the docs. Make changes in Kernel/Config.pm. Do not touch Defaults.pm (but read the file!)
3.1: http://otrs.github.io/doc/manual/admin/ ... ckend-ldap
3.1: http://otrs.github.io/doc/manual/admin/ ... ckend-ldap
3.1: http://otrs.github.io/doc/manual/admin/ ... ckend-ldap

Agents, and agents *only* sync with the database. if the AuthSyncModule is enabled. (Don't forget UseSyncBackend) There is no need for *customers* to sync to the database from LDAP. Any customer information in LDAP is available by query.
Three reasons for not customers:
  1. customers aren't constantly using OTRS
  2. the database doesn't need mass updates to query information
  3. AuthSync for Agents is the integrated solution for the issue where legitimate agents can authenticate on index.pl but can't be found in the database because they weren't manually set up. The membership of AuthSync *is* the list of allowed agents from LDAP.
Remember that you'll need a list of users (and customers) and how to authenticate them. They are two different things. You could, for instance, use LDAP to authenticate a user list in database, or HTTPBasicAuth to authenticate LDAP customers. The key is to remember that the login for a customer/agent must be viable in the authentication method. Note, this doesn't mean it has to be the same. As in the "errors" section above, what the user enters for a login name has ample means of transformation within the authentication method -- changing a login to an email, for instance, or bundling the username into a distinguished name.

$Self->{'Customer::AuthModule'} (Customer::AuthModule::LDAP, etc) is for Customer authentication (permission) (customer.pl)
$Self->{CustomerUser} is for Data (information)
$Self->{AuthModule} is for Agent (User) authentication (index.pl)
$Self->{'AuthSyncModule'} is for Agent (User) Data -- information, but mostly frontend (web interface) connection/allow access to OTRS. The documentation states "the LDAP directory is the last instance for authentication". It really means, "an additional instance for authentication." LDAP is checked as one of the user-configured (Config.pm) backend methods to verify the user attempting to login has a valid username/password pair. If that verify is invalid, OTRS won't allow the user to access the web interface. AuthSyncModule is interface-side (frontend), but both backend and frontend must succeed in order for access.

If you want to use LDAP in addition to other backends (or multiple ldap connections), you will need to append an index value (1-9) to the Array keys of the entries in Config.pm
What that means in "I don't know what you mean" speak:
$Self->{AuthModule1} = ...
$Self->{'AuthModule::LDAP::Host1'} = ...
and so on.

The following is taken directly from 3.1.7 Defaults.pm

Code: Select all

#
    # (take care that Net::LDAP is installed!)
#    $Self->{AuthModule} = 'Kernel::System::Auth::LDAP';
#    $Self->{'AuthModule::LDAP::Host'} = 'ldap.example.com';
#    $Self->{'AuthModule::LDAP::BaseDN'} = 'dc=example,dc=com';
#    $Self->{'AuthModule::LDAP::UID'} = 'uid';

    # 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::GroupDN'} = 'cn=otrsallow,ou=posixGroups,dc=example,dc=com';
#    $Self->{'AuthModule::LDAP::AccessAttr'} = 'memberUid';
    # for ldap posixGroups objectclass (just uid)
#    $Self->{'AuthModule::LDAP::UserAttr'} = 'UID';
    # for non ldap posixGroups objectclass (with full user dn)
#    $Self->{'AuthModule::LDAP::UserAttr'} = '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::SearchUserDN'} = '';
#    $Self->{'AuthModule::LDAP::SearchUserPw'} = '';

    # 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,
#    };

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

 
so, let's break it down:
$Self->{AuthModule} = 'Kernel::System::Auth::LDAP'; #You need this line to start talking about LDAP as the method to authenticate.

$Self->{'AuthModule::LDAP::Host'} = 'ldap.example.com'; #This tells us where we're going to authenticate against

$Self->{'AuthModule::LDAP::BaseDN'} = 'dc=example,dc=com'; #Where do we start looking? We can start lower (OU level, for instance)
$Self->{'AuthModule::LDAP::UID'} = 'uid'; #a field named uid. don't need to change this unless it doesn't exist in ldap. sAMAccountName is good to use here for Active Directory

$Self->{'AuthModule::LDAP::GroupDN'} = 'cn=otrsallow,ou=posixGroups,dc=example,dc=com'; #directly assigned members of this group are allowed to authenticate

$Self->{'AuthModule::LDAP::AccessAttr'} = 'memberUid'; #only relevant if GroupDN is specified. This is an attribute that exists only to indicate group membership. (See also member, or memberOf for instance)
$Self->{'AuthModule::LDAP::UserAttr'} = 'UID'; #This is a unique user attribute. In Active Directory, try 'DN', or maybe userPrincipalName

$Self->{'AuthModule::LDAP::SearchUserDN'} = ''; #a distinguished name for the user who is authorized to read ldap, if necessary. Don't use a domain admin.
$Self->{'AuthModule::LDAP::SearchUserPw'} = ''; #the user's password to read ldap

$Self->{'AuthModule::LDAP::AlwaysFilter'} = ''; #Don't try to use a bunch of "not"s here. start your BaseDN as inclusive of everyone, and filter here. For instance, users only, people with email addresses. Some examples
$Self->{'AuthModule::LDAP::Params'} = { #Keep the defaults unless you must try the global catalog port, have nonstandard ldap, etc. }
...
}
$Self->{'AuthModule::LDAP::Die'} = 1; #it's not nice to kill your app, but then again, if you can't authenticate, does it really matter? Probably good for troubleshooting, maybe not so much in production.
http://wiki.otterhub.org/index.php?titl ... for_agents

Note that an OU is not a group. If all and only agents are part of an OU, set that OU as the BaseDN for agents, and ignore Group. An OU can be considered like a nested folder structure where a user is uniquely positioned. A group can be considered like a label attached to a user. A user is in exactly one OU. A user can be a member of multiple groups.


There will likely be more, but I thought this might be helpful.
Note that AuthSyncModule, CustomerUser, and CustomerAuth for LDAP use the same concepts to connect. The use of "Map" in CustomerUser may be addressed in another post.

Advanced User Hint:
If you're using the same information multiple times (like BaseDN, Host, SearchUserDN, SearchUserPw for Authentication and Information of both Customers and Agents/Users), create and set them up as variables before you start your configuration of the rest:

Code: Select all

my $BaseDN = 'dc=domain,dc=tld';
my $Host = 'ldapserver.domain.tld';
my $SearchUserDN = 'cn=ldapreader,ou=someOU,dc=domain,dc=tld';
my $SearchUserPw = 'som3$3cr3t';
#... code...
$Self->{'Customer::AuthModule::LDAP::Host'} = $Host;
$Self->{'Authmodule::LDAP::Host'} = $Host;
$Self->{'AuthSyncModule::LDAP::Host'}  = $Host;
$Self->{CustomerUser} = {
#... other params (Name, Module)
   Params => {
      Host => $Host,
      #other params ...
   }
};
 
(Please note that the above code snippet is just a *part* of the configuration. It's intended to show you how to use the variables, but is not a completely functional configuration.)
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
crythias
Moderator
Posts: 10169
Joined: 04 May 2010, 18:38
Znuny Version: 5.0.x
Location: SouthWest Florida, USA
Contact:

Re: LDAP Troubleshooting, Info

Post by crythias »

From Defaults.pm (Don't modify Defaults.pm. Copy and modify Config.pm)

Code: Select all

    # AuthSyncModule::LDAP::UserSyncGroupsDefinition
    # (If "LDAP" was selected for AuthModule and you want to sync LDAP
    # groups to otrs groups, define the following.)
#    $Self->{'AuthSyncModule::LDAP::UserSyncGroupsDefinition'} = {
#        # ldap group
#        'cn=agent,o=otrs' => {
#            # otrs group
#            'admin' => {
#                # permission
#                rw => 1,
#                ro => 1,
#            },
#            'faq' => {
#                rw => 0,
#                ro => 1,
#            },
#        },
#        'cn=agent2,o=otrs' => {
#            'users' => {
#                rw => 1,
#                ro => 1,
#            },
#        }
#    };
 
What's it do?
If you want to assign agents to groups (see also Roles, and AttributeGroups) based upon ldap group membership or other ldap attribute, this is how you do it.

I think you could spend a good few hours looking at Defaults.pm and smack your head a bit saying, "I didn't know OTRS could do that..."
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
crythias
Moderator
Posts: 10169
Joined: 04 May 2010, 18:38
Znuny Version: 5.0.x
Location: SouthWest Florida, USA
Contact:

Re: LDAP Troubleshooting, Info

Post by crythias »

Just throwing an image in here ... hopefully it makes sense to someone.
LDAP -OTRS.png
A BaseDN is supposed to be the top of the AD tree, or the highest up you'll want to select a user below this point.
"What does that mean?"
A BaseDN could be an OU. If a BaseDN is an OU, and a user exists outside of that OU, it won't be found within/below that OU.
A BaseDN needs to be as big as necessary to include *everyone* who would be applicable. A BaseDN must not be a user.

A GroupDN must not be a user. Members must be directly members of the GroupDN, not inherited.
A GroupDN is optional, but probably desirable for Agents. If a GroupDN is not specified, and a user authenticates, but doesn't exist (especially as an Agent), an ugly error will let you know this. It's better to make sure unauthorized users can't authenticate than to authenticate and throw "UserID not found!". Note that if the agents are all in an OU, and only agents are in that OU, and the OU is a BaseDN, you may not need a GroupDN for this purpose.

A GroupDN can be a Security Group or a Distribution Group. For LDAP, all it checks is membership, not type of group.

A Filter is any ldap filter. http://www.petri.co.il/ldap_search_samp ... change.htm is a great site to help make good filters. If you don't want to use GroupDN or you want multiple Group membership, you can look to this to assist. Basically, if you want only users, or only users with email addresses, or any other type of filter, this is where to include it.
You do not have the required permissions to view the files attached to this post.
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
Post Reply