Chapter 11. LDAP Integration

OTRS kann an mehreren Stellen ein LDAP Verzeichnis als Quelle nutzen. Die folgende Anleitung beschreibt, wie ein Active Directory Server mit OTRS genutzt wird. Das Beispiel dient auch dem grundsätzlichen Verständnis, wie gegen einen LDAP-Server gebunden wird.

Active Directory

Diese Anleitung beschreibt, wie OTRS mit Microsoft's Active Directory (im folgenden AD genannt) integriert wird. Via LDAP werden sowohl Agenten wie auch Kunden authentifiziert, und die Kunden-informationen beschafft werden.

Wir nehmen an, dass OTRS auf einem Linux Server läuft und dass Sie wissen, wie mit dem AD und dessen administrativen Werkzeugen umzugehen ist.

Die Nennung spezifischer Produkte und Marken erfolgt ohne weitergehende Absicht.

Fühlen Sie sich aufgerufen, vor Änderungen am System ein desselben Backup vorzunehmen, und dies auch regelmäßig zu tun.

Vorbereitungen

Als einzige Voraussetzung für den OTRS Server ergibt sich ein instal.liertes Net::LDAP. Das Modul kann von http://ldap.perl.org/ heruntergeladen werden.

Zudem ist es eine gute Idee, zunächst einen OTRS-Adminzugange in der Datenbank anzulegen, oder Sie werden sich nicht einloggen können. Erstellen Sie einen Admin, dessen Name dem im AD entspricht.

Um die LDAP-Fähigkeiten des OTRS mit einem AD nutzen zu können, benötigen Sie mindestens einen AD-Controller. Dieser muss als sog. Global Catalog Server (GCS) fungieren, um Authentifizierungen gegen das AD zu erlauben.

Sie können das AD sowohl von Windows 2000 als auch von Windows 2003 aus nutzen.

Details, die während der Konfiguration von OTRS und LDAP benötigt werden.

  • Hostname des AD Servers

  • Basis-DN Ihres AD-Baumes

  • Username und Passwort, mit denen die LDAP-Abfragen durchgeführt werden (AD erlaubt keine anonymen Abfragen!)

Konfiguration

Konfiguration des Active Directory

Erstellen Sie im AD einen neuen Benutzer mit dem werkzeug "AD Benutzer und Computer". Der Benutzer muss lediglich die Rechte eines regulären Domänen-Benutzers besitzen. Existiert eine Richtlinie, die nach einer gewissen Zeit zum Wechsel des Passwortes auffordern wird, konfigurieren Sie den Zugang so, dass das Password nie abläuft.

OTRS LDAP Optionen

OTRS kann LDAP an drei Stellen nutzen.

  • Authentifizierung der Agenten

  • Authentifizierung der Kundenbenutzer

  • Daten der Kundenbenutzer

Die beiden Module betreffend Kundenbenutzer werden am besten zusammen verwendet, oder es ist viel Handarbeit notwendig. Diese Anleitung bezieht sich nicht auf die wechselseitige Nutzung der beiden Optionen.

Authentifizierung der Agenten

Bearbeiten Sie die Konfigurationsdatei von OTRS, üblicherweise zu finden in <OTRS_HOME>/Kernel/Config.pm.

Fügen Sie folgendes hinzu:

Example 11-1. Kernel/Config.pm - AuthModule

   $Self->{'AuthModule'} = 'Kernel::System::Auth::LDAP';

Hiermit wird der Modus zur Authentifizierung auf LDAP umgeschaltet.

Nun fügen Sie die folgenden drei Zeilen hinzu:

Example 11-2. Kernel/Config.pm - AuthModule::LDAP Einstellungen

   $Self->{'AuthModule::LDAP::Host'} = '[AD_server]'; 
   $Self->{'AuthModule::LDAP::BaseDN'} = '[base_dn]';
   $Self->{'AuthModule::LDAP::UID'} = 'sAMAccountName';

Ersetzen Sie [AD_server] mit dem Hostnamen (w2kad.example.com) oder der IP Adresse Ihres AD Servers (192.168.1.23).

Ersetzen Sie [base_dn] mit der Basis-DN Ihres AD-Baumes. Sie folgt dieser Syntax "dc=example, dc=com".

Ein einfacher Weg, an die Basis-DN zu gelangen, bietet das Werkzeug "AD Benutzer und Computer". Der Name des AD-Baumes zeigt den Domänennamen als "domain.tld" oder "subdomain.domain.tld", je nachdem, wie Ihr AD aufgesetzt wurde. Bei der Konversion in eine DN werden obige Beispiele dann zu "dc=domain, dc=tld" und "dc=subdomain, dc=domain, dc=com".

Finden Sie die Basis-DN Ihres ADs immer noch nciht, können Sie weitere Tools nutzen, wie etwa LDIFDE (finden Sie auf dem AD Server) oder ADSI Edit (von der W2K Support Kit CD/Resource Kit CD).

Da das AD ein spezielles und von einem reinen inetOrg abweichendes Schema nutzt, müssen wir "sAMAccountName" für die UID des Zugangs benutzen. Dieses Merkmal ist bestimmend im AD.

Sie müssen den Zugang angeben, über den OTRS mit dem AD kommuniziert. Dies geschieht mit den folgenden Einstellungen:

Example 11-3. Kernel/Config.pm - AuthModule::LDAP Einstellungen zum SearchUser

  $Self->{'AuthModule::LDAP::SearchUserDN'} = '[user_dn]';
  $Self->{'AuthModule::LDAP::SearchUserPw'} = '[passwort]';

Ersetzen Sie [user_dn] mit der vollständigen DN des gewünschten AD/OTRS Benutzers. Folgen Sie der Standard-LDAP-Syntax. Die vollständige DN richtet sich nach dem Kontainer, in dem Sie den Benutzerzugang mit "AD Benutzer und Gruppen" erstellt haben. Haben Sie den Benutzer im Standard-Kontainer "Benutzer" erstellt, lautet die Syntax "cn=Vorname Nachname, cn=Benutzer, [base_dn]". Wenn Sie unsicher sind, welches die korrekte DN ist, führen Sie LDIFDE.EXE auf Ihrem AD controller aus und durchsuchen sie dessen Ausgabe.

Ersetzen Sie [passwort] mit dem Password dieses Zugangs.

Authentifizierung der Kundenbenutzer

Die Konfiguration der Authentifizierung der Kundenbenutzer wird durch folgende Parameter bestimmt:

Example 11-4. Kernel/Config.pm - Customer::AuthModule LDAP Einstellungen

  $Self->{'Customer::AuthModule'} = 'Kernel::System::CustomerAuth::LDAP';
  $Self->{'Customer::AuthModule::LDAP::Host'} = '[AD_server]';
  $Self->{'Customer::AuthModule::LDAP::BaseDN'} = '[base_dn]';
  $Self->{'Customer::AuthModule::LDAP::UID'} = 'sAMAccountName';
  $Self->{'Customer::AuthModule::LDAP::SearchUserDN'} = '[user_dn]';
  $Self->{'Customer::AuthModule::LDAP::SearchUserPw'} = '[passwort]';

Ersetzen Sie [AD_server] mit dem Hostnamen Ihres AD Servers, z.B.: w2kad.example.com.

Ersetzen Sie [base_dn] mit der DN des Astes, in dem Ihre Kundenbenutzer untergebracht sind. Befinden Sich alle Kundenbenutzer in einem "People" Kontainer, spezifizieren Sie diesen als Basis-DN für CustomerAuth: "ou=People, dc=example, dc=com". Haben Sie Kundenbenutzerdaten in mehreren Kontainern, richten Sie mehrere LDAP-Quellen ein. Sie können $Self->{CustomerUser1} bis $Self->{CustomerUser10} zusätzlich erstellen.

Ersetzen Sie [user_dn] wie oben mit dem OTRS/AD Benutzer und [passwort] mit dessen Passwort.

Daten der Kundenbenutzer

Dies sind die notwendigen Einstellungen, um die Daten der Kundenbenutzer aus dem LDAP/AD zu lesen:

Example 11-5. Kernel/Config.pm - CustomerUser::LDAP Einstellungen

  $Self->{CustomerUser} = {
    Module => 'Kernel::System::CustomerUser::LDAP',
    Params => {
      Host => '[AD_server]',
      BaseDN => '[base_dn]',
      SSCOPE => 'sub',
      UserDN => '[user_dn]',
      UserPw => '[password]',
    },
    CustomerKey => 'sAMAccountName',
    CustomerID => '[customer_id]',
    CustomerUserListFields => ['sAMAccountName', 'cn', 'mail'],
    CustomerUserSearchFields => ['sAMAccountName', 'cn', 'mail'],
    CustomerUserPostMasterSearchFields => ['mail'],
    CustomerUserNameFields => ['givenname', 'sn'],
    Map => [
      # note: Login, Email and CustomerID needed!
      # var, frontend, storage, shown, required, storage-type
#       [ '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' ],
    ],
  };

Ersetzen Sie [AD_server] mit dem Namen oder der IP Adresse Ihres AD servers.

Ersetzen Sie [base_dn] mit der DN des Astes Ihrer Kundenbenutzer, z.B.: "ou=People, dc=example, dc=com".

Ersetzen Sie [user_dn] und [password] wie gehabt.

Ersetzen Sie [customer_id] mit einem geeigneten Attribut. Üblich ist hier das Attribut 'mail' oder 'o'.

Mit CustomerUserListFields bestimmen Sie, wie Kundenbenutzer angezeigt während der Arbeit werden. Mit den obigen Standardeinstellungen wird der Kundenbenutzer angeziegt als: "Username Nachhname email@addresse"

Möchten Sie lediglich die eMail Adressen anzeigen, ändern Sie den Eintrag so ab, dass er nur noch 'mail' enthält. Sie können hier auch weitere LDAP/AD Attribute hinzufügen.

CustomerUserSearchFields hat dieselben Optionen wie CustomerUserListFields. Hiermit bestimmen Sie, über welche Attribute Kundenbesucher gesucht werden. Fügen Sie bspw. das Attribut 'o' hinzu, genügt die Angabe des Firmennamens, um alle Kundenbenutzer einer Firma aufzulisten, sofern dieser Wert im AD vorhanden ist.

Tipps & Tricks

Control who's let in

Verhindern Sie, dass Kundenbernutzer und Agenten sich im OTRS einloggen können. Dies wird umso wichtiger, je größer und unübersichtlicher Ihre AD-Strukur ist/wird. Legen Sie eine Gruppe der Objectklasse posixGroup an und füllen Sie sie mit entweder der UID oder der DN der gewünschten Mitglieder.

Example 11-6. Kernel/Config.pm - GroupDN für Agenten

  $Self->{'AuthModule::LDAP::GroupDN'} = 'cn=otrsallow_A, ou=posixGroups, dc=example, dc=com';
  $Self->{'AuthModule::LDAP::AccessAttr'} = 'memberUid';
 #$Self->{'AuthModule::LDAP::UserAttr'} = 'UID';
  $Self->{'AuthModule::LDAP::UserAttr'} = 'DN';

Example 11-7. Kernel/Config.pm - GroupDN for Customers

  $Self->{'Customer::AuthModule::LDAP::GroupDN'} = 'cn=otrsallow_C, ou=posixGroups, dc=example, dc=com';
  $Self->{'Customer::AuthModule::LDAP::AccessAttr'} = 'memberUid';
 #$Self->{'Customer::AuthModule::LDAP::UserAttr'} = 'UID';
  $Self->{'Customer::AuthModule::LDAP::UserAttr'} = 'DN';

Konfigurationsbeispiel

Dies ist ein komplettes Beispiel, wie OTRS für die Authentifizierung von Kundenbenutzern und Agenten gegen ein AD konfiguriert werden kann. Auch die Kundenbenutzerdaten werden aus dem AD gelesen, die Datenbankeinstellungen wurden hier ebenfalls beibehalten.

Die benutzten Einstel,lungen:

  • Windows AD Server: w2kad.example.com

  • Windows OTRS/AD Benutzer: otrs (Vollständiger Name: OTRS Service)

  • Windows OTRS/AD Benutzer Passwort: secret

  • Windows OTRS/AD Benutzer DN: cn=OTRS Service, ou=People, dc=example, dc=com

  • Windows Domäne: example.com

  • Windows LDAP Basis-DN: dc=example, dc=com

  • Windows Benutzer Container: People

  • Windows Benutzer LDAP DN: ou=People, dc=example, dc=com

  • Windows Agenten LDAP DN: ou=People, dc=example, dc=com

Example 11-8. Kernel/Config.pm - AuthModule LDAP settings

  #------------------------------------------------------------------------
  # Start of Example Config
  $Self->{'AuthModule'} = 'Kernel::System::Auth::LDAP';
  $Self->{'AuthModule::LDAP::Host'} = 'w2kad.example.com';
  $Self->{'AuthModule::LDAP::BaseDN'} = 'dc=example, dc=com';
  $Self->{'AuthModule::LDAP::UID'} = 'sAMAccountName';

  $Self->{'AuthModule::LDAP::SearchUserDN'} = 'cn=OTRS Service, ou=People, dc=example, dc=com';
  $Self->{'AuthModule::LDAP::SearchUserPw'} = 'secret';


  # This is an example configuration for an LDAP auth. backend.
  # (take care that Net::LDAP is installed!)
  $Self->{'Customer::AuthModule'} = 'Kernel::System::CustomerAuth::LDAP';
  $Self->{'Customer::AuthModule::LDAP::Host'} = 'w2kad.example.com';
  $Self->{'Customer::AuthModule::LDAP::BaseDN'} = 'ou=People, dc=example, dc=com';
  $Self->{'Customer::AuthModule::LDAP::UID'} = '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->{'Customer::AuthModule::LDAP::SearchUserDN'} = 'cn=OTRS Service, ou=People, dc=example, dc=com';
  $Self->{'Customer::AuthModule::LDAP::SearchUserPw'} = 'secret';

  # CustomerUser
  # (customer user database backend and settings)
    $Self->{CustomerUser} = {
        Name => 'Datenbank',
        Module => 'Kernel::System::CustomerUser::DB',
        Params => { Table => 'customer_user',
            # to use an external database
#           DSN => 'DBI:odbc:yourdsn',
#           DSN => 'DBI:mysql:database=customerdb;host=customerdbhost',
#           User => '', Password => '',
        },
        # customer uniq id
        CustomerKey => 'login',
        CustomerID => 'customer_id',
        CustomerValid => 'valid_id',
        CustomerUserListFields => ['first_name', 'last_name', 'email'],
#       CustomerUserListFields => ['login', 'first_name', 'last_name', 'customer_id', 'email'],
        CustomerUserSearchFields => ['login', 'last_name', 'customer_id'],
        CustomerUserSearchPrefix => '',
        CustomerUserSearchSuffix => '*',
        CustomerUserSearchListLimit => 250,
        CustomerUserPostMasterSearchFields => ['email'],
        CustomerUserNameFields => ['salutation', 'first_name', 'last_name'],
#       ReadOnly => 1,
        Map => [
            # note: Login, Email and CustomerID needed!
            # var, frontend, storage, shown, required, storage-type, http-link
            [ 'UserSalutation', 'Salutation', 'salutation', 1, 0, 'var' ],
            [ 'UserFirstname', 'Firstname', 'first_name', 1, 1, 'var' ],
            [ 'UserLastname', 'Lastname', 'last_name', 1, 1, 'var' ],
            [ 'UserLogin', 'Login', 'login', 1, 1, 'var' ],
            [ 'UserPassword', 'Password', 'pw', 0, 1, 'var' ],
            [ 'UserEmail', 'Email', 'email', 0, 1, 'var' ],
            [ 'UserCustomerID', 'CustomerID', 'customer_id', 0, 1, 'var' ],
            [ 'UserComment', 'Comment', 'comments', 1, 0, 'var' ],
            [ 'ValidID', 'Valid', 'valid_id', 0, 1, 'int' ],
        ],
    };

  # CustomerUser1
  # (customer user ldap backend and settings)
  $Self->{CustomerUser1} = {
    Module => 'Kernel::System::CustomerUser::LDAP',
    Params => {
      # ldap host
      Host => 'w2kad.example.com',
      # ldap base dn
      BaseDN => 'ou=People, dc=example, dc=com',
      # search scope (one|sub)
      SSCOPE => 'sub',
      # The following is valid but would only be necessary if the
      # anonymous user does NOT have permission to read from the LDAP tree
      UserDN => 'cn=OTRS Service, ou=People, dc=example, dc=com',
      UserPw => 'secret',
      AlwaysFilter => '',
      SourceCharset => 'utf-8',
      DestCharset => 'iso-8859-1',
    },
    # customer uniq id
    CustomerKey => 'sAMAccountName',
    # customer #
    CustomerID => 'mail',
    CustomerUserListFields => ['sAMAccountName', 'cn', 'mail'],
    CustomerUserSearchFields => ['sAMAccountName', 'cn', 'mail'],
    CustomerUserSearchPrefix => '',
    CustomerUserSearchSuffix => '*',
    CustomerUserSearchListLimit => 250,
    CustomerUserPostMasterSearchFields => ['mail'],
    CustomerUserNameFields => ['givenname', 'sn'],
    Map => [
      # note: Login, Email and CustomerID needed!
      # var, frontend, storage, shown, required, storage-type
      #[ '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 example config
  #------------------------------------------------------------------------